@agent-native/dispatch 0.40.30 → 0.40.33

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 (100) hide show
  1. package/CHANGELOG.md +28 -25
  2. package/dist/actions/connect-external-agent.d.ts.map +1 -1
  3. package/dist/actions/connect-external-agent.js +2 -9
  4. package/dist/actions/connect-external-agent.js.map +1 -1
  5. package/dist/actions/list-connected-agents.js +7 -3
  6. package/dist/actions/list-connected-agents.js.map +1 -1
  7. package/dist/actions/list-dispatch-usage-metrics.js +1 -1
  8. package/dist/actions/list-dispatch-usage-metrics.js.map +1 -1
  9. package/dist/actions/list-workspace-connections.d.ts.map +1 -1
  10. package/dist/actions/list-workspace-connections.js +13 -18
  11. package/dist/actions/list-workspace-connections.js.map +1 -1
  12. package/dist/actions/provider-api-register.d.ts +8 -8
  13. package/dist/actions/provider-api-register.js +2 -14
  14. package/dist/actions/provider-api-register.js.map +1 -1
  15. package/dist/components/action-query-error.d.ts +2 -1
  16. package/dist/components/action-query-error.d.ts.map +1 -1
  17. package/dist/components/action-query-error.js +25 -2
  18. package/dist/components/action-query-error.js.map +1 -1
  19. package/dist/components/chat-home-apps.d.ts.map +1 -1
  20. package/dist/components/chat-home-apps.js +2 -2
  21. package/dist/components/chat-home-apps.js.map +1 -1
  22. package/dist/components/dispatch-control-plane.d.ts.map +1 -1
  23. package/dist/components/dispatch-control-plane.js +1 -1
  24. package/dist/components/dispatch-control-plane.js.map +1 -1
  25. package/dist/components/layout/Layout.d.ts +1 -0
  26. package/dist/components/layout/Layout.d.ts.map +1 -1
  27. package/dist/components/layout/Layout.js +7 -0
  28. package/dist/components/layout/Layout.js.map +1 -1
  29. package/dist/db/index.d.ts.map +1 -1
  30. package/dist/db/index.js +4 -9
  31. package/dist/db/index.js.map +1 -1
  32. package/dist/routes/pages/$appId.d.ts.map +1 -1
  33. package/dist/routes/pages/$appId.js +1 -1
  34. package/dist/routes/pages/$appId.js.map +1 -1
  35. package/dist/routes/pages/apps.js +1 -1
  36. package/dist/routes/pages/apps.js.map +1 -1
  37. package/dist/server/lib/admin-config.d.ts.map +1 -1
  38. package/dist/server/lib/admin-config.js +3 -1
  39. package/dist/server/lib/admin-config.js.map +1 -1
  40. package/dist/server/lib/app-creation-store.d.ts.map +1 -1
  41. package/dist/server/lib/app-creation-store.js +124 -65
  42. package/dist/server/lib/app-creation-store.js.map +1 -1
  43. package/dist/server/lib/community-apps.js +1 -1
  44. package/dist/server/lib/community-apps.js.map +1 -1
  45. package/dist/server/lib/mcp-access-store.d.ts.map +1 -1
  46. package/dist/server/lib/mcp-access-store.js +2 -10
  47. package/dist/server/lib/mcp-access-store.js.map +1 -1
  48. package/dist/server/lib/thread-debug-store.d.ts.map +1 -1
  49. package/dist/server/lib/thread-debug-store.js +2 -6
  50. package/dist/server/lib/thread-debug-store.js.map +1 -1
  51. package/dist/server/lib/usage-metrics-store.d.ts.map +1 -1
  52. package/dist/server/lib/usage-metrics-store.js +2 -11
  53. package/dist/server/lib/usage-metrics-store.js.map +1 -1
  54. package/dist/server/lib/vault-store.d.ts.map +1 -1
  55. package/dist/server/lib/vault-store.js +2 -9
  56. package/dist/server/lib/vault-store.js.map +1 -1
  57. package/dist/server/lib/workspace-app-action-auth.d.ts.map +1 -1
  58. package/dist/server/lib/workspace-app-action-auth.js +7 -2
  59. package/dist/server/lib/workspace-app-action-auth.js.map +1 -1
  60. package/dist/server/plugins/agent-chat.js +1 -1
  61. package/dist/server/plugins/agent-chat.js.map +1 -1
  62. package/package.json +3 -3
  63. package/src/actions/connect-external-agent.spec.ts +25 -11
  64. package/src/actions/connect-external-agent.ts +2 -9
  65. package/src/actions/index.spec.ts +3 -0
  66. package/src/actions/list-connected-agents.spec.ts +17 -1
  67. package/src/actions/list-connected-agents.ts +7 -2
  68. package/src/actions/list-dispatch-usage-metrics.ts +1 -1
  69. package/src/actions/list-workspace-connections.spec.ts +14 -3
  70. package/src/actions/list-workspace-connections.ts +13 -17
  71. package/src/actions/provider-api-register.spec.ts +15 -9
  72. package/src/actions/provider-api-register.ts +5 -13
  73. package/src/components/action-query-error.spec.tsx +20 -0
  74. package/src/components/action-query-error.tsx +40 -0
  75. package/src/components/chat-home-apps.spec.tsx +32 -1
  76. package/src/components/chat-home-apps.tsx +6 -1
  77. package/src/components/dispatch-control-plane.tsx +1 -0
  78. package/src/components/layout/Layout.tsx +9 -0
  79. package/src/db/index.spec.ts +74 -0
  80. package/src/db/index.ts +4 -9
  81. package/src/routes/pages/$appId.tsx +1 -0
  82. package/src/routes/pages/apps.spec.tsx +26 -2
  83. package/src/routes/pages/apps.tsx +2 -0
  84. package/src/server/lib/admin-config.spec.ts +51 -0
  85. package/src/server/lib/admin-config.ts +2 -1
  86. package/src/server/lib/app-creation-store.spec.ts +308 -10
  87. package/src/server/lib/app-creation-store.ts +174 -70
  88. package/src/server/lib/community-apps.ts +1 -1
  89. package/src/server/lib/mcp-access-store.spec.ts +39 -12
  90. package/src/server/lib/mcp-access-store.ts +3 -10
  91. package/src/server/lib/thread-debug-store.spec.ts +64 -0
  92. package/src/server/lib/thread-debug-store.ts +2 -9
  93. package/src/server/lib/usage-metrics-store.spec.ts +64 -0
  94. package/src/server/lib/usage-metrics-store.ts +2 -17
  95. package/src/server/lib/vault-store.spec.ts +26 -9
  96. package/src/server/lib/vault-store.ts +3 -10
  97. package/src/server/lib/workspace-app-action-auth.spec.ts +37 -6
  98. package/src/server/lib/workspace-app-action-auth.ts +12 -2
  99. package/src/server/plugins/agent-chat.spec.ts +14 -0
  100. package/src/server/plugins/agent-chat.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @agent-native/dispatch
2
2
 
3
+ ## 0.40.33
4
+
5
+ ### Patch Changes
6
+
7
+ - e9efe95: Keep the curated QR catalog pinned to the current template files.
8
+ - Release all public npm packages with a patch version bump.
9
+ - Updated dependencies
10
+ - @agent-native/toolkit@0.213.1
11
+
12
+ ## 0.40.32
13
+
14
+ ### Patch Changes
15
+
16
+ - Release all public npm packages with a patch version bump.
17
+ - b58658d: Allow organization owners to opt in to current-member A2A delegation with capped member permissions and durable audit provenance. Improve app discovery and Dispatch routing for connected analytics and customer credit questions.
18
+ - Updated dependencies
19
+ - Updated dependencies [b58658d]
20
+ - @agent-native/toolkit@0.213.0
21
+
22
+ ## 0.40.31
23
+
24
+ ### Patch Changes
25
+
26
+ - Release all public npm packages with a patch version bump.
27
+ - b697ec4: Use organization-scoped secrets for workspace app registry authentication and show which Dispatch query failed.
28
+ - Updated dependencies
29
+ - @agent-native/toolkit@0.212.1
30
+
3
31
  ## 0.40.30
4
32
 
5
33
  ### Patch Changes
@@ -1282,29 +1310,4 @@
1282
1310
 
1283
1311
  - 8cab236: Speed up workspace app opens in Dispatch by reusing the app catalog cache and deferring granted-app discovery until needed.
1284
1312
 
1285
- ## 0.29.2
1286
-
1287
- ### Patch Changes
1288
-
1289
- - 66b2a1c: Navigate workspace apps in the top window when Dispatch runs in Builder or an iframe.
1290
-
1291
- ## 0.29.1
1292
-
1293
- ### Patch Changes
1294
-
1295
- - 96ecc13: Use compact app search and pin labels that stay on one line.
1296
-
1297
- ## 0.29.0
1298
-
1299
- ### Minor Changes
1300
-
1301
- - 772f59a: Point the chat beside an open workspace app at that app's own agent. Dispatch now proxies `/_agent-native/workspace-app-chat/<appId>/**` to the app's `/_agent-native/agent-chat`, authenticated with the app's own embed session, so the rail has the app's tools, AGENTS.md, skills, app-scoped resources, and dev-mode surface instead of Dispatch's. When the proxy cannot be established the rail shows a retryable error rather than silently answering from Dispatch's agent, and workspace-level chat with no app open is unchanged.
1302
-
1303
- ### Patch Changes
1304
-
1305
- - 772f59a: Allow workspace members to update mounted app names and descriptions from Dispatch.
1306
- - 772f59a: Report the embedded workspace app to the Dispatch agent as structured context. `/apps/<id>` now resolves to a `workspace-app` navigation view that keeps the app id and in-app path instead of collapsing to the apps list, and `view-screen` emits an `embeddedApp` block for both that route and chat-first mode, where the route stays on `/chat` and the open app is named only by `chat-first-pane` state. An app that is open but cannot be identified reports `status: "unknown"` rather than a default or an omitted field.
1307
- - 772f59a: Share the canonical localized authentication copy with native sign-in surfaces
1308
- and allow authenticated packaged callers to mint workspace embed sessions.
1309
-
1310
1313
  For the full list of releases, see the [changelog archive](./changelog/archive/CHANGELOG.md).
