@agent-native/dispatch 0.24.5 → 0.25.0

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 (151) hide show
  1. package/README.md +12 -1
  2. package/dist/actions/connect-external-agent.d.ts +18 -0
  3. package/dist/actions/connect-external-agent.d.ts.map +1 -0
  4. package/dist/actions/connect-external-agent.js +68 -0
  5. package/dist/actions/connect-external-agent.js.map +1 -0
  6. package/dist/actions/create-workspace-resource.d.ts +14 -14
  7. package/dist/actions/create-workspace-resource.js +9 -2
  8. package/dist/actions/create-workspace-resource.js.map +1 -1
  9. package/dist/actions/create_workspace_app_embed_session.d.ts +13 -0
  10. package/dist/actions/create_workspace_app_embed_session.d.ts.map +1 -0
  11. package/dist/actions/create_workspace_app_embed_session.js +30 -0
  12. package/dist/actions/create_workspace_app_embed_session.js.map +1 -0
  13. package/dist/actions/import-agent-pack.d.ts +96 -0
  14. package/dist/actions/import-agent-pack.d.ts.map +1 -0
  15. package/dist/actions/import-agent-pack.js +116 -0
  16. package/dist/actions/import-agent-pack.js.map +1 -0
  17. package/dist/actions/import-agent.d.ts +60 -0
  18. package/dist/actions/import-agent.d.ts.map +1 -0
  19. package/dist/actions/import-agent.js +82 -0
  20. package/dist/actions/import-agent.js.map +1 -0
  21. package/dist/actions/index.d.ts.map +1 -1
  22. package/dist/actions/index.js +10 -0
  23. package/dist/actions/index.js.map +1 -1
  24. package/dist/actions/list-agent-pack.d.ts +36 -0
  25. package/dist/actions/list-agent-pack.d.ts.map +1 -0
  26. package/dist/actions/list-agent-pack.js +32 -0
  27. package/dist/actions/list-agent-pack.js.map +1 -0
  28. package/dist/actions/list-workspace-resource-options.d.ts +1 -1
  29. package/dist/actions/list-workspace-resource-options.js +8 -1
  30. package/dist/actions/list-workspace-resource-options.js.map +1 -1
  31. package/dist/actions/list-workspace-resources.d.ts +1 -1
  32. package/dist/actions/list-workspace-resources.js +8 -1
  33. package/dist/actions/list-workspace-resources.js.map +1 -1
  34. package/dist/actions/navigate.js +1 -1
  35. package/dist/actions/navigate.js.map +1 -1
  36. package/dist/actions/provider-api-register.d.ts +10 -10
  37. package/dist/actions/update-workspace-resource.d.ts +13 -13
  38. package/dist/actions/view-screen.js +18 -1
  39. package/dist/actions/view-screen.js.map +1 -1
  40. package/dist/components/index.d.ts +1 -0
  41. package/dist/components/index.d.ts.map +1 -1
  42. package/dist/components/index.js +1 -0
  43. package/dist/components/index.js.map +1 -1
  44. package/dist/components/layout/Layout.d.ts +1 -8
  45. package/dist/components/layout/Layout.d.ts.map +1 -1
  46. package/dist/components/layout/Layout.js +33 -106
  47. package/dist/components/layout/Layout.js.map +1 -1
  48. package/dist/components/simple-agents-panel.d.ts +9 -0
  49. package/dist/components/simple-agents-panel.d.ts.map +1 -0
  50. package/dist/components/simple-agents-panel.js +405 -0
  51. package/dist/components/simple-agents-panel.js.map +1 -0
  52. package/dist/components/workspace-app-host.d.ts +29 -0
  53. package/dist/components/workspace-app-host.d.ts.map +1 -0
  54. package/dist/components/workspace-app-host.js +145 -0
  55. package/dist/components/workspace-app-host.js.map +1 -0
  56. package/dist/db/migrations.d.ts +2 -4
  57. package/dist/db/migrations.d.ts.map +1 -1
  58. package/dist/db/migrations.js +25 -0
  59. package/dist/db/migrations.js.map +1 -1
  60. package/dist/db/schema.js +1 -1
  61. package/dist/db/schema.js.map +1 -1
  62. package/dist/hooks/use-navigation-state.d.ts +1 -0
  63. package/dist/hooks/use-navigation-state.d.ts.map +1 -1
  64. package/dist/hooks/use-navigation-state.js +10 -0
  65. package/dist/hooks/use-navigation-state.js.map +1 -1
  66. package/dist/lib/agent-pack.d.ts +31 -0
  67. package/dist/lib/agent-pack.d.ts.map +1 -0
  68. package/dist/lib/agent-pack.js +149 -0
  69. package/dist/lib/agent-pack.js.map +1 -0
  70. package/dist/lib/simple-agent-profile.d.ts +36 -0
  71. package/dist/lib/simple-agent-profile.d.ts.map +1 -0
  72. package/dist/lib/simple-agent-profile.js +183 -0
  73. package/dist/lib/simple-agent-profile.js.map +1 -0
  74. package/dist/routes/pages/agents.d.ts.map +1 -1
  75. package/dist/routes/pages/agents.js +11 -1
  76. package/dist/routes/pages/agents.js.map +1 -1
  77. package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
  78. package/dist/routes/pages/apps.$appId.js +4 -95
  79. package/dist/routes/pages/apps.$appId.js.map +1 -1
  80. package/dist/routes/pages/chat.d.ts.map +1 -1
  81. package/dist/routes/pages/chat.js +62 -10
  82. package/dist/routes/pages/chat.js.map +1 -1
  83. package/dist/server/lib/agent-pack-store.d.ts +24 -0
  84. package/dist/server/lib/agent-pack-store.d.ts.map +1 -0
  85. package/dist/server/lib/agent-pack-store.js +22 -0
  86. package/dist/server/lib/agent-pack-store.js.map +1 -0
  87. package/dist/server/lib/dispatch-store.d.ts.map +1 -1
  88. package/dist/server/lib/dispatch-store.js +4 -0
  89. package/dist/server/lib/dispatch-store.js.map +1 -1
  90. package/dist/server/lib/mcp-gateway.d.ts +11 -0
  91. package/dist/server/lib/mcp-gateway.d.ts.map +1 -1
  92. package/dist/server/lib/mcp-gateway.js +155 -9
  93. package/dist/server/lib/mcp-gateway.js.map +1 -1
  94. package/dist/server/lib/workspace-resources-store.d.ts +15 -1
  95. package/dist/server/lib/workspace-resources-store.d.ts.map +1 -1
  96. package/dist/server/lib/workspace-resources-store.js +11 -2
  97. package/dist/server/lib/workspace-resources-store.js.map +1 -1
  98. package/dist/server/plugins/agent-chat.js +13 -0
  99. package/dist/server/plugins/agent-chat.js.map +1 -1
  100. package/dist/shared/feature-flags.d.ts +7 -0
  101. package/dist/shared/feature-flags.d.ts.map +1 -0
  102. package/dist/shared/feature-flags.js +12 -0
  103. package/dist/shared/feature-flags.js.map +1 -0
  104. package/dist/shared/workspace-sso.d.ts +36 -0
  105. package/dist/shared/workspace-sso.d.ts.map +1 -0
  106. package/dist/shared/workspace-sso.js +99 -0
  107. package/dist/shared/workspace-sso.js.map +1 -0
  108. package/package.json +5 -3
  109. package/src/actions/connect-external-agent.ts +92 -0
  110. package/src/actions/create-workspace-resource.ts +9 -2
  111. package/src/actions/create_workspace_app_embed_session.ts +32 -0
  112. package/src/actions/import-agent-pack.ts +146 -0
  113. package/src/actions/import-agent.ts +102 -0
  114. package/src/actions/index.spec.ts +13 -0
  115. package/src/actions/index.ts +10 -0
  116. package/src/actions/list-agent-pack.ts +43 -0
  117. package/src/actions/list-workspace-resource-options.ts +8 -1
  118. package/src/actions/list-workspace-resources.ts +8 -1
  119. package/src/actions/navigate.ts +1 -1
  120. package/src/actions/view-screen.spec.ts +29 -1
  121. package/src/actions/view-screen.ts +19 -1
  122. package/src/components/app-icon.spec.tsx +10 -0
  123. package/src/components/index.ts +1 -0
  124. package/src/components/layout/Layout.spec.tsx +2 -0
  125. package/src/components/layout/Layout.tsx +59 -171
  126. package/src/components/simple-agents-panel.spec.tsx +73 -0
  127. package/src/components/simple-agents-panel.tsx +1226 -0
  128. package/src/components/workspace-app-host.spec.tsx +204 -0
  129. package/src/components/workspace-app-host.tsx +359 -0
  130. package/src/db/migrations.spec.ts +5 -1
  131. package/src/db/migrations.ts +28 -1
  132. package/src/db/schema.ts +1 -1
  133. package/src/hooks/use-navigation-state.spec.ts +25 -0
  134. package/src/hooks/use-navigation-state.ts +11 -0
  135. package/src/lib/agent-pack.spec.ts +47 -0
  136. package/src/lib/agent-pack.ts +226 -0
  137. package/src/lib/simple-agent-profile.spec.ts +77 -0
  138. package/src/lib/simple-agent-profile.ts +247 -0
  139. package/src/routes/index.spec.ts +1 -0
  140. package/src/routes/pages/agents.tsx +21 -1
  141. package/src/routes/pages/apps.$appId.tsx +3 -240
  142. package/src/routes/pages/chat.spec.tsx +62 -0
  143. package/src/routes/pages/chat.tsx +117 -9
  144. package/src/server/lib/agent-pack-store.ts +35 -0
  145. package/src/server/lib/dispatch-store.ts +8 -0
  146. package/src/server/lib/mcp-gateway.spec.ts +141 -0
  147. package/src/server/lib/mcp-gateway.ts +227 -15
  148. package/src/server/lib/workspace-resources-store.ts +9 -2
  149. package/src/server/plugins/agent-chat.ts +13 -0
  150. package/src/shared/feature-flags.ts +13 -0
  151. package/src/shared/workspace-sso.ts +118 -0
