@agent-native/dispatch 0.40.0 → 0.40.2

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.
Files changed (121) hide show
  1. package/CHANGELOG.md +38 -12
  2. package/dist/actions/provider-api-register.d.ts +7 -7
  3. package/dist/components/app-open-actions.d.ts +1 -1
  4. package/dist/components/app-open-actions.d.ts.map +1 -1
  5. package/dist/components/app-open-actions.js +1 -1
  6. package/dist/components/app-open-actions.js.map +1 -1
  7. package/dist/components/app-row-settings.js +1 -1
  8. package/dist/components/app-row-settings.js.map +1 -1
  9. package/dist/components/automation-create-dialog.js +2 -2
  10. package/dist/components/automation-create-dialog.js.map +1 -1
  11. package/dist/components/automation-details-panel.js +1 -1
  12. package/dist/components/automation-details-panel.js.map +1 -1
  13. package/dist/components/chat-home-apps.js +1 -1
  14. package/dist/components/chat-home-apps.js.map +1 -1
  15. package/dist/components/create-app-popover.js +3 -3
  16. package/dist/components/create-app-popover.js.map +1 -1
  17. package/dist/components/dispatch-control-plane.d.ts.map +1 -1
  18. package/dist/components/dispatch-control-plane.js +9 -30
  19. package/dist/components/dispatch-control-plane.js.map +1 -1
  20. package/dist/components/layout/Header.js +2 -2
  21. package/dist/components/layout/Header.js.map +1 -1
  22. package/dist/components/layout/Layout.d.ts +6 -5
  23. package/dist/components/layout/Layout.d.ts.map +1 -1
  24. package/dist/components/layout/Layout.js +73 -113
  25. package/dist/components/layout/Layout.js.map +1 -1
  26. package/dist/components/layout/workspace-apps-rail.d.ts.map +1 -1
  27. package/dist/components/layout/workspace-apps-rail.js +7 -19
  28. package/dist/components/layout/workspace-apps-rail.js.map +1 -1
  29. package/dist/components/messaging-setup-panel.js +2 -1
  30. package/dist/components/messaging-setup-panel.js.map +1 -1
  31. package/dist/components/workspace-app-card.js +2 -2
  32. package/dist/components/workspace-app-card.js.map +1 -1
  33. package/dist/components/workspace-app-host.d.ts +1 -1
  34. package/dist/components/workspace-app-host.d.ts.map +1 -1
  35. package/dist/components/workspace-app-host.js +7 -74
  36. package/dist/components/workspace-app-host.js.map +1 -1
  37. package/dist/hooks/use-navigation-state.js +1 -1
  38. package/dist/hooks/use-navigation-state.js.map +1 -1
  39. package/dist/lib/workspace-apps.js +1 -1
  40. package/dist/lib/workspace-apps.js.map +1 -1
  41. package/dist/routes/pages/$appId.js +1 -1
  42. package/dist/routes/pages/$appId.js.map +1 -1
  43. package/dist/routes/pages/_index.js +1 -1
  44. package/dist/routes/pages/_index.js.map +1 -1
  45. package/dist/routes/pages/admin._index.js +1 -1
  46. package/dist/routes/pages/admin._index.js.map +1 -1
  47. package/dist/routes/pages/agent-integrations.js +1 -1
  48. package/dist/routes/pages/agent-integrations.js.map +1 -1
  49. package/dist/routes/pages/apps.d.ts.map +1 -1
  50. package/dist/routes/pages/apps.js +3 -43
  51. package/dist/routes/pages/apps.js.map +1 -1
  52. package/dist/routes/pages/browser-chat.js +1 -1
  53. package/dist/routes/pages/browser-chat.js.map +1 -1
  54. package/dist/routes/pages/chat.d.ts.map +1 -1
  55. package/dist/routes/pages/chat.js +24 -43
  56. package/dist/routes/pages/chat.js.map +1 -1
  57. package/dist/routes/pages/extensions.$id.js +1 -1
  58. package/dist/routes/pages/extensions.$id.js.map +1 -1
  59. package/dist/routes/pages/extensions._index.js +1 -1
  60. package/dist/routes/pages/extensions._index.js.map +1 -1
  61. package/dist/routes/pages/integrations.js +1 -1
  62. package/dist/routes/pages/integrations.js.map +1 -1
  63. package/dist/routes/pages/new-app.js +1 -1
  64. package/dist/routes/pages/new-app.js.map +1 -1
  65. package/dist/routes/pages/operations.js +2 -2
  66. package/dist/routes/pages/operations.js.map +1 -1
  67. package/dist/routes/pages/overview.d.ts +2 -2
  68. package/dist/routes/pages/settings.d.ts.map +1 -1
  69. package/dist/routes/pages/settings.js +26 -8
  70. package/dist/routes/pages/settings.js.map +1 -1
  71. package/dist/routes/pages/tools.$id.js +1 -1
  72. package/dist/routes/pages/tools.$id.js.map +1 -1
  73. package/dist/routes/pages/tools._index.js +1 -1
  74. package/dist/routes/pages/tools._index.js.map +1 -1
  75. package/dist/routes/pages/vault.d.ts +1 -1
  76. package/dist/routes/pages/vault.js +1 -1
  77. package/dist/routes/pages/vault.js.map +1 -1
  78. package/dist/shared/app-roles.js.map +1 -1
  79. package/package.json +3 -3
  80. package/src/components/app-open-actions.tsx +1 -1
  81. package/src/components/app-row-settings.tsx +1 -1
  82. package/src/components/automation-create-dialog.tsx +7 -7
  83. package/src/components/automation-details-panel.tsx +1 -1
  84. package/src/components/chat-home-apps.tsx +1 -1
  85. package/src/components/create-app-popover.spec.tsx +5 -7
  86. package/src/components/create-app-popover.tsx +3 -3
  87. package/src/components/dispatch-control-plane.spec.tsx +12 -19
  88. package/src/components/dispatch-control-plane.tsx +10 -84
  89. package/src/components/layout/Header.tsx +2 -2
  90. package/src/components/layout/Layout.app-chat.spec.ts +1 -0
  91. package/src/components/layout/Layout.spec.tsx +18 -20
  92. package/src/components/layout/Layout.tsx +153 -205
  93. package/src/components/layout/workspace-apps-rail.spec.tsx +79 -0
  94. package/src/components/layout/workspace-apps-rail.tsx +6 -30
  95. package/src/components/messaging-setup-panel.tsx +1 -1
  96. package/src/components/workspace-app-card.tsx +2 -2
  97. package/src/components/workspace-app-chat-rail.spec.tsx +1 -1
  98. package/src/components/workspace-app-host.spec.tsx +19 -19
  99. package/src/components/workspace-app-host.tsx +12 -129
  100. package/src/hooks/use-navigation-state.ts +1 -1
  101. package/src/lib/workspace-apps.ts +1 -1
  102. package/src/routes/pages/$appId.tsx +1 -1
  103. package/src/routes/pages/_index.tsx +1 -1
  104. package/src/routes/pages/admin._index.tsx +1 -1
  105. package/src/routes/pages/agent-integrations.tsx +1 -1
  106. package/src/routes/pages/apps.tsx +2 -86
  107. package/src/routes/pages/automations.spec.tsx +1 -1
  108. package/src/routes/pages/browser-chat.tsx +1 -1
  109. package/src/routes/pages/chat.spec.tsx +23 -46
  110. package/src/routes/pages/chat.tsx +20 -57
  111. package/src/routes/pages/extensions.$id.tsx +1 -1
  112. package/src/routes/pages/extensions._index.tsx +1 -1
  113. package/src/routes/pages/integrations.tsx +1 -1
  114. package/src/routes/pages/new-app.tsx +1 -1
  115. package/src/routes/pages/operations.tsx +2 -2
  116. package/src/routes/pages/settings.spec.tsx +30 -8
  117. package/src/routes/pages/settings.tsx +75 -7
  118. package/src/routes/pages/tools.$id.tsx +1 -1
  119. package/src/routes/pages/tools._index.tsx +1 -1
  120. package/src/routes/pages/vault.tsx +1 -1
  121. package/src/shared/app-roles.ts +1 -1
