@agent-native/dispatch 0.29.2 → 0.29.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-app-host.d.ts","sourceRoot":"","sources":["../../src/components/workspace-app-host.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,sCAAsC,CAAC;AAc9C,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAyBf,UAAU,iBAAiB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,CAAC;CACnB;AAqBD,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,iBAAiB,CAEnB;AAkED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,KAAK,EACL,OAAO,EACP,QAAQ,EACR,IAA2B,EAC3B,aAAa,EACb,mBAAmB,GACpB,EAAE,yBAAyB,mDAiE3B;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,UAAU,sBAAsB;IAC9B,GAAG,EAAE,oBAAoB,CAAC;IAC1B,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;IACvD,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,GAAG,EACH,mBAA4C,EAC5C,SAAS,EACT,WAAmB,EACnB,IAA2B,GAC5B,EAAE,sBAAsB,mDA4MxB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,mBAA4C,GAC7C,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;CACxD,mDA8JA;AAID,wBAAgB,qBAAqB,CAAC,EACpC,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,mDAwCA"}
1
+ {"version":3,"file":"workspace-app-host.d.ts","sourceRoot":"","sources":["../../src/components/workspace-app-host.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,sCAAsC,CAAC;AAc9C,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAyBf,UAAU,iBAAiB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,CAAC;CACnB;AAqBD,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,iBAAiB,CAEnB;AAkED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,KAAK,EACL,OAAO,EACP,QAAQ,EACR,IAA2B,EAC3B,aAAa,EACb,mBAAmB,GACpB,EAAE,yBAAyB,mDAiE3B;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,UAAU,sBAAsB;IAC9B,GAAG,EAAE,oBAAoB,CAAC;IAC1B,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;IACvD,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,GAAG,EACH,mBAA4C,EAC5C,SAAS,EACT,WAAmB,EACnB,IAA2B,GAC5B,EAAE,sBAAsB,mDA4MxB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,mBAA4C,GAC7C,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;CACxD,mDA6LA;AAID,wBAAgB,qBAAqB,CAAC,EACpC,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,mDAwCA"}
@@ -265,17 +265,29 @@ export function WorkspaceAppFrame({ app, navigateToTopWindow = navigateToWorkspa
265
265
  }
266
266
  export function WorkspaceAppHost({ appId, navigateToTopWindow = navigateToWorkspaceApp, }) {
267
267
  const t = useT();
268
- const workspaceAppsQuery = useActionQuery("list-workspace-apps", { includeAgentCards: false });
269
- const grantedAppsQuery = useActionQuery("list_apps", {});
268
+ const workspaceAppsQuery = useActionQuery("list-workspace-apps", { includeAgentCards: false, includeArchived: true });
269
+ const workspaceApps = useMemo(() => mergeChatFirstWorkspaceApps(workspaceAppsQuery.data), [workspaceAppsQuery.data]);
270
+ const visibleWorkspaceApps = useMemo(() => workspaceApps.filter((item) => !item.archived), [workspaceApps]);
271
+ const workspaceAppIds = useMemo(() => new Set(workspaceApps.map((item) => item.id.trim().toLowerCase())), [workspaceApps]);
272
+ const workspaceApp = useMemo(() => visibleWorkspaceApps.find((item) => item.id.trim().toLowerCase() === appId?.trim().toLowerCase()) ?? null, [appId, visibleWorkspaceApps]);
273
+ const grantedAppsQuery = useActionQuery("list_apps", {}, {
274
+ // Mounted workspace apps are already fully described by the workspace
275
+ // registry. Defer the broader MCP grant/discovery scan until that
276
+ // lookup misses; it is only needed for externally granted apps.
277
+ enabled: !workspaceAppsQuery.isLoading && !workspaceApp,
278
+ });
270
279
  const apps = useMemo(() => {
271
280
  const merged = new Map();
272
- for (const app of mergeChatFirstWorkspaceApps(workspaceAppsQuery.data)) {
281
+ for (const app of visibleWorkspaceApps) {
273
282
  merged.set(app.id.trim().toLowerCase(), app);
274
283
  }
275
284
  for (const app of grantedAppsQuery.data?.apps ?? []) {
276
285
  const id = app.id.trim();
277
- if (!id || merged.has(id.toLowerCase()))
286
+ if (!id ||
287
+ workspaceAppIds.has(id.toLowerCase()) ||
288
+ merged.has(id.toLowerCase())) {
278
289
  continue;
290
+ }
279
291
  merged.set(id.toLowerCase(), {
280
292
  id,
281
293
  name: app.name.trim() || id,
@@ -285,7 +297,7 @@ export function WorkspaceAppHost({ appId, navigateToTopWindow = navigateToWorksp
285
297
  });
286
298
  }
287
299
  return [...merged.values()];
288
- }, [grantedAppsQuery.data?.apps, workspaceAppsQuery.data]);
300
+ }, [grantedAppsQuery.data?.apps, visibleWorkspaceApps, workspaceAppIds]);
289
301
  const app = useMemo(() => apps.find((item) => item.id.trim().toLowerCase() === appId?.trim().toLowerCase()) ?? null, [appId, apps]);
290
302
  const isLoading = workspaceAppsQuery.isLoading || grantedAppsQuery.isLoading;
291
303
  const queryError = workspaceAppsQuery.isError
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-app-host.js","sourceRoot":"","sources":["../../src/components/workspace-app-host.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GAErB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EACL,iBAAiB,EACjB,cAAc,GACf,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EAAE,4BAA4B,EAAE,MAAM,iDAAiD,CAAC;AAC/F,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EACL,WAAW,EACX,SAAS,EACT,OAAO,EACP,MAAM,EACN,QAAQ,GAET,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,EACtB,iCAAiC,EACjC,sBAAsB,EACtB,uBAAuB,EACvB,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAwBzC,SAAS,4BAA4B,CAAC,KAAwB;IAC5D,OAAO;QACL,IAAI,EAAE,2BAAoC;QAC1C,KAAK;QACL,MAAM,EAAE,KAAK,KAAK,MAAM;KACzB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC7C,KAAa,EACb,IAAY;IAEZ,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AACjD,CAAC;AAED,KAAK,UAAU,8BAA8B,CAC3C,QAAkB;IAElB,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,8EAA8E;QAC9E,OAAO,6BAA6B,QAAQ,CAAC,MAAM,2BAA2B,CAAC;IACjF,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAwB,CAAC;QACvD,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC;IAC5E,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;IACzE,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,6BAA6B,QAAQ,CAAC,MAAM,GAAG,CAAC;AACxE,CAAC;AAED;;;;;;GAMG;AACH,SAAS,sBAAsB,CAAC,KAAa;IAC3C,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,EAAE,CAAC,eAAe,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC,EACvD,CAAC,KAAK,CAAC,CACR,CAAC;IACF,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC1C,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEtD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,cAAc,CAAC,KAAK,CAAC,CAAC;QACtB,0EAA0E;QAC1E,gEAAgE;QAChE,KAAK,KAAK,CAAC,GAAG,MAAM,OAAO,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;aACrD,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;YACvB,IAAI,QAAQ,CAAC,EAAE;gBAAE,OAAO;YACxB,MAAM,IAAI,KAAK,CAAC,MAAM,8BAA8B,CAAC,QAAQ,CAAC,CAAC,CAAC;QAClE,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACxB,IAAI,SAAS;gBAAE,OAAO;YACtB,OAAO,CAAC,IAAI,CACV,6CAA6C,KAAK,EAAE,EACpD,KAAK,CACN,CAAC;YACF,cAAc,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IAE7B,OAAO;QACL,MAAM;QACN,WAAW;QACX,KAAK,EAAE,WAAW,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;KAC/D,CAAC;AACJ,CAAC;AAWD;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,EACnC,KAAK,EACL,OAAO,EACP,QAAQ,EACR,IAAI,GAAG,oBAAoB,EAC3B,aAAa,EACb,mBAAmB,GACO;IAC1B,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,OAAO,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAE9C,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,OAAO,CACL,eAAK,SAAS,EAAC,qBAAqB,aAClC,0DAEE,SAAS,EAAC,0CAA0C,YAEpD,MAAC,KAAK,IAAC,OAAO,EAAC,aAAa,aAC1B,KAAC,iBAAiB,IAAC,SAAS,EAAC,QAAQ,GAAG,EACxC,MAAC,gBAAgB,IAAC,SAAS,EAAC,mDAAmD,aAC7E,yBACG,CAAC,CAAC,mCAAmC,EAAE;4CACtC,YAAY,EACV,kFAAkF;4CACpF,IAAI,EAAE,OAAO;yCACd,CAAC,GACG,EACP,KAAC,MAAM,IACL,IAAI,EAAC,QAAQ,EACb,OAAO,EAAC,SAAS,EACjB,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,OAAO,CAAC,KAAK,YAErB,IAAI,CAAC,OAAO,CAAC,GACP,IACQ,IACb,GACJ,EACN,cAAK,SAAS,EAAC,gBAAgB,YAAE,QAAQ,GAAO,IAC5C,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,YAAY,IACX,QAAQ,EAAC,MAAM,EACf,WAAW,QACX,cAAc,EAAC,mBAAmB,EAClC,UAAU,EAAE,qBAAqB,KAAK,EAAE,EACxC,KAAK,EAAE;YACL,IAAI,EAAE,eAAe;YACrB,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,OAAO;YACd,UAAU,EAAE,iBAAiB,KAAK,EAAE;SACrC;QACD,mEAAmE;QACnE,uEAAuE;QACvE,iDAAiD;QACjD,MAAM,EAAE,OAAO,CAAC,MAAM,EACtB,gBAAgB,EAAC,KAAK,EACtB,UAAU,QACV,qBAAqB,QACrB,kBAAkB,EAAE,KAAK,EACzB,WAAW,EAAE,EAAE,EACf,cAAc,EAAE,aAAa,OAAO,EAAE,KAClC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACxC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,YAEvD,QAAQ,GACI,CAChB,CAAC;AACJ,CAAC;AAmBD,MAAM,UAAU,iBAAiB,CAAC,EAChC,GAAG,EACH,mBAAmB,GAAG,sBAAsB,EAC5C,SAAS,EACT,WAAW,GAAG,KAAK,EACnB,IAAI,GAAG,oBAAoB,GACJ;IACvB,MAAM,EAAE,aAAa,EAAE,GAAG,QAAQ,EAAE,CAAC;IACrC,MAAM,KAAK,GACT,aAAa,KAAK,MAAM,IAAI,aAAa,KAAK,OAAO;QACnD,CAAC,CAAC,aAAa;QACf,CAAC,CAAC,OAAO,QAAQ,KAAK,WAAW;YAC7B,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;YACrD,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,OAAO,CAAC;IAChB,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC9D,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IACjE,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,CAAC,yBAAyB,EAAE,4BAA4B,CAAC,GAC7D,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClB,MAAM,aAAa,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IACtD,MAAM,gBAAgB,GAAG,WAAW,CAAC,GAAG,EAAE;QACxC,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,CAC/C,4BAA4B,CAAC,KAAK,CAAC,EACnC,GAAG,CACJ,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACZ,MAAM,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;QACvC,gBAAgB,EAAE,CAAC;QACnB,IAAI,gBAAgB;YAAE,aAAa,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACzC,MAAM,mBAAmB,GAAG,cAAc,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;IAC5E,MAAM,kBAAkB,GAAG,iBAAiB,CAG1C,sBAAsB,EAAE;QACxB,2BAA2B,EAAE,IAAI;KAClC,CAAC,CAAC;IACH,MAAM,8BAA8B,GAAG,iBAAiB,CAGtD,oCAAoC,EAAE;QACtC,2BAA2B,EAAE,IAAI;KAClC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,gBAAgB,CAAC;QAC/B,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE;QACpB,GAAG,EAAE,GAAG,CAAC,GAAG;KACb,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE;QACjC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,sBAAsB,CAC3B,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,EAChC,SAAS,CACV,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,uBAAuB,CAAC;YACrC,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE;YACpB,GAAG,EAAE,GAAG,CAAC,GAAG;SACb,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC;IAC3C,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;IACnC,MAAM,eAAe,GAAG,iCAAiC,EAAE,CAAC;IAC5D,MAAM,UAAU,GAAG,OAAO,CAA2B,GAAG,EAAE;QACxD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,+BAA+B,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,OAAO;YACL,GAAG,EAAE,GAAG,CAAC,EAAE;YACX,GAAG,uBAAuB,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAClE,MAAM,EAAE,SAAS;SAClB,CAAC;IACJ,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IAEpD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,4BAA4B,CAAC,KAAK,CAAC,CAAC;YACpC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,4BAA4B,CAAC,IAAI,CAAC,CAAC;YACnC,OAAO;QACT,CAAC;QAED,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC;YACH,WAAW,GAAG,mBAAmB,CAAC,aAAa,CAAC,KAAK,KAAK,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,GAAG,KAAK,CAAC;QACtB,CAAC;QACD,4BAA4B,CAAC,CAAC,WAAW,CAAC,CAAC;IAC7C,CAAC,EAAE,CAAC,mBAAmB,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC,CAAC;IAE1D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,UAAU,IAAI,CAAC,eAAe,IAAI,CAAC,yBAAyB,CAAC;YAAE,OAAO;QAC3E,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAC3B,MAAM,aAAa,GAAG,mBAAmB;YACvC,CAAC,CAAC,8BAA8B;YAChC,CAAC,CAAC,kBAAkB,CAAC;QACvB,KAAK,aAAa;aACf,WAAW,CAAC,UAAU,CAAC;aACvB,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACf,IAAI,CAAC,SAAS;gBAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC/C,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACxB,IAAI,SAAS;gBAAE,OAAO;YACtB,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACxE,IAAI,mBAAmB,EAAE,CAAC;gBACxB,8DAA8D;gBAC9D,gEAAgE;gBAChE,8DAA8D;gBAC9D,cAAc;gBACd,mBAAmB,CAAC,KAAK,CAAC,CAAC;gBAC3B,WAAW,CAAC,IAAI,CAAC,CAAC;gBAClB,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,OAAO;YACT,CAAC;YACD,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAC1B,WAAW,CACT,sBAAsB,CACpB,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,EACtC,SAAS,IAAI,GAAG,CACjB,CACF,CAAC;YACF,aAAa,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE;QACD,GAAG,CAAC,EAAE;QACN,GAAG,CAAC,IAAI;QACR,GAAG,CAAC,GAAG;QACP,kBAAkB,CAAC,WAAW;QAC9B,8BAA8B,CAAC,WAAW;QAC1C,UAAU;QACV,SAAS;QACT,YAAY;QACZ,eAAe;QACf,yBAAyB;QACzB,mBAAmB;KACpB,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,yBAAyB,GAAG,CAAC,KAAmB,EAAE,EAAE;YACxD,IACE,CAAC,4BAA4B,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,EACrE,CAAC;gBACD,OAAO;YACT,CAAC;YACD,eAAe,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,yBAAyB,CAAC,CAAC;QAC9D,OAAO,GAAG,EAAE,CACV,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,yBAAyB,CAAC,CAAC;IACrE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,SAAS,CAAC,GAAG,EAAE;QACb,gBAAgB,EAAE,CAAC;IACrB,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAEjC,MAAM,OAAO,GAAG,CACd,KAAC,gBAAgB,IACf,GAAG,EAAE,GAAG,EACR,MAAM,EACJ,QAAQ;YACN,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,UAAU;gBACV,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,UAAU;oBACV,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,YAAY,EAEtB,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,UAAU,EAAE,OAAO,EACjC,OAAO,EACL,UAAU,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAE1E,WAAW,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAC/B,4DAGE,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,IAAI,GAAG,CAAC,IAAI,EACxB,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,eAAe,EACvB,cAAc,EAAC,aAAa,EAC5B,KAAK,EAAC,iCAAiC,EACvC,SAAS,EAAC,sCAAsC,IAR3C,GAAG,GAAG,GAAG,GAAG,YAAY,CAS7B,CACH,EACD,IAAI,EAAE,IAAI,GACV,CACH,CAAC;IAEF,IAAI,CAAC,WAAW;QAAE,OAAO,OAAO,CAAC;IAEjC,OAAO,CACL,KAAC,oBAAoB,IAAC,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,YAC/D,OAAO,GACa,CACxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAC/B,KAAK,EACL,mBAAmB,GAAG,sBAAsB,GAI7C;IACC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,kBAAkB,GAAG,cAAc,CACvC,qBAAqB,EACrB,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAC7B,CAAC;IACF,MAAM,gBAAgB,GAAG,cAAc,CACrC,WAAW,EACX,EAAE,CACH,CAAC;IACF,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;QACxB,MAAM,MAAM,GAAG,IAAI,GAAG,EAA+B,CAAC;QAEtD,KAAK,MAAM,GAAG,IAAI,2BAA2B,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;YACvE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/C,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;YACpD,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,EAAE,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC;gBAAE,SAAS;YAClD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE;gBAC3B,EAAE;gBACF,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE;gBAC3B,IAAI,EAAE,EAAE;gBACR,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,IAAI;gBAC5B,MAAM,EAAE,OAAO;aAChB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9B,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,OAAO,CACjB,GAAG,EAAE,CACH,IAAI,CAAC,IAAI,CACP,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,KAAK,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CACvE,IAAI,IAAI,EACX,CAAC,KAAK,EAAE,IAAI,CAAC,CACd,CAAC;IACF,MAAM,SAAS,GAAG,kBAAkB,CAAC,SAAS,IAAI,gBAAgB,CAAC,SAAS,CAAC;IAC7E,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO;QAC3C,CAAC,CAAC,kBAAkB,CAAC,KAAK;QAC1B,CAAC,CAAC,gBAAgB,CAAC,OAAO;YACxB,CAAC,CAAC,gBAAgB,CAAC,KAAK;YACxB,CAAC,CAAC,IAAI,CAAC;IAEX,IAAI,UAAU,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,OAAO,CACL,cAAK,SAAS,EAAC,qDAAqD,YAClE,cAAK,SAAS,EAAC,kBAAkB,YAC/B,KAAC,gBAAgB,IACf,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,GAAG,EAAE;wBACZ,KAAK,kBAAkB,CAAC,OAAO,EAAE,CAAC;wBAClC,KAAK,gBAAgB,CAAC,OAAO,EAAE,CAAC;oBAClC,CAAC,GACD,GACE,GACF,CACP,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC;QACtB,OAAO,CACL,cAAK,SAAS,EAAC,qDAAqD,YAClE,eAAK,SAAS,EAAC,0DAA0D,aACvE,KAAC,QAAQ,IAAC,SAAS,EAAC,UAAU,GAAG,EACjC,KAAC,QAAQ,IAAC,SAAS,EAAC,YAAY,GAAG,EACnC,KAAC,QAAQ,IAAC,SAAS,EAAC,WAAW,GAAG,IAC9B,GACF,CACP,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,CACL,cAAK,SAAS,EAAC,qDAAqD,YAClE,eAAK,SAAS,EAAC,gDAAgD,aAC7D,KAAC,MAAM,IAAC,OAAO,QAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAC,SAAS,EAAC,YAAY,YAC9D,MAAC,IAAI,IAAC,EAAE,EAAC,OAAO,aACd,KAAC,aAAa,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,QAAQ,GAAG,EAC7C,CAAC,CAAC,mBAAmB,CAAC,IAClB,GACA,EACT,eAAK,SAAS,EAAC,WAAW,aACxB,aAAI,SAAS,EAAC,yCAAyC,YACpD,CAAC,CAAC,4BAA4B,CAAC,GAC7B,EACL,YAAG,SAAS,EAAC,+BAA+B,YACzC,CAAC,CAAC,wCAAwC,CAAC,GAC1C,IACA,IACF,GACF,CACP,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,CACL,cAAK,SAAS,EAAC,qDAAqD,YAClE,eAAK,SAAS,EAAC,gDAAgD,aAC7D,KAAC,MAAM,IAAC,OAAO,QAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAC,SAAS,EAAC,YAAY,YAC9D,MAAC,IAAI,IAAC,EAAE,EAAC,OAAO,aACd,KAAC,aAAa,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,QAAQ,GAAG,EAC7C,CAAC,CAAC,mBAAmB,CAAC,IAClB,GACA,EACT,eAAK,SAAS,EAAC,WAAW,aACxB,eAAK,SAAS,EAAC,mCAAmC,aAChD,aAAI,SAAS,EAAC,yCAAyC,YACpD,GAAG,CAAC,IAAI,GACN,EACL,MAAC,KAAK,IACJ,OAAO,EAAC,SAAS,EACjB,SAAS,EAAC,8EAA8E,aAExF,KAAC,cAAc,IAAC,IAAI,EAAE,EAAE,GAAI,EAC3B,CAAC,CAAC,yBAAyB,CAAC,IACvB,IACJ,EACN,aAAG,SAAS,EAAC,+BAA+B,aACzC,CAAC,CAAC,kCAAkC,CAAC,EAAE,GAAG,EAC3C,eAAM,SAAS,EAAC,2BAA2B,YAAE,GAAG,CAAC,IAAI,GAAQ,EAAC,GAAG,EAChE,CAAC,CAAC,kCAAkC,CAAC,IACpC,EACH,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAChB,KAAC,MAAM,IAAC,OAAO,kBACb,YACE,IAAI,EAAE,4BAA4B,CAAC,GAAG,CAAC,UAAU,EAAE;wCACjD,QAAQ,EAAE,SAAS;wCACnB,OAAO,EAAE,iBAAiB;qCAC3B,CAAC,EACF,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,YAEf,CAAC,CAAC,kCAAkC,EAAE;wCACrC,YAAY,EAAE,iBAAiB;qCAChC,CAAC,GACA,GACG,CACV,CAAC,CAAC,CAAC,IAAI,IACJ,IACF,GACF,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,wDAEE,SAAS,EAAC,4CAA4C,YAEtD,cAAK,SAAS,EAAC,4BAA4B,YACzC,KAAC,iBAAiB,IAChB,GAAG,EAAE,GAAG,EACR,mBAAmB,EAAE,mBAAmB,GACxC,GACE,GACF,CACP,CAAC;AACJ,CAAC;AAED,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAE9B,MAAM,UAAU,qBAAqB,CAAC,EACpC,WAAW,GAGZ;IACC,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAW,GAAG,EAAE,CAChE,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CACjC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,WAAW;YAAE,OAAO;QACzB,gBAAgB,CAAC,CAAC,OAAO,EAAE,EAAE,CAC3B,CAAC,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,CACtE,CAAC,EACD,mBAAmB,CACpB,CACF,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,cAAc,GAClB,WAAW,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC;QACjD,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,aAAa,CAAC;QACjC,CAAC,CAAC,aAAa,CAAC;IAEpB,OAAO,CACL,yDAEE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,QAAQ,YAErE,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5B,MAAM,MAAM,GAAG,KAAK,KAAK,WAAW,CAAC;YACrC,OAAO,CACL,yDAE2C,KAAK,iBACjC,CAAC,MAAM,EACpB,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,YAE/C,KAAC,gBAAgB,IAAC,KAAK,EAAE,KAAK,GAAI,IAL7B,KAAK,CAMN,CACP,CAAC;QACJ,CAAC,CAAC,GACE,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { AgentSidebar } from \"@agent-native/core/client/agent-chat\";\nimport { agentNativePath } from \"@agent-native/core/client/api-path\";\nimport {\n ChatFirstAppPane,\n defaultChatFirstCopy,\n type ChatFirstCopy,\n} from \"@agent-native/core/client/chat-first\";\nimport { useFeatureFlag } from \"@agent-native/core/client/feature-flags\";\nimport {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { withBuilderUtmTrackingParams } from \"@agent-native/core/shared/builder-link-tracking\";\nimport {\n IconAlertTriangle,\n IconArrowLeft,\n IconClockHour4,\n} from \"@tabler/icons-react\";\nimport { useTheme } from \"next-themes\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { Link } from \"react-router\";\n\nimport { isEmbedSessionExpiredMessage } from \"../lib/embed-session-recovery\";\nimport {\n mergeChatFirstWorkspaceApps,\n navigateToWorkspaceApp,\n shouldOpenWorkspaceAppInTopWindow,\n workspaceAppDirectHref,\n workspaceAppEmbedTarget,\n workspaceAppHref,\n type WorkspaceAppSummary,\n} from \"../lib/workspace-apps\";\nimport { DISPATCH_WORKSPACE_SSO_FLAG } from \"../shared/feature-flags\";\nimport { workspaceAppChatProxyPath } from \"../shared/workspace-app-chat\";\nimport { ActionQueryError } from \"./action-query-error\";\nimport { Alert, AlertDescription } from \"./ui/alert\";\nimport { Badge } from \"./ui/badge\";\nimport { Button } from \"./ui/button\";\nimport { Skeleton } from \"./ui/skeleton\";\n\ninterface EmbedSessionResult {\n startUrl: string;\n}\n\ninterface EmbedSessionInput {\n app?: string;\n path?: string;\n url?: string;\n chrome: \"minimal\";\n}\n\ninterface GrantedWorkspaceAppSummary {\n id: string;\n name: string;\n url?: string | null;\n}\n\ninterface GrantedWorkspaceAppsResult {\n apps: GrantedWorkspaceAppSummary[];\n}\n\ntype WorkspaceAppTheme = \"light\" | \"dark\";\nfunction buildWorkspaceAppThemeUpdate(theme: WorkspaceAppTheme) {\n return {\n type: \"agent-native-theme-update\" as const,\n theme,\n isDark: theme === \"dark\",\n };\n}\n\nexport function buildChatFirstEmbedSessionInput(\n appId: string,\n path: string,\n): EmbedSessionInput {\n return { app: appId, path, chrome: \"minimal\" };\n}\n\nasync function readWorkspaceAppChatProxyError(\n response: Response,\n): Promise<string> {\n let body: string;\n try {\n body = await response.text();\n } catch {\n // coercion-ok: an unreadable body is reported as such, not as an empty error.\n return `Agent chat proxy returned ${response.status} with an unreadable body.`;\n }\n try {\n const parsed = JSON.parse(body) as { error?: unknown };\n if (typeof parsed.error === \"string\" && parsed.error) return parsed.error;\n } catch {\n // coercion-ok: a non-JSON body is still reportable as the status line.\n }\n return body.trim() || `Agent chat proxy returned ${response.status}.`;\n}\n\n/**\n * Point the app pane's chat rail at the app's OWN agent through the Dispatch\n * proxy, and prove the proxy answers before claiming it works. A rail that\n * quietly fell back to Dispatch's agent would look identical while running the\n * wrong tools, instructions, and app resources, so a failed probe is a visible\n * error state instead.\n */\nfunction useWorkspaceAppChatApi(appId: string) {\n const apiUrl = useMemo(\n () => agentNativePath(workspaceAppChatProxyPath(appId)),\n [appId],\n );\n const [attempt, setAttempt] = useState(0);\n const [unavailable, setUnavailable] = useState(false);\n\n useEffect(() => {\n let cancelled = false;\n setUnavailable(false);\n // `/mode` is the app's own dev-mode surface: reaching it proves the proxy\n // minted an app session and the app's agent-chat routes answer.\n void fetch(`${apiUrl}/mode`, { credentials: \"include\" })\n .then(async (response) => {\n if (response.ok) return;\n throw new Error(await readWorkspaceAppChatProxyError(response));\n })\n .catch((cause: unknown) => {\n if (cancelled) return;\n console.warn(\n `[dispatch] app chat proxy unavailable for ${appId}`,\n cause,\n );\n setUnavailable(true);\n });\n return () => {\n cancelled = true;\n };\n }, [apiUrl, appId, attempt]);\n\n return {\n apiUrl,\n unavailable,\n retry: useCallback(() => setAttempt((value) => value + 1), []),\n };\n}\n\nexport interface WorkspaceAppChatRailProps {\n appId: string;\n appName: string;\n children: ReactNode;\n copy?: ChatFirstCopy;\n agentPageHref?: string;\n onFullscreenRequest?: () => void;\n}\n\n/**\n * The chat beside an open workspace app. Every surface that hosts an app pane\n * must go through here so the rail is always the app's own agent — same tools,\n * AGENTS.md, skills, app-scoped resources, and dev-mode surface as the app's\n * native chat — and so an unreachable app is one visible error state rather\n * than a per-surface silent handoff back to Dispatch's agent.\n */\nexport function WorkspaceAppChatRail({\n appId,\n appName,\n children,\n copy = defaultChatFirstCopy,\n agentPageHref,\n onFullscreenRequest,\n}: WorkspaceAppChatRailProps) {\n const t = useT();\n const appChat = useWorkspaceAppChatApi(appId);\n\n if (appChat.unavailable) {\n return (\n <div className=\"flex h-full min-h-0\">\n <div\n data-dispatch-app-chat-unavailable\n className=\"w-88 shrink-0 overflow-auto border-r p-4\"\n >\n <Alert variant=\"destructive\">\n <IconAlertTriangle className=\"size-4\" />\n <AlertDescription className=\"flex flex-wrap items-center justify-between gap-3\">\n <span>\n {t(\"dispatch.pages.appChatUnavailable\", {\n defaultValue:\n \"Dispatch could not connect to {{name}}'s agent, so its chat is unavailable here.\",\n name: appName,\n })}\n </span>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={appChat.retry}\n >\n {copy(\"retry\")}\n </Button>\n </AlertDescription>\n </Alert>\n </div>\n <div className=\"min-w-0 flex-1\">{children}</div>\n </div>\n );\n }\n\n return (\n <AgentSidebar\n position=\"left\"\n defaultOpen\n openStorageKey=\"dispatch-app-chat\"\n storageKey={`dispatch-app-chat:${appId}`}\n scope={{\n type: \"workspace-app\",\n id: appId,\n label: appName,\n contextKey: `workspace-app:${appId}`,\n }}\n // The app's own server answers this chat, so its tools, AGENTS.md,\n // skills, app-scoped resources, and dev-mode surface are the real ones\n // rather than a copy maintained inside Dispatch.\n apiUrl={appChat.apiUrl}\n agentChatSurface=\"app\"\n showTabBar\n suppressInlineOpenApp\n dynamicSuggestions={false}\n suggestions={[]}\n emptyStateText={`Ask about ${appName}`}\n {...(agentPageHref ? { agentPageHref } : {})}\n {...(onFullscreenRequest ? { onFullscreenRequest } : {})}\n >\n {children}\n </AgentSidebar>\n );\n}\n\nexport interface WorkspaceAppFrameApp {\n id: string;\n name: string;\n path?: string | null;\n url?: string | null;\n}\n\ninterface WorkspaceAppFrameProps {\n app: WorkspaceAppFrameApp;\n navigateToTopWindow?: (href: string) => boolean | void;\n /** Chat-first app tabs use their own route while standalone hosts use app metadata. */\n embedPath?: string;\n /** Chat-first app surfaces own the parent chat rail around the iframe. */\n chatSidebar?: boolean;\n copy?: ChatFirstCopy;\n}\n\nexport function WorkspaceAppFrame({\n app,\n navigateToTopWindow = navigateToWorkspaceApp,\n embedPath,\n chatSidebar = false,\n copy = defaultChatFirstCopy,\n}: WorkspaceAppFrameProps) {\n const { resolvedTheme } = useTheme();\n const theme: WorkspaceAppTheme =\n resolvedTheme === \"dark\" || resolvedTheme === \"light\"\n ? resolvedTheme\n : typeof document !== \"undefined\" &&\n document.documentElement.classList.contains(\"dark\")\n ? \"dark\"\n : \"light\";\n const [embedUrl, setEmbedUrl] = useState<string | null>(null);\n const [embedError, setEmbedError] = useState<Error | null>(null);\n const [isDirectFallback, setIsDirectFallback] = useState(false);\n const [embedAttempt, setEmbedAttempt] = useState(0);\n const [topWindowNavigationFailed, setTopWindowNavigationFailed] =\n useState(false);\n const embedFrameRef = useRef<HTMLIFrameElement>(null);\n const postThemeToFrame = useCallback(() => {\n embedFrameRef.current?.contentWindow?.postMessage(\n buildWorkspaceAppThemeUpdate(theme),\n \"*\",\n );\n }, [theme]);\n const handleFrameLoad = useCallback(() => {\n postThemeToFrame();\n if (isDirectFallback) setEmbedError(null);\n }, [isDirectFallback, postThemeToFrame]);\n const workspaceSsoEnabled = useFeatureFlag(DISPATCH_WORKSPACE_SSO_FLAG.key);\n const createEmbedSession = useActionMutation<\n EmbedSessionResult,\n EmbedSessionInput\n >(\"create_embed_session\", {\n skipActionQueryInvalidation: true,\n });\n const createWorkspaceSsoEmbedSession = useActionMutation<\n EmbedSessionResult,\n EmbedSessionInput\n >(\"create-workspace-app-embed-session\", {\n skipActionQueryInvalidation: true,\n });\n const appHref = workspaceAppHref({\n id: app.id,\n name: app.name,\n path: app.path ?? \"\",\n url: app.url,\n });\n const topWindowHref = useMemo(() => {\n if (embedPath !== undefined) {\n return workspaceAppDirectHref(\n { path: app.path, url: app.url },\n embedPath,\n );\n }\n\n const target = workspaceAppEmbedTarget({\n path: app.path ?? \"\",\n url: app.url,\n });\n return target.url ?? target.path ?? null;\n }, [app.path, app.url, embedPath]);\n const openInTopWindow = shouldOpenWorkspaceAppInTopWindow();\n const embedInput = useMemo<EmbedSessionInput | null>(() => {\n if (embedPath !== undefined) {\n return buildChatFirstEmbedSessionInput(app.id, embedPath);\n }\n if (!appHref) return null;\n return {\n app: app.id,\n ...workspaceAppEmbedTarget({ path: app.path ?? \"\", url: app.url }),\n chrome: \"minimal\",\n };\n }, [app.id, app.path, app.url, appHref, embedPath]);\n\n useEffect(() => {\n if (!openInTopWindow) {\n setTopWindowNavigationFailed(false);\n return;\n }\n if (!topWindowHref) {\n setTopWindowNavigationFailed(true);\n return;\n }\n\n let didNavigate = false;\n try {\n didNavigate = navigateToTopWindow(topWindowHref) !== false;\n } catch {\n didNavigate = false;\n }\n setTopWindowNavigationFailed(!didNavigate);\n }, [navigateToTopWindow, openInTopWindow, topWindowHref]);\n\n useEffect(() => {\n if (!embedInput || (openInTopWindow && !topWindowNavigationFailed)) return;\n let cancelled = false;\n setEmbedUrl(null);\n setEmbedError(null);\n setIsDirectFallback(false);\n const createSession = workspaceSsoEnabled\n ? createWorkspaceSsoEmbedSession\n : createEmbedSession;\n void createSession\n .mutateAsync(embedInput)\n .then((result) => {\n if (!cancelled) setEmbedUrl(result.startUrl);\n })\n .catch((cause: unknown) => {\n if (cancelled) return;\n const error = cause instanceof Error ? cause : new Error(String(cause));\n if (workspaceSsoEnabled) {\n // An SSO-enabled pane must never fall back to the child app's\n // unauthenticated shell. Keep the parent-owned retry surface in\n // place so a transient exchange failure cannot expose another\n // login form.\n setIsDirectFallback(false);\n setEmbedUrl(null);\n setEmbedError(error);\n return;\n }\n setIsDirectFallback(true);\n setEmbedUrl(\n workspaceAppDirectHref(\n { path: app.path ?? \"\", url: app.url },\n embedPath ?? \"/\",\n ),\n );\n setEmbedError(error);\n });\n return () => {\n cancelled = true;\n };\n }, [\n app.id,\n app.path,\n app.url,\n createEmbedSession.mutateAsync,\n createWorkspaceSsoEmbedSession.mutateAsync,\n embedInput,\n embedPath,\n embedAttempt,\n openInTopWindow,\n topWindowNavigationFailed,\n workspaceSsoEnabled,\n ]);\n\n useEffect(() => {\n const handleEmbedSessionExpired = (event: MessageEvent) => {\n if (\n !isEmbedSessionExpiredMessage(event, embedFrameRef.current, embedUrl)\n ) {\n return;\n }\n setEmbedAttempt((attempt) => attempt + 1);\n };\n\n window.addEventListener(\"message\", handleEmbedSessionExpired);\n return () =>\n window.removeEventListener(\"message\", handleEmbedSessionExpired);\n }, [embedUrl]);\n\n useEffect(() => {\n postThemeToFrame();\n }, [embedUrl, postThemeToFrame]);\n\n const appPane = (\n <ChatFirstAppPane\n app={app}\n status={\n embedUrl\n ? \"ready\"\n : embedError\n ? \"error\"\n : embedInput\n ? \"loading\"\n : \"unresolved\"\n }\n embedUrl={embedUrl}\n errorMessage={embedError?.message}\n onRetry={\n embedInput ? () => setEmbedAttempt((attempt) => attempt + 1) : undefined\n }\n renderEmbed={({ url, title }) => (\n <iframe\n key={url + \":\" + embedAttempt}\n data-dispatch-workspace-app-frame\n src={url}\n title={title ?? app.name}\n ref={embedFrameRef}\n onLoad={handleFrameLoad}\n referrerPolicy=\"no-referrer\"\n allow=\"clipboard-read; clipboard-write\"\n className=\"h-full w-full border-0 bg-background\"\n />\n )}\n copy={copy}\n />\n );\n\n if (!chatSidebar) return appPane;\n\n return (\n <WorkspaceAppChatRail appId={app.id} appName={app.name} copy={copy}>\n {appPane}\n </WorkspaceAppChatRail>\n );\n}\n\nexport function WorkspaceAppHost({\n appId,\n navigateToTopWindow = navigateToWorkspaceApp,\n}: {\n appId?: string;\n navigateToTopWindow?: (href: string) => boolean | void;\n}) {\n const t = useT();\n const workspaceAppsQuery = useActionQuery<WorkspaceAppSummary[]>(\n \"list-workspace-apps\",\n { includeAgentCards: false },\n );\n const grantedAppsQuery = useActionQuery<GrantedWorkspaceAppsResult>(\n \"list_apps\",\n {},\n );\n const apps = useMemo(() => {\n const merged = new Map<string, WorkspaceAppSummary>();\n\n for (const app of mergeChatFirstWorkspaceApps(workspaceAppsQuery.data)) {\n merged.set(app.id.trim().toLowerCase(), app);\n }\n for (const app of grantedAppsQuery.data?.apps ?? []) {\n const id = app.id.trim();\n if (!id || merged.has(id.toLowerCase())) continue;\n merged.set(id.toLowerCase(), {\n id,\n name: app.name.trim() || id,\n path: \"\",\n url: app.url?.trim() || null,\n status: \"ready\",\n });\n }\n\n return [...merged.values()];\n }, [grantedAppsQuery.data?.apps, workspaceAppsQuery.data]);\n const app = useMemo(\n () =>\n apps.find(\n (item) => item.id.trim().toLowerCase() === appId?.trim().toLowerCase(),\n ) ?? null,\n [appId, apps],\n );\n const isLoading = workspaceAppsQuery.isLoading || grantedAppsQuery.isLoading;\n const queryError = workspaceAppsQuery.isError\n ? workspaceAppsQuery.error\n : grantedAppsQuery.isError\n ? grantedAppsQuery.error\n : null;\n\n if (queryError && !app) {\n return (\n <div className=\"flex h-full min-h-0 items-center justify-center p-6\">\n <div className=\"w-full max-w-2xl\">\n <ActionQueryError\n error={queryError}\n onRetry={() => {\n void workspaceAppsQuery.refetch();\n void grantedAppsQuery.refetch();\n }}\n />\n </div>\n </div>\n );\n }\n\n if (isLoading && !app) {\n return (\n <div className=\"flex h-full min-h-0 items-center justify-center p-6\">\n <div className=\"w-full max-w-2xl space-y-3 rounded-xl border bg-card p-6\">\n <Skeleton className=\"h-5 w-48\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-2/3\" />\n </div>\n </div>\n );\n }\n\n if (!app) {\n return (\n <div className=\"flex h-full min-h-0 items-center justify-center p-6\">\n <div className=\"w-full max-w-2xl rounded-xl border bg-card p-6\">\n <Button asChild size=\"sm\" variant=\"ghost\" className=\"-ml-2 mb-4\">\n <Link to=\"/apps\">\n <IconArrowLeft size={15} className=\"mr-1.5\" />\n {t(\"dispatch.nav.apps\")}\n </Link>\n </Button>\n <div className=\"space-y-3\">\n <h2 className=\"text-base font-semibold text-foreground\">\n {t(\"dispatch.pages.appNotFound\")}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {t(\"dispatch.pages.pageNotFoundDescription\")}\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n if (app.status === \"pending\") {\n return (\n <div className=\"flex h-full min-h-0 items-center justify-center p-6\">\n <div className=\"w-full max-w-2xl rounded-xl border bg-card p-6\">\n <Button asChild size=\"sm\" variant=\"ghost\" className=\"-ml-2 mb-4\">\n <Link to=\"/apps\">\n <IconArrowLeft size={15} className=\"mr-1.5\" />\n {t(\"dispatch.nav.apps\")}\n </Link>\n </Button>\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h2 className=\"text-base font-semibold text-foreground\">\n {app.name}\n </h2>\n <Badge\n variant=\"outline\"\n className=\"gap-1 border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300\"\n >\n <IconClockHour4 size={12} />\n {t(\"dispatch.pages.building\")}\n </Badge>\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {t(\"dispatch.pages.appBuildingPrefix\")}{\" \"}\n <span className=\"font-mono text-foreground\">{app.path}</span>{\" \"}\n {t(\"dispatch.pages.appBuildingSuffix\")}\n </p>\n {app.builderUrl ? (\n <Button asChild>\n <a\n href={withBuilderUtmTrackingParams(app.builderUrl, {\n campaign: \"product\",\n content: \"dispatch_branch\",\n })}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {t(\"dispatch.pages.openBuilderBranch\", {\n defaultValue: \"Open in Builder\",\n })}\n </a>\n </Button>\n ) : null}\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n data-dispatch-workspace-app-host\n className=\"flex h-full min-h-0 flex-col bg-background\"\n >\n <div className=\"min-h-0 flex-1 bg-muted/20\">\n <WorkspaceAppFrame\n app={app}\n navigateToTopWindow={navigateToTopWindow}\n />\n </div>\n </div>\n );\n}\n\nconst MAX_KEEP_ALIVE_APPS = 3;\n\nexport function WorkspaceAppKeepAlive({\n activeAppId,\n}: {\n activeAppId: string | null;\n}) {\n const [visitedAppIds, setVisitedAppIds] = useState<string[]>(() =>\n activeAppId ? [activeAppId] : [],\n );\n\n useEffect(() => {\n if (!activeAppId) return;\n setVisitedAppIds((current) =>\n [activeAppId, ...current.filter((appId) => appId !== activeAppId)].slice(\n 0,\n MAX_KEEP_ALIVE_APPS,\n ),\n );\n }, [activeAppId]);\n\n const renderedAppIds =\n activeAppId && !visitedAppIds.includes(activeAppId)\n ? [activeAppId, ...visitedAppIds]\n : visitedAppIds;\n\n return (\n <div\n data-dispatch-workspace-app-cache\n className={activeAppId ? \"absolute inset-0 overflow-hidden\" : \"hidden\"}\n >\n {renderedAppIds.map((appId) => {\n const active = appId === activeAppId;\n return (\n <div\n key={appId}\n data-dispatch-workspace-app-cache-entry={appId}\n aria-hidden={!active}\n className={active ? \"h-full min-h-0\" : \"hidden\"}\n >\n <WorkspaceAppHost appId={appId} />\n </div>\n );\n })}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"workspace-app-host.js","sourceRoot":"","sources":["../../src/components/workspace-app-host.tsx"],"names":[],"mappings":"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","sourcesContent":["import { AgentSidebar } from \"@agent-native/core/client/agent-chat\";\nimport { agentNativePath } from \"@agent-native/core/client/api-path\";\nimport {\n ChatFirstAppPane,\n defaultChatFirstCopy,\n type ChatFirstCopy,\n} from \"@agent-native/core/client/chat-first\";\nimport { useFeatureFlag } from \"@agent-native/core/client/feature-flags\";\nimport {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { withBuilderUtmTrackingParams } from \"@agent-native/core/shared/builder-link-tracking\";\nimport {\n IconAlertTriangle,\n IconArrowLeft,\n IconClockHour4,\n} from \"@tabler/icons-react\";\nimport { useTheme } from \"next-themes\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { Link } from \"react-router\";\n\nimport { isEmbedSessionExpiredMessage } from \"../lib/embed-session-recovery\";\nimport {\n mergeChatFirstWorkspaceApps,\n navigateToWorkspaceApp,\n shouldOpenWorkspaceAppInTopWindow,\n workspaceAppDirectHref,\n workspaceAppEmbedTarget,\n workspaceAppHref,\n type WorkspaceAppSummary,\n} from \"../lib/workspace-apps\";\nimport { DISPATCH_WORKSPACE_SSO_FLAG } from \"../shared/feature-flags\";\nimport { workspaceAppChatProxyPath } from \"../shared/workspace-app-chat\";\nimport { ActionQueryError } from \"./action-query-error\";\nimport { Alert, AlertDescription } from \"./ui/alert\";\nimport { Badge } from \"./ui/badge\";\nimport { Button } from \"./ui/button\";\nimport { Skeleton } from \"./ui/skeleton\";\n\ninterface EmbedSessionResult {\n startUrl: string;\n}\n\ninterface EmbedSessionInput {\n app?: string;\n path?: string;\n url?: string;\n chrome: \"minimal\";\n}\n\ninterface GrantedWorkspaceAppSummary {\n id: string;\n name: string;\n url?: string | null;\n}\n\ninterface GrantedWorkspaceAppsResult {\n apps: GrantedWorkspaceAppSummary[];\n}\n\ntype WorkspaceAppTheme = \"light\" | \"dark\";\nfunction buildWorkspaceAppThemeUpdate(theme: WorkspaceAppTheme) {\n return {\n type: \"agent-native-theme-update\" as const,\n theme,\n isDark: theme === \"dark\",\n };\n}\n\nexport function buildChatFirstEmbedSessionInput(\n appId: string,\n path: string,\n): EmbedSessionInput {\n return { app: appId, path, chrome: \"minimal\" };\n}\n\nasync function readWorkspaceAppChatProxyError(\n response: Response,\n): Promise<string> {\n let body: string;\n try {\n body = await response.text();\n } catch {\n // coercion-ok: an unreadable body is reported as such, not as an empty error.\n return `Agent chat proxy returned ${response.status} with an unreadable body.`;\n }\n try {\n const parsed = JSON.parse(body) as { error?: unknown };\n if (typeof parsed.error === \"string\" && parsed.error) return parsed.error;\n } catch {\n // coercion-ok: a non-JSON body is still reportable as the status line.\n }\n return body.trim() || `Agent chat proxy returned ${response.status}.`;\n}\n\n/**\n * Point the app pane's chat rail at the app's OWN agent through the Dispatch\n * proxy, and prove the proxy answers before claiming it works. A rail that\n * quietly fell back to Dispatch's agent would look identical while running the\n * wrong tools, instructions, and app resources, so a failed probe is a visible\n * error state instead.\n */\nfunction useWorkspaceAppChatApi(appId: string) {\n const apiUrl = useMemo(\n () => agentNativePath(workspaceAppChatProxyPath(appId)),\n [appId],\n );\n const [attempt, setAttempt] = useState(0);\n const [unavailable, setUnavailable] = useState(false);\n\n useEffect(() => {\n let cancelled = false;\n setUnavailable(false);\n // `/mode` is the app's own dev-mode surface: reaching it proves the proxy\n // minted an app session and the app's agent-chat routes answer.\n void fetch(`${apiUrl}/mode`, { credentials: \"include\" })\n .then(async (response) => {\n if (response.ok) return;\n throw new Error(await readWorkspaceAppChatProxyError(response));\n })\n .catch((cause: unknown) => {\n if (cancelled) return;\n console.warn(\n `[dispatch] app chat proxy unavailable for ${appId}`,\n cause,\n );\n setUnavailable(true);\n });\n return () => {\n cancelled = true;\n };\n }, [apiUrl, appId, attempt]);\n\n return {\n apiUrl,\n unavailable,\n retry: useCallback(() => setAttempt((value) => value + 1), []),\n };\n}\n\nexport interface WorkspaceAppChatRailProps {\n appId: string;\n appName: string;\n children: ReactNode;\n copy?: ChatFirstCopy;\n agentPageHref?: string;\n onFullscreenRequest?: () => void;\n}\n\n/**\n * The chat beside an open workspace app. Every surface that hosts an app pane\n * must go through here so the rail is always the app's own agent — same tools,\n * AGENTS.md, skills, app-scoped resources, and dev-mode surface as the app's\n * native chat — and so an unreachable app is one visible error state rather\n * than a per-surface silent handoff back to Dispatch's agent.\n */\nexport function WorkspaceAppChatRail({\n appId,\n appName,\n children,\n copy = defaultChatFirstCopy,\n agentPageHref,\n onFullscreenRequest,\n}: WorkspaceAppChatRailProps) {\n const t = useT();\n const appChat = useWorkspaceAppChatApi(appId);\n\n if (appChat.unavailable) {\n return (\n <div className=\"flex h-full min-h-0\">\n <div\n data-dispatch-app-chat-unavailable\n className=\"w-88 shrink-0 overflow-auto border-r p-4\"\n >\n <Alert variant=\"destructive\">\n <IconAlertTriangle className=\"size-4\" />\n <AlertDescription className=\"flex flex-wrap items-center justify-between gap-3\">\n <span>\n {t(\"dispatch.pages.appChatUnavailable\", {\n defaultValue:\n \"Dispatch could not connect to {{name}}'s agent, so its chat is unavailable here.\",\n name: appName,\n })}\n </span>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={appChat.retry}\n >\n {copy(\"retry\")}\n </Button>\n </AlertDescription>\n </Alert>\n </div>\n <div className=\"min-w-0 flex-1\">{children}</div>\n </div>\n );\n }\n\n return (\n <AgentSidebar\n position=\"left\"\n defaultOpen\n openStorageKey=\"dispatch-app-chat\"\n storageKey={`dispatch-app-chat:${appId}`}\n scope={{\n type: \"workspace-app\",\n id: appId,\n label: appName,\n contextKey: `workspace-app:${appId}`,\n }}\n // The app's own server answers this chat, so its tools, AGENTS.md,\n // skills, app-scoped resources, and dev-mode surface are the real ones\n // rather than a copy maintained inside Dispatch.\n apiUrl={appChat.apiUrl}\n agentChatSurface=\"app\"\n showTabBar\n suppressInlineOpenApp\n dynamicSuggestions={false}\n suggestions={[]}\n emptyStateText={`Ask about ${appName}`}\n {...(agentPageHref ? { agentPageHref } : {})}\n {...(onFullscreenRequest ? { onFullscreenRequest } : {})}\n >\n {children}\n </AgentSidebar>\n );\n}\n\nexport interface WorkspaceAppFrameApp {\n id: string;\n name: string;\n path?: string | null;\n url?: string | null;\n}\n\ninterface WorkspaceAppFrameProps {\n app: WorkspaceAppFrameApp;\n navigateToTopWindow?: (href: string) => boolean | void;\n /** Chat-first app tabs use their own route while standalone hosts use app metadata. */\n embedPath?: string;\n /** Chat-first app surfaces own the parent chat rail around the iframe. */\n chatSidebar?: boolean;\n copy?: ChatFirstCopy;\n}\n\nexport function WorkspaceAppFrame({\n app,\n navigateToTopWindow = navigateToWorkspaceApp,\n embedPath,\n chatSidebar = false,\n copy = defaultChatFirstCopy,\n}: WorkspaceAppFrameProps) {\n const { resolvedTheme } = useTheme();\n const theme: WorkspaceAppTheme =\n resolvedTheme === \"dark\" || resolvedTheme === \"light\"\n ? resolvedTheme\n : typeof document !== \"undefined\" &&\n document.documentElement.classList.contains(\"dark\")\n ? \"dark\"\n : \"light\";\n const [embedUrl, setEmbedUrl] = useState<string | null>(null);\n const [embedError, setEmbedError] = useState<Error | null>(null);\n const [isDirectFallback, setIsDirectFallback] = useState(false);\n const [embedAttempt, setEmbedAttempt] = useState(0);\n const [topWindowNavigationFailed, setTopWindowNavigationFailed] =\n useState(false);\n const embedFrameRef = useRef<HTMLIFrameElement>(null);\n const postThemeToFrame = useCallback(() => {\n embedFrameRef.current?.contentWindow?.postMessage(\n buildWorkspaceAppThemeUpdate(theme),\n \"*\",\n );\n }, [theme]);\n const handleFrameLoad = useCallback(() => {\n postThemeToFrame();\n if (isDirectFallback) setEmbedError(null);\n }, [isDirectFallback, postThemeToFrame]);\n const workspaceSsoEnabled = useFeatureFlag(DISPATCH_WORKSPACE_SSO_FLAG.key);\n const createEmbedSession = useActionMutation<\n EmbedSessionResult,\n EmbedSessionInput\n >(\"create_embed_session\", {\n skipActionQueryInvalidation: true,\n });\n const createWorkspaceSsoEmbedSession = useActionMutation<\n EmbedSessionResult,\n EmbedSessionInput\n >(\"create-workspace-app-embed-session\", {\n skipActionQueryInvalidation: true,\n });\n const appHref = workspaceAppHref({\n id: app.id,\n name: app.name,\n path: app.path ?? \"\",\n url: app.url,\n });\n const topWindowHref = useMemo(() => {\n if (embedPath !== undefined) {\n return workspaceAppDirectHref(\n { path: app.path, url: app.url },\n embedPath,\n );\n }\n\n const target = workspaceAppEmbedTarget({\n path: app.path ?? \"\",\n url: app.url,\n });\n return target.url ?? target.path ?? null;\n }, [app.path, app.url, embedPath]);\n const openInTopWindow = shouldOpenWorkspaceAppInTopWindow();\n const embedInput = useMemo<EmbedSessionInput | null>(() => {\n if (embedPath !== undefined) {\n return buildChatFirstEmbedSessionInput(app.id, embedPath);\n }\n if (!appHref) return null;\n return {\n app: app.id,\n ...workspaceAppEmbedTarget({ path: app.path ?? \"\", url: app.url }),\n chrome: \"minimal\",\n };\n }, [app.id, app.path, app.url, appHref, embedPath]);\n\n useEffect(() => {\n if (!openInTopWindow) {\n setTopWindowNavigationFailed(false);\n return;\n }\n if (!topWindowHref) {\n setTopWindowNavigationFailed(true);\n return;\n }\n\n let didNavigate = false;\n try {\n didNavigate = navigateToTopWindow(topWindowHref) !== false;\n } catch {\n didNavigate = false;\n }\n setTopWindowNavigationFailed(!didNavigate);\n }, [navigateToTopWindow, openInTopWindow, topWindowHref]);\n\n useEffect(() => {\n if (!embedInput || (openInTopWindow && !topWindowNavigationFailed)) return;\n let cancelled = false;\n setEmbedUrl(null);\n setEmbedError(null);\n setIsDirectFallback(false);\n const createSession = workspaceSsoEnabled\n ? createWorkspaceSsoEmbedSession\n : createEmbedSession;\n void createSession\n .mutateAsync(embedInput)\n .then((result) => {\n if (!cancelled) setEmbedUrl(result.startUrl);\n })\n .catch((cause: unknown) => {\n if (cancelled) return;\n const error = cause instanceof Error ? cause : new Error(String(cause));\n if (workspaceSsoEnabled) {\n // An SSO-enabled pane must never fall back to the child app's\n // unauthenticated shell. Keep the parent-owned retry surface in\n // place so a transient exchange failure cannot expose another\n // login form.\n setIsDirectFallback(false);\n setEmbedUrl(null);\n setEmbedError(error);\n return;\n }\n setIsDirectFallback(true);\n setEmbedUrl(\n workspaceAppDirectHref(\n { path: app.path ?? \"\", url: app.url },\n embedPath ?? \"/\",\n ),\n );\n setEmbedError(error);\n });\n return () => {\n cancelled = true;\n };\n }, [\n app.id,\n app.path,\n app.url,\n createEmbedSession.mutateAsync,\n createWorkspaceSsoEmbedSession.mutateAsync,\n embedInput,\n embedPath,\n embedAttempt,\n openInTopWindow,\n topWindowNavigationFailed,\n workspaceSsoEnabled,\n ]);\n\n useEffect(() => {\n const handleEmbedSessionExpired = (event: MessageEvent) => {\n if (\n !isEmbedSessionExpiredMessage(event, embedFrameRef.current, embedUrl)\n ) {\n return;\n }\n setEmbedAttempt((attempt) => attempt + 1);\n };\n\n window.addEventListener(\"message\", handleEmbedSessionExpired);\n return () =>\n window.removeEventListener(\"message\", handleEmbedSessionExpired);\n }, [embedUrl]);\n\n useEffect(() => {\n postThemeToFrame();\n }, [embedUrl, postThemeToFrame]);\n\n const appPane = (\n <ChatFirstAppPane\n app={app}\n status={\n embedUrl\n ? \"ready\"\n : embedError\n ? \"error\"\n : embedInput\n ? \"loading\"\n : \"unresolved\"\n }\n embedUrl={embedUrl}\n errorMessage={embedError?.message}\n onRetry={\n embedInput ? () => setEmbedAttempt((attempt) => attempt + 1) : undefined\n }\n renderEmbed={({ url, title }) => (\n <iframe\n key={url + \":\" + embedAttempt}\n data-dispatch-workspace-app-frame\n src={url}\n title={title ?? app.name}\n ref={embedFrameRef}\n onLoad={handleFrameLoad}\n referrerPolicy=\"no-referrer\"\n allow=\"clipboard-read; clipboard-write\"\n className=\"h-full w-full border-0 bg-background\"\n />\n )}\n copy={copy}\n />\n );\n\n if (!chatSidebar) return appPane;\n\n return (\n <WorkspaceAppChatRail appId={app.id} appName={app.name} copy={copy}>\n {appPane}\n </WorkspaceAppChatRail>\n );\n}\n\nexport function WorkspaceAppHost({\n appId,\n navigateToTopWindow = navigateToWorkspaceApp,\n}: {\n appId?: string;\n navigateToTopWindow?: (href: string) => boolean | void;\n}) {\n const t = useT();\n const workspaceAppsQuery = useActionQuery<WorkspaceAppSummary[]>(\n \"list-workspace-apps\",\n { includeAgentCards: false, includeArchived: true },\n );\n const workspaceApps = useMemo(\n () => mergeChatFirstWorkspaceApps(workspaceAppsQuery.data),\n [workspaceAppsQuery.data],\n );\n const visibleWorkspaceApps = useMemo(\n () => workspaceApps.filter((item) => !item.archived),\n [workspaceApps],\n );\n const workspaceAppIds = useMemo(\n () => new Set(workspaceApps.map((item) => item.id.trim().toLowerCase())),\n [workspaceApps],\n );\n const workspaceApp = useMemo(\n () =>\n visibleWorkspaceApps.find(\n (item) => item.id.trim().toLowerCase() === appId?.trim().toLowerCase(),\n ) ?? null,\n [appId, visibleWorkspaceApps],\n );\n const grantedAppsQuery = useActionQuery<GrantedWorkspaceAppsResult>(\n \"list_apps\",\n {},\n {\n // Mounted workspace apps are already fully described by the workspace\n // registry. Defer the broader MCP grant/discovery scan until that\n // lookup misses; it is only needed for externally granted apps.\n enabled: !workspaceAppsQuery.isLoading && !workspaceApp,\n },\n );\n const apps = useMemo(() => {\n const merged = new Map<string, WorkspaceAppSummary>();\n\n for (const app of visibleWorkspaceApps) {\n merged.set(app.id.trim().toLowerCase(), app);\n }\n for (const app of grantedAppsQuery.data?.apps ?? []) {\n const id = app.id.trim();\n if (\n !id ||\n workspaceAppIds.has(id.toLowerCase()) ||\n merged.has(id.toLowerCase())\n ) {\n continue;\n }\n merged.set(id.toLowerCase(), {\n id,\n name: app.name.trim() || id,\n path: \"\",\n url: app.url?.trim() || null,\n status: \"ready\",\n });\n }\n\n return [...merged.values()];\n }, [grantedAppsQuery.data?.apps, visibleWorkspaceApps, workspaceAppIds]);\n const app = useMemo(\n () =>\n apps.find(\n (item) => item.id.trim().toLowerCase() === appId?.trim().toLowerCase(),\n ) ?? null,\n [appId, apps],\n );\n const isLoading = workspaceAppsQuery.isLoading || grantedAppsQuery.isLoading;\n const queryError = workspaceAppsQuery.isError\n ? workspaceAppsQuery.error\n : grantedAppsQuery.isError\n ? grantedAppsQuery.error\n : null;\n\n if (queryError && !app) {\n return (\n <div className=\"flex h-full min-h-0 items-center justify-center p-6\">\n <div className=\"w-full max-w-2xl\">\n <ActionQueryError\n error={queryError}\n onRetry={() => {\n void workspaceAppsQuery.refetch();\n void grantedAppsQuery.refetch();\n }}\n />\n </div>\n </div>\n );\n }\n\n if (isLoading && !app) {\n return (\n <div className=\"flex h-full min-h-0 items-center justify-center p-6\">\n <div className=\"w-full max-w-2xl space-y-3 rounded-xl border bg-card p-6\">\n <Skeleton className=\"h-5 w-48\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-2/3\" />\n </div>\n </div>\n );\n }\n\n if (!app) {\n return (\n <div className=\"flex h-full min-h-0 items-center justify-center p-6\">\n <div className=\"w-full max-w-2xl rounded-xl border bg-card p-6\">\n <Button asChild size=\"sm\" variant=\"ghost\" className=\"-ml-2 mb-4\">\n <Link to=\"/apps\">\n <IconArrowLeft size={15} className=\"mr-1.5\" />\n {t(\"dispatch.nav.apps\")}\n </Link>\n </Button>\n <div className=\"space-y-3\">\n <h2 className=\"text-base font-semibold text-foreground\">\n {t(\"dispatch.pages.appNotFound\")}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {t(\"dispatch.pages.pageNotFoundDescription\")}\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n if (app.status === \"pending\") {\n return (\n <div className=\"flex h-full min-h-0 items-center justify-center p-6\">\n <div className=\"w-full max-w-2xl rounded-xl border bg-card p-6\">\n <Button asChild size=\"sm\" variant=\"ghost\" className=\"-ml-2 mb-4\">\n <Link to=\"/apps\">\n <IconArrowLeft size={15} className=\"mr-1.5\" />\n {t(\"dispatch.nav.apps\")}\n </Link>\n </Button>\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h2 className=\"text-base font-semibold text-foreground\">\n {app.name}\n </h2>\n <Badge\n variant=\"outline\"\n className=\"gap-1 border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300\"\n >\n <IconClockHour4 size={12} />\n {t(\"dispatch.pages.building\")}\n </Badge>\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {t(\"dispatch.pages.appBuildingPrefix\")}{\" \"}\n <span className=\"font-mono text-foreground\">{app.path}</span>{\" \"}\n {t(\"dispatch.pages.appBuildingSuffix\")}\n </p>\n {app.builderUrl ? (\n <Button asChild>\n <a\n href={withBuilderUtmTrackingParams(app.builderUrl, {\n campaign: \"product\",\n content: \"dispatch_branch\",\n })}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {t(\"dispatch.pages.openBuilderBranch\", {\n defaultValue: \"Open in Builder\",\n })}\n </a>\n </Button>\n ) : null}\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n data-dispatch-workspace-app-host\n className=\"flex h-full min-h-0 flex-col bg-background\"\n >\n <div className=\"min-h-0 flex-1 bg-muted/20\">\n <WorkspaceAppFrame\n app={app}\n navigateToTopWindow={navigateToTopWindow}\n />\n </div>\n </div>\n );\n}\n\nconst MAX_KEEP_ALIVE_APPS = 3;\n\nexport function WorkspaceAppKeepAlive({\n activeAppId,\n}: {\n activeAppId: string | null;\n}) {\n const [visitedAppIds, setVisitedAppIds] = useState<string[]>(() =>\n activeAppId ? [activeAppId] : [],\n );\n\n useEffect(() => {\n if (!activeAppId) return;\n setVisitedAppIds((current) =>\n [activeAppId, ...current.filter((appId) => appId !== activeAppId)].slice(\n 0,\n MAX_KEEP_ALIVE_APPS,\n ),\n );\n }, [activeAppId]);\n\n const renderedAppIds =\n activeAppId && !visitedAppIds.includes(activeAppId)\n ? [activeAppId, ...visitedAppIds]\n : visitedAppIds;\n\n return (\n <div\n data-dispatch-workspace-app-cache\n className={activeAppId ? \"absolute inset-0 overflow-hidden\" : \"hidden\"}\n >\n {renderedAppIds.map((appId) => {\n const active = appId === activeAppId;\n return (\n <div\n key={appId}\n data-dispatch-workspace-app-cache-entry={appId}\n aria-hidden={!active}\n className={active ? \"h-full min-h-0\" : \"hidden\"}\n >\n <WorkspaceAppHost appId={appId} />\n </div>\n );\n })}\n </div>\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/dispatch",
3
- "version": "0.29.2",
3
+ "version": "0.29.3",
4
4
  "description": "Dispatch — workspace control plane for agent-native apps. Vault, integrations, destinations, scheduled jobs, and cross-app delegation, shipped as a single drop-in package.",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -101,7 +101,7 @@
101
101
  "typescript-7": "npm:typescript@^7.0.2",
102
102
  "vite": "8.1.0",
103
103
  "vitest": "^4.1.5",
104
- "@agent-native/core": "0.161.16"
104
+ "@agent-native/core": "0.161.17"
105
105
  },
106
106
  "peerDependencies": {
107
107
  "@agent-native/core": ">=0.8.0",
@@ -20,6 +20,9 @@ export default defineAction({
20
20
  .describe(
21
21
  "Fetch each ready app's /.well-known/agent-card.json with a short non-throwing timeout and include agentCardUrl, agentCardReachable, a2aEndpointUrl, agentName, and agentSkillsCount. Defaults to true for agent calls; UI polling should pass false. Pending Builder apps are not probed.",
22
22
  ),
23
+ includeArchived: httpBoolean
24
+ .default(false)
25
+ .describe("Include archived workspace apps in the result."),
23
26
  audience: z
24
27
  .enum(["all", "internal", "public"])
25
28
  .default("all")
@@ -1403,7 +1403,7 @@ export function Layout({
1403
1403
  const chatFirstAppLayoutHydratedRef = useRef(false);
1404
1404
  const chatFirstAppsQuery = useActionQuery<WorkspaceAppSummary[]>(
1405
1405
  "list-workspace-apps",
1406
- { includeAgentCards: false },
1406
+ { includeAgentCards: false, includeArchived: true },
1407
1407
  { enabled: chatFirstMode },
1408
1408
  );
1409
1409
  const chatFirstGrantedAppsQuery = useActionQuery<ChatFirstGrantedAppsResult>(
@@ -2,6 +2,7 @@
2
2
 
3
3
  import React, { act } from "react";
4
4
  import { createRoot, type Root } from "react-dom/client";
5
+ import { MemoryRouter } from "react-router";
5
6
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
6
7
 
7
8
  const clientState = vi.hoisted(() => {
@@ -13,8 +14,19 @@ const clientState = vi.hoisted(() => {
13
14
  }));
14
15
  const legacyErrorMutateAsync = vi.fn();
15
16
  const actionNames: string[] = [];
17
+ const actionQueryParams: Array<{
18
+ name: string;
19
+ params?: unknown;
20
+ }> = [];
21
+ const actionQueryOptions: Array<{
22
+ name: string;
23
+ options?: Record<string, unknown>;
24
+ }> = [];
16
25
  return {
17
26
  actionNames,
27
+ actionQueryParams,
28
+ actionQueryOptions,
29
+ workspaceApps: null as Array<Record<string, unknown>> | null,
18
30
  grantedApps: [
19
31
  {
20
32
  id: "analytics.agent-native.com",
@@ -98,44 +110,54 @@ vi.mock("@agent-native/core/client/hooks", () => ({
98
110
  : clientState.legacyMutateAsync,
99
111
  };
100
112
  },
101
- useActionQuery: (name: string) => ({
102
- data:
103
- name === "list_apps"
104
- ? { apps: clientState.grantedApps }
105
- : [
106
- {
107
- id: "mail",
108
- name: "Mail",
109
- path: "/mail",
110
- url: null,
111
- status: "ready",
112
- },
113
- {
114
- id: "calendar",
115
- name: "Calendar",
116
- path: "/calendar",
117
- url: null,
118
- status: "ready",
119
- },
120
- {
121
- id: "documents",
122
- name: "Documents",
123
- path: "/documents",
124
- url: null,
125
- status: "ready",
126
- },
127
- {
128
- id: "settings",
129
- name: "Settings",
130
- path: "/settings",
131
- url: null,
132
- status: "ready",
133
- },
134
- ],
135
- isError: false,
136
- isLoading: false,
137
- refetch: vi.fn(),
138
- }),
113
+ useActionQuery: (name: string, params?: unknown, options?: unknown) => {
114
+ clientState.actionQueryParams.push({ name, params });
115
+ clientState.actionQueryOptions.push({
116
+ name,
117
+ options:
118
+ options && typeof options === "object"
119
+ ? (options as Record<string, unknown>)
120
+ : undefined,
121
+ });
122
+ return {
123
+ data:
124
+ name === "list_apps"
125
+ ? { apps: clientState.grantedApps }
126
+ : (clientState.workspaceApps ?? [
127
+ {
128
+ id: "mail",
129
+ name: "Mail",
130
+ path: "/mail",
131
+ url: null,
132
+ status: "ready",
133
+ },
134
+ {
135
+ id: "calendar",
136
+ name: "Calendar",
137
+ path: "/calendar",
138
+ url: null,
139
+ status: "ready",
140
+ },
141
+ {
142
+ id: "documents",
143
+ name: "Documents",
144
+ path: "/documents",
145
+ url: null,
146
+ status: "ready",
147
+ },
148
+ {
149
+ id: "settings",
150
+ name: "Settings",
151
+ path: "/settings",
152
+ url: null,
153
+ status: "ready",
154
+ },
155
+ ]),
156
+ isError: false,
157
+ isLoading: false,
158
+ refetch: vi.fn(),
159
+ };
160
+ },
139
161
  }));
140
162
 
141
163
  vi.mock("@agent-native/core/client/i18n", () => ({
@@ -158,6 +180,9 @@ describe("WorkspaceAppKeepAlive", () => {
158
180
  document.body.appendChild(container);
159
181
  root = createRoot(container);
160
182
  clientState.actionNames.length = 0;
183
+ clientState.actionQueryParams.length = 0;
184
+ clientState.actionQueryOptions.length = 0;
185
+ clientState.workspaceApps = null;
161
186
  clientState.legacyMutateAsync.mockClear();
162
187
  clientState.legacyMutateError = null;
163
188
  clientState.legacyErrorMutateAsync.mockReset();
@@ -212,6 +237,15 @@ describe("WorkspaceAppKeepAlive", () => {
212
237
  expect(calendarEntry?.classList.contains("hidden")).toBe(false);
213
238
  expect(calendarEntry?.querySelector("iframe")).not.toBeNull();
214
239
  expect(container.querySelectorAll("iframe")).toHaveLength(2);
240
+ expect(
241
+ clientState.actionQueryParams.find(
242
+ (query) => query.name === "list-workspace-apps",
243
+ )?.params,
244
+ ).toEqual({ includeAgentCards: false, includeArchived: true });
245
+ expect(
246
+ clientState.actionQueryOptions.find((query) => query.name === "list_apps")
247
+ ?.options?.enabled,
248
+ ).toBe(false);
215
249
  });
216
250
 
217
251
  it("resolves a granted external app instead of showing app not found", async () => {
@@ -236,6 +270,38 @@ describe("WorkspaceAppKeepAlive", () => {
236
270
  url: "https://analytics.agent-native.com",
237
271
  chrome: "minimal",
238
272
  });
273
+ expect(
274
+ clientState.actionQueryOptions.find((query) => query.name === "list_apps")
275
+ ?.options?.enabled,
276
+ ).toBe(true);
277
+ });
278
+
279
+ it("does not resolve archived workspace apps from granted discovery", async () => {
280
+ clientState.workspaceApps = [
281
+ {
282
+ id: "analytics.agent-native.com",
283
+ name: "Hidden app",
284
+ path: "/hidden-app",
285
+ url: null,
286
+ status: "ready",
287
+ archived: true,
288
+ },
289
+ ];
290
+
291
+ await act(async () => {
292
+ root.render(
293
+ <MemoryRouter>
294
+ <WorkspaceAppKeepAlive activeAppId="analytics.agent-native.com" />
295
+ </MemoryRouter>,
296
+ );
297
+ await Promise.resolve();
298
+ await Promise.resolve();
299
+ });
300
+
301
+ expect(
302
+ container.querySelector('[data-chat-first-app-status="ready"]'),
303
+ ).toBeNull();
304
+ expect(clientState.legacyMutateAsync).not.toHaveBeenCalled();
239
305
  });
240
306
 
241
307
  it("uses the app-scoped workspace session action when the rollout is enabled", async () => {
@@ -476,21 +476,52 @@ export function WorkspaceAppHost({
476
476
  const t = useT();
477
477
  const workspaceAppsQuery = useActionQuery<WorkspaceAppSummary[]>(
478
478
  "list-workspace-apps",
479
- { includeAgentCards: false },
479
+ { includeAgentCards: false, includeArchived: true },
480
+ );
481
+ const workspaceApps = useMemo(
482
+ () => mergeChatFirstWorkspaceApps(workspaceAppsQuery.data),
483
+ [workspaceAppsQuery.data],
484
+ );
485
+ const visibleWorkspaceApps = useMemo(
486
+ () => workspaceApps.filter((item) => !item.archived),
487
+ [workspaceApps],
488
+ );
489
+ const workspaceAppIds = useMemo(
490
+ () => new Set(workspaceApps.map((item) => item.id.trim().toLowerCase())),
491
+ [workspaceApps],
492
+ );
493
+ const workspaceApp = useMemo(
494
+ () =>
495
+ visibleWorkspaceApps.find(
496
+ (item) => item.id.trim().toLowerCase() === appId?.trim().toLowerCase(),
497
+ ) ?? null,
498
+ [appId, visibleWorkspaceApps],
480
499
  );
481
500
  const grantedAppsQuery = useActionQuery<GrantedWorkspaceAppsResult>(
482
501
  "list_apps",
483
502
  {},
503
+ {
504
+ // Mounted workspace apps are already fully described by the workspace
505
+ // registry. Defer the broader MCP grant/discovery scan until that
506
+ // lookup misses; it is only needed for externally granted apps.
507
+ enabled: !workspaceAppsQuery.isLoading && !workspaceApp,
508
+ },
484
509
  );
485
510
  const apps = useMemo(() => {
486
511
  const merged = new Map<string, WorkspaceAppSummary>();
487
512
 
488
- for (const app of mergeChatFirstWorkspaceApps(workspaceAppsQuery.data)) {
513
+ for (const app of visibleWorkspaceApps) {
489
514
  merged.set(app.id.trim().toLowerCase(), app);
490
515
  }
491
516
  for (const app of grantedAppsQuery.data?.apps ?? []) {
492
517
  const id = app.id.trim();
493
- if (!id || merged.has(id.toLowerCase())) continue;
518
+ if (
519
+ !id ||
520
+ workspaceAppIds.has(id.toLowerCase()) ||
521
+ merged.has(id.toLowerCase())
522
+ ) {
523
+ continue;
524
+ }
494
525
  merged.set(id.toLowerCase(), {
495
526
  id,
496
527
  name: app.name.trim() || id,
@@ -501,7 +532,7 @@ export function WorkspaceAppHost({
501
532
  }
502
533
 
503
534
  return [...merged.values()];
504
- }, [grantedAppsQuery.data?.apps, workspaceAppsQuery.data]);
535
+ }, [grantedAppsQuery.data?.apps, visibleWorkspaceApps, workspaceAppIds]);
505
536
  const app = useMemo(
506
537
  () =>
507
538
  apps.find(