@@ -1,102 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useActionMutation, useActionQuery, } from "@agent-native/core/client/hooks";
3
- import { useT } from "@agent-native/core/client/i18n";
4
- import { withBuilderUtmTrackingParams } from "@agent-native/core/shared/builder-link-tracking";
5
- import { IconArrowLeft, IconClockHour4 } from "@tabler/icons-react";
6
- import { useEffect, useMemo, useRef, useState } from "react";
7
- import { Link, useParams } from "react-router";
8
- import { ActionQueryError } from "../../components/action-query-error.js";
9
- import { Badge } from "../../components/ui/badge.js";
10
- import { Button } from "../../components/ui/button.js";
11
- import { Skeleton } from "../../components/ui/skeleton.js";
12
- import { Spinner } from "../../components/ui/spinner.js";
13
- import { isEmbedSessionExpiredMessage } from "../../lib/embed-session-recovery.js";
14
- import { workspaceAppDirectHref, workspaceAppEmbedTarget, workspaceAppHref, } from "../../lib/workspace-apps.js";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useParams } from "react-router";
3
+ import { WorkspaceAppHost } from "../../components/workspace-app-host.js";
15
4
  export function meta() {
16
5
  return [{ title: "Workspace app - Dispatch" }];
17
6
  }
18
7
  export default function WorkspaceAppRoute() {
19
- const t = useT();
20
8
  const { appId } = useParams();
21
- const appsQuery = useActionQuery("list-workspace-apps", {
22
- includeAgentCards: false,
23
- });
24
- const { data: apps = [], isLoading } = appsQuery;
25
- const app = useMemo(() => apps.find((item) => item.id === appId) ?? null, [appId, apps]);
26
- const href = app ? workspaceAppHref(app) : null;
27
- const [embedUrl, setEmbedUrl] = useState(null);
28
- const [embedError, setEmbedError] = useState(null);
29
- const [embedAttempt, setEmbedAttempt] = useState(0);
30
- const embedFrameRef = useRef(null);
31
- const createEmbedSession = useActionMutation("create_embed_session", {
32
- skipActionQueryInvalidation: true,
33
- });
34
- const embedInput = useMemo(() => {
35
- if (!app || !href)
36
- return null;
37
- return {
38
- app: app.id,
39
- ...workspaceAppEmbedTarget(app),
40
- chrome: "minimal",
41
- };
42
- }, [app?.id, app?.path, app?.url, href]);
43
- useEffect(() => {
44
- if (!app || app.status === "pending" || !embedInput)
45
- return;
46
- let cancelled = false;
47
- setEmbedUrl(null);
48
- setEmbedError(null);
49
- void createEmbedSession
50
- .mutateAsync(embedInput)
51
- .then((result) => {
52
- if (!cancelled)
53
- setEmbedUrl(result.startUrl);
54
- })
55
- .catch((cause) => {
56
- if (!cancelled) {
57
- const directAppUrl = workspaceAppDirectHref(app, "/");
58
- if (directAppUrl)
59
- setEmbedUrl(directAppUrl);
60
- setEmbedError(cause instanceof Error ? cause : new Error(String(cause)));
61
- }
62
- });
63
- return () => {
64
- cancelled = true;
65
- };
66
- }, [
67
- app?.id,
68
- app?.path,
69
- app?.status,
70
- createEmbedSession.mutateAsync,
71
- embedAttempt,
72
- embedInput,
73
- ]);
74
- useEffect(() => {
75
- const handleEmbedSessionExpired = (event) => {
76
- if (!isEmbedSessionExpiredMessage(event, embedFrameRef.current, null))
77
- return;
78
- setEmbedAttempt((attempt) => attempt + 1);
79
- };
80
- window.addEventListener("message", handleEmbedSessionExpired);
81
- return () => window.removeEventListener("message", handleEmbedSessionExpired);
82
- }, []);
83
- if (appsQuery.isError) {
84
- return (_jsx("div", { className: "flex h-full min-h-0 items-center justify-center p-6", children: _jsx("div", { className: "w-full max-w-2xl", children: _jsx(ActionQueryError, { error: appsQuery.error, onRetry: () => void appsQuery.refetch() }) }) }));
85
- }
86
- if (isLoading && !app) {
87
- return (_jsx("div", { className: "flex h-full min-h-0 items-center justify-center p-6", children: _jsxs("div", { className: "w-full max-w-2xl space-y-3 rounded-xl border bg-card p-6", children: [_jsx(Skeleton, { className: "h-5 w-48" }), _jsx(Skeleton, { className: "h-4 w-full" }), _jsx(Skeleton, { className: "h-4 w-2/3" })] }) }));
88
- }
89
- if (!app) {
90
- return (_jsx("div", { className: "flex h-full min-h-0 items-center justify-center p-6", children: _jsxs("div", { className: "w-full max-w-2xl rounded-xl border bg-card p-6", children: [_jsx(Button, { asChild: true, size: "sm", variant: "ghost", className: "-ml-2 mb-4", children: _jsxs(Link, { to: "/apps", children: [_jsx(IconArrowLeft, { size: 15, className: "mr-1.5" }), t("dispatch.nav.apps")] }) }), _jsxs("div", { className: "space-y-3", children: [_jsx("h2", { className: "text-base font-semibold text-foreground", children: t("dispatch.pages.appNotFound") }), _jsx("p", { className: "text-sm text-muted-foreground", children: t("dispatch.pages.pageNotFoundDescription") })] })] }) }));
91
- }
92
- if (app.status === "pending") {
93
- return (_jsx("div", { className: "flex h-full min-h-0 items-center justify-center p-6", children: _jsxs("div", { className: "w-full max-w-2xl rounded-xl border bg-card p-6", children: [_jsx(Button, { asChild: true, size: "sm", variant: "ghost", className: "-ml-2 mb-4", children: _jsxs(Link, { to: "/apps", children: [_jsx(IconArrowLeft, { size: 15, className: "mr-1.5" }), t("dispatch.nav.apps")] }) }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("h2", { className: "text-base font-semibold text-foreground", children: app.name }), _jsxs(Badge, { variant: "outline", className: "gap-1 border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300", children: [_jsx(IconClockHour4, { size: 12 }), t("dispatch.pages.building")] })] }), _jsxs("p", { className: "text-sm text-muted-foreground", children: [t("dispatch.pages.appBuildingPrefix"), " ", _jsx("span", { className: "font-mono text-foreground", children: app.path }), " ", t("dispatch.pages.appBuildingSuffix")] }), app.builderUrl ? (_jsx(Button, { asChild: true, children: _jsx("a", { href: withBuilderUtmTrackingParams(app.builderUrl, {
94
- campaign: "product",
95
- content: "dispatch_branch",
96
- }), target: "_blank", rel: "noreferrer", children: t("dispatch.pages.openBuilderBranch", {
97
- defaultValue: "Open in Builder",
98
- }) }) })) : null] })] }) }));
99
- }
100
- return (_jsx("div", { "data-dispatch-workspace-app-host": true, className: "flex h-full min-h-0 flex-col bg-background", children: _jsx("div", { className: "min-h-0 flex-1 bg-muted/20", children: embedUrl ? (_jsx("iframe", { "data-dispatch-workspace-app-frame": true, src: embedUrl, title: app.name, ref: embedFrameRef, referrerPolicy: "no-referrer", className: "h-full w-full border-0 bg-background" }, `${embedUrl}:${embedAttempt}`)) : embedError ? (_jsx("div", { className: "flex h-full items-center justify-center p-6", children: _jsx("div", { className: "w-full max-w-2xl", children: _jsx(ActionQueryError, { error: embedError, onRetry: () => setEmbedAttempt((attempt) => attempt + 1) }) }) })) : (_jsxs("div", { className: "flex h-full items-center justify-center", children: [_jsx(Spinner, { className: "size-5 text-muted-foreground" }), _jsx("span", { className: "sr-only", children: t("dispatch.pages.loading") })] })) }) }));
9
+ return _jsx(WorkspaceAppHost, { appId: appId });
101
10
  }
