fix(aiui): content loads progressively — own first, peers when they arrive
Regression from wiring the peers scope: requestArchyAllContent awaited all three scopes together, so the grid waited on the slowest. `peers` browses every federated node over FIPS (Tor fallback) and routinely takes tens of seconds or times out when a peer is offline. On-device that read as "content(peers) failed: Content request timed out" plus an AIUI that felt very slow to open — with nothing rendered meanwhile, even though local content was ready immediately. Now `own` paints as soon as it lands and `owned`/`peers` fold in as they arrive. A scope that times out costs only its own results. Also records the operator's console findings as tasks: the `files` context timeout, the web-search CSP block (13-09, now firing on every query), the strfry icon 404, IndeeHub's relay.nostr.band socket, and the ask that `!archy` over mesh be able to action container commands with text responses. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
086d381c4f
commit
05b459a65f
@@ -270,55 +270,73 @@ export function useArchy() {
|
||||
*/
|
||||
async function requestArchyAllContent() {
|
||||
if (!isInitialized.value) return
|
||||
const scopes: Array<'own' | 'owned' | 'peers'> = ['own', 'owned', 'peers']
|
||||
|
||||
const results = await Promise.all(
|
||||
scopes.map((s) =>
|
||||
archyBridge
|
||||
.requestArchyContent('all', s)
|
||||
.then((res) => {
|
||||
// Log the denial per scope. A silent null here is indistinguishable
|
||||
// from "the node genuinely has no content", which is exactly the
|
||||
// ambiguity that made an ungranted Media/File permission look like
|
||||
// a broken films search on-device.
|
||||
if (!res.permitted) {
|
||||
console.warn(
|
||||
`[AIUI Archy] content(${s}): not permitted — enable Media/File access in Archy Settings`,
|
||||
)
|
||||
return null
|
||||
}
|
||||
return res
|
||||
})
|
||||
.catch((err) => {
|
||||
console.warn(`[AIUI Archy] content(${s}) failed:`, (err as Error)?.message ?? err)
|
||||
return null
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
const seen = new Set<string>()
|
||||
// PROGRESSIVE, not all-at-once. The first version awaited all three scopes
|
||||
// together, so the grid waited on the slowest — and `peers` browses every
|
||||
// federated node over FIPS (falling back to Tor), which routinely takes
|
||||
// tens of seconds or times out entirely when a peer is offline. On-device
|
||||
// that showed up as "content(peers) failed: Content request timed out" and
|
||||
// an AIUI that felt very slow to open, with NOTHING rendered in the
|
||||
// meantime even though local content was ready immediately.
|
||||
//
|
||||
// So: paint `own` as soon as it lands, then fold in the slower sources as
|
||||
// they arrive. A scope that times out costs only its own results.
|
||||
const films: Film[] = []
|
||||
const podcasts: Podcast[] = []
|
||||
for (const res of results) {
|
||||
if (!res) continue
|
||||
const seen = new Set<string>()
|
||||
|
||||
const merge = (res: { films?: unknown; podcasts?: unknown } | null) => {
|
||||
if (!res) return false
|
||||
let added = false
|
||||
for (const f of (res.films ?? []) as Film[]) {
|
||||
const key = `film:${f.id}`
|
||||
if (seen.has(key)) continue
|
||||
seen.add(key)
|
||||
films.push(f)
|
||||
const k = `film:${f.id}`
|
||||
if (seen.has(k)) continue
|
||||
seen.add(k); films.push(f); added = true
|
||||
}
|
||||
for (const p of (res.podcasts ?? []) as Podcast[]) {
|
||||
const key = `pod:${p.id}`
|
||||
if (seen.has(key)) continue
|
||||
seen.add(key)
|
||||
podcasts.push(p)
|
||||
const k = `pod:${p.id}`
|
||||
if (seen.has(k)) continue
|
||||
seen.add(k); podcasts.push(p); added = true
|
||||
}
|
||||
return added
|
||||
}
|
||||
|
||||
const panel = useContentPanel()
|
||||
panel.setArchyContent({ films, songs: panel.panelSongs.value, podcasts })
|
||||
const paint = () => {
|
||||
const panel = useContentPanel()
|
||||
panel.setArchyContent({ films: [...films], songs: panel.panelSongs.value, podcasts: [...podcasts] })
|
||||
}
|
||||
|
||||
const fetchScope = (scope: 'own' | 'owned' | 'peers') =>
|
||||
archyBridge
|
||||
.requestArchyContent('all', scope)
|
||||
.then((res) => {
|
||||
if (!res.permitted) {
|
||||
console.warn(`[AIUI Archy] content(${scope}): not permitted — enable Media/File access in Archy Settings`)
|
||||
return null
|
||||
}
|
||||
return res
|
||||
})
|
||||
.catch((err) => {
|
||||
// A slow or absent peer is ordinary, not exceptional.
|
||||
console.warn(`[AIUI Archy] content(${scope}) failed:`, (err as Error)?.message ?? err)
|
||||
return null
|
||||
})
|
||||
|
||||
// Local content first — it is fast and is what the operator sees instantly.
|
||||
if (merge(await fetchScope('own'))) paint()
|
||||
|
||||
// Then the slower sources, each painting as it lands rather than blocking
|
||||
// the others or the initial render.
|
||||
await Promise.all(
|
||||
(['owned', 'peers'] as const).map((scope) =>
|
||||
fetchScope(scope).then((res) => {
|
||||
if (merge(res)) paint()
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Request the node's real music library (13-11 — the D-13 wave) and hand
|
||||
* it to the same `setArchyContent` sink `requestArchyContent` uses, so
|
||||
|
||||
Reference in New Issue
Block a user