@@ -1 +1 @@
1
- {"version":3,"file":"connect-external-agent.d.ts","sourceRoot":"","sources":["../../src/actions/connect-external-agent.ts"],"names":[],"mappings":";;;;;;YA4FqB,SAAS"}
1
+ {"version":3,"file":"connect-external-agent.d.ts","sourceRoot":"","sources":["../../src/actions/connect-external-agent.ts"],"names":[],"mappings":";;;;;;YAqFqB,SAAS"}
@@ -1,6 +1,6 @@
1
1
  import { defineAction, fail } from "@agent-native/core/action";
2
- import { getDbExec } from "@agent-native/core/db";
3
2
  import { resourcePutIfAbsent, sharedResourceOwner, } from "@agent-native/core/resources/store";
3
+ import { readOrgMemberRole } from "@agent-native/core/server";
4
4
  import { z } from "zod";
5
5
  import { normalizeConnectUrl } from "../lib/connect-apps.js";
6
6
  import { currentOrgId, currentOwnerEmail, } from "../server/lib/dispatch-store.js";
@@ -19,14 +19,7 @@ async function assertCanManageSharedAgent() {
19
19
  });
20
20
  }
21
21
  const actor = currentOwnerEmail().trim().toLowerCase();
22
- const result = await getDbExec().execute({
23
- sql: `SELECT role FROM org_members
24
- WHERE org_id = ? AND LOWER(email) = ?
25
- AND federation_removal_pending_at IS NULL
26
- LIMIT 1`,
27
- args: [orgId, actor],
28
- });
29
- const role = result.rows[0]?.role;
22
+ const role = await readOrgMemberRole(orgId, actor);
30
23
  if (role !== "owner" && role !== "admin") {
31
24
  fail("Only organization owners and admins can connect agents.", {
32
25
  statusCode: 403,
@@ -1 +1 @@
1
- {"version":3,"file":"connect-external-agent.js","sourceRoot":"","sources":["../../src/actions/connect-external-agent.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineAction, fail } from \"@agent-native/core/action\";\nimport { getDbExec } from \"@agent-native/core/db\";\nimport {\n resourcePutIfAbsent,\n sharedResourceOwner,\n} from \"@agent-native/core/resources/store\";\nimport { z } from \"zod\";\n\nimport { normalizeConnectUrl } from \"../lib/connect-apps.js\";\nimport {\n currentOrgId,\n currentOwnerEmail,\n} from \"../server/lib/dispatch-store.js\";\n\nfunction slugify(value: string): string {\n return (\n value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"agent\"\n );\n}\n\nasync function assertCanManageSharedAgent() {\n const orgId = currentOrgId();\n if (!orgId) {\n fail(\"An active organization is required to connect an agent.\", {\n statusCode: 403,\n });\n }\n const actor = currentOwnerEmail().trim().toLowerCase();\n const result = await getDbExec().execute({\n sql: `SELECT role FROM org_members\n WHERE org_id = ? AND LOWER(email) = ?\n AND federation_removal_pending_at IS NULL\n LIMIT 1`,\n args: [orgId, actor],\n });\n const role = result.rows[0]?.role;\n if (role !== \"owner\" && role !== \"admin\") {\n fail(\"Only organization owners and admins can connect agents.\", {\n statusCode: 403,\n });\n }\n}\n\nexport default defineAction({\n description:\n \"Connect an existing HTTPS/A2A agent to Dispatch. This stores only its public endpoint and metadata; authentication remains in the normal A2A/MCP connection flow.\",\n schema: z.object({\n url: z.string().min(1).describe(\"HTTPS agent endpoint\"),\n name: z.string().max(160).optional().describe(\"Agent name\"),\n description: z.string().max(500).optional().describe(\"Short description\"),\n scope: z\n .enum([\"shared\", \"personal\"])\n .default(\"shared\")\n .describe(\"Share with the workspace or keep the connection personal\"),\n }),\n run: async ({ url, name, description, scope }) => {\n const parsed = normalizeConnectUrl(url);\n if (!parsed)\n fail(\"Use an HTTPS URL without credentials or private addresses.\");\n\n if (scope === \"shared\") await assertCanManageSharedAgent();\n const agentName = name?.trim() || parsed.hostname.replace(/^www\\./, \"\");\n const id = slugify(agentName);\n const path = `remote-agents/${id}.json`;\n const owner =\n scope === \"shared\"\n ? sharedResourceOwner(currentOrgId())\n : currentOwnerEmail();\n\n const manifest = {\n id,\n name: agentName,\n ...(description?.trim() ? { description: description.trim() } : {}),\n url: parsed.toString(),\n };\n const resource = await resourcePutIfAbsent(\n owner,\n path,\n JSON.stringify(manifest, null, 2),\n \"application/json\",\n );\n if (!resource) {\n fail(\n `An external agent already exists at ${path}. Rename it before connecting again.`,\n { statusCode: 409 },\n );\n }\n\n return { status: \"created\" as const, resource, agent: manifest, scope };\n },\n});\n"]}
1
+ {"version":3,"file":"connect-external-agent.js","sourceRoot":"","sources":["../../src/actions/connect-external-agent.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineAction, fail } from \"@agent-native/core/action\";\nimport {\n resourcePutIfAbsent,\n sharedResourceOwner,\n} from \"@agent-native/core/resources/store\";\nimport { readOrgMemberRole } from \"@agent-native/core/server\";\nimport { z } from \"zod\";\n\nimport { normalizeConnectUrl } from \"../lib/connect-apps.js\";\nimport {\n currentOrgId,\n currentOwnerEmail,\n} from \"../server/lib/dispatch-store.js\";\n\nfunction slugify(value: string): string {\n return (\n value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"agent\"\n );\n}\n\nasync function assertCanManageSharedAgent() {\n const orgId = currentOrgId();\n if (!orgId) {\n fail(\"An active organization is required to connect an agent.\", {\n statusCode: 403,\n });\n }\n const actor = currentOwnerEmail().trim().toLowerCase();\n const role = await readOrgMemberRole(orgId, actor);\n if (role !== \"owner\" && role !== \"admin\") {\n fail(\"Only organization owners and admins can connect agents.\", {\n statusCode: 403,\n });\n }\n}\n\nexport default defineAction({\n description:\n \"Connect an existing HTTPS/A2A agent to Dispatch. This stores only its public endpoint and metadata; authentication remains in the normal A2A/MCP connection flow.\",\n schema: z.object({\n url: z.string().min(1).describe(\"HTTPS agent endpoint\"),\n name: z.string().max(160).optional().describe(\"Agent name\"),\n description: z.string().max(500).optional().describe(\"Short description\"),\n scope: z\n .enum([\"shared\", \"personal\"])\n .default(\"shared\")\n .describe(\"Share with the workspace or keep the connection personal\"),\n }),\n run: async ({ url, name, description, scope }) => {\n const parsed = normalizeConnectUrl(url);\n if (!parsed)\n fail(\"Use an HTTPS URL without credentials or private addresses.\");\n\n if (scope === \"shared\") await assertCanManageSharedAgent();\n const agentName = name?.trim() || parsed.hostname.replace(/^www\\./, \"\");\n const id = slugify(agentName);\n const path = `remote-agents/${id}.json`;\n const owner =\n scope === \"shared\"\n ? sharedResourceOwner(currentOrgId())\n : currentOwnerEmail();\n\n const manifest = {\n id,\n name: agentName,\n ...(description?.trim() ? { description: description.trim() } : {}),\n url: parsed.toString(),\n };\n const resource = await resourcePutIfAbsent(\n owner,\n path,\n JSON.stringify(manifest, null, 2),\n \"application/json\",\n );\n if (!resource) {\n fail(\n `An external agent already exists at ${path}. Rename it before connecting again.`,\n { statusCode: 409 },\n );\n }\n\n return { status: \"created\" as const, resource, agent: manifest, scope };\n },\n});\n"]}
@@ -1,4 +1,4 @@
1
- import { defineAction } from "@agent-native/core/action";
1
+ import { defineAction, fail } from "@agent-native/core/action";
2
2
  import { REMOTE_AGENT_RESOURCE_PREFIXES, parseRemoteAgentManifest, } from "@agent-native/core/resources/metadata";
3
3
  import { resourceGet, resourceListAccessible, SHARED_OWNER, } from "@agent-native/core/resources/store";
4
4
  import { getRequestUserEmail } from "@agent-native/core/server";
@@ -21,8 +21,12 @@ export default defineAction({
21
21
  const builtinIds = new Set(builtins.map((agent) => agent.id).filter((id) => !workspaceIds.has(id)));
22
22
  const builtinHomeUrls = new Map(builtins.map((agent) => [agent.id, agent.url]));
23
23
  const ownerEmail = getRequestUserEmail();
24
- if (!ownerEmail)
25
- throw new Error("no authenticated user");
24
+ if (!ownerEmail) {
25
+ fail("Sign in to list connected agents.", {
26
+ errorCode: "dispatch_user_identity_missing",
27
+ statusCode: 401,
28
+ });
29
+ }
26
30
  const resources = [];
27
31
  for (const prefix of [...REMOTE_AGENT_RESOURCE_PREFIXES].reverse()) {
28
32
  resources.push(...(await resourceListAccessible(ownerEmail, prefix)));
@@ -1 +1 @@
1
- {"version":3,"file":"list-connected-agents.js","sourceRoot":"","sources":["../../src/actions/list-connected-agents.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineAction } from \"@agent-native/core/action\";\nimport {\n REMOTE_AGENT_RESOURCE_PREFIXES,\n parseRemoteAgentManifest,\n} from \"@agent-native/core/resources/metadata\";\nimport {\n resourceGet,\n resourceListAccessible,\n SHARED_OWNER,\n} from \"@agent-native/core/resources/store\";\nimport { getRequestUserEmail } from \"@agent-native/core/server\";\nimport {\n discoverAgents,\n getBuiltinAgents,\n isBuiltinAgentCatalogId,\n loadWorkspaceAppsManifest,\n normalizeAgentId,\n shouldIncludeRemoteAgentManifest,\n} from \"@agent-native/core/server/agent-discovery\";\nimport { z } from \"zod\";\n\nexport default defineAction({\n description:\n \"List agents available to dispatch for A2A delegation, including built-in apps and connected remote agents.\",\n schema: z.object({}),\n http: { method: \"GET\" },\n run: async () => {\n const { hiddenAgentIds = [] } = await import(\"../server/index.js\").then(\n (m) => m.getDispatchConfig(),\n );\n const [discovered, workspaceApps] = await Promise.all([\n discoverAgents(\"dispatch\"),\n loadWorkspaceAppsManifest(),\n ]);\n // A mounted workspace app with a built-in's id is a workspace app; the\n // built-in config never applies to it.\n const workspaceIds = new Set(\n (workspaceApps ?? []).map((app) => normalizeAgentId(app.id)),\n );\n const builtins = getBuiltinAgents(\"dispatch\");\n const builtinIds = new Set(\n builtins.map((agent) => agent.id).filter((id) => !workspaceIds.has(id)),\n );\n const builtinHomeUrls = new Map(\n builtins.map((agent) => [agent.id, agent.url]),\n );\n const ownerEmail = getRequestUserEmail();\n if (!ownerEmail) throw new Error(\"no authenticated user\");\n const resources: Array<{ id: string; path: string; owner: string }> = [];\n for (const prefix of [...REMOTE_AGENT_RESOURCE_PREFIXES].reverse()) {\n resources.push(...(await resourceListAccessible(ownerEmail, prefix)));\n }\n const customById = new Map<\n string,\n {\n resourceId: string;\n path: string;\n scope: \"shared\" | \"personal\";\n name: string;\n description: string;\n url: string;\n color: string;\n }\n >();\n\n for (const resource of resources) {\n if (!resource.path.endsWith(\".json\")) continue;\n const full = await resourceGet(resource.id);\n if (!full) continue;\n const manifest = parseRemoteAgentManifest(full.content, resource.path);\n if (!manifest) continue;\n if (!shouldIncludeRemoteAgentManifest(manifest, \"dispatch\")) continue;\n const manifestId = normalizeAgentId(manifest.id);\n // Built-in ids stay under the workspace's built-in config even when a\n // seeded manifest for them exists in resources.\n if (isBuiltinAgentCatalogId(manifestId)) continue;\n customById.set(manifestId, {\n resourceId: resource.id,\n path: resource.path,\n scope: resource.owner === SHARED_OWNER ? \"shared\" : \"personal\",\n name: manifest.name,\n description: manifest.description || \"\",\n url: manifest.url,\n color: manifest.color || \"#6B7280\",\n });\n }\n\n const connected = discovered.map((agent) => {\n const custom = customById.get(agent.id);\n const isBuiltin = builtinIds.has(agent.id);\n const homeUrl = isBuiltin ? builtinHomeUrls.get(agent.id) : undefined;\n return {\n ...agent,\n ...(homeUrl ? { homeUrl } : {}),\n source: isBuiltin ? \"builtin\" : custom ? \"custom\" : \"workspace\",\n resourceId: custom?.resourceId,\n path: custom?.path,\n scope: custom?.scope,\n };\n });\n\n const discoveredIds = new Set(connected.map((agent) => agent.id));\n for (const [id, custom] of customById) {\n if (discoveredIds.has(id)) continue;\n connected.push({\n id,\n name: custom.name,\n description: custom.description,\n url: custom.url,\n color: custom.color,\n source: \"custom\",\n resourceId: custom.resourceId,\n path: custom.path,\n scope: custom.scope,\n });\n }\n\n return connected.filter((a) => !hiddenAgentIds.includes(a.id));\n },\n});\n"]}
1
+ {"version":3,"file":"list-connected-agents.js","sourceRoot":"","sources":["../../src/actions/list-connected-agents.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineAction, fail } from \"@agent-native/core/action\";\nimport {\n REMOTE_AGENT_RESOURCE_PREFIXES,\n parseRemoteAgentManifest,\n} from \"@agent-native/core/resources/metadata\";\nimport {\n resourceGet,\n resourceListAccessible,\n SHARED_OWNER,\n} from \"@agent-native/core/resources/store\";\nimport { getRequestUserEmail } from \"@agent-native/core/server\";\nimport {\n discoverAgents,\n getBuiltinAgents,\n isBuiltinAgentCatalogId,\n loadWorkspaceAppsManifest,\n normalizeAgentId,\n shouldIncludeRemoteAgentManifest,\n} from \"@agent-native/core/server/agent-discovery\";\nimport { z } from \"zod\";\n\nexport default defineAction({\n description:\n \"List agents available to dispatch for A2A delegation, including built-in apps and connected remote agents.\",\n schema: z.object({}),\n http: { method: \"GET\" },\n run: async () => {\n const { hiddenAgentIds = [] } = await import(\"../server/index.js\").then(\n (m) => m.getDispatchConfig(),\n );\n const [discovered, workspaceApps] = await Promise.all([\n discoverAgents(\"dispatch\"),\n loadWorkspaceAppsManifest(),\n ]);\n // A mounted workspace app with a built-in's id is a workspace app; the\n // built-in config never applies to it.\n const workspaceIds = new Set(\n (workspaceApps ?? []).map((app) => normalizeAgentId(app.id)),\n );\n const builtins = getBuiltinAgents(\"dispatch\");\n const builtinIds = new Set(\n builtins.map((agent) => agent.id).filter((id) => !workspaceIds.has(id)),\n );\n const builtinHomeUrls = new Map(\n builtins.map((agent) => [agent.id, agent.url]),\n );\n const ownerEmail = getRequestUserEmail();\n if (!ownerEmail) {\n fail(\"Sign in to list connected agents.\", {\n errorCode: \"dispatch_user_identity_missing\",\n statusCode: 401,\n });\n }\n const resources: Array<{ id: string; path: string; owner: string }> = [];\n for (const prefix of [...REMOTE_AGENT_RESOURCE_PREFIXES].reverse()) {\n resources.push(...(await resourceListAccessible(ownerEmail, prefix)));\n }\n const customById = new Map<\n string,\n {\n resourceId: string;\n path: string;\n scope: \"shared\" | \"personal\";\n name: string;\n description: string;\n url: string;\n color: string;\n }\n >();\n\n for (const resource of resources) {\n if (!resource.path.endsWith(\".json\")) continue;\n const full = await resourceGet(resource.id);\n if (!full) continue;\n const manifest = parseRemoteAgentManifest(full.content, resource.path);\n if (!manifest) continue;\n if (!shouldIncludeRemoteAgentManifest(manifest, \"dispatch\")) continue;\n const manifestId = normalizeAgentId(manifest.id);\n // Built-in ids stay under the workspace's built-in config even when a\n // seeded manifest for them exists in resources.\n if (isBuiltinAgentCatalogId(manifestId)) continue;\n customById.set(manifestId, {\n resourceId: resource.id,\n path: resource.path,\n scope: resource.owner === SHARED_OWNER ? \"shared\" : \"personal\",\n name: manifest.name,\n description: manifest.description || \"\",\n url: manifest.url,\n color: manifest.color || \"#6B7280\",\n });\n }\n\n const connected = discovered.map((agent) => {\n const custom = customById.get(agent.id);\n const isBuiltin = builtinIds.has(agent.id);\n const homeUrl = isBuiltin ? builtinHomeUrls.get(agent.id) : undefined;\n return {\n ...agent,\n ...(homeUrl ? { homeUrl } : {}),\n source: isBuiltin ? \"builtin\" : custom ? \"custom\" : \"workspace\",\n resourceId: custom?.resourceId,\n path: custom?.path,\n scope: custom?.scope,\n };\n });\n\n const discoveredIds = new Set(connected.map((agent) => agent.id));\n for (const [id, custom] of customById) {\n if (discoveredIds.has(id)) continue;\n connected.push({\n id,\n name: custom.name,\n description: custom.description,\n url: custom.url,\n color: custom.color,\n source: \"custom\",\n resourceId: custom.resourceId,\n path: custom.path,\n scope: custom.scope,\n });\n }\n\n return connected.filter((a) => !hiddenAgentIds.includes(a.id));\n },\n});\n"]}
@@ -2,7 +2,7 @@ import { defineAction } from "@agent-native/core/action";
2
2
  import { z } from "zod";
3
3
  import { listDispatchUsageMetrics } from "../server/lib/usage-metrics-store.js";
4
4
  export default defineAction({
5
- description: "Get personal, workspace, or owner-authorized app adoption metrics for Dispatch, including LLM usage, spend or Builder.io credit spend, active users, tracked app actions, app attribution, prompt previews, and recent activity. billing.unit is unknown when historical usage lacks engine metadata or mixes billing sources; monthlyByUser credits are null in that case. Workspace results also include monthlyByUser credit rows and workspaceAppCreationsByUserMonth rows from the shared token_usage and Dispatch audit tables. App scope is aggregate-only and returns daily/weekly active users plus tracked action counts for the selected app.",
5
+ description: "Get personal or workspace-member agent usage and spend, or aggregate app adoption metrics for Dispatch. Workspace results do not include customer/account/company usage or product data; use the relevant workspace app for those. Results may include active users, tracked app actions, app attribution, prompt previews, and recent activity. billing.unit is unknown when historical usage lacks engine metadata or mixes billing sources; monthlyByUser credits are null in that case. Workspace results also include monthlyByUser credit rows and workspaceAppCreationsByUserMonth rows from the shared token_usage and Dispatch audit tables. App scope is aggregate-only and returns daily/weekly active users plus tracked action counts for the selected app.",
6
6
  schema: z.object({
7
7
  sinceDays: z.coerce
8
8
  .number()
@@ -1 +1 @@
1
- {"version":3,"file":"list-dispatch-usage-metrics.js","sourceRoot":"","sources":["../../src/actions/list-dispatch-usage-metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAEhF,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,0nBAA0nB;IAC5nB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,SAAS,EAAE,CAAC,CAAC,MAAM;aAChB,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,GAAG,CAAC;aACR,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,0CAA0C,CAAC;QACvD,KAAK,EAAE,CAAC;aACL,IAAI,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;aAChC,OAAO,CAAC,WAAW,CAAC;aACpB,QAAQ,CACP,wFAAwF,CACzF;QACH,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CAAC,yDAAyD,CAAC;QACtE,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CACP,+GAA+G,CAChH;KACJ,CAAC;IACF,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;IACvB,QAAQ,EAAE,IAAI;IACd,YAAY,EAAE,IAAI;IAClB,WAAW,EAAE;QACX,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;QAClB,eAAe,EAAE,KAAK;KACvB;IACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,wBAAwB,CAAC,IAAI,CAAC;CACpD,CAAC,CAAC","sourcesContent":["import { defineAction } from \"@agent-native/core/action\";\nimport { z } from \"zod\";\n\nimport { listDispatchUsageMetrics } from \"../server/lib/usage-metrics-store.js\";\n\nexport default defineAction({\n description:\n \"Get personal, workspace, or owner-authorized app adoption metrics for Dispatch, including LLM usage, spend or Builder.io credit spend, active users, tracked app actions, app attribution, prompt previews, and recent activity. billing.unit is unknown when historical usage lacks engine metadata or mixes billing sources; monthlyByUser credits are null in that case. Workspace results also include monthlyByUser credit rows and workspaceAppCreationsByUserMonth rows from the shared token_usage and Dispatch audit tables. App scope is aggregate-only and returns daily/weekly active users plus tracked action counts for the selected app.\",\n schema: z.object({\n sinceDays: z.coerce\n .number()\n .int()\n .min(1)\n .max(365)\n .default(30)\n .describe(\"Lookback window in days. Defaults to 30.\"),\n scope: z\n .enum([\"me\", \"workspace\", \"app\"])\n .default(\"workspace\")\n .describe(\n \"Whether to inspect your account, the whole workspace, or one app's aggregate adoption.\",\n ),\n userEmail: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\"Optional workspace member email to filter all usage to.\"),\n appId: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\n \"Workspace app id for scope=app. The app owner or an organization owner/admin can view its aggregate adoption.\",\n ),\n }),\n http: { method: \"GET\" },\n readOnly: true,\n parallelSafe: true,\n publicAgent: {\n expose: true,\n readOnly: true,\n requiresAuth: true,\n isConsequential: false,\n },\n run: async (args) => listDispatchUsageMetrics(args),\n});\n"]}
1
+ {"version":3,"file":"list-dispatch-usage-metrics.js","sourceRoot":"","sources":["../../src/actions/list-dispatch-usage-metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAEhF,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,0uBAA0uB;IAC5uB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,SAAS,EAAE,CAAC,CAAC,MAAM;aAChB,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,GAAG,CAAC;aACR,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,0CAA0C,CAAC;QACvD,KAAK,EAAE,CAAC;aACL,IAAI,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;aAChC,OAAO,CAAC,WAAW,CAAC;aACpB,QAAQ,CACP,wFAAwF,CACzF;QACH,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CAAC,yDAAyD,CAAC;QACtE,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CACP,+GAA+G,CAChH;KACJ,CAAC;IACF,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;IACvB,QAAQ,EAAE,IAAI;IACd,YAAY,EAAE,IAAI;IAClB,WAAW,EAAE;QACX,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;QAClB,eAAe,EAAE,KAAK;KACvB;IACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,wBAAwB,CAAC,IAAI,CAAC;CACpD,CAAC,CAAC","sourcesContent":["import { defineAction } from \"@agent-native/core/action\";\nimport { z } from \"zod\";\n\nimport { listDispatchUsageMetrics } from \"../server/lib/usage-metrics-store.js\";\n\nexport default defineAction({\n description:\n \"Get personal or workspace-member agent usage and spend, or aggregate app adoption metrics for Dispatch. Workspace results do not include customer/account/company usage or product data; use the relevant workspace app for those. Results may include active users, tracked app actions, app attribution, prompt previews, and recent activity. billing.unit is unknown when historical usage lacks engine metadata or mixes billing sources; monthlyByUser credits are null in that case. Workspace results also include monthlyByUser credit rows and workspaceAppCreationsByUserMonth rows from the shared token_usage and Dispatch audit tables. App scope is aggregate-only and returns daily/weekly active users plus tracked action counts for the selected app.\",\n schema: z.object({\n sinceDays: z.coerce\n .number()\n .int()\n .min(1)\n .max(365)\n .default(30)\n .describe(\"Lookback window in days. Defaults to 30.\"),\n scope: z\n .enum([\"me\", \"workspace\", \"app\"])\n .default(\"workspace\")\n .describe(\n \"Whether to inspect your account, the whole workspace, or one app's aggregate adoption.\",\n ),\n userEmail: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\"Optional workspace member email to filter all usage to.\"),\n appId: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\n \"Workspace app id for scope=app. The app owner or an organization owner/admin can view its aggregate adoption.\",\n ),\n }),\n http: { method: \"GET\" },\n readOnly: true,\n parallelSafe: true,\n publicAgent: {\n expose: true,\n readOnly: true,\n requiresAuth: true,\n isConsequential: false,\n },\n run: async (args) => listDispatchUsageMetrics(args),\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"list-workspace-connections.d.ts","sourceRoot":"","sources":["../../src/actions/list-workspace-connections.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EACpC,MAAM,gCAAgC,CAAC;AA2BxC,KAAK,QAAQ,GAAG;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AASF,KAAK,YAAY,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,GAAG,cAAc,GAAG,gBAAgB,CAAC;IACvD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,KAAK,uBAAuB,GAAG,YAAY,GAAG,cAAc,GAAG,aAAa,CAAC;;;;;;;;;QA0OrE,WAAW;YACT,MAAM;YACN,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QASX,SAAS;QACT,WAAW;QACX,MAAM;QACN,iBAAiB;QAEjB,sBAAsB;QAGtB,cAAc"}
1
+ {"version":3,"file":"list-workspace-connections.d.ts","sourceRoot":"","sources":["../../src/actions/list-workspace-connections.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EACpC,MAAM,gCAAgC,CAAC;AA2BxC,KAAK,QAAQ,GAAG;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AASF,KAAK,YAAY,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,GAAG,cAAc,GAAG,gBAAgB,CAAC;IACvD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,KAAK,uBAAuB,GAAG,YAAY,GAAG,cAAc,GAAG,aAAa,CAAC;;;;;;;;;QAsOrE,WAAW;YACT,MAAM;YACN,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QASX,SAAS;QACT,WAAW;QACX,MAAM;QACN,iBAAiB;QAEjB,sBAAsB;QAGtB,cAAc"}
@@ -39,24 +39,19 @@ async function listGrantApps() {
39
39
  const listWorkspaceApps = dispatchActions["list-workspace-apps"];
40
40
  if (!listWorkspaceApps)
41
41
  return [{ id: "dispatch", label: "Dispatch" }];
42
- try {
43
- const apps = (await listWorkspaceApps.run({
44
- includeAgentCards: false,
45
- audience: "all",
46
- }));
47
- const grantApps = apps
48
- .filter((app) => !app.archived && app.status !== "pending")
49
- .map((app) => ({
50
- id: app.id,
51
- label: app.name || humanizeAppId(app.id),
52
- }));
53
- return grantApps.length > 0
54
- ? grantApps
55
- : [{ id: "dispatch", label: "Dispatch" }];
56
- }
57
- catch {
58
- return [{ id: "dispatch", label: "Dispatch" }];
59
- }
42
+ const apps = (await listWorkspaceApps.run({
43
+ includeAgentCards: false,
44
+ audience: "all",
45
+ }));
46
+ const grantApps = apps
47
+ .filter((app) => !app.archived && app.status !== "pending")
48
+ .map((app) => ({
49
+ id: app.id,
50
+ label: app.name || humanizeAppId(app.id),
51
+ }));
52
+ return grantApps.length > 0
53
+ ? grantApps
54
+ : [{ id: "dispatch", label: "Dispatch" }];
60
55
  }
61
56
  export default defineAction({
62
57
  description: "List the workspace integration provider catalog, saved shared connections, and app access grants.",
@@ -1 +1 @@
1
- {"version":3,"file":"list-workspace-connections.js","sourceRoot":"","sources":["../../src/actions/list-workspace-connections.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineAction } from \"@agent-native/core/action\";\nimport {\n listWorkspaceConnectionProviders,\n type WorkspaceConnectionCapability,\n type WorkspaceConnectionTemplateUse,\n} from \"@agent-native/core/connections\";\nimport {\n isProviderApiId,\n listProviderApiCatalog,\n} from \"@agent-native/core/provider-api\";\nimport {\n CredentialStoreUnavailableError,\n hasWorkspaceProviderOAuthCredentials,\n isGoogleWorkspaceOAuthProvider,\n} from \"@agent-native/core/server\";\nimport {\n getWorkspaceConnectionAppAccess,\n listWorkspaceConnectionGrants,\n listWorkspaceConnectionsForUser,\n summarizeWorkspaceConnectionProviderReadiness,\n} from \"@agent-native/core/workspace-connections\";\nimport { dispatchActions } from \"@agent-native/dispatch/actions\";\nimport { z } from \"zod\";\n\nconst httpBoolean = z.preprocess((value) => {\n if (typeof value !== \"string\") return value;\n const normalized = value.trim().toLowerCase();\n if ([\"true\", \"1\", \"yes\", \"on\"].includes(normalized)) return true;\n if ([\"false\", \"0\", \"no\", \"off\"].includes(normalized)) return false;\n return value;\n}, z.boolean());\n\ntype GrantApp = {\n id: string;\n label: string;\n};\n\ntype WorkspaceApp = {\n id: string;\n name?: string;\n status?: \"ready\" | \"pending\";\n archived?: boolean;\n};\n\ntype GrantSummary = {\n id: string;\n connectionId: string;\n provider: string;\n appId: string;\n access: \"all-apps\" | \"selected-app\" | \"explicit-grant\";\n lastUsedAt?: string | null;\n};\n\ntype GoogleOAuthAvailability = \"configured\" | \"unconfigured\" | \"unavailable\";\n\nfunction unique(values: string[]) {\n return Array.from(\n new Set(values.map((value) => value.trim()).filter(Boolean)),\n );\n}\n\nfunction optionalTimestamp(source: object, key: string) {\n if (!Object.prototype.hasOwnProperty.call(source, key)) return undefined;\n const value = (source as Record<string, unknown>)[key];\n if (value == null) return null;\n if (value instanceof Date) return value.toISOString();\n return typeof value === \"string\" ? value : (JSON.stringify(value) ?? \"\");\n}\n\nfunction humanizeAppId(appId: string): string {\n return appId\n .split(/[-_]/)\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n}\n\nasync function listGrantApps(): Promise<GrantApp[]> {\n const listWorkspaceApps = dispatchActions[\"list-workspace-apps\"];\n if (!listWorkspaceApps) return [{ id: \"dispatch\", label: \"Dispatch\" }];\n\n try {\n const apps = (await listWorkspaceApps.run({\n includeAgentCards: false,\n audience: \"all\",\n } as any)) as WorkspaceApp[];\n const grantApps = apps\n .filter((app) => !app.archived && app.status !== \"pending\")\n .map((app) => ({\n id: app.id,\n label: app.name || humanizeAppId(app.id),\n }));\n return grantApps.length > 0\n ? grantApps\n : [{ id: \"dispatch\", label: \"Dispatch\" }];\n } catch {\n return [{ id: \"dispatch\", label: \"Dispatch\" }];\n }\n}\n\nexport default defineAction({\n description:\n \"List the workspace integration provider catalog, saved shared connections, and app access grants.\",\n schema: z.object({\n provider: z\n .string()\n .optional()\n .describe(\"Optional provider ID such as slack, github, or notion.\"),\n appId: z\n .string()\n .optional()\n .describe(\"Only include connections available to this app ID.\"),\n includeDisabled: httpBoolean\n .default(false)\n .describe(\"Include disabled connections. Defaults to false.\"),\n capability: z\n .string()\n .optional()\n .describe(\"Optional capability filter such as search, import, or docs.\"),\n templateUse: z\n .string()\n .optional()\n .describe(\"Optional template-use filter such as brain or analytics.\"),\n }),\n http: { method: \"GET\" },\n run: async (args) => {\n const catalogProviders = listWorkspaceConnectionProviders({\n capability: args.capability as WorkspaceConnectionCapability | undefined,\n templateUse: args.templateUse as\n | WorkspaceConnectionTemplateUse\n | undefined,\n });\n let googleOAuthAvailability: GoogleOAuthAvailability;\n try {\n googleOAuthAvailability = (await hasWorkspaceProviderOAuthCredentials(\n \"gmail\",\n ))\n ? \"configured\"\n : \"unconfigured\";\n } catch (error) {\n if (!(error instanceof CredentialStoreUnavailableError)) throw error;\n googleOAuthAvailability = \"unavailable\";\n }\n const googleOAuthConfigured = googleOAuthAvailability === \"configured\";\n const providers = catalogProviders.filter(\n (provider) =>\n (!args.provider || provider.id === args.provider) &&\n (googleOAuthConfigured || !isGoogleWorkspaceOAuthProvider(provider.id)),\n );\n const allConnections = await listWorkspaceConnectionsForUser({\n provider: args.provider,\n appId: args.appId,\n includeDisabled: args.includeDisabled,\n });\n const connections = allConnections.filter(\n (connection) =>\n googleOAuthConfigured ||\n !isGoogleWorkspaceOAuthProvider(connection.provider),\n );\n const allExplicitGrants = await listWorkspaceConnectionGrants({\n provider: args.provider,\n appId: args.appId,\n });\n const visibleConnectionIds = new Set(\n connections.map((connection) => connection.id),\n );\n const explicitGrants = allExplicitGrants.filter(\n (grant) =>\n visibleConnectionIds.has(grant.connectionId) &&\n (googleOAuthConfigured ||\n !isGoogleWorkspaceOAuthProvider(grant.provider)),\n );\n const grantApps = await listGrantApps();\n const legacyGrants = connections.flatMap<GrantSummary>((connection) => {\n if (connection.allowedApps.length === 0) {\n return [\n {\n id: `${connection.id}:all-apps`,\n connectionId: connection.id,\n provider: connection.provider,\n appId: \"*\",\n access: \"all-apps\" as const,\n },\n ];\n }\n return connection.allowedApps.map(\n (appId): GrantSummary => ({\n id: `${connection.id}:${appId}`,\n connectionId: connection.id,\n provider: connection.provider,\n appId,\n access: \"selected-app\" as const,\n }),\n );\n });\n const grants: GrantSummary[] = [\n ...legacyGrants,\n ...explicitGrants.map((grant) => {\n const lastUsedAt = optionalTimestamp(grant, \"lastUsedAt\");\n return {\n id: grant.id,\n connectionId: grant.connectionId,\n provider: grant.provider,\n appId: grant.appId,\n access: \"explicit-grant\" as const,\n ...(lastUsedAt !== undefined ? { lastUsedAt } : {}),\n };\n }),\n ];\n const grantSummaries = connections.map((connection) => {\n const explicitGrantAppIds = unique(\n explicitGrants\n .filter((grant) => grant.connectionId === connection.id)\n .map((grant) => grant.appId),\n );\n const selectedAppIds = unique(connection.allowedApps);\n const allApps = selectedAppIds.length === 0;\n const effectiveAppIds = allApps\n ? [\"*\"]\n : unique([...selectedAppIds, ...explicitGrantAppIds]);\n\n return {\n connectionId: connection.id,\n provider: connection.provider,\n accessMode: allApps\n ? (\"all-apps\" as const)\n : (\"selected-apps\" as const),\n allApps,\n selectedAppIds,\n explicitGrantAppIds,\n effectiveAppIds,\n trackedApps: grantApps.map((app) => {\n const access = getWorkspaceConnectionAppAccess(\n connection,\n app.id,\n explicitGrants,\n );\n return {\n appId: app.id,\n label: app.label,\n granted: access.available,\n mode: access.mode,\n grantId: access.grantId,\n };\n }),\n };\n });\n\n const providersWithReadiness = providers.map((provider) => {\n const providerApi = isProviderApiId(provider.id)\n ? listProviderApiCatalog(provider.id)[0]\n : null;\n return {\n ...provider,\n readiness: summarizeWorkspaceConnectionProviderReadiness({\n provider,\n connections,\n grants: explicitGrants,\n appId: args.appId,\n includeConnections: \"all\",\n }),\n rawProviderApi: providerApi\n ? {\n available: true,\n actionNames: [\n \"provider-api-catalog\",\n \"provider-api-docs\",\n \"provider-api-request\",\n ],\n docsUrls: providerApi.docsUrls,\n specUrls: providerApi.specUrls,\n auth: providerApi.auth,\n examples: providerApi.examples,\n }\n : {\n available: false,\n actionNames: [],\n docsUrls: [],\n specUrls: [],\n auth: null,\n examples: [],\n },\n };\n });\n\n return {\n availability: {\n googleOAuth: {\n status: googleOAuthAvailability,\n retryable: googleOAuthAvailability === \"unavailable\",\n },\n },\n providers: providersWithReadiness,\n connections,\n grants,\n grantSummaries,\n suggestedApps: grantApps,\n counts: {\n providers: providersWithReadiness.length,\n connections: connections.length,\n grants: grants.length,\n allAppConnections: grantSummaries.filter((summary) => summary.allApps)\n .length,\n selectedAppConnections: grantSummaries.filter(\n (summary) => !summary.allApps,\n ).length,\n readyProviders: providersWithReadiness.filter(\n (provider) => provider.readiness.status === \"ready\",\n ).length,\n },\n };\n },\n});\n"]}
1
+ {"version":3,"file":"list-workspace-connections.js","sourceRoot":"","sources":["../../src/actions/list-workspace-connections.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineAction } from \"@agent-native/core/action\";\nimport {\n listWorkspaceConnectionProviders,\n type WorkspaceConnectionCapability,\n type WorkspaceConnectionTemplateUse,\n} from \"@agent-native/core/connections\";\nimport {\n isProviderApiId,\n listProviderApiCatalog,\n} from \"@agent-native/core/provider-api\";\nimport {\n CredentialStoreUnavailableError,\n hasWorkspaceProviderOAuthCredentials,\n isGoogleWorkspaceOAuthProvider,\n} from \"@agent-native/core/server\";\nimport {\n getWorkspaceConnectionAppAccess,\n listWorkspaceConnectionGrants,\n listWorkspaceConnectionsForUser,\n summarizeWorkspaceConnectionProviderReadiness,\n} from \"@agent-native/core/workspace-connections\";\nimport { dispatchActions } from \"@agent-native/dispatch/actions\";\nimport { z } from \"zod\";\n\nconst httpBoolean = z.preprocess((value) => {\n if (typeof value !== \"string\") return value;\n const normalized = value.trim().toLowerCase();\n if ([\"true\", \"1\", \"yes\", \"on\"].includes(normalized)) return true;\n if ([\"false\", \"0\", \"no\", \"off\"].includes(normalized)) return false;\n return value;\n}, z.boolean());\n\ntype GrantApp = {\n id: string;\n label: string;\n};\n\ntype WorkspaceApp = {\n id: string;\n name?: string;\n status?: \"ready\" | \"pending\";\n archived?: boolean;\n};\n\ntype GrantSummary = {\n id: string;\n connectionId: string;\n provider: string;\n appId: string;\n access: \"all-apps\" | \"selected-app\" | \"explicit-grant\";\n lastUsedAt?: string | null;\n};\n\ntype GoogleOAuthAvailability = \"configured\" | \"unconfigured\" | \"unavailable\";\n\nfunction unique(values: string[]) {\n return Array.from(\n new Set(values.map((value) => value.trim()).filter(Boolean)),\n );\n}\n\nfunction optionalTimestamp(source: object, key: string) {\n if (!Object.prototype.hasOwnProperty.call(source, key)) return undefined;\n const value = (source as Record<string, unknown>)[key];\n if (value == null) return null;\n if (value instanceof Date) return value.toISOString();\n return typeof value === \"string\" ? value : (JSON.stringify(value) ?? \"\");\n}\n\nfunction humanizeAppId(appId: string): string {\n return appId\n .split(/[-_]/)\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n}\n\nasync function listGrantApps(): Promise<GrantApp[]> {\n const listWorkspaceApps = dispatchActions[\"list-workspace-apps\"];\n if (!listWorkspaceApps) return [{ id: \"dispatch\", label: \"Dispatch\" }];\n\n const apps = (await listWorkspaceApps.run({\n includeAgentCards: false,\n audience: \"all\",\n } as any)) as WorkspaceApp[];\n const grantApps = apps\n .filter((app) => !app.archived && app.status !== \"pending\")\n .map((app) => ({\n id: app.id,\n label: app.name || humanizeAppId(app.id),\n }));\n return grantApps.length > 0\n ? grantApps\n : [{ id: \"dispatch\", label: \"Dispatch\" }];\n}\n\nexport default defineAction({\n description:\n \"List the workspace integration provider catalog, saved shared connections, and app access grants.\",\n schema: z.object({\n provider: z\n .string()\n .optional()\n .describe(\"Optional provider ID such as slack, github, or notion.\"),\n appId: z\n .string()\n .optional()\n .describe(\"Only include connections available to this app ID.\"),\n includeDisabled: httpBoolean\n .default(false)\n .describe(\"Include disabled connections. Defaults to false.\"),\n capability: z\n .string()\n .optional()\n .describe(\"Optional capability filter such as search, import, or docs.\"),\n templateUse: z\n .string()\n .optional()\n .describe(\"Optional template-use filter such as brain or analytics.\"),\n }),\n http: { method: \"GET\" },\n run: async (args) => {\n const catalogProviders = listWorkspaceConnectionProviders({\n capability: args.capability as WorkspaceConnectionCapability | undefined,\n templateUse: args.templateUse as\n | WorkspaceConnectionTemplateUse\n | undefined,\n });\n let googleOAuthAvailability: GoogleOAuthAvailability;\n try {\n googleOAuthAvailability = (await hasWorkspaceProviderOAuthCredentials(\n \"gmail\",\n ))\n ? \"configured\"\n : \"unconfigured\";\n } catch (error) {\n if (!(error instanceof CredentialStoreUnavailableError)) throw error;\n googleOAuthAvailability = \"unavailable\";\n }\n const googleOAuthConfigured = googleOAuthAvailability === \"configured\";\n const providers = catalogProviders.filter(\n (provider) =>\n (!args.provider || provider.id === args.provider) &&\n (googleOAuthConfigured || !isGoogleWorkspaceOAuthProvider(provider.id)),\n );\n const allConnections = await listWorkspaceConnectionsForUser({\n provider: args.provider,\n appId: args.appId,\n includeDisabled: args.includeDisabled,\n });\n const connections = allConnections.filter(\n (connection) =>\n googleOAuthConfigured ||\n !isGoogleWorkspaceOAuthProvider(connection.provider),\n );\n const allExplicitGrants = await listWorkspaceConnectionGrants({\n provider: args.provider,\n appId: args.appId,\n });\n const visibleConnectionIds = new Set(\n connections.map((connection) => connection.id),\n );\n const explicitGrants = allExplicitGrants.filter(\n (grant) =>\n visibleConnectionIds.has(grant.connectionId) &&\n (googleOAuthConfigured ||\n !isGoogleWorkspaceOAuthProvider(grant.provider)),\n );\n const grantApps = await listGrantApps();\n const legacyGrants = connections.flatMap<GrantSummary>((connection) => {\n if (connection.allowedApps.length === 0) {\n return [\n {\n id: `${connection.id}:all-apps`,\n connectionId: connection.id,\n provider: connection.provider,\n appId: \"*\",\n access: \"all-apps\" as const,\n },\n ];\n }\n return connection.allowedApps.map(\n (appId): GrantSummary => ({\n id: `${connection.id}:${appId}`,\n connectionId: connection.id,\n provider: connection.provider,\n appId,\n access: \"selected-app\" as const,\n }),\n );\n });\n const grants: GrantSummary[] = [\n ...legacyGrants,\n ...explicitGrants.map((grant) => {\n const lastUsedAt = optionalTimestamp(grant, \"lastUsedAt\");\n return {\n id: grant.id,\n connectionId: grant.connectionId,\n provider: grant.provider,\n appId: grant.appId,\n access: \"explicit-grant\" as const,\n ...(lastUsedAt !== undefined ? { lastUsedAt } : {}),\n };\n }),\n ];\n const grantSummaries = connections.map((connection) => {\n const explicitGrantAppIds = unique(\n explicitGrants\n .filter((grant) => grant.connectionId === connection.id)\n .map((grant) => grant.appId),\n );\n const selectedAppIds = unique(connection.allowedApps);\n const allApps = selectedAppIds.length === 0;\n const effectiveAppIds = allApps\n ? [\"*\"]\n : unique([...selectedAppIds, ...explicitGrantAppIds]);\n\n return {\n connectionId: connection.id,\n provider: connection.provider,\n accessMode: allApps\n ? (\"all-apps\" as const)\n : (\"selected-apps\" as const),\n allApps,\n selectedAppIds,\n explicitGrantAppIds,\n effectiveAppIds,\n trackedApps: grantApps.map((app) => {\n const access = getWorkspaceConnectionAppAccess(\n connection,\n app.id,\n explicitGrants,\n );\n return {\n appId: app.id,\n label: app.label,\n granted: access.available,\n mode: access.mode,\n grantId: access.grantId,\n };\n }),\n };\n });\n\n const providersWithReadiness = providers.map((provider) => {\n const providerApi = isProviderApiId(provider.id)\n ? listProviderApiCatalog(provider.id)[0]\n : null;\n return {\n ...provider,\n readiness: summarizeWorkspaceConnectionProviderReadiness({\n provider,\n connections,\n grants: explicitGrants,\n appId: args.appId,\n includeConnections: \"all\",\n }),\n rawProviderApi: providerApi\n ? {\n available: true,\n actionNames: [\n \"provider-api-catalog\",\n \"provider-api-docs\",\n \"provider-api-request\",\n ],\n docsUrls: providerApi.docsUrls,\n specUrls: providerApi.specUrls,\n auth: providerApi.auth,\n examples: providerApi.examples,\n }\n : {\n available: false,\n actionNames: [],\n docsUrls: [],\n specUrls: [],\n auth: null,\n examples: [],\n },\n };\n });\n\n return {\n availability: {\n googleOAuth: {\n status: googleOAuthAvailability,\n retryable: googleOAuthAvailability === \"unavailable\",\n },\n },\n providers: providersWithReadiness,\n connections,\n grants,\n grantSummaries,\n suggestedApps: grantApps,\n counts: {\n providers: providersWithReadiness.length,\n connections: connections.length,\n grants: grants.length,\n allAppConnections: grantSummaries.filter((summary) => summary.allApps)\n .length,\n selectedAppConnections: grantSummaries.filter(\n (summary) => !summary.allApps,\n ).length,\n readyProviders: providersWithReadiness.filter(\n (provider) => provider.readiness.status === \"ready\",\n ).length,\n },\n };\n },\n});\n"]}
@@ -47,7 +47,7 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
47
47
  notes?: string | undefined;
48
48
  scope?: "org" | "user" | undefined;
49
49
  }, {
50
- provider?: undefined;
50
+ message?: undefined;
51
51
  providers: {
52
52
  id: string;
53
53
  label: string;
@@ -58,13 +58,14 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
58
58
  updatedAt: number;
59
59
  }[];
60
60
  count: number;
61
+ provider?: undefined;
61
62
  found?: undefined;
62
63
  deleted?: undefined;
63
64
  registered?: undefined;
64
65
  id?: undefined;
65
66
  label?: undefined;
66
- message?: undefined;
67
67
  } | {
68
+ message?: undefined;
68
69
  providers?: undefined;
69
70
  count?: undefined;
70
71
  found: boolean;
@@ -73,31 +74,30 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
73
74
  registered?: undefined;
74
75
  id?: undefined;
75
76
  label?: undefined;
76
- message?: undefined;
77
77
  } | {
78
- provider?: undefined;
78
+ message?: undefined;
79
79
  providers?: undefined;
80
80
  count?: undefined;
81
+ provider?: undefined;
81
82
  found: boolean;
82
83
  id: string;
83
84
  deleted?: undefined;
84
85
  registered?: undefined;
85
86
  label?: undefined;
86
- message?: undefined;
87
87
  } | {
88
- provider?: undefined;
88
+ message?: undefined;
89
89
  providers?: undefined;
90
90
  count?: undefined;
91
+ provider?: undefined;
91
92
  found?: undefined;
92
93
  deleted: boolean;
93
94
  id: string;
94
95
  registered?: undefined;
95
96
  label?: undefined;
96
- message?: undefined;
97
97
  } | {
98
- provider?: undefined;
99
98
  providers?: undefined;
100
99
  count?: undefined;
100
+ provider?: undefined;
101
101
  found?: undefined;
102
102
  deleted?: undefined;
103
103
  registered: boolean;
@@ -1,20 +1,8 @@
1
- import { getDbExec } from "@agent-native/core/db";
2
1
  import { createCustomProviderRegistrationAction } from "@agent-native/core/provider-api/actions/custom-provider-registration";
3
- import { getCredentialContext } from "@agent-native/core/server";
2
+ import { getCredentialContext, readOrgMemberRole, } from "@agent-native/core/server";
4
3
  async function resolveCallerOrgRole(orgId, email) {
5
4
  try {
6
- const client = getDbExec();
7
- const { rows } = await client.execute({
8
- sql: `SELECT role FROM org_members
9
- WHERE org_id = ? AND LOWER(email) = ?
10
- AND federation_removal_pending_at IS NULL
11
- LIMIT 1`,
12
- args: [orgId, email.toLowerCase()],
13
- });
14
- if (rows.length === 0)
15
- return null;
16
- const role = rows[0].role;
17
- return typeof role === "string" && role ? role : null;
5
+ return await readOrgMemberRole(orgId, email);
18
6
  }
19
7
  catch {
20
8
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"provider-api-register.js","sourceRoot":"","sources":["../../src/actions/provider-api-register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,sCAAsC,EAAE,MAAM,sEAAsE,CAAC;AAC9H,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,KAAK,UAAU,oBAAoB,CACjC,KAAa,EACb,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;YACpC,GAAG,EAAE;;;oBAGS;YACd,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;SACnC,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,IAAI,GAAI,IAAI,CAAC,CAAC,CAAwB,CAAC,IAAI,CAAC;QAClD,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,eAAe,sCAAsC,CAAC;IACpD,WAAW,EAAE;;;;;;;;2GAQ4F;IACzG,UAAU,EAAE,oBAAoB;IAChC,cAAc,EAAE,oBAAoB;CACrC,CAAC,CAAC","sourcesContent":["import { getDbExec } from \"@agent-native/core/db\";\nimport { createCustomProviderRegistrationAction } from \"@agent-native/core/provider-api/actions/custom-provider-registration\";\nimport { getCredentialContext } from \"@agent-native/core/server\";\n\nasync function resolveCallerOrgRole(\n orgId: string,\n email: string,\n): Promise<string | null> {\n try {\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT role FROM org_members\n WHERE org_id = ? AND LOWER(email) = ?\n AND federation_removal_pending_at IS NULL\n LIMIT 1`,\n args: [orgId, email.toLowerCase()],\n });\n if (rows.length === 0) return null;\n const role = (rows[0] as { role?: unknown }).role;\n return typeof role === \"string\" && role ? role : null;\n } catch {\n return null;\n }\n}\n\nexport default createCustomProviderRegistrationAction({\n description: `Register or update a custom API provider so the agent can call it via provider-api-request and look up its docs via provider-api-docs.\n\nIMPORTANT — credentials:\n- This action stores only credential KEY NAMES, never secret values.\n- If the required API key is not yet saved, instruct the user to add it via app Settings → Keys, or use the create-vault-secret action, before calling this action.\n- Supported auth kinds: none, bearer, basic, api-key-header.\n google-service-account and oauth-bearer are NOT supported for custom providers.\n\nAfter registration the provider appears in provider-api-catalog and can be used with provider-api-request.`,\n getContext: getCredentialContext,\n resolveOrgRole: resolveCallerOrgRole,\n});\n"]}
1
+ {"version":3,"file":"provider-api-register.js","sourceRoot":"","sources":["../../src/actions/provider-api-register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sCAAsC,EAAE,MAAM,sEAAsE,CAAC;AAC9H,OAAO,EACL,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AAEnC,KAAK,UAAU,oBAAoB,CACjC,KAAa,EACb,KAAa;IAEb,IAAI,CAAC;QACH,OAAO,MAAM,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,eAAe,sCAAsC,CAAC;IACpD,WAAW,EAAE;;;;;;;;2GAQ4F;IACzG,UAAU,EAAE,oBAAoB;IAChC,cAAc,EAAE,oBAAoB;CACrC,CAAC,CAAC","sourcesContent":["import { createCustomProviderRegistrationAction } from \"@agent-native/core/provider-api/actions/custom-provider-registration\";\nimport {\n getCredentialContext,\n readOrgMemberRole,\n} from \"@agent-native/core/server\";\n\nasync function resolveCallerOrgRole(\n orgId: string,\n email: string,\n): Promise<string | null> {\n try {\n return await readOrgMemberRole(orgId, email);\n } catch {\n return null;\n }\n}\n\nexport default createCustomProviderRegistrationAction({\n description: `Register or update a custom API provider so the agent can call it via provider-api-request and look up its docs via provider-api-docs.\n\nIMPORTANT — credentials:\n- This action stores only credential KEY NAMES, never secret values.\n- If the required API key is not yet saved, instruct the user to add it via app Settings → Keys, or use the create-vault-secret action, before calling this action.\n- Supported auth kinds: none, bearer, basic, api-key-header.\n google-service-account and oauth-bearer are NOT supported for custom providers.\n\nAfter registration the provider appears in provider-api-catalog and can be used with provider-api-request.`,\n getContext: getCredentialContext,\n resolveOrgRole: resolveCallerOrgRole,\n});\n"]}
@@ -2,7 +2,8 @@ interface ActionQueryErrorProps {
2
2
  error?: unknown;
3
3
  onRetry: () => unknown;
4
4
  className?: string;
5
+ queryName?: string;
5
6
  }
6
- export declare function ActionQueryError({ onRetry, className, }: ActionQueryErrorProps): import("node_modules/@types/react").JSX.Element;
7
+ export declare function ActionQueryError({ error, onRetry, className, queryName, }: ActionQueryErrorProps): import("node_modules/@types/react").JSX.Element;
7
8
  export {};
8
9
  //# sourceMappingURL=action-query-error.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"action-query-error.d.ts","sourceRoot":"","sources":["../../src/components/action-query-error.tsx"],"names":[],"mappings":"AAMA,UAAU,qBAAqB;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,SAAS,GACV,EAAE,qBAAqB,mDAgBvB"}
1
+ {"version":3,"file":"action-query-error.d.ts","sourceRoot":"","sources":["../../src/components/action-query-error.tsx"],"names":[],"mappings":"AAMA,UAAU,qBAAqB;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiCD,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,OAAO,EACP,SAAS,EACT,SAAS,GACV,EAAE,qBAAqB,mDAsBvB"}
@@ -3,8 +3,31 @@ import { useT } from "@agent-native/core/client/i18n";
3
3
  import { IconAlertTriangle, IconRefresh } from "@tabler/icons-react";
4
4
  import { Alert, AlertDescription, AlertTitle } from "./ui/alert.js";
5
5
  import { Button } from "./ui/button.js";
6
- export function ActionQueryError({ onRetry, className, }) {
6
+ function actionQueryDiagnostic(error, queryName) {
7
+ const parts = [];
8
+ if (queryName)
9
+ parts.push(queryName);
10
+ if (error && typeof error === "object") {
11
+ const details = error;
12
+ const status = typeof details.statusCode === "number"
13
+ ? details.statusCode
14
+ : details.status;
15
+ if (typeof status === "number" &&
16
+ Number.isInteger(status) &&
17
+ status >= 100 &&
18
+ status <= 599) {
19
+ parts.push(`HTTP ${status}`);
20
+ }
21
+ const code = details.errorCode ?? details.code;
22
+ if (typeof code === "string" && /^[a-zA-Z0-9_.-]{1,80}$/.test(code)) {
23
+ parts.push(code);
24
+ }
25
+ }
26
+ return parts.length > 0 ? parts.join(" · ") : null;
27
+ }
28
+ export function ActionQueryError({ error, onRetry, className, queryName, }) {
7
29
  const t = useT();
8
- return (_jsxs(Alert, { variant: "destructive", className: className, children: [_jsx(IconAlertTriangle, { className: "size-4" }), _jsx(AlertTitle, { children: t("dispatch.pages.dataLoadFailed") }), _jsxs(AlertDescription, { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsx("span", { children: t("dispatch.pages.dataLoadFailedDescription") }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: onRetry, children: [_jsx(IconRefresh, { className: "size-4" }), t("dispatch.pages.tryAgain")] })] })] }));
30
+ const diagnostic = actionQueryDiagnostic(error, queryName);
31
+ return (_jsxs(Alert, { variant: "destructive", className: className, children: [_jsx(IconAlertTriangle, { className: "size-4" }), _jsx(AlertTitle, { children: t("dispatch.pages.dataLoadFailed") }), _jsxs(AlertDescription, { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsx("span", { children: t("dispatch.pages.dataLoadFailedDescription") }), diagnostic ? (_jsx("code", { className: "w-full break-all text-xs text-muted-foreground", children: diagnostic })) : null, _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: onRetry, children: [_jsx(IconRefresh, { className: "size-4" }), t("dispatch.pages.tryAgain")] })] })] }));
9
32
  }
10
33
  //# sourceMappingURL=action-query-error.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"action-query-error.js","sourceRoot":"","sources":["../../src/components/action-query-error.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAQrC,MAAM,UAAU,gBAAgB,CAAC,EAC/B,OAAO,EACP,SAAS,GACa;IACtB,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IAEjB,OAAO,CACL,MAAC,KAAK,IAAC,OAAO,EAAC,aAAa,EAAC,SAAS,EAAE,SAAS,aAC/C,KAAC,iBAAiB,IAAC,SAAS,EAAC,QAAQ,GAAG,EACxC,KAAC,UAAU,cAAE,CAAC,CAAC,+BAA+B,CAAC,GAAc,EAC7D,MAAC,gBAAgB,IAAC,SAAS,EAAC,mDAAmD,aAC7E,yBAAO,CAAC,CAAC,0CAA0C,CAAC,GAAQ,EAC5D,MAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,OAAO,aAChE,KAAC,WAAW,IAAC,SAAS,EAAC,QAAQ,GAAG,EACjC,CAAC,CAAC,yBAAyB,CAAC,IACtB,IACQ,IACb,CACT,CAAC;AACJ,CAAC","sourcesContent":["import { useT } from \"@agent-native/core/client/i18n\";\nimport { IconAlertTriangle, IconRefresh } from \"@tabler/icons-react\";\n\nimport { Alert, AlertDescription, AlertTitle } from \"./ui/alert\";\nimport { Button } from \"./ui/button\";\n\ninterface ActionQueryErrorProps {\n error?: unknown;\n onRetry: () => unknown;\n className?: string;\n}\n\nexport function ActionQueryError({\n onRetry,\n className,\n}: ActionQueryErrorProps) {\n const t = useT();\n\n return (\n <Alert variant=\"destructive\" className={className}>\n <IconAlertTriangle className=\"size-4\" />\n <AlertTitle>{t(\"dispatch.pages.dataLoadFailed\")}</AlertTitle>\n <AlertDescription className=\"flex flex-wrap items-center justify-between gap-3\">\n <span>{t(\"dispatch.pages.dataLoadFailedDescription\")}</span>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={onRetry}>\n <IconRefresh className=\"size-4\" />\n {t(\"dispatch.pages.tryAgain\")}\n </Button>\n </AlertDescription>\n </Alert>\n );\n}\n"]}
1
+ {"version":3,"file":"action-query-error.js","sourceRoot":"","sources":["../../src/components/action-query-error.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AASrC,SAAS,qBAAqB,CAC5B,KAAc,EACd,SAA6B;IAE7B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAErC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,KAAgC,CAAC;QACjD,MAAM,MAAM,GACV,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ;YACpC,CAAC,CAAC,OAAO,CAAC,UAAU;YACpB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QACrB,IACE,OAAO,MAAM,KAAK,QAAQ;YAC1B,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;YACxB,MAAM,IAAI,GAAG;YACb,MAAM,IAAI,GAAG,EACb,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;QAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACpE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAC/B,KAAK,EACL,OAAO,EACP,SAAS,EACT,SAAS,GACa;IACtB,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,UAAU,GAAG,qBAAqB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAE3D,OAAO,CACL,MAAC,KAAK,IAAC,OAAO,EAAC,aAAa,EAAC,SAAS,EAAE,SAAS,aAC/C,KAAC,iBAAiB,IAAC,SAAS,EAAC,QAAQ,GAAG,EACxC,KAAC,UAAU,cAAE,CAAC,CAAC,+BAA+B,CAAC,GAAc,EAC7D,MAAC,gBAAgB,IAAC,SAAS,EAAC,mDAAmD,aAC7E,yBAAO,CAAC,CAAC,0CAA0C,CAAC,GAAQ,EAC3D,UAAU,CAAC,CAAC,CAAC,CACZ,eAAM,SAAS,EAAC,gDAAgD,YAC7D,UAAU,GACN,CACR,CAAC,CAAC,CAAC,IAAI,EACR,MAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,OAAO,aAChE,KAAC,WAAW,IAAC,SAAS,EAAC,QAAQ,GAAG,EACjC,CAAC,CAAC,yBAAyB,CAAC,IACtB,IACQ,IACb,CACT,CAAC;AACJ,CAAC","sourcesContent":["import { useT } from \"@agent-native/core/client/i18n\";\nimport { IconAlertTriangle, IconRefresh } from \"@tabler/icons-react\";\n\nimport { Alert, AlertDescription, AlertTitle } from \"./ui/alert\";\nimport { Button } from \"./ui/button\";\n\ninterface ActionQueryErrorProps {\n error?: unknown;\n onRetry: () => unknown;\n className?: string;\n queryName?: string;\n}\n\nfunction actionQueryDiagnostic(\n error: unknown,\n queryName: string | undefined,\n): string | null {\n const parts: string[] = [];\n if (queryName) parts.push(queryName);\n\n if (error && typeof error === \"object\") {\n const details = error as Record<string, unknown>;\n const status =\n typeof details.statusCode === \"number\"\n ? details.statusCode\n : details.status;\n if (\n typeof status === \"number\" &&\n Number.isInteger(status) &&\n status >= 100 &&\n status <= 599\n ) {\n parts.push(`HTTP ${status}`);\n }\n\n const code = details.errorCode ?? details.code;\n if (typeof code === \"string\" && /^[a-zA-Z0-9_.-]{1,80}$/.test(code)) {\n parts.push(code);\n }\n }\n\n return parts.length > 0 ? parts.join(\" · \") : null;\n}\n\nexport function ActionQueryError({\n error,\n onRetry,\n className,\n queryName,\n}: ActionQueryErrorProps) {\n const t = useT();\n const diagnostic = actionQueryDiagnostic(error, queryName);\n\n return (\n <Alert variant=\"destructive\" className={className}>\n <IconAlertTriangle className=\"size-4\" />\n <AlertTitle>{t(\"dispatch.pages.dataLoadFailed\")}</AlertTitle>\n <AlertDescription className=\"flex flex-wrap items-center justify-between gap-3\">\n <span>{t(\"dispatch.pages.dataLoadFailedDescription\")}</span>\n {diagnostic ? (\n <code className=\"w-full break-all text-xs text-muted-foreground\">\n {diagnostic}\n </code>\n ) : null}\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={onRetry}>\n <IconRefresh className=\"size-4\" />\n {t(\"dispatch.pages.tryAgain\")}\n </Button>\n </AlertDescription>\n </Alert>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-home-apps.d.ts","sourceRoot":"","sources":["../../src/components/chat-home-apps.tsx"],"names":[],"mappings":"AA0BA,wBAAgB,oBAAoB,2DAuInC"}
1
+ {"version":3,"file":"chat-home-apps.d.ts","sourceRoot":"","sources":["../../src/components/chat-home-apps.tsx"],"names":[],"mappings":"AA0BA,wBAAgB,oBAAoB,2DA4InC"}
@@ -29,11 +29,11 @@ export function DispatchChatHomeApps() {
29
29
  if (!launcher)
30
30
  return null;
31
31
  if (launcher.error && launcher.workspaceApps.length === 0) {
32
- return (_jsx("div", { className: "mx-auto w-full max-w-[1000px]", children: _jsx(ActionQueryError, { error: launcher.error, onRetry: launcher.retry }) }));
32
+ return (_jsx("div", { className: "mx-auto w-full max-w-[1000px]", children: _jsx(ActionQueryError, { error: launcher.error, onRetry: launcher.retry, queryName: launcher.errorQueryName }) }));
33
33
  }
34
34
  if (!launcher.isLoading && launcher.workspaceApps.length === 0)
35
35
  return null;
36
- return (_jsxs("div", { className: "mx-auto w-full max-w-[1000px]", children: [launcher.error ? (_jsx(ActionQueryError, { error: launcher.error, onRetry: launcher.retry, className: "mb-3" })) : null, _jsxs("section", { "aria-label": t("dispatch.nav.apps"), children: [_jsxs("header", { className: "mb-3 flex flex-wrap items-center justify-between gap-3", children: [_jsx("h2", { className: "text-sm font-semibold text-foreground", children: t("dispatch.nav.apps") }), _jsxs("div", { className: "flex min-w-0 flex-1 items-center justify-end gap-2 sm:flex-none", children: [_jsx(WorkspaceAppSearch, { query: query, onQueryChange: setQuery, className: "w-full max-w-[280px]" }), _jsx(CreateAppPopover, { align: "end", onCreated: launcher.retry, trigger: _jsxs(Button, { type: "button", size: "sm", variant: "outline", children: [_jsx(IconPlus, { size: 16, "aria-hidden": "true" }), t("dispatch.pages.chatFirstNewApp")] }) })] })] }), launcher.isLoading && launcher.workspaceApps.length === 0 ? (_jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: Array.from({ length: 6 }, (_, index) => (_jsxs("div", { className: "flex min-w-0 items-center gap-3 rounded-xl bg-muted/30 px-3 py-2.5", children: [_jsx(Skeleton, { className: "size-7 rounded-lg" }), _jsxs("div", { className: "min-w-0 flex-1 space-y-1.5", children: [_jsx(Skeleton, { className: "h-4 w-20" }), _jsx(Skeleton, { className: "h-3 w-40 max-w-full" })] }), _jsx(Skeleton, { className: "h-7 w-20" })] }, index))) })) : apps.length > 0 ? (_jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: apps.map(({ app, description }) => {
36
+ return (_jsxs("div", { className: "mx-auto w-full max-w-[1000px]", children: [launcher.error ? (_jsx(ActionQueryError, { error: launcher.error, onRetry: launcher.retry, className: "mb-3", queryName: launcher.errorQueryName })) : null, _jsxs("section", { "aria-label": t("dispatch.nav.apps"), children: [_jsxs("header", { className: "mb-3 flex flex-wrap items-center justify-between gap-3", children: [_jsx("h2", { className: "text-sm font-semibold text-foreground", children: t("dispatch.nav.apps") }), _jsxs("div", { className: "flex min-w-0 flex-1 items-center justify-end gap-2 sm:flex-none", children: [_jsx(WorkspaceAppSearch, { query: query, onQueryChange: setQuery, className: "w-full max-w-[280px]" }), _jsx(CreateAppPopover, { align: "end", onCreated: launcher.retry, trigger: _jsxs(Button, { type: "button", size: "sm", variant: "outline", children: [_jsx(IconPlus, { size: 16, "aria-hidden": "true" }), t("dispatch.pages.chatFirstNewApp")] }) })] })] }), launcher.isLoading && launcher.workspaceApps.length === 0 ? (_jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: Array.from({ length: 6 }, (_, index) => (_jsxs("div", { className: "flex min-w-0 items-center gap-3 rounded-xl bg-muted/30 px-3 py-2.5", children: [_jsx(Skeleton, { className: "size-7 rounded-lg" }), _jsxs("div", { className: "min-w-0 flex-1 space-y-1.5", children: [_jsx(Skeleton, { className: "h-4 w-20" }), _jsx(Skeleton, { className: "h-3 w-40 max-w-full" })] }), _jsx(Skeleton, { className: "h-7 w-20" })] }, index))) })) : apps.length > 0 ? (_jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: apps.map(({ app, description }) => {
37
37
  const href = workspaceAppHref(app);
38
38
  return (_jsxs("article", { className: "flex min-w-0 items-center gap-3 rounded-xl bg-muted/30 px-3 py-2.5 transition-colors hover:bg-muted/50", children: [_jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [_jsx(AppIcon, { id: app.id, name: app.name, size: "sm" }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block truncate text-sm font-semibold text-foreground", children: app.name }), description ? (_jsx("span", { className: "mt-0.5 block truncate text-xs text-muted-foreground", children: description })) : null] })] }), _jsx(AppOpenActions, { name: app.name, href: href, onOpen: () => launcher.openApp(app), showNewTabOption: Boolean(href), labels: {
39
39
  openApp: t("dispatch.pages.openApp", {