102
11
  //# sourceMappingURL=apps.$appId.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"apps.$appId.js","sourceRoot":"","sources":["../../../src/routes/pages/apps.$appId.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\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 { IconArrowLeft, IconClockHour4 } from \"@tabler/icons-react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Link, useParams } from \"react-router\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { Spinner } from \"../../components/ui/spinner\";\nimport { isEmbedSessionExpiredMessage } from \"../../lib/embed-session-recovery\";\nimport {\n workspaceAppDirectHref,\n workspaceAppEmbedTarget,\n workspaceAppHref,\n type WorkspaceAppSummary,\n} from \"../../lib/workspace-apps\";\n\ninterface EmbedSessionResult {\n startUrl: string;\n targetPath?: string;\n expiresAt?: number;\n app: string;\n}\n\ninterface EmbedSessionInput {\n app: string;\n path?: string;\n url?: string;\n chrome: \"minimal\";\n}\n\nexport function meta() {\n return [{ title: \"Workspace app - Dispatch\" }];\n}\n\nexport default function WorkspaceAppRoute() {\n const t = useT();\n const { appId } = useParams();\n const appsQuery = useActionQuery(\"list-workspace-apps\", {\n includeAgentCards: false,\n });\n const { data: apps = [], isLoading } = appsQuery;\n const app = useMemo(\n () =>\n (apps as WorkspaceAppSummary[]).find((item) => item.id === appId) ?? null,\n [appId, apps],\n );\n const href = app ? workspaceAppHref(app) : null;\n const [embedUrl, setEmbedUrl] = useState<string | null>(null);\n const [embedError, setEmbedError] = useState<Error | null>(null);\n const [embedAttempt, setEmbedAttempt] = useState(0);\n const embedFrameRef = useRef<HTMLIFrameElement>(null);\n const createEmbedSession = useActionMutation<\n EmbedSessionResult,\n EmbedSessionInput\n >(\"create_embed_session\", {\n skipActionQueryInvalidation: true,\n });\n const embedInput = useMemo<EmbedSessionInput | null>(() => {\n if (!app || !href) return null;\n return {\n app: app.id,\n ...workspaceAppEmbedTarget(app),\n chrome: \"minimal\",\n };\n }, [app?.id, app?.path, app?.url, href]);\n\n useEffect(() => {\n if (!app || app.status === \"pending\" || !embedInput) return;\n let cancelled = false;\n setEmbedUrl(null);\n setEmbedError(null);\n void createEmbedSession\n .mutateAsync(embedInput)\n .then((result) => {\n if (!cancelled) setEmbedUrl(result.startUrl);\n })\n .catch((cause: unknown) => {\n if (!cancelled) {\n const directAppUrl = workspaceAppDirectHref(app, \"/\");\n if (directAppUrl) setEmbedUrl(directAppUrl);\n setEmbedError(\n cause instanceof Error ? cause : new Error(String(cause)),\n );\n }\n });\n return () => {\n cancelled = true;\n };\n }, [\n app?.id,\n app?.path,\n app?.status,\n createEmbedSession.mutateAsync,\n embedAttempt,\n embedInput,\n ]);\n\n useEffect(() => {\n const handleEmbedSessionExpired = (event: MessageEvent) => {\n if (!isEmbedSessionExpiredMessage(event, embedFrameRef.current, null))\n return;\n setEmbedAttempt((attempt) => attempt + 1);\n };\n\n window.addEventListener(\"message\", handleEmbedSessionExpired);\n return () =>\n window.removeEventListener(\"message\", handleEmbedSessionExpired);\n }, []);\n\n if (appsQuery.isError) {\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={appsQuery.error}\n onRetry={() => void appsQuery.refetch()}\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 {embedUrl ? (\n <iframe\n key={`${embedUrl}:${embedAttempt}`}\n data-dispatch-workspace-app-frame\n src={embedUrl}\n title={app.name}\n ref={embedFrameRef}\n referrerPolicy=\"no-referrer\"\n className=\"h-full w-full border-0 bg-background\"\n />\n ) : embedError ? (\n <div className=\"flex h-full items-center justify-center p-6\">\n <div className=\"w-full max-w-2xl\">\n <ActionQueryError\n error={embedError}\n onRetry={() => setEmbedAttempt((attempt) => attempt + 1)}\n />\n </div>\n </div>\n ) : (\n <div className=\"flex h-full items-center justify-center\">\n <Spinner className=\"size-5 text-muted-foreground\" />\n <span className=\"sr-only\">{t(\"dispatch.pages.loading\")}</span>\n </div>\n )}\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"apps.$appId.js","sourceRoot":"","sources":["../../../src/routes/pages/apps.$appId.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAEvE,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,iBAAiB;IACvC,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,CAAC;IAC9B,OAAO,KAAC,gBAAgB,IAAC,KAAK,EAAE,KAAK,GAAI,CAAC;AAC5C,CAAC","sourcesContent":["import { useParams } from \"react-router\";\n\nimport { WorkspaceAppHost } from \"../../components/workspace-app-host\";\n\nexport function meta() {\n return [{ title: \"Workspace app - Dispatch\" }];\n}\n\nexport default function WorkspaceAppRoute() {\n const { appId } = useParams();\n return <WorkspaceAppHost appId={appId} />;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/chat.tsx"],"names":[],"mappings":"AAuFA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,SAAS,oDAuIhC"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/chat.tsx"],"names":[],"mappings":"AAsGA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,SAAS,oDAoOhC"}