@@ -1,6 +1,5 @@
1
1
  import { useFormatters, useT } from "@agent-native/core/client/i18n";
2
2
  import {
3
- channelIcon,
4
3
  disconnectManagedIntegrationInstallation,
5
4
  hasMissingRequiredCredentials,
6
5
  listManagedIntegrationBudgets,
@@ -26,6 +25,7 @@ import {
26
25
  listBuiltInChannelIntegrations,
27
26
  type IntegrationCatalogEntry,
28
27
  } from "@agent-native/core/integrations";
28
+ import { channelIcon } from "@agent-native/toolkit/app/integrations";
29
29
  import {
30
30
  IconBrandSlack,
31
31
  IconCheck,
@@ -1,10 +1,10 @@
1
- import { APP_ACTION_MENU_CONTENT_CLASS } from "@agent-native/core/client/chat-first";
2
1
  import {
3
2
  useActionMutation,
4
3
  useActionQuery,
5
4
  } from "@agent-native/core/client/hooks";
6
5
  import { useT } from "@agent-native/core/client/i18n";
7
- import { ShareButton } from "@agent-native/core/client/sharing";
6
+ import { APP_ACTION_MENU_CONTENT_CLASS } from "@agent-native/toolkit/app/chat/chat-first";
7
+ import { ShareButton } from "@agent-native/toolkit/app/sharing";
8
8
  import {
9
9
  IconChevronDown,
10
10
  IconChevronRight,
@@ -25,7 +25,7 @@ vi.mock("@agent-native/core/client/api-path", () => ({
25
25
  agentNativePath: (path: string) => path,
26
26
  }));
27
27
 
28
- vi.mock("@agent-native/core/client/chat-first", () => ({
28
+ vi.mock("@agent-native/toolkit/app/chat/chat-first", () => ({
29
29
  ChatFirstAppPane: ({ app }: { app: { name: string } | null }) => (
30
30
  <div data-app-pane>{app?.name}</div>
31
31
  ),
@@ -47,7 +47,7 @@ const clientState = vi.hoisted(() => {
47
47
  };
48
48
  });
49
49
 
50
- vi.mock("@agent-native/core/client/chat-first", () => ({
50
+ vi.mock("@agent-native/toolkit/app/chat/chat-first", () => ({
51
51
  CHAT_FIRST_DEFAULT_APP_IDS: [
52
52
  "content",
53
53
  "design",
@@ -91,6 +91,10 @@ vi.mock("@agent-native/core/client/chat-first", () => ({
91
91
  defaultChatFirstCopy: (key: string) => key,
92
92
  }));
93
93
 
94
+ vi.mock("@agent-native/toolkit/app/chat", () => ({
95
+ AgentSidebar: () => null,
96
+ }));
97
+
94
98
  vi.mock("@agent-native/core/client/feature-flags", () => ({
95
99
  useFeatureFlag: () => clientState.workspaceSsoEnabled,
96
100
  }));
@@ -249,37 +253,33 @@ describe("WorkspaceAppKeepAlive", () => {
249
253
  )?.params,
250
254
  ).toEqual({ includeAgentCards: false, includeArchived: true });
251
255
  expect(
252
- clientState.actionQueryOptions.find((query) => query.name === "list_apps")
253
- ?.options?.enabled,
256
+ clientState.actionQueryParams.some((query) => query.name === "list_apps"),
254
257
  ).toBe(false);
255
258
  });
256
259
 
257
- it("resolves a granted external app instead of showing app not found", async () => {
260
+ it("does not resolve apps granted through Dispatch MCP", async () => {
258
261
  await act(async () => {
259
262
  root.render(
260
- <WorkspaceAppKeepAlive activeAppId="analytics.agent-native.com" />,
263
+ <MemoryRouter>
264
+ <WorkspaceAppKeepAlive activeAppId="analytics.agent-native.com" />
265
+ </MemoryRouter>,
261
266
  );
262
267
  await Promise.resolve();
263
268
  await Promise.resolve();
264
269
  });
265
270
 
266
- expect(
267
- container.querySelector(
268
- '[data-dispatch-workspace-app-cache-entry="analytics.agent-native.com"]',
269
- ),
270
- ).not.toBeNull();
271
271
  expect(
272
272
  container.querySelector('[data-chat-first-app-status="ready"]'),
273
- ).not.toBeNull();
274
- expect(clientState.legacyMutateAsync).toHaveBeenCalledWith({
275
- app: "analytics.agent-native.com",
276
- url: "https://analytics.agent-native.com/home",
277
- chrome: "minimal",
278
- });
273
+ ).toBeNull();
274
+ expect(clientState.legacyMutateAsync).not.toHaveBeenCalled();
279
275
  expect(
280
- clientState.actionQueryOptions.find((query) => query.name === "list_apps")
281
- ?.options?.enabled,
282
- ).toBe(true);
276
+ clientState.actionQueryParams.some((query) => query.name === "list_apps"),
277
+ ).toBe(false);
278
+ expect(
279
+ clientState.actionQueryParams.some(
280
+ (query) => query.name === "list-connected-agents",
281
+ ),
282
+ ).toBe(false);
283
283
  });
284
284
 
285
285
  it("does not resolve archived workspace apps from granted discovery", async () => {
@@ -1,10 +1,4 @@
1
- import { AgentSidebar } from "@agent-native/core/client/agent-chat";
2
1
  import { agentNativePath } from "@agent-native/core/client/api-path";
3
- import {
4
- ChatFirstAppPane,
5
- defaultChatFirstCopy,
6
- type ChatFirstCopy,
7
- } from "@agent-native/core/client/chat-first";
8
2
  import { useFeatureFlag } from "@agent-native/core/client/feature-flags";
9
3
  import {
10
4
  useActionMutation,
@@ -13,6 +7,12 @@ import {
13
7
  import { useT } from "@agent-native/core/client/i18n";
14
8
  import { AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE } from "@agent-native/core/client/navigation";
15
9
  import { withBuilderUtmTrackingParams } from "@agent-native/core/shared/builder-link-tracking";
10
+ import { AgentSidebar } from "@agent-native/toolkit/app/chat";
11
+ import {
12
+ ChatFirstAppPane,
13
+ defaultChatFirstCopy,
14
+ type ChatFirstCopy,
15
+ } from "@agent-native/toolkit/app/chat/chat-first";
16
16
  import {
17
17
  IconAlertTriangle,
18
18
  IconArrowLeft,
@@ -30,9 +30,7 @@ import {
30
30
  import { Link } from "react-router";
31
31
 
32
32
  import { isEmbedSessionExpiredMessage } from "../lib/embed-session-recovery";
33
- import { filterOtherApps, type ConnectedAppSummary } from "../lib/other-apps";
34
33
  import {
35
- mergeChatFirstWorkspaceApps,
36
34
  isWorkspaceSsoApp,
37
35
  isDispatchWorkspaceAppId,
38
36
  navigateToWorkspaceApp,
@@ -63,16 +61,6 @@ interface EmbedSessionInput {
63
61
  chrome: "minimal";
64
62
  }
65
63
 
66
- interface GrantedWorkspaceAppSummary {
67
- id: string;
68
- name: string;
69
- url?: string | null;
70
- }
71
-
72
- interface GrantedWorkspaceAppsResult {
73
- apps: GrantedWorkspaceAppSummary[];
74
- }
75
-
76
64
  type WorkspaceAppTheme = "light" | "dark";
77
65
  function buildWorkspaceAppThemeUpdate(theme: WorkspaceAppTheme) {
78
66
  return {
@@ -568,104 +556,10 @@ export function WorkspaceAppHost({
568
556
  "list-workspace-apps",
569
557
  { includeAgentCards: false, includeArchived: true },
570
558
  );
571
- const mountedWorkspaceApp = useMemo(
572
- () =>
573
- workspaceAppsQuery.data?.find(
574
- (item) =>
575
- !item.archived &&
576
- item.id.trim().toLowerCase() === appId?.trim().toLowerCase(),
577
- ) ?? null,
578
- [appId, workspaceAppsQuery.data],
579
- );
580
- const grantedAppsQuery = useActionQuery<GrantedWorkspaceAppsResult>(
581
- "list_apps",
582
- {},
583
- {
584
- enabled: !workspaceAppsQuery.isLoading && !mountedWorkspaceApp,
585
- },
586
- );
587
- const connectedAppsQuery = useActionQuery<ConnectedAppSummary[]>(
588
- "list-connected-agents",
589
- {},
590
- {
591
- enabled: !workspaceAppsQuery.isLoading && !mountedWorkspaceApp,
592
- },
593
- );
594
- const enabledBuiltinAppIds = useMemo(
595
- () =>
596
- connectedAppsQuery.data
597
- ?.filter((app) => app.source === "builtin")
598
- .map((app) => app.id),
599
- [connectedAppsQuery.data],
559
+ const apps = useMemo(
560
+ () => (workspaceAppsQuery.data ?? []).filter((item) => !item.archived),
561
+ [workspaceAppsQuery.data],
600
562
  );
601
- const workspaceApps = useMemo(
602
- () =>
603
- mergeChatFirstWorkspaceApps(
604
- workspaceAppsQuery.data,
605
- enabledBuiltinAppIds,
606
- ),
607
- [enabledBuiltinAppIds, workspaceAppsQuery.data],
608
- );
609
- const visibleWorkspaceApps = useMemo(
610
- () => workspaceApps.filter((item) => !item.archived),
611
- [workspaceApps],
612
- );
613
- const workspaceAppIds = useMemo(
614
- () => new Set(workspaceApps.map((item) => item.id.trim().toLowerCase())),
615
- [workspaceApps],
616
- );
617
- const apps = useMemo(() => {
618
- const merged = new Map<string, WorkspaceAppSummary>();
619
-
620
- for (const app of visibleWorkspaceApps) {
621
- merged.set(app.id.trim().toLowerCase(), app);
622
- }
623
- for (const app of grantedAppsQuery.data?.apps ?? []) {
624
- const id = app.id.trim();
625
- if (
626
- !id ||
627
- workspaceAppIds.has(id.toLowerCase()) ||
628
- merged.has(id.toLowerCase())
629
- ) {
630
- continue;
631
- }
632
- merged.set(id.toLowerCase(), {
633
- id,
634
- name: app.name.trim() || id,
635
- path: "",
636
- url: app.url?.trim() || null,
637
- status: "ready",
638
- });
639
- }
640
- for (const app of filterOtherApps(
641
- connectedAppsQuery.data ?? [],
642
- visibleWorkspaceApps,
643
- )) {
644
- const id = app.id.trim();
645
- if (
646
- !id ||
647
- workspaceAppIds.has(id.toLowerCase()) ||
648
- merged.has(id.toLowerCase())
649
- ) {
650
- continue;
651
- }
652
- merged.set(id.toLowerCase(), {
653
- id,
654
- name: app.name.trim() || id,
655
- description: app.description,
656
- path: "",
657
- url: app.homeUrl?.trim() || app.url.trim(),
658
- status: "ready",
659
- });
660
- }
661
-
662
- return [...merged.values()];
663
- }, [
664
- connectedAppsQuery.data,
665
- grantedAppsQuery.data?.apps,
666
- visibleWorkspaceApps,
667
- workspaceAppIds,
668
- ]);
669
563
  const app = useMemo(
670
564
  () =>
671
565
  apps.find(
@@ -673,17 +567,10 @@ export function WorkspaceAppHost({
673
567
  ) ?? null,
674
568
  [appId, apps],
675
569
  );
676
- const isLoading =
677
- workspaceAppsQuery.isLoading ||
678
- grantedAppsQuery.isLoading ||
679
- connectedAppsQuery.isLoading;
570
+ const isLoading = workspaceAppsQuery.isLoading;
680
571
  const queryError = workspaceAppsQuery.isError
681
572
  ? workspaceAppsQuery.error
682
- : grantedAppsQuery.isError
683
- ? grantedAppsQuery.error
684
- : connectedAppsQuery.isError
685
- ? connectedAppsQuery.error
686
- : null;
573
+ : null;
687
574
 
688
575
  if (queryError && !app) {
689
576
  return (
@@ -691,11 +578,7 @@ export function WorkspaceAppHost({
691
578
  <div className="w-full max-w-2xl">
692
579
  <ActionQueryError
693
580
  error={queryError}
694
- onRetry={() => {
695
- void workspaceAppsQuery.refetch();
696
- void grantedAppsQuery.refetch();
697
- void connectedAppsQuery.refetch();
698
- }}
581
+ onRetry={() => void workspaceAppsQuery.refetch()}
699
582
  />
700
583
  </div>
701
584
  </div>
@@ -7,8 +7,8 @@ import {
7
7
  appBasePath,
8
8
  appPath,
9
9
  } from "@agent-native/core/client/api-path";
10
- import { extensionIdFromPathname } from "@agent-native/core/client/extensions";
11
10
  import { getBrowserTabId } from "@agent-native/core/client/hooks";
11
+ import { extensionIdFromPathname } from "@agent-native/toolkit/app/extensions";
12
12
  import { useQuery, useQueryClient } from "@tanstack/react-query";
13
13
  import { useEffect } from "react";
14
14
  import { useLocation, useNavigate } from "react-router";
@@ -1,4 +1,3 @@
1
- import { CHAT_FIRST_DEFAULT_APP_IDS } from "@agent-native/core/client/chat-first";
2
1
  import {
3
2
  getClientSurface,
4
3
  isInBuilderFrame,
@@ -8,6 +7,7 @@ import {
8
7
  resolveEnvironmentTargets,
9
8
  withBuilderUtmTrackingParams,
10
9
  } from "@agent-native/core/shared";
10
+ import { CHAT_FIRST_DEFAULT_APP_IDS } from "@agent-native/toolkit/app/chat/chat-first";
11
11
 
12
12
  import {
13
13
  CANONICAL_WORKSPACE_SSO_APP_ORIGINS,
@@ -1,9 +1,9 @@
1
1
  import { appPath } from "@agent-native/core/client/api-path";
2
2
  import { useActionQuery } from "@agent-native/core/client/hooks";
3
3
  import { useT } from "@agent-native/core/client/i18n";
4
- import { DefaultSpinner } from "@agent-native/core/client/ui";
5
4
  import { withSsrHtmlContentType } from "@agent-native/core/shared";
6
5
  import { withBuilderUtmTrackingParams } from "@agent-native/core/shared/builder-link-tracking";
6
+ import { DefaultSpinner } from "@agent-native/toolkit/app/shared";
7
7
  import {
8
8
  IconArrowLeft,
9
9
  IconArrowUpRight,
@@ -1,6 +1,6 @@
1
1
  import { appPath } from "@agent-native/core/client/api-path";
2
- import { DefaultSpinner } from "@agent-native/core/client/ui";
3
2
  import { withSsrHtmlContentType } from "@agent-native/core/shared";
3
+ import { DefaultSpinner } from "@agent-native/toolkit/app/shared";
4
4
  import { redirect, type LoaderFunctionArgs } from "react-router";
5
5
 
6
6
  const SEO_TITLE =
@@ -1,5 +1,5 @@
1
1
  import { useT } from "@agent-native/core/client/i18n";
2
- import { SettingsGroup } from "@agent-native/core/client/settings";
2
+ import { SettingsGroup } from "@agent-native/toolkit/app/settings";
3
3
  import { IconChevronRight } from "@tabler/icons-react";
4
4
  import { Link } from "react-router";
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { useT } from "@agent-native/core/client/i18n";
2
- import { McpIntegrationsLanding } from "@agent-native/core/client/integrations";
2
+ import { McpIntegrationsLanding } from "@agent-native/toolkit/app/integrations";
3
3
  import { Link } from "react-router";
4
4
 
5
5
  import { DispatchShell } from "../../components/dispatch-shell";
@@ -16,14 +16,8 @@ import {
16
16
  APP_LIST_GRID_ROW_CLASS,
17
17
  AppList,
18
18
  } from "../../components/app-list-row";
19
- import { AvailableAppsSection } from "../../components/available-apps-section";
20
19
  import { CreateAppPopover } from "../../components/create-app-popover";
21
20
  import { DispatchShell } from "../../components/dispatch-shell";
22
- import {
23
- filterOtherAppEntries,
24
- mergeOtherAppEntries,
25
- OtherAppsSection,
26
- } from "../../components/other-apps-section";
27
21
  import { Button } from "../../components/ui/button";
28
22
  import {
29
23
  Collapsible,
@@ -36,12 +30,6 @@ import {
36
30
  WorkspaceAppSearch,
37
31
  WorkspaceAppSearchEmpty,
38
32
  } from "../../components/workspace-app-search";
39
- import type {
40
- CuratedWorkspaceTemplatesResult,
41
- WorkspaceTemplateLabels,
42
- } from "../../components/workspace-template-card";
43
- import { AVAILABLE_APPS } from "../../lib/available-apps";
44
- import type { ConnectedAppSummary } from "../../lib/other-apps";
45
33
  import { cn } from "../../lib/utils";
46
34
  import {
47
35
  orderWorkspaceApps,
@@ -78,11 +66,6 @@ function AppsRoute() {
78
66
  includeAgentCards: false,
79
67
  includeArchived: true,
80
68
  });
81
- const connectedAppsQuery = useActionQuery("list-connected-agents", {});
82
- const curatedTemplatesQuery = useActionQuery(
83
- "list-curated-workspace-templates",
84
- {},
85
- );
86
69
  const { data: apps = [], isLoading: appsLoading } = appsQuery;
87
70
  const { data: workspace } = useActionQuery(
88
71
  "get-workspace-info",
@@ -98,23 +81,6 @@ function AppsRoute() {
98
81
  const activeApps = visibleApps.filter((app) => app.status !== "pending");
99
82
  const pendingApps = visibleApps.filter((app) => app.status === "pending");
100
83
  const archivedApps = allApps.filter((app) => app.archived);
101
- const connectedApps =
102
- (connectedAppsQuery.data as ConnectedAppSummary[] | undefined) ?? [];
103
- const curatedTemplates = curatedTemplatesQuery.data as
104
- | CuratedWorkspaceTemplatesResult
105
- | undefined;
106
- const filteredOtherApps = filterOtherAppEntries(
107
- mergeOtherAppEntries({
108
- templates: curatedTemplates,
109
- connectedApps,
110
- workspaceApps: allApps,
111
- }),
112
- searchQuery,
113
- );
114
- const otherAppsLoading =
115
- curatedTemplatesQuery.isLoading || connectedAppsQuery.isLoading;
116
- const otherAppsError =
117
- curatedTemplatesQuery.error || connectedAppsQuery.error;
118
84
  const orderedActiveApps = orderWorkspaceApps(activeApps, layout);
119
85
  const orderedPendingApps = orderWorkspaceApps(pendingApps, layout);
120
86
  const orderedArchivedApps = orderWorkspaceApps(archivedApps, layout);
@@ -130,30 +96,8 @@ function AppsRoute() {
130
96
  const hasSearchResults =
131
97
  filteredActiveApps.length > 0 ||
132
98
  filteredPendingApps.length > 0 ||
133
- filteredArchivedApps.length > 0 ||
134
- filteredOtherApps.length > 0 ||
135
- AVAILABLE_APPS.some((app) => {
136
- const query = searchQuery.trim().toLowerCase();
137
- return (
138
- !query || `${app.name} ${app.description}`.toLowerCase().includes(query)
139
- );
140
- });
99
+ filteredArchivedApps.length > 0;
141
100
  const showAppSkeletons = appsLoading && allApps.length === 0;
142
- const templateLabels: WorkspaceTemplateLabels = {
143
- appId: t("dispatch.pages.remixAppIdLabel"),
144
- appIdDescription: t("dispatch.pages.remixAppIdDescription"),
145
- cancel: t("dispatch.pages.cancel"),
146
- integrationSetup: t("dispatch.pages.integrationSetup"),
147
- installed: t("dispatch.pages.alreadyInWorkspace"),
148
- remix: t("dispatch.pages.addApp", { defaultValue: "Add app" }),
149
- remixing: t("dispatch.pages.remixing"),
150
- remixSuccess: t("dispatch.pages.remixSuccess"),
151
- remixError: t("dispatch.pages.remixError"),
152
- appIdRequired: t("dispatch.pages.appIdRequired"),
153
- source: t("dispatch.pages.source"),
154
- openApp: t("dispatch.pages.openApp", { defaultValue: "Open app" }),
155
- viewLiveApp: t("dispatch.pages.openApp", { defaultValue: "Open" }),
156
- };
157
101
 
158
102
  return (
159
103
  <DispatchShell
@@ -223,10 +167,7 @@ function AppsRoute() {
223
167
  />
224
168
  ) : showAppSkeletons ? (
225
169
  <AppsSkeletonGrid />
226
- ) : !hasSearchResults &&
227
- searchQuery.trim() &&
228
- !otherAppsLoading &&
229
- !otherAppsError ? (
170
+ ) : !hasSearchResults && searchQuery.trim() ? (
230
171
  <WorkspaceAppSearchEmpty
231
172
  query={searchQuery}
232
173
  onClear={() => setSearchQuery("")}
@@ -310,31 +251,6 @@ function AppsRoute() {
310
251
  </Collapsible>
311
252
  ) : null}
312
253
 
313
- <OtherAppsSection
314
- templates={curatedTemplates}
315
- connectedApps={connectedApps}
316
- workspaceApps={allApps}
317
- query={searchQuery}
318
- templatesLoading={curatedTemplatesQuery.isLoading}
319
- connectedAppsLoading={connectedAppsQuery.isLoading}
320
- templatesError={curatedTemplatesQuery.error}
321
- connectedAppsError={connectedAppsQuery.error}
322
- onRetryTemplates={() => void curatedTemplatesQuery.refetch()}
323
- onRetryConnectedApps={() => void connectedAppsQuery.refetch()}
324
- templateLabels={templateLabels}
325
- onRemixSuccess={() => {
326
- void appsQuery.refetch();
327
- void curatedTemplatesQuery.refetch();
328
- }}
329
- />
330
-
331
- <AvailableAppsSection
332
- connectedApps={connectedApps}
333
- workspaceApps={allApps}
334
- query={searchQuery}
335
- onConnected={() => void connectedAppsQuery.refetch()}
336
- />
337
-
338
254
  {archivedApps.length > 0 &&
339
255
  (!searchQuery.trim() || filteredArchivedApps.length > 0) ? (
340
256
  <Collapsible
@@ -79,7 +79,7 @@ vi.mock("@agent-native/core/client/agent-chat", () => ({
79
79
  sendToAgentChat: vi.fn(),
80
80
  }));
81
81
 
82
- vi.mock("@agent-native/core/client/composer", () => ({
82
+ vi.mock("@agent-native/toolkit/app/chat/composer/index", () => ({
83
83
  PromptComposer: () => null,
84
84
  }));
85
85
 
@@ -1,6 +1,6 @@
1
- import { AgentChatSurface } from "@agent-native/core/client/agent-chat";
2
1
  import { isEmbedAuthActive } from "@agent-native/core/client/host";
3
2
  import { useT } from "@agent-native/core/client/i18n";
3
+ import { AgentChatSurface } from "@agent-native/toolkit/app/chat";
4
4
  import { useEffect, useState } from "react";
5
5
  import { useSearchParams } from "react-router";
6
6
 
@@ -8,8 +8,6 @@ import ChatRoute from "./chat";
8
8
 
9
9
  const clientState = vi.hoisted(() => ({
10
10
  surfaceProps: null as Record<string, unknown> | null,
11
- activeRunId: null as string | null,
12
- writeClipboardText: vi.fn(),
13
11
  openWorkspaceApp: vi.fn(),
14
12
  workspaceApps: [
15
13
  {
@@ -33,6 +31,17 @@ const clientState = vi.hoisted(() => ({
33
31
  }));
34
32
 
35
33
  vi.mock("@agent-native/core/client/agent-chat", () => ({
34
+ insertAgentComposerReference: vi.fn(),
35
+ markAgentChatHomeHandoff: vi.fn(),
36
+ readChatFirstMode: () => true,
37
+ navigateWithAgentChatViewTransition: (
38
+ navigate: (path: string) => void,
39
+ path: string,
40
+ ) => navigate(path),
41
+ sendToAgentChat: vi.fn(),
42
+ }));
43
+
44
+ vi.mock("@agent-native/toolkit/app/chat", () => ({
36
45
  AgentChatHome: (props: Record<string, unknown>) => {
37
46
  clientState.surfaceProps = { mode: "page", ...props };
38
47
  return (
@@ -42,19 +51,10 @@ vi.mock("@agent-native/core/client/agent-chat", () => ({
42
51
  </>
43
52
  );
44
53
  },
45
- insertAgentComposerReference: vi.fn(),
46
- markAgentChatHomeHandoff: vi.fn(),
47
- readChatFirstMode: () => true,
48
- useActiveAgentChatRunId: () => clientState.activeRunId,
49
- navigateWithAgentChatViewTransition: (
50
- navigate: (path: string) => void,
51
- path: string,
52
- ) => navigate(path),
53
- sendToAgentChat: vi.fn(),
54
54
  }));
55
55
 
56
- vi.mock("@agent-native/core/client/clipboard", () => ({
57
- writeClipboardText: clientState.writeClipboardText,
56
+ vi.mock("../../components/create-app-popover", () => ({
57
+ CreateAppPopover: () => null,
58
58
  }));
59
59
 
60
60
  vi.mock("@agent-native/core/client/hooks", () => ({
@@ -120,7 +120,6 @@ describe("Dispatch ChatRoute", () => {
120
120
  vi.useFakeTimers();
121
121
  vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
122
122
  clientState.surfaceProps = null;
123
- clientState.activeRunId = null;
124
123
  clientState.agents = [];
125
124
  clientState.openWorkspaceApp.mockReset();
126
125
  clientState.retryWorkspaceApps.mockReset();
@@ -257,6 +256,13 @@ describe("Dispatch ChatRoute", () => {
257
256
  );
258
257
  expect(clientState.surfaceProps?.suggestions).toEqual([]);
259
258
  expect(container.textContent).not.toContain("What should we do today?");
259
+
260
+ await act(async () => {
261
+ vi.runOnlyPendingTimers();
262
+ await Promise.resolve();
263
+ });
264
+
265
+ expect(container.textContent).not.toContain("What should we do today?");
260
266
  });
261
267
 
262
268
  it("keeps an agent chat scoped and preserves the scope in thread URLs", async () => {
@@ -300,10 +306,7 @@ describe("Dispatch ChatRoute", () => {
300
306
  ).toBe("/chat/thread-1?agent=agents%2Fresearch-partner.md");
301
307
  });
302
308
 
303
- it("exposes a copyable request ID affordance on threaded chats", async () => {
304
- clientState.activeRunId = "run-456";
305
- clientState.writeClipboardText.mockResolvedValue(true);
306
-
309
+ it("keeps threaded chats free of request ID chrome", async () => {
307
310
  await act(async () => {
308
311
  root.render(
309
312
  <MemoryRouter initialEntries={["/chat/chat-123"]}>
@@ -313,33 +316,7 @@ describe("Dispatch ChatRoute", () => {
313
316
  });
314
317
 
315
318
  expect(clientState.surfaceProps?.suggestions).toEqual([]);
316
-
317
- const button = Array.from(container.querySelectorAll("button")).find((el) =>
318
- el.textContent?.includes("Copy request ID"),
319
- );
320
- expect(button).toBeTruthy();
321
-
322
- await act(async () => {
323
- button?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
324
- await Promise.resolve();
325
- });
326
-
327
- expect(clientState.writeClipboardText).toHaveBeenCalledWith("run-456");
328
- });
329
-
330
- it("keeps the request ID affordance unavailable before a run starts", async () => {
331
- await act(async () => {
332
- root.render(
333
- <MemoryRouter initialEntries={["/chat/chat-123"]}>
334
- <ChatRoute />
335
- </MemoryRouter>,
336
- );
337
- });
338
-
339
- const button = Array.from(container.querySelectorAll("button")).find((el) =>
340
- el.textContent?.includes("Request ID unavailable"),
341
- );
342
- expect(button).toBeTruthy();
343
- expect(button).toHaveProperty("disabled", true);
319
+ expect(clientState.surfaceProps?.contentClassName).toBe("max-w-none");
320
+ expect(container.textContent).not.toContain("Request ID");
344
321
  });
345
322
  });