mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-09-22 09:43:58 +02:00
Compare commits
2 Commits
c8ca11604e
...
59690b157d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59690b157d | ||
|
|
020d0ca897 |
29
.github/workflows/on_issues_ai_triage.yaml
vendored
29
.github/workflows/on_issues_ai_triage.yaml
vendored
@@ -362,6 +362,25 @@ jobs:
|
|||||||
"$EXECUTION_FILE" >/dev/null 2>&1
|
"$EXECUTION_FILE" >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Did the run die because the Claude credential is bad? The action
|
||||||
|
# reports this uselessly — a revoked token surfaces as "--json-schema
|
||||||
|
# was provided but Claude did not return structured_output", which
|
||||||
|
# points at the schema and not at auth. The execution file carries the
|
||||||
|
# truth: api_retry / result objects with error "authentication_failed"
|
||||||
|
# and a 401. Same array guard and fail-closed posture as above; an
|
||||||
|
# unrecognised shape simply is not an auth failure and falls through
|
||||||
|
# to the generic branch.
|
||||||
|
hit_auth_failure() {
|
||||||
|
[ -n "${EXECUTION_FILE:-}" ] && [ -s "${EXECUTION_FILE:-}" ] || return 1
|
||||||
|
jq -e '(type == "array") and
|
||||||
|
any(.[]?;
|
||||||
|
(type == "object") and
|
||||||
|
(((.error? // "") == "authentication_failed") or
|
||||||
|
((.error_status? // 0) == 401) or
|
||||||
|
((.api_error_status? // 0) == 401)))' \
|
||||||
|
"$EXECUTION_FILE" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
# GATE 1 — did the action itself run? This is checked BEFORE looking
|
# GATE 1 — did the action itself run? This is checked BEFORE looking
|
||||||
# at the payload, because the action can fail *after* having written
|
# at the payload, because the action can fail *after* having written
|
||||||
# a valid structured output: the object would sail through the shape
|
# a valid structured output: the object would sail through the shape
|
||||||
@@ -380,6 +399,16 @@ jobs:
|
|||||||
if [ "${CLASSIFY_OUTCOME:-}" = "failure" ]; then
|
if [ "${CLASSIFY_OUTCOME:-}" = "failure" ]; then
|
||||||
restore_needs_info
|
restore_needs_info
|
||||||
|
|
||||||
|
# Checked before anything else, because it is the one failure with
|
||||||
|
# a specific remedy and it takes down every tier at once — tier 1
|
||||||
|
# cannot label, so tier 2's batch is empty and the whole pipeline
|
||||||
|
# goes quiet while each run still fails in a way that reads like a
|
||||||
|
# per-issue problem. Say plainly what is wrong and what to do.
|
||||||
|
if hit_auth_failure; then
|
||||||
|
echo "::error::CLAUDE_CODE_OAUTH_TOKEN is rejected (HTTP 401 / authentication_failed). This is NOT a problem with issue #$ISSUE — every AI workflow is down until the credential is replaced. Regenerate it with 'claude setup-token' and update the CLAUDE_CODE_OAUTH_TOKEN secret in the CR_PAT environment. Set the AI_DISABLED repo variable to 'true' to silence these runs meanwhile."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# ...with one exception. Exhausting the turn budget is NOT a
|
# ...with one exception. Exhausting the turn budget is NOT a
|
||||||
# workflow fault: the action ran fine and this particular issue was
|
# workflow fault: the action ran fine and this particular issue was
|
||||||
# just too tangled to finish inside the turn budget. Treating it as systemic
|
# just too tangled to finish inside the turn budget. Treating it as systemic
|
||||||
|
|||||||
@@ -1,4 +1,18 @@
|
|||||||
|
|
||||||
|
## 1.5.3.3 (2026-08-31)
|
||||||
|
- Complete the iOS companion app fix from 1.5.3.2. The "no preview available"
|
||||||
|
screen -- what you get for a `.zip`, `.bin` or anything else FileBrowser
|
||||||
|
cannot render -- offers its Download and "Open file" buttons as new-tab
|
||||||
|
links, and so does the share list in settings. The app hands every new tab
|
||||||
|
to an external browser, which carries no ingress session, so those answered
|
||||||
|
401. Those two buttons and the settings share links now stay in the panel
|
||||||
|
when running in the companion app, and open a new tab as before in a normal
|
||||||
|
browser -- as does a cmd/ctrl/shift-click anywhere, which is left alone.
|
||||||
|
Download also saves the file instead of displaying it, which 1.5.3.2 only
|
||||||
|
fixed for the download button in the file list. Links the app opens without
|
||||||
|
a link element, such as the public-share sidebar download, are still
|
||||||
|
affected.
|
||||||
|
|
||||||
## 1.5.3.2 (2026-08-30)
|
## 1.5.3.2 (2026-08-30)
|
||||||
- Fix Download in the Home Assistant iOS companion app (iOS 17 and later),
|
- Fix Download in the Home Assistant iOS companion app (iOS 17 and later),
|
||||||
where a file opened and showed its content with no way to save it.
|
where a file opened and showed its content with no way to save it.
|
||||||
|
|||||||
@@ -118,4 +118,4 @@ schema:
|
|||||||
slug: filebrowser_quantum
|
slug: filebrowser_quantum
|
||||||
udev: true
|
udev: true
|
||||||
url: https://github.com/alexbelgium/hassio-addons
|
url: https://github.com/alexbelgium/hassio-addons
|
||||||
version: "1.5.3.2"
|
version: "1.5.3.3"
|
||||||
|
|||||||
@@ -41,31 +41,72 @@ server {
|
|||||||
# same instance's files/ or public/share/ route. Same shape as the komga
|
# same instance's files/ or public/share/ route. Same shape as the komga
|
||||||
# add-on's ingress filter.
|
# add-on's ingress filter.
|
||||||
#
|
#
|
||||||
# 2. Download. FileBrowser downloads a file by building an <a> with no
|
# 2. Saving and opening a file. FileBrowser downloads by clicking an <a>
|
||||||
# download attribute, clicking it, and letting the attachment response do
|
# that carries no download attribute -- a hidden one it builds itself
|
||||||
# the rest. The Home Assistant iOS companion app is a WKWebView, and a
|
# (api/resources.js), and two visible ones in the "no preview available"
|
||||||
# download happens there only when WebKit turns a navigation *action*
|
# fallback (views/files/Preview.vue), which are also target="_blank".
|
||||||
# into a WKDownload, which is what the download attribute does -- the app
|
# Neither works in the Home Assistant companion app:
|
||||||
# hands that to its own download manager
|
|
||||||
# (WebViewController+WebKitDelegates.swift, navigationAction:didBecome
|
|
||||||
# download:). Its response policy delegate returns .allow for every
|
|
||||||
# sub-frame and never returns .download, so a plain attachment navigation
|
|
||||||
# inside the ingress panel is just rendered: a text file opens and shows
|
|
||||||
# its content with no way to save it. Adding the attribute makes the same
|
|
||||||
# click a real download. Desktop browsers already downloaded these and
|
|
||||||
# are unaffected, and an empty value keeps the filename the server sends
|
|
||||||
# in Content-Disposition. Matched on the two exact download endpoints,
|
|
||||||
# minus inline=true: the "no preview available" fallback renders an
|
|
||||||
# "Open file" link on the same endpoint with that parameter
|
|
||||||
# (views/files/Preview.vue), and it is meant to open, not save. Only
|
|
||||||
# programmatic clicks pass through here -- a person clicking a link never
|
|
||||||
# calls HTMLAnchorElement.prototype.click -- so this reaches
|
|
||||||
# FileBrowser's own hidden download anchor and nothing a user clicks.
|
|
||||||
#
|
#
|
||||||
# Not covered: the public-share sidebar downloads with window.open()
|
# - A download happens in its WKWebView only when WebKit turns a
|
||||||
# rather than an anchor, and the app's download manager is gated on
|
# navigation *action* into a WKDownload, which is what the download
|
||||||
# iOS 17 (WebViewController+WebKitDelegates.swift).
|
# attribute does; the app hands that to its own download manager
|
||||||
sub_filter "window.__pwaDeferredPrompt = null;" "window.__pwaDeferredPrompt = null;(function(){var o=window.open;window.open=function(u,n,f){try{var b=(window.globalVars||{}).baseURL;if(u&&n==='_blank'&&!f&&b){if(b.slice(-1)!=='/')b+='/';var t=new URL(u,location.href);if((t.protocol==='http:'||t.protocol==='https:')&&t.origin===location.origin&&(t.pathname.indexOf(b+'files/')===0||t.pathname.indexOf(b+'public/share/')===0)){location.assign(t.href);return window}}}catch(e){}return o.apply(window,arguments)};var c=HTMLAnchorElement.prototype.click;HTMLAnchorElement.prototype.click=function(){try{var b=(window.globalVars||{}).baseURL;if(b&&this.href&&!this.hasAttribute('download')){if(b.slice(-1)!=='/')b+='/';var t=new URL(this.href,location.href);if(t.origin===location.origin&&t.searchParams.get('inline')!=='true'&&(t.pathname===b+'api/resources/download'||t.pathname===b+'public/api/resources/download')){this.download=''}}}catch(e){}return c.apply(this,arguments)}})();";
|
# (WebViewController+WebKitDelegates.swift, navigationAction:didBecome
|
||||||
|
# download:, iOS 17+). Its response policy delegate returns .allow for
|
||||||
|
# every sub-frame and never returns .download, so a plain attachment
|
||||||
|
# navigation in the ingress panel is just rendered: the file opens and
|
||||||
|
# shows its content with no way to save it.
|
||||||
|
# - target="_blank" is worse. The app has no navigationAction policy
|
||||||
|
# delegate, so every new-window request reaches createWebViewWith,
|
||||||
|
# which hands the url to an external browser. That browser carries no
|
||||||
|
# ingress session cookie, so Home Assistant answers 401.
|
||||||
|
#
|
||||||
|
# One capturing click listener covers both, and covers the hidden anchor
|
||||||
|
# too: a programmatic .click() on an anchor that is in the document
|
||||||
|
# dispatches through it exactly like a real one -- same event, button 0,
|
||||||
|
# no modifiers -- and the capture phase runs before the link is followed.
|
||||||
|
# It replaces an earlier wrapper around HTMLAnchorElement.prototype.click,
|
||||||
|
# which reached the hidden anchor but not the two the user clicks. The
|
||||||
|
# wrapper would also have caught a click on a *detached* anchor, which
|
||||||
|
# this cannot; both of FileBrowser's download paths append theirs to the
|
||||||
|
# body first (api/resources.js), so nothing is lost today.
|
||||||
|
#
|
||||||
|
# Only unmodified primary clicks are touched. A cmd/ctrl/shift-click is
|
||||||
|
# an explicit request for a separate context and is left alone, which
|
||||||
|
# matters on desktop and in the Mac Catalyst app.
|
||||||
|
#
|
||||||
|
# Downloads gain the attribute everywhere -- desktop browsers already
|
||||||
|
# saved these on a plain click, and an empty value keeps the filename the
|
||||||
|
# server sends in Content-Disposition. One behaviour does change there:
|
||||||
|
# if the endpoint answers with an error the body is saved as a file
|
||||||
|
# instead of being shown, because the decision is made before the
|
||||||
|
# response exists. Matched on the two exact download endpoints minus
|
||||||
|
# inline=true, which is the fallback's "Open file" link and is meant to
|
||||||
|
# open rather than save. That branch drops target="_blank" in every
|
||||||
|
# browser too: with the attribute present a same-origin link downloads
|
||||||
|
# and never opens a tab (measured), so it changes nothing here, but it
|
||||||
|
# stops the companion app from taking its new-window path before it
|
||||||
|
# considers the download -- an ordering that cannot be tested from
|
||||||
|
# outside iOS.
|
||||||
|
#
|
||||||
|
# Dropping target="_blank" from links that are *not* downloads is limited
|
||||||
|
# to the companion app, identified by the Mobile/HomeAssistant marker it
|
||||||
|
# appends to the user agent
|
||||||
|
# (HAAPI.swift, applicationNameForUserAgent -- it covers iPhone, iPad and
|
||||||
|
# Mac Catalyst). In a real browser a new tab is the better behaviour and
|
||||||
|
# is left alone; in the app it is a 401. It applies to any same-origin
|
||||||
|
# link below the add-on's own base path, which in practice is the
|
||||||
|
# "Open file" button and the share links in settings
|
||||||
|
# (views/settings/Shares.vue). Links to other origins keep their new tab,
|
||||||
|
# and only an exact target="_blank" is matched, so named windows, _parent
|
||||||
|
# and _top are untouched.
|
||||||
|
#
|
||||||
|
# Not covered, and still 401 in the app: anything the app opens with
|
||||||
|
# window.open() rather than an anchor, which is the public-share sidebar
|
||||||
|
# download and absolute sidebar links (components/sidebar/Links.vue); and
|
||||||
|
# links inside a document FileBrowser renders in its own iframe -- the
|
||||||
|
# pdf viewer, the srcdoc markdown/html preview, OnlyOffice -- because a
|
||||||
|
# listener on this document never sees another document's clicks.
|
||||||
|
sub_filter "window.__pwaDeferredPrompt = null;" "window.__pwaDeferredPrompt = null;(function(){var o=window.open;window.open=function(u,n,f){try{var b=(window.globalVars||{}).baseURL;if(u&&n==='_blank'&&!f&&b){if(b.slice(-1)!=='/')b+='/';var t=new URL(u,location.href);if((t.protocol==='http:'||t.protocol==='https:')&&t.origin===location.origin&&(t.pathname.indexOf(b+'files/')===0||t.pathname.indexOf(b+'public/share/')===0)){location.assign(t.href);return window}}}catch(e){}return o.apply(window,arguments)};document.addEventListener('click',function(e){try{if(e.button||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;var a=e.target&&e.target.closest?e.target.closest('a'):null;if(!a||!a.href)return;var b=(window.globalVars||{}).baseURL;if(!b)return;if(b.slice(-1)!=='/')b+='/';var t=new URL(a.href,location.href);if(t.origin!==location.origin)return;if(!a.hasAttribute('download')&&t.searchParams.get('inline')!=='true'&&(t.pathname===b+'api/resources/download'||t.pathname===b+'public/api/resources/download')){a.download='';a.removeAttribute('target');return}if(a.target==='_blank'&&t.pathname.indexOf(b)===0&&navigator.userAgent.indexOf('Mobile/HomeAssistant')!==-1){a.removeAttribute('target')}}catch(err){}},true)})();";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user