@@ -1,13 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { AgentChatSurface, markAgentChatHomeHandoff, readChatFirstMode, } from "@agent-native/core/client/agent-chat";
2
+ import { AgentChatSurface, insertAgentComposerReference, markAgentChatHomeHandoff, readChatFirstMode, } from "@agent-native/core/client/agent-chat";
3
3
  import { appBasePath, appPath } from "@agent-native/core/client/api-path";
4
+ import { useActionQuery } from "@agent-native/core/client/hooks";
4
5
  import { useT } from "@agent-native/core/client/i18n";
5
6
  import { useCallback, useEffect, useMemo, useRef, } from "react";
6
7
  import { useLocation, useNavigate } from "react-router";
8
+ import { ActionQueryError } from "../../components/action-query-error.js";
7
9
  import { useDispatchExtensions } from "../../components/layout/Layout.js";
10
+ import { Skeleton } from "../../components/ui/skeleton.js";
8
11
  import { submitOverviewPrompt } from "../../lib/overview-chat.js";
9
- function chatThreadPath(threadId) {
10
- return threadId ? `/chat/${encodeURIComponent(threadId)}` : "/chat";
12
+ function chatThreadPath(threadId, agentPath) {
13
+ const path = threadId ? `/chat/${encodeURIComponent(threadId)}` : "/chat";
14
+ return agentPath ? `${path}?agent=${encodeURIComponent(agentPath)}` : path;
11
15
  }
12
16
  function stripBasePath(pathname) {
13
17
  const basePath = appBasePath();
@@ -58,6 +62,26 @@ export default function ChatRoute() {
58
62
  const location = useLocation();
59
63
  const navigate = useNavigate();
60
64
  const routeThreadId = threadIdFromPath(location.pathname);
65
+ const agentPath = new URLSearchParams(location.search).get("agent");
66
+ const agentsQuery = useActionQuery("list-workspace-resources", { kind: "agent" }, { enabled: Boolean(agentPath), staleTime: 30_000 });
67
+ const agent = useMemo(() => agentPath
68
+ ? (agentsQuery.data ?? []).find((resource) => {
69
+ const profileId = resource.path
70
+ .replace(/^agents\//, "")
71
+ .replace(/\.md$/, "");
72
+ return (resource.path === agentPath ||
73
+ resource.id === agentPath ||
74
+ profileId === agentPath);
75
+ })
76
+ : undefined, [agentPath, agentsQuery.data]);
77
+ const agentScope = useMemo(() => agent
78
+ ? {
79
+ type: "agent",
80
+ id: agent.id,
81
+ label: agent.name,
82
+ contextKey: `dispatch-agent:${agent.id}`,
83
+ }
84
+ : null, [agent]);
61
85
  const handledStateIds = useRef(new Set());
62
86
  const extensions = useDispatchExtensions();
63
87
  const suppressInlineOpenApp = extensions?.chatFirst === true ||
@@ -66,9 +90,9 @@ export default function ChatRoute() {
66
90
  const navigateThreadUrl = useCallback((path, options) => navigate(dispatchNavTarget(path), options), [navigate]);
67
91
  const threadUrlSync = useMemo(() => ({
68
92
  routeThreadId: routeThreadId ?? null,
69
- getPath: chatThreadPath,
93
+ getPath: (threadId) => chatThreadPath(threadId, agentPath ?? undefined),
70
94
  navigate: navigateThreadUrl,
71
- }), [routeThreadId, navigateThreadUrl]);
95
+ }), [agentPath, routeThreadId, navigateThreadUrl]);
72
96
  const state = location.state;
73
97
  const prompt = state?.dispatchPrompt;
74
98
  const thread = state?.dispatchThread;
@@ -122,19 +146,47 @@ export default function ChatRoute() {
122
146
  window.addEventListener("agentNative.chatRunning", handleChatRunning);
123
147
  return () => window.removeEventListener("agentNative.chatRunning", handleChatRunning);
124
148
  }, []);
125
- return (_jsx("div", { className: "flex h-full min-h-0 flex-col bg-background", children: _jsx(DispatchAgentChatSurface, { mode: "page", chatViewTransition: true, className: "dispatch-chat-panel px-4 sm:px-6", defaultMode: "chat", storageKey: "dispatch", threadUrlSync: threadUrlSync, showHeader: false, showTabBar: false, dynamicSuggestions: false, suppressInlineOpenApp: suppressInlineOpenApp, suggestions: [], emptyStateText: t("dispatch.pages.chatAcrossAppsDescription", {
149
+ useEffect(() => {
150
+ if (!agent)
151
+ return;
152
+ const timer = window.setTimeout(() => {
153
+ insertAgentComposerReference({
154
+ label: agent.name,
155
+ icon: "agent",
156
+ source: "agent:custom",
157
+ refType: "custom-agent",
158
+ refId: agent.id,
159
+ refPath: agent.path,
160
+ slotKey: "dispatch-agent",
161
+ slotLabel: "Agent",
162
+ }, { openSidebar: false });
163
+ }, 0);
164
+ return () => window.clearTimeout(timer);
165
+ }, [agent?.id, agent?.name, agent?.path]);
166
+ if (agentPath && agentsQuery.isLoading) {
167
+ return (_jsxs("div", { className: "flex h-full min-h-0 flex-col gap-4 bg-background px-4 py-6 sm:px-6", children: [_jsx(Skeleton, { className: "mx-auto h-6 w-48" }), _jsx(Skeleton, { className: "mx-auto h-12 w-full max-w-2xl" })] }));
168
+ }
169
+ if (agentPath && agentsQuery.isError) {
170
+ return (_jsx("div", { className: "flex h-full min-h-0 items-center justify-center bg-background px-4", children: _jsx(ActionQueryError, { error: agentsQuery.error, onRetry: () => void agentsQuery.refetch() }) }));
171
+ }
172
+ if (agentPath && !agent) {
173
+ return (_jsx("div", { className: "flex h-full min-h-0 items-center justify-center bg-background px-4 text-sm text-muted-foreground", children: "This agent is no longer available." }));
174
+ }
175
+ return (_jsx("div", { className: "flex h-full min-h-0 flex-col bg-background", children: _jsx(DispatchAgentChatSurface, { mode: "page", chatViewTransition: true, className: "dispatch-chat-panel px-4 sm:px-6", defaultMode: "chat", storageKey: agent ? `dispatch-agent-${agent.id}` : "dispatch", scope: agentScope, threadUrlSync: threadUrlSync, showHeader: false, showTabBar: false, dynamicSuggestions: false, suppressInlineOpenApp: suppressInlineOpenApp, suggestions: [], emptyStateText: t("dispatch.pages.chatAcrossAppsDescription", {
126
176
  defaultValue: "Route work, inspect status, or create something new from one place.",
127
177
  }), emptyStateDisplay: "hidden", ...(!prompt?.message
128
178
  ? {
129
179
  centerComposerWhenEmpty: true,
130
180
  composerLayoutVariant: "hero",
131
181
  }
132
- : {}), composerPlaceholder: t("dispatch.pages.chatPromptPlaceholder", {
133
- defaultValue: "Ask Dispatch...",
134
- }), composerSlot: !prompt?.message ? (_jsxs("div", { className: "dispatch-chat-intro", children: [_jsx("h1", { children: t("dispatch.pages.chatAcrossApps", {
182
+ : {}), composerPlaceholder: agent
183
+ ? `Ask ${agent.name}...`
184
+ : t("dispatch.pages.chatPromptPlaceholder", {
185
+ defaultValue: "Ask Dispatch...",
186
+ }), composerSlot: agent ? (_jsxs("div", { className: "dispatch-chat-intro", children: [_jsx("h1", { children: agent.name }), agent.description ? _jsx("p", { children: agent.description }) : null] })) : !prompt?.message ? (_jsxs("div", { className: "dispatch-chat-intro", children: [_jsx("h1", { children: t("dispatch.pages.chatAcrossApps", {
135
187
  defaultValue: "Chat across your apps",
136
188
  }) }), _jsx("p", { children: t("dispatch.pages.chatAcrossAppsDescription", {
137
189
  defaultValue: "Route work, inspect status, or create something new from one place.",
138
- }) })] })) : null }) }));
190
+ }) })] })) : null }, agent ? `agent-${agent.id}` : "dispatch") }));
139
191
  }
140
192
  //# sourceMappingURL=chat.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/routes/pages/chat.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n AgentChatSurface,\n markAgentChatHomeHandoff,\n readChatFirstMode,\n} from \"@agent-native/core/client/agent-chat\";\nimport { appBasePath, appPath } from \"@agent-native/core/client/api-path\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n type ComponentProps,\n} from \"react\";\nimport { useLocation, useNavigate } from \"react-router\";\n\nimport { useDispatchExtensions } from \"../../components/layout/Layout\";\nimport { submitOverviewPrompt } from \"../../lib/overview-chat\";\n\nfunction chatThreadPath(threadId: string | null): string {\n return threadId ? `/chat/${encodeURIComponent(threadId)}` : \"/chat\";\n}\n\nfunction stripBasePath(pathname: string): string {\n const basePath = appBasePath();\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\n// The chat surface renders for both `/chat` and the `/chat/:threadId` deep\n// link. The thread id is read from the pathname (not `useParams`) because the\n// param is owned by the nested deep-link route, not this leaf component.\nfunction threadIdFromPath(pathname: string): string | null {\n const match = stripBasePath(pathname).match(/^\\/chat\\/([^/]+)/);\n if (!match) return null;\n try {\n const value = decodeURIComponent(match[1]).trim();\n return value || null;\n } catch {\n return null;\n }\n}\n\n// Mirror the basename handling Dispatch's nav links use: pass a router-local\n// path when the live URL is already under the mount, otherwise prefix it.\nfunction dispatchNavTarget(path: string): string {\n if (typeof window === \"undefined\") return path;\n const basePath = appBasePath();\n if (!basePath) return path;\n const pathname = window.location.pathname;\n const routerHasBasename =\n pathname === basePath || pathname.startsWith(`${basePath}/`);\n return routerHasBasename ? path : appPath(path);\n}\n\ninterface DispatchThreadUrlSync {\n routeThreadId: string | null;\n getPath: (threadId: string | null) => string;\n navigate: (path: string, options?: { replace?: boolean }) => void;\n}\n\ntype DispatchAgentChatSurfaceProps = ComponentProps<typeof AgentChatSurface> & {\n threadUrlSync?: DispatchThreadUrlSync;\n};\n\nfunction DispatchAgentChatSurface(props: DispatchAgentChatSurfaceProps) {\n return <AgentChatSurface {...props} />;\n}\n\ninterface DispatchChatLocationState {\n dispatchPrompt?: {\n id?: string | number;\n message?: string;\n selectedModel?: string | null;\n selectedEngine?: string | null;\n selectedEffort?: ComponentProps<typeof AgentChatSurface>[\"selectedEffort\"];\n };\n dispatchThread?: {\n id?: string | number;\n threadId?: string;\n };\n}\n\nexport function meta() {\n return [{ title: \"Chat — Dispatch\" }];\n}\n\nexport default function ChatRoute() {\n const t = useT();\n const location = useLocation();\n const navigate = useNavigate();\n const routeThreadId = threadIdFromPath(location.pathname);\n const handledStateIds = useRef(new Set<string>());\n const extensions = useDispatchExtensions();\n const suppressInlineOpenApp =\n extensions?.chatFirst === true ||\n readChatFirstMode() ||\n new URLSearchParams(location.search).get(\"chatFirst\") === \"1\";\n\n const navigateThreadUrl = useCallback(\n (path: string, options?: { replace?: boolean }) =>\n navigate(dispatchNavTarget(path), options),\n [navigate],\n );\n const threadUrlSync = useMemo<DispatchThreadUrlSync>(\n () => ({\n routeThreadId: routeThreadId ?? null,\n getPath: chatThreadPath,\n navigate: navigateThreadUrl,\n }),\n [routeThreadId, navigateThreadUrl],\n );\n const state = location.state as DispatchChatLocationState | null;\n const prompt = state?.dispatchPrompt;\n const thread = state?.dispatchThread;\n\n useEffect(() => {\n const message = prompt?.message?.trim();\n const threadId = thread?.threadId?.trim();\n if (!message && !threadId) return;\n\n const stateId = String(\n prompt?.id ?? thread?.id ?? `${message ?? \"\"}:${threadId ?? \"\"}`,\n );\n if (handledStateIds.current.has(stateId)) return;\n handledStateIds.current.add(stateId);\n\n const timer = window.setTimeout(() => {\n if (threadId) {\n window.dispatchEvent(\n new CustomEvent(\"agent-chat:open-thread\", {\n detail: { threadId },\n }),\n );\n }\n if (message) {\n submitOverviewPrompt(message, prompt?.selectedModel, {\n openSidebar: false,\n selectedEngine: prompt?.selectedEngine,\n selectedEffort: prompt?.selectedEffort,\n });\n }\n navigate(`${location.pathname}${location.search}${location.hash}`, {\n replace: true,\n state: null,\n });\n }, 0);\n\n return () => window.clearTimeout(timer);\n }, [\n location.hash,\n location.pathname,\n location.search,\n navigate,\n prompt?.id,\n prompt?.message,\n prompt?.selectedModel,\n prompt?.selectedEngine,\n prompt?.selectedEffort,\n thread?.id,\n thread?.threadId,\n ]);\n\n useEffect(() => {\n function handleChatRunning(event: Event) {\n const detail = (event as CustomEvent).detail;\n if (detail?.isRunning === true) markAgentChatHomeHandoff(\"dispatch\");\n }\n\n window.addEventListener(\"agentNative.chatRunning\", handleChatRunning);\n return () =>\n window.removeEventListener(\"agentNative.chatRunning\", handleChatRunning);\n }, []);\n\n return (\n <div className=\"flex h-full min-h-0 flex-col bg-background\">\n <DispatchAgentChatSurface\n mode=\"page\"\n chatViewTransition\n className=\"dispatch-chat-panel px-4 sm:px-6\"\n defaultMode=\"chat\"\n storageKey=\"dispatch\"\n threadUrlSync={threadUrlSync}\n showHeader={false}\n showTabBar={false}\n dynamicSuggestions={false}\n suppressInlineOpenApp={suppressInlineOpenApp}\n suggestions={[]}\n emptyStateText={t(\"dispatch.pages.chatAcrossAppsDescription\", {\n defaultValue:\n \"Route work, inspect status, or create something new from one place.\",\n })}\n emptyStateDisplay=\"hidden\"\n {...(!prompt?.message\n ? {\n centerComposerWhenEmpty: true,\n composerLayoutVariant: \"hero\" as const,\n }\n : {})}\n composerPlaceholder={t(\"dispatch.pages.chatPromptPlaceholder\", {\n defaultValue: \"Ask Dispatch...\",\n })}\n composerSlot={\n !prompt?.message ? (\n <div className=\"dispatch-chat-intro\">\n <h1>\n {t(\"dispatch.pages.chatAcrossApps\", {\n defaultValue: \"Chat across your apps\",\n })}\n </h1>\n <p>\n {t(\"dispatch.pages.chatAcrossAppsDescription\", {\n defaultValue:\n \"Route work, inspect status, or create something new from one place.\",\n })}\n </p>\n </div>\n ) : null\n }\n />\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/routes/pages/chat.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n AgentChatSurface,\n insertAgentComposerReference,\n markAgentChatHomeHandoff,\n readChatFirstMode,\n} from \"@agent-native/core/client/agent-chat\";\nimport { appBasePath, appPath } from \"@agent-native/core/client/api-path\";\nimport { useActionQuery } from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n type ComponentProps,\n} from \"react\";\nimport { useLocation, useNavigate } from \"react-router\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { useDispatchExtensions } from \"../../components/layout/Layout\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { submitOverviewPrompt } from \"../../lib/overview-chat\";\n\ninterface WorkspaceAgentResource {\n id: string;\n name: string;\n description: string | null;\n path: string;\n content: string;\n scope: \"all\" | \"selected\";\n updatedAt: number;\n}\n\nfunction chatThreadPath(threadId: string | null, agentPath?: string): string {\n const path = threadId ? `/chat/${encodeURIComponent(threadId)}` : \"/chat\";\n return agentPath ? `${path}?agent=${encodeURIComponent(agentPath)}` : path;\n}\n\nfunction stripBasePath(pathname: string): string {\n const basePath = appBasePath();\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\n// The chat surface renders for both `/chat` and the `/chat/:threadId` deep\n// link. The thread id is read from the pathname (not `useParams`) because the\n// param is owned by the nested deep-link route, not this leaf component.\nfunction threadIdFromPath(pathname: string): string | null {\n const match = stripBasePath(pathname).match(/^\\/chat\\/([^/]+)/);\n if (!match) return null;\n try {\n const value = decodeURIComponent(match[1]).trim();\n return value || null;\n } catch {\n return null;\n }\n}\n\n// Mirror the basename handling Dispatch's nav links use: pass a router-local\n// path when the live URL is already under the mount, otherwise prefix it.\nfunction dispatchNavTarget(path: string): string {\n if (typeof window === \"undefined\") return path;\n const basePath = appBasePath();\n if (!basePath) return path;\n const pathname = window.location.pathname;\n const routerHasBasename =\n pathname === basePath || pathname.startsWith(`${basePath}/`);\n return routerHasBasename ? path : appPath(path);\n}\n\ninterface DispatchThreadUrlSync {\n routeThreadId: string | null;\n getPath: (threadId: string | null) => string;\n navigate: (path: string, options?: { replace?: boolean }) => void;\n}\n\ntype DispatchAgentChatSurfaceProps = ComponentProps<typeof AgentChatSurface> & {\n threadUrlSync?: DispatchThreadUrlSync;\n};\n\nfunction DispatchAgentChatSurface(props: DispatchAgentChatSurfaceProps) {\n return <AgentChatSurface {...props} />;\n}\n\ninterface DispatchChatLocationState {\n dispatchPrompt?: {\n id?: string | number;\n message?: string;\n selectedModel?: string | null;\n selectedEngine?: string | null;\n selectedEffort?: ComponentProps<typeof AgentChatSurface>[\"selectedEffort\"];\n };\n dispatchThread?: {\n id?: string | number;\n threadId?: string;\n };\n}\n\nexport function meta() {\n return [{ title: \"Chat — Dispatch\" }];\n}\n\nexport default function ChatRoute() {\n const t = useT();\n const location = useLocation();\n const navigate = useNavigate();\n const routeThreadId = threadIdFromPath(location.pathname);\n const agentPath = new URLSearchParams(location.search).get(\"agent\");\n const agentsQuery = useActionQuery<WorkspaceAgentResource[]>(\n \"list-workspace-resources\",\n { kind: \"agent\" },\n { enabled: Boolean(agentPath), staleTime: 30_000 },\n );\n const agent = useMemo(\n () =>\n agentPath\n ? (agentsQuery.data ?? []).find((resource) => {\n const profileId = resource.path\n .replace(/^agents\\//, \"\")\n .replace(/\\.md$/, \"\");\n return (\n resource.path === agentPath ||\n resource.id === agentPath ||\n profileId === agentPath\n );\n })\n : undefined,\n [agentPath, agentsQuery.data],\n );\n const agentScope = useMemo(\n () =>\n agent\n ? {\n type: \"agent\",\n id: agent.id,\n label: agent.name,\n contextKey: `dispatch-agent:${agent.id}`,\n }\n : null,\n [agent],\n );\n const handledStateIds = useRef(new Set<string>());\n const extensions = useDispatchExtensions();\n const suppressInlineOpenApp =\n extensions?.chatFirst === true ||\n readChatFirstMode() ||\n new URLSearchParams(location.search).get(\"chatFirst\") === \"1\";\n\n const navigateThreadUrl = useCallback(\n (path: string, options?: { replace?: boolean }) =>\n navigate(dispatchNavTarget(path), options),\n [navigate],\n );\n const threadUrlSync = useMemo<DispatchThreadUrlSync>(\n () => ({\n routeThreadId: routeThreadId ?? null,\n getPath: (threadId) => chatThreadPath(threadId, agentPath ?? undefined),\n navigate: navigateThreadUrl,\n }),\n [agentPath, routeThreadId, navigateThreadUrl],\n );\n const state = location.state as DispatchChatLocationState | null;\n const prompt = state?.dispatchPrompt;\n const thread = state?.dispatchThread;\n\n useEffect(() => {\n const message = prompt?.message?.trim();\n const threadId = thread?.threadId?.trim();\n if (!message && !threadId) return;\n\n const stateId = String(\n prompt?.id ?? thread?.id ?? `${message ?? \"\"}:${threadId ?? \"\"}`,\n );\n if (handledStateIds.current.has(stateId)) return;\n handledStateIds.current.add(stateId);\n\n const timer = window.setTimeout(() => {\n if (threadId) {\n window.dispatchEvent(\n new CustomEvent(\"agent-chat:open-thread\", {\n detail: { threadId },\n }),\n );\n }\n if (message) {\n submitOverviewPrompt(message, prompt?.selectedModel, {\n openSidebar: false,\n selectedEngine: prompt?.selectedEngine,\n selectedEffort: prompt?.selectedEffort,\n });\n }\n navigate(`${location.pathname}${location.search}${location.hash}`, {\n replace: true,\n state: null,\n });\n }, 0);\n\n return () => window.clearTimeout(timer);\n }, [\n location.hash,\n location.pathname,\n location.search,\n navigate,\n prompt?.id,\n prompt?.message,\n prompt?.selectedModel,\n prompt?.selectedEngine,\n prompt?.selectedEffort,\n thread?.id,\n thread?.threadId,\n ]);\n\n useEffect(() => {\n function handleChatRunning(event: Event) {\n const detail = (event as CustomEvent).detail;\n if (detail?.isRunning === true) markAgentChatHomeHandoff(\"dispatch\");\n }\n\n window.addEventListener(\"agentNative.chatRunning\", handleChatRunning);\n return () =>\n window.removeEventListener(\"agentNative.chatRunning\", handleChatRunning);\n }, []);\n\n useEffect(() => {\n if (!agent) return;\n const timer = window.setTimeout(() => {\n insertAgentComposerReference(\n {\n label: agent.name,\n icon: \"agent\",\n source: \"agent:custom\",\n refType: \"custom-agent\",\n refId: agent.id,\n refPath: agent.path,\n slotKey: \"dispatch-agent\",\n slotLabel: \"Agent\",\n },\n { openSidebar: false },\n );\n }, 0);\n return () => window.clearTimeout(timer);\n }, [agent?.id, agent?.name, agent?.path]);\n\n if (agentPath && agentsQuery.isLoading) {\n return (\n <div className=\"flex h-full min-h-0 flex-col gap-4 bg-background px-4 py-6 sm:px-6\">\n <Skeleton className=\"mx-auto h-6 w-48\" />\n <Skeleton className=\"mx-auto h-12 w-full max-w-2xl\" />\n </div>\n );\n }\n\n if (agentPath && agentsQuery.isError) {\n return (\n <div className=\"flex h-full min-h-0 items-center justify-center bg-background px-4\">\n <ActionQueryError\n error={agentsQuery.error}\n onRetry={() => void agentsQuery.refetch()}\n />\n </div>\n );\n }\n\n if (agentPath && !agent) {\n return (\n <div className=\"flex h-full min-h-0 items-center justify-center bg-background px-4 text-sm text-muted-foreground\">\n This agent is no longer available.\n </div>\n );\n }\n\n return (\n <div className=\"flex h-full min-h-0 flex-col bg-background\">\n <DispatchAgentChatSurface\n key={agent ? `agent-${agent.id}` : \"dispatch\"}\n mode=\"page\"\n chatViewTransition\n className=\"dispatch-chat-panel px-4 sm:px-6\"\n defaultMode=\"chat\"\n storageKey={agent ? `dispatch-agent-${agent.id}` : \"dispatch\"}\n scope={agentScope}\n threadUrlSync={threadUrlSync}\n showHeader={false}\n showTabBar={false}\n dynamicSuggestions={false}\n suppressInlineOpenApp={suppressInlineOpenApp}\n suggestions={[]}\n emptyStateText={t(\"dispatch.pages.chatAcrossAppsDescription\", {\n defaultValue:\n \"Route work, inspect status, or create something new from one place.\",\n })}\n emptyStateDisplay=\"hidden\"\n {...(!prompt?.message\n ? {\n centerComposerWhenEmpty: true,\n composerLayoutVariant: \"hero\" as const,\n }\n : {})}\n composerPlaceholder={\n agent\n ? `Ask ${agent.name}...`\n : t(\"dispatch.pages.chatPromptPlaceholder\", {\n defaultValue: \"Ask Dispatch...\",\n })\n }\n composerSlot={\n agent ? (\n <div className=\"dispatch-chat-intro\">\n <h1>{agent.name}</h1>\n {agent.description ? <p>{agent.description}</p> : null}\n </div>\n ) : !prompt?.message ? (\n <div className=\"dispatch-chat-intro\">\n <h1>\n {t(\"dispatch.pages.chatAcrossApps\", {\n defaultValue: \"Chat across your apps\",\n })}\n </h1>\n <p>\n {t(\"dispatch.pages.chatAcrossAppsDescription\", {\n defaultValue:\n \"Route work, inspect status, or create something new from one place.\",\n })}\n </p>\n </div>\n ) : null\n }\n />\n </div>\n );\n}\n"]}
@@ -0,0 +1,24 @@
1
+ import { type WorkspaceResourceInput } from "./workspace-resources-store.js";
2
+ /**
3
+ * Apply a pack as one logical operation. Approval is handled by the action
4
+ * before this helper is called, so this function must never call the
5
+ * approval-aware create wrapper for individual files.
6
+ */
7
+ export declare function applyAgentPackCreate(inputs: WorkspaceResourceInput[], actor?: string, ctx?: {
8
+ ownerEmail: string;
9
+ orgId: string | null;
10
+ }): Promise<{
11
+ id: string;
12
+ ownerEmail: string;
13
+ orgId: string | null;
14
+ kind: string;
15
+ name: string;
16
+ description: string | null;
17
+ path: string;
18
+ content: string;
19
+ scope: string;
20
+ createdBy: string;
21
+ createdAt: number;
22
+ updatedAt: number;
23
+ }[]>;
24
+ //# sourceMappingURL=agent-pack-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-pack-store.d.ts","sourceRoot":"","sources":["../../../src/server/lib/agent-pack-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,sBAAsB,EAC5B,MAAM,gCAAgC,CAAC;AAExC;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,sBAAsB,EAAE,EAChC,KAAK,CAAC,EAAE,MAAM,EACd,GAAG,CAAC,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE;;;;;;;;;;;;;KAmBnD"}
@@ -0,0 +1,22 @@
1
+ import { applyWorkspaceResourceCreate, getWorkspaceResourceByPath, requireWorkspaceResourceCtx, } from "./workspace-resources-store.js";
2
+ /**
3
+ * Apply a pack as one logical operation. Approval is handled by the action
4
+ * before this helper is called, so this function must never call the
5
+ * approval-aware create wrapper for individual files.
6
+ */
7
+ export async function applyAgentPackCreate(inputs, actor, ctx) {
8
+ const resourceCtx = ctx ?? requireWorkspaceResourceCtx();
9
+ const existing = await Promise.all(inputs.map((input) => getWorkspaceResourceByPath(input.path, resourceCtx)));
10
+ const duplicate = existing.find(Boolean);
11
+ if (duplicate) {
12
+ throw new Error(`An agent pack resource already exists at ${duplicate.path}. Rename the source before importing it.`);
13
+ }
14
+ const created = [];
15
+ for (const input of inputs) {
16
+ const resource = await applyWorkspaceResourceCreate(input, actor, ctx);
17
+ if (resource)
18
+ created.push(resource);
19
+ }
20
+ return created;
21
+ }
22
+ //# sourceMappingURL=agent-pack-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-pack-store.js","sourceRoot":"","sources":["../../../src/server/lib/agent-pack-store.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,2BAA2B,GAE5B,MAAM,gCAAgC,CAAC;AAExC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAgC,EAChC,KAAc,EACd,GAAkD;IAElD,MAAM,WAAW,GAAG,GAAG,IAAI,2BAA2B,EAAE,CAAC;IACzD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,0BAA0B,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAC3E,CAAC;IACF,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,4CAA4C,SAAS,CAAC,IAAI,0CAA0C,CACrG,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC;IACnB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,MAAM,4BAA4B,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACvE,IAAI,QAAQ;YAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import {\n applyWorkspaceResourceCreate,\n getWorkspaceResourceByPath,\n requireWorkspaceResourceCtx,\n type WorkspaceResourceInput,\n} from \"./workspace-resources-store.js\";\n\n/**\n * Apply a pack as one logical operation. Approval is handled by the action\n * before this helper is called, so this function must never call the\n * approval-aware create wrapper for individual files.\n */\nexport async function applyAgentPackCreate(\n inputs: WorkspaceResourceInput[],\n actor?: string,\n ctx?: { ownerEmail: string; orgId: string | null },\n) {\n const resourceCtx = ctx ?? requireWorkspaceResourceCtx();\n const existing = await Promise.all(\n inputs.map((input) => getWorkspaceResourceByPath(input.path, resourceCtx)),\n );\n const duplicate = existing.find(Boolean);\n if (duplicate) {\n throw new Error(\n `An agent pack resource already exists at ${duplicate.path}. Rename the source before importing it.`,\n );\n }\n\n const created = [];\n for (const input of inputs) {\n const resource = await applyWorkspaceResourceCreate(input, actor, ctx);\n if (resource) created.push(resource);\n }\n return created;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch-store.d.ts","sourceRoot":"","sources":["../../../src/server/lib/dispatch-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dispatch-store.d.ts","sourceRoot":"","sources":["../../../src/server/lib/dispatch-store.ts"],"names":[],"mappings":"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"}
@@ -408,6 +408,10 @@ async function applyApprovedRequest(request) {
408
408
  const { applyWorkspaceResourceCreate } = await import("./workspace-resources-store.js");
409
409
  return applyWorkspaceResourceCreate(payload.input, request.reviewedBy || currentOwnerEmail(), requestCtx);
410
410
  }
411
+ if (request.changeType === "workspace-agent-pack.create") {
412
+ const { applyAgentPackCreate } = await import("./agent-pack-store.js");
413
+ return applyAgentPackCreate(payload.inputs, request.reviewedBy || currentOwnerEmail(), requestCtx);
414
+ }
411
415
  if (request.changeType === "workspace-resource.update") {
412
416
  const { applyWorkspaceResourceUpdate } = await import("./workspace-resources-store.js");
413
417
  return applyWorkspaceResourceUpdate(payload.id, payload.input, request.reviewedBy || currentOwnerEmail(), requestCtx);