From a91bc55df8fcefcf2bc83e53943bd338ddd75bcb Mon Sep 17 00:00:00 2001 From: archipelago Date: Fri, 7 Aug 2026 09:16:52 -0400 Subject: [PATCH] =?UTF-8?q?fix(assistant):=20surface=20shape=20bugs=20?= =?UTF-8?q?=E2=80=94=20films=20scope=20mime=20hint,=20apps=5Flist=20items?= =?UTF-8?q?=20wrap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two reasons the content surface 'often doesn't surface the content': - content.indeehub-projects items carried no mime/filename, so the UI adapter classified every film 'excluded' and the films grid could never render. They are films: they now declare video/mp4. - apps_list surfaced the container-list RPC's BARE ARRAY; the broker reads { items: [...] }, so the apps grid was silently dropped every turn. Wrapped at the tool boundary — the shared RPC's own shape is untouched. Co-Authored-By: Claude --- core/archipelago/src/api/rpc/content.rs | 5 +++++ core/archipelago/src/assistant/tools.rs | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/core/archipelago/src/api/rpc/content.rs b/core/archipelago/src/api/rpc/content.rs index eb36b875..6eacf538 100644 --- a/core/archipelago/src/api/rpc/content.rs +++ b/core/archipelago/src/api/rpc/content.rs @@ -1223,6 +1223,11 @@ impl RpcHandler { "synopsis": p.synopsis.clone().unwrap_or_default(), "poster": p.poster.clone().unwrap_or_default(), "year": p.year_num(), + // Films are video by definition. The UI adapter buckets + // purely on mime/extension, so an item carrying neither + // silently classified 'excluded' and this scope's + // surface could never render a card. + "mime_type": "video/mp4", })) }) .collect(); diff --git a/core/archipelago/src/assistant/tools.rs b/core/archipelago/src/assistant/tools.rs index ff2918a5..5a99dbf5 100644 --- a/core/archipelago/src/assistant/tools.rs +++ b/core/archipelago/src/assistant/tools.rs @@ -747,6 +747,14 @@ pub async fn dispatch(name: &str, args: &ToolArgs, handler: &RpcHandler) -> Resu "apps_list" => handler .assistant_dispatch_tool("container-list", None) .await + // `container-list` answers a bare array, but surface consumers + // read `{ items: [...] }` — a bare array is silently dropped by + // the broker and the apps grid never renders. Wrap here, at the + // tool boundary, so the shared RPC's own shape is untouched. + .map(|v| match v { + serde_json::Value::Array(_) => json!({ "items": v }), + other => other, + }) .map_err(|e| format!("tool execution failed: {e}")), "app_logs" => { let ToolArgs::AppLogs(a) = args else {