@agent-native/dispatch 0.24.6 → 0.25.1
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.
- package/README.md +12 -1
- package/dist/actions/connect-external-agent.d.ts +18 -0
- package/dist/actions/connect-external-agent.d.ts.map +1 -0
- package/dist/actions/connect-external-agent.js +68 -0
- package/dist/actions/connect-external-agent.js.map +1 -0
- package/dist/actions/create-workspace-resource.d.ts +14 -14
- package/dist/actions/create-workspace-resource.js +9 -2
- package/dist/actions/create-workspace-resource.js.map +1 -1
- package/dist/actions/create_workspace_app_embed_session.d.ts +13 -0
- package/dist/actions/create_workspace_app_embed_session.d.ts.map +1 -0
- package/dist/actions/create_workspace_app_embed_session.js +30 -0
- package/dist/actions/create_workspace_app_embed_session.js.map +1 -0
- package/dist/actions/import-agent-pack.d.ts +96 -0
- package/dist/actions/import-agent-pack.d.ts.map +1 -0
- package/dist/actions/import-agent-pack.js +116 -0
- package/dist/actions/import-agent-pack.js.map +1 -0
- package/dist/actions/import-agent.d.ts +60 -0
- package/dist/actions/import-agent.d.ts.map +1 -0
- package/dist/actions/import-agent.js +82 -0
- package/dist/actions/import-agent.js.map +1 -0
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +10 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/list-agent-pack.d.ts +36 -0
- package/dist/actions/list-agent-pack.d.ts.map +1 -0
- package/dist/actions/list-agent-pack.js +32 -0
- package/dist/actions/list-agent-pack.js.map +1 -0
- package/dist/actions/list-workspace-resource-options.d.ts +1 -1
- package/dist/actions/list-workspace-resource-options.js +8 -1
- package/dist/actions/list-workspace-resource-options.js.map +1 -1
- package/dist/actions/list-workspace-resources.d.ts +1 -1
- package/dist/actions/list-workspace-resources.js +8 -1
- package/dist/actions/list-workspace-resources.js.map +1 -1
- package/dist/actions/navigate.js +1 -1
- package/dist/actions/navigate.js.map +1 -1
- package/dist/actions/provider-api-register.d.ts +10 -10
- package/dist/actions/update-workspace-resource.d.ts +13 -13
- package/dist/actions/view-screen.js +18 -1
- package/dist/actions/view-screen.js.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/layout/Layout.d.ts +1 -8
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +33 -106
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/simple-agents-panel.d.ts +9 -0
- package/dist/components/simple-agents-panel.d.ts.map +1 -0
- package/dist/components/simple-agents-panel.js +405 -0
- package/dist/components/simple-agents-panel.js.map +1 -0
- package/dist/components/workspace-app-host.d.ts +29 -0
- package/dist/components/workspace-app-host.d.ts.map +1 -0
- package/dist/components/workspace-app-host.js +145 -0
- package/dist/components/workspace-app-host.js.map +1 -0
- package/dist/db/migrations.d.ts +2 -4
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +25 -0
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/schema.js +1 -1
- package/dist/db/schema.js.map +1 -1
- package/dist/hooks/use-navigation-state.d.ts +1 -0
- package/dist/hooks/use-navigation-state.d.ts.map +1 -1
- package/dist/hooks/use-navigation-state.js +10 -0
- package/dist/hooks/use-navigation-state.js.map +1 -1
- package/dist/lib/agent-pack.d.ts +31 -0
- package/dist/lib/agent-pack.d.ts.map +1 -0
- package/dist/lib/agent-pack.js +149 -0
- package/dist/lib/agent-pack.js.map +1 -0
- package/dist/lib/simple-agent-profile.d.ts +36 -0
- package/dist/lib/simple-agent-profile.d.ts.map +1 -0
- package/dist/lib/simple-agent-profile.js +183 -0
- package/dist/lib/simple-agent-profile.js.map +1 -0
- package/dist/routes/pages/agents.d.ts.map +1 -1
- package/dist/routes/pages/agents.js +11 -1
- package/dist/routes/pages/agents.js.map +1 -1
- package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
- package/dist/routes/pages/apps.$appId.js +4 -95
- package/dist/routes/pages/apps.$appId.js.map +1 -1
- package/dist/routes/pages/chat.d.ts.map +1 -1
- package/dist/routes/pages/chat.js +62 -10
- package/dist/routes/pages/chat.js.map +1 -1
- package/dist/server/lib/agent-pack-store.d.ts +24 -0
- package/dist/server/lib/agent-pack-store.d.ts.map +1 -0
- package/dist/server/lib/agent-pack-store.js +22 -0
- package/dist/server/lib/agent-pack-store.js.map +1 -0
- package/dist/server/lib/dispatch-store.d.ts.map +1 -1
- package/dist/server/lib/dispatch-store.js +4 -0
- package/dist/server/lib/dispatch-store.js.map +1 -1
- package/dist/server/lib/mcp-gateway.d.ts +11 -0
- package/dist/server/lib/mcp-gateway.d.ts.map +1 -1
- package/dist/server/lib/mcp-gateway.js +155 -9
- package/dist/server/lib/mcp-gateway.js.map +1 -1
- package/dist/server/lib/workspace-resources-store.d.ts +15 -1
- package/dist/server/lib/workspace-resources-store.d.ts.map +1 -1
- package/dist/server/lib/workspace-resources-store.js +11 -2
- package/dist/server/lib/workspace-resources-store.js.map +1 -1
- package/dist/server/plugins/agent-chat.js +13 -0
- package/dist/server/plugins/agent-chat.js.map +1 -1
- package/dist/shared/feature-flags.d.ts +7 -0
- package/dist/shared/feature-flags.d.ts.map +1 -0
- package/dist/shared/feature-flags.js +12 -0
- package/dist/shared/feature-flags.js.map +1 -0
- package/dist/shared/workspace-sso.d.ts +36 -0
- package/dist/shared/workspace-sso.d.ts.map +1 -0
- package/dist/shared/workspace-sso.js +99 -0
- package/dist/shared/workspace-sso.js.map +1 -0
- package/package.json +5 -3
- package/src/actions/connect-external-agent.ts +92 -0
- package/src/actions/create-workspace-resource.ts +9 -2
- package/src/actions/create_workspace_app_embed_session.ts +32 -0
- package/src/actions/import-agent-pack.ts +146 -0
- package/src/actions/import-agent.ts +102 -0
- package/src/actions/index.spec.ts +13 -0
- package/src/actions/index.ts +10 -0
- package/src/actions/list-agent-pack.ts +43 -0
- package/src/actions/list-workspace-resource-options.ts +8 -1
- package/src/actions/list-workspace-resources.ts +8 -1
- package/src/actions/navigate.ts +1 -1
- package/src/actions/view-screen.spec.ts +29 -1
- package/src/actions/view-screen.ts +19 -1
- package/src/components/app-icon.spec.tsx +10 -0
- package/src/components/index.ts +1 -0
- package/src/components/layout/Layout.spec.tsx +2 -0
- package/src/components/layout/Layout.tsx +59 -171
- package/src/components/simple-agents-panel.spec.tsx +73 -0
- package/src/components/simple-agents-panel.tsx +1226 -0
- package/src/components/workspace-app-host.spec.tsx +204 -0
- package/src/components/workspace-app-host.tsx +359 -0
- package/src/db/migrations.spec.ts +5 -1
- package/src/db/migrations.ts +28 -1
- package/src/db/schema.ts +1 -1
- package/src/hooks/use-navigation-state.spec.ts +25 -0
- package/src/hooks/use-navigation-state.ts +11 -0
- package/src/lib/agent-pack.spec.ts +47 -0
- package/src/lib/agent-pack.ts +226 -0
- package/src/lib/simple-agent-profile.spec.ts +77 -0
- package/src/lib/simple-agent-profile.ts +247 -0
- package/src/routes/index.spec.ts +1 -0
- package/src/routes/pages/agents.tsx +21 -1
- package/src/routes/pages/apps.$appId.tsx +3 -240
- package/src/routes/pages/chat.spec.tsx +62 -0
- package/src/routes/pages/chat.tsx +117 -9
- package/src/server/lib/agent-pack-store.ts +35 -0
- package/src/server/lib/dispatch-store.ts +8 -0
- package/src/server/lib/mcp-gateway.spec.ts +141 -0
- package/src/server/lib/mcp-gateway.ts +227 -15
- package/src/server/lib/workspace-resources-store.ts +9 -2
- package/src/server/plugins/agent-chat.ts +13 -0
- package/src/shared/feature-flags.ts +13 -0
- package/src/shared/workspace-sso.ts +118 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-sso.js","sourceRoot":"","sources":["../../src/shared/workspace-sso.ts"],"names":[],"mappings":"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","sourcesContent":["import { DISPATCH_WORKSPACE_SSO_FLAG } from \"./feature-flags.js\";\n\nexport { DISPATCH_WORKSPACE_SSO_FLAG };\n\n/** Exact first-party origins. Never replace this with a suffix or wildcard. */\nexport const CANONICAL_WORKSPACE_SSO_APP_ORIGINS = {\n analytics: \"https://analytics.agent-native.com\",\n assets: \"https://assets.agent-native.com\",\n brain: \"https://brain.agent-native.com\",\n calendar: \"https://calendar.agent-native.com\",\n chat: \"https://chat.agent-native.com\",\n clips: \"https://clips.agent-native.com\",\n content: \"https://content.agent-native.com\",\n crm: \"https://crm.agent-native.com\",\n design: \"https://design.agent-native.com\",\n dispatch: \"https://dispatch.agent-native.com\",\n forms: \"https://forms.agent-native.com\",\n macros: \"https://macros.agent-native.com\",\n mail: \"https://mail.agent-native.com\",\n plan: \"https://plan.agent-native.com\",\n slides: \"https://slides.agent-native.com\",\n tasks: \"https://tasks.agent-native.com\",\n} as const;\n\nexport const WORKSPACE_SSO_CALLBACK_PATH =\n \"/_agent-native/identity/callback\" as const;\n\nconst CONTROL_CHARS = /[\\u0000-\\u001f\\u007f]/;\nconst APP_ID = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\nconst CLIENT_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;\nconst LOCALHOST_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"[::1]\", \"::1\"]);\n\nexport interface WorkspaceSsoAppRegistration {\n appId: string;\n clientId: string;\n origin: string;\n callbackPath: typeof WORKSPACE_SSO_CALLBACK_PATH;\n}\n\nexport function exactWorkspaceSsoOrigin(raw: unknown): string | null {\n if (typeof raw !== \"string\" || !raw || CONTROL_CHARS.test(raw)) return null;\n try {\n const url = new URL(raw);\n if (\n url.protocol !== \"https:\" &&\n !(url.protocol === \"http:\" && LOCALHOST_HOSTS.has(url.hostname))\n ) {\n return null;\n }\n if (\n url.username ||\n url.password ||\n url.pathname !== \"/\" ||\n url.search ||\n url.hash\n ) {\n return null;\n }\n return url.origin;\n } catch {\n // coercion-ok: malformed registry origins are rejected as absent.\n return null;\n }\n}\n\n/**\n * Parse the same additive custom registry used by browser identity SSO. The\n * raw value is passed in so this shared module stays safe to import in the\n * browser bundle.\n */\nexport function parseWorkspaceSsoAppRegistrations(\n raw: unknown,\n): WorkspaceSsoAppRegistration[] {\n if (typeof raw !== \"string\" || !raw.trim()) return [];\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n // coercion-ok: malformed custom registry data must fail closed.\n return [];\n }\n if (!Array.isArray(value)) return [];\n\n const registrations: WorkspaceSsoAppRegistration[] = [];\n const seen = new Set<string>();\n for (const entry of value) {\n if (!entry || typeof entry !== \"object\") continue;\n const candidate = entry as Record<string, unknown>;\n const appId = candidate.appId;\n const clientId = candidate.clientId;\n const origin = exactWorkspaceSsoOrigin(candidate.origin);\n if (\n typeof appId !== \"string\" ||\n !APP_ID.test(appId) ||\n typeof clientId !== \"string\" ||\n !CLIENT_ID.test(clientId) ||\n !origin ||\n candidate.callbackPath !== WORKSPACE_SSO_CALLBACK_PATH ||\n !Array.isArray(candidate.capabilities) ||\n !candidate.capabilities.includes(\"identity-sso\") ||\n seen.has(appId) ||\n Object.prototype.hasOwnProperty.call(\n CANONICAL_WORKSPACE_SSO_APP_ORIGINS,\n appId,\n )\n ) {\n continue;\n }\n seen.add(appId);\n registrations.push({\n appId,\n clientId,\n origin,\n callbackPath: WORKSPACE_SSO_CALLBACK_PATH,\n });\n }\n return registrations;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/dispatch",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"description": "Dispatch — workspace control plane for agent-native apps. Vault, integrations, destinations, scheduled jobs, and cross-app delegation, shipped as a single drop-in package.",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
"./routes/pages/*": "./dist/routes/pages/*.js",
|
|
30
30
|
"./server": "./dist/server/index.js",
|
|
31
31
|
"./shared/app-roles": "./dist/shared/app-roles.js",
|
|
32
|
+
"./shared/feature-flags": "./dist/shared/feature-flags.js",
|
|
33
|
+
"./shared/workspace-sso": "./dist/shared/workspace-sso.js",
|
|
32
34
|
"./server/lib/thread-link-preview": "./dist/server/lib/thread-link-preview.js",
|
|
33
35
|
"./actions": "./dist/actions/index.js",
|
|
34
36
|
"./db": "./dist/db/index.js",
|
|
@@ -85,7 +87,7 @@
|
|
|
85
87
|
"tailwind-merge": "^3.5.0",
|
|
86
88
|
"vaul": "^1.1.2",
|
|
87
89
|
"zod": "^4.3.6",
|
|
88
|
-
"@agent-native/toolkit": "0.
|
|
90
|
+
"@agent-native/toolkit": "0.15.0"
|
|
89
91
|
},
|
|
90
92
|
"devDependencies": {
|
|
91
93
|
"@react-router/dev": "^8.1.0",
|
|
@@ -99,7 +101,7 @@
|
|
|
99
101
|
"typescript-7": "npm:typescript@^7.0.2",
|
|
100
102
|
"vite": "8.1.0",
|
|
101
103
|
"vitest": "^4.1.5",
|
|
102
|
-
"@agent-native/core": "0.
|
|
104
|
+
"@agent-native/core": "0.157.0"
|
|
103
105
|
},
|
|
104
106
|
"peerDependencies": {
|
|
105
107
|
"@agent-native/core": ">=0.8.0",
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { getDbExec } from "@agent-native/core/db";
|
|
3
|
+
import {
|
|
4
|
+
resourceGetByPath,
|
|
5
|
+
resourcePut,
|
|
6
|
+
sharedResourceOwner,
|
|
7
|
+
} from "@agent-native/core/resources/store";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
currentOrgId,
|
|
12
|
+
currentOwnerEmail,
|
|
13
|
+
} from "../server/lib/dispatch-store.js";
|
|
14
|
+
|
|
15
|
+
function slugify(value: string): string {
|
|
16
|
+
return (
|
|
17
|
+
value
|
|
18
|
+
.trim()
|
|
19
|
+
.toLowerCase()
|
|
20
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
21
|
+
.replace(/^-+|-+$/g, "") || "agent"
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function assertCanManageSharedAgent() {
|
|
26
|
+
const orgId = currentOrgId();
|
|
27
|
+
if (!orgId) return;
|
|
28
|
+
const actor = currentOwnerEmail().trim().toLowerCase();
|
|
29
|
+
const result = await getDbExec().execute({
|
|
30
|
+
sql: "SELECT role FROM org_members WHERE org_id = ? AND LOWER(email) = ? LIMIT 1",
|
|
31
|
+
args: [orgId, actor],
|
|
32
|
+
});
|
|
33
|
+
const role = result.rows[0]?.role;
|
|
34
|
+
if (role !== "owner" && role !== "admin") {
|
|
35
|
+
throw new Error(
|
|
36
|
+
"Only organization owners and admins can connect shared agents.",
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default defineAction({
|
|
42
|
+
description:
|
|
43
|
+
"Connect an existing HTTP/A2A agent to Dispatch. This stores only its public endpoint and metadata; authentication remains in the normal A2A/MCP connection flow.",
|
|
44
|
+
schema: z.object({
|
|
45
|
+
url: z.string().min(1).describe("HTTP or HTTPS agent endpoint"),
|
|
46
|
+
name: z.string().max(160).optional().describe("Agent name"),
|
|
47
|
+
description: z.string().max(500).optional().describe("Short description"),
|
|
48
|
+
scope: z
|
|
49
|
+
.enum(["shared", "personal"])
|
|
50
|
+
.default("shared")
|
|
51
|
+
.describe("Share with the workspace or keep the connection personal"),
|
|
52
|
+
}),
|
|
53
|
+
run: async ({ url, name, description, scope }) => {
|
|
54
|
+
const parsed = new URL(url.trim());
|
|
55
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
56
|
+
throw new Error("Use an http:// or https:// endpoint URL.");
|
|
57
|
+
}
|
|
58
|
+
if (parsed.username || parsed.password) {
|
|
59
|
+
throw new Error("Do not include credentials in the endpoint URL.");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (scope === "shared") await assertCanManageSharedAgent();
|
|
63
|
+
const agentName = name?.trim() || parsed.hostname.replace(/^www\./, "");
|
|
64
|
+
const id = slugify(agentName);
|
|
65
|
+
const path = `remote-agents/${id}.json`;
|
|
66
|
+
const owner =
|
|
67
|
+
scope === "shared"
|
|
68
|
+
? sharedResourceOwner(currentOrgId())
|
|
69
|
+
: currentOwnerEmail();
|
|
70
|
+
const existing = await resourceGetByPath(owner, path);
|
|
71
|
+
if (existing) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`An external agent already exists at ${path}. Rename it before connecting again.`,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const manifest = {
|
|
78
|
+
id,
|
|
79
|
+
name: agentName,
|
|
80
|
+
...(description?.trim() ? { description: description.trim() } : {}),
|
|
81
|
+
url: parsed.toString(),
|
|
82
|
+
};
|
|
83
|
+
const resource = await resourcePut(
|
|
84
|
+
owner,
|
|
85
|
+
path,
|
|
86
|
+
JSON.stringify(manifest, null, 2),
|
|
87
|
+
"application/json",
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return { status: "created" as const, resource, agent: manifest, scope };
|
|
91
|
+
},
|
|
92
|
+
});
|
|
@@ -8,9 +8,16 @@ export default defineAction({
|
|
|
8
8
|
'Create a workspace-wide skill, instruction, agent profile, reference resource, or MCP server. Set scope to "all" for runtime inheritance by every app, or "selected" to grant per-app. When Dispatch approval policy is enabled, All-app creates queue an approval request before taking effect.',
|
|
9
9
|
schema: z.object({
|
|
10
10
|
kind: z
|
|
11
|
-
.enum([
|
|
11
|
+
.enum([
|
|
12
|
+
"skill",
|
|
13
|
+
"instruction",
|
|
14
|
+
"agent",
|
|
15
|
+
"agent-file",
|
|
16
|
+
"knowledge",
|
|
17
|
+
"mcp-server",
|
|
18
|
+
])
|
|
12
19
|
.describe(
|
|
13
|
-
"Resource kind: skill, instruction, agent, knowledge, or mcp-server",
|
|
20
|
+
"Resource kind: skill, instruction, agent, agent-file, knowledge, or mcp-server",
|
|
14
21
|
),
|
|
15
22
|
name: z.string().describe("Human-readable name"),
|
|
16
23
|
description: z.string().optional().describe("Short description"),
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
import { createWorkspaceSsoEmbedSession } from "../server/lib/mcp-gateway.js";
|
|
5
|
+
|
|
6
|
+
export default defineAction({
|
|
7
|
+
description:
|
|
8
|
+
"Create a one-time app-scoped embed session for a workspace app opened inside Dispatch. This browser-only path is rollout-gated and never exposes an app's reusable session to another app.",
|
|
9
|
+
schema: z.object({
|
|
10
|
+
app: z
|
|
11
|
+
.string()
|
|
12
|
+
.optional()
|
|
13
|
+
.describe("Workspace app id when path is app-relative."),
|
|
14
|
+
url: z
|
|
15
|
+
.string()
|
|
16
|
+
.optional()
|
|
17
|
+
.describe("Absolute app URL or app-relative path."),
|
|
18
|
+
path: z
|
|
19
|
+
.string()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("App-relative path. Requires app when url is not provided."),
|
|
22
|
+
chrome: z
|
|
23
|
+
.enum(["full", "minimal"])
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("Embed chrome preference. Defaults to full."),
|
|
26
|
+
}),
|
|
27
|
+
readOnly: false,
|
|
28
|
+
parallelSafe: false,
|
|
29
|
+
agentTool: false,
|
|
30
|
+
toolCallable: false,
|
|
31
|
+
run: async (args) => createWorkspaceSsoEmbedSession(args),
|
|
32
|
+
});
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import { defineAction } from "@agent-native/core";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
AGENT_PACK_MAX_FILE_BYTES,
|
|
8
|
+
AGENT_PACK_MAX_FILES,
|
|
9
|
+
agentPackProfileContent,
|
|
10
|
+
agentPackRoot,
|
|
11
|
+
normalizeAgentPack,
|
|
12
|
+
type AgentPackFileInput,
|
|
13
|
+
} from "../lib/agent-pack.js";
|
|
14
|
+
import { validateImportedAgentTools } from "../lib/simple-agent-profile.js";
|
|
15
|
+
import { applyAgentPackCreate } from "../server/lib/agent-pack-store.js";
|
|
16
|
+
import {
|
|
17
|
+
createApprovalRequest,
|
|
18
|
+
getApprovalPolicy,
|
|
19
|
+
} from "../server/lib/dispatch-store.js";
|
|
20
|
+
import {
|
|
21
|
+
listWorkspaceResources,
|
|
22
|
+
type WorkspaceResourceInput,
|
|
23
|
+
} from "../server/lib/workspace-resources-store.js";
|
|
24
|
+
|
|
25
|
+
const packFileSchema = z.object({
|
|
26
|
+
path: z.string().trim().min(1).max(240),
|
|
27
|
+
content: z.string().max(AGENT_PACK_MAX_FILE_BYTES),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const schema = z.object({
|
|
31
|
+
files: z
|
|
32
|
+
.array(packFileSchema)
|
|
33
|
+
.min(1)
|
|
34
|
+
.max(AGENT_PACK_MAX_FILES)
|
|
35
|
+
.describe("Text files from an agent folder, including its profile"),
|
|
36
|
+
scope: z
|
|
37
|
+
.enum(["all", "selected"])
|
|
38
|
+
.default("all")
|
|
39
|
+
.describe("Make the pack available to all apps or selected apps"),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
function availableToolNames(dispatchToolNames: string[]): Set<string> {
|
|
43
|
+
return new Set([
|
|
44
|
+
...dispatchToolNames,
|
|
45
|
+
"agent-teams",
|
|
46
|
+
"bash",
|
|
47
|
+
"call-agent",
|
|
48
|
+
"db-query",
|
|
49
|
+
"db-schema",
|
|
50
|
+
"refresh-screen",
|
|
51
|
+
"resources",
|
|
52
|
+
"set-search-params",
|
|
53
|
+
"set-url-path",
|
|
54
|
+
"tool-search",
|
|
55
|
+
"web-request",
|
|
56
|
+
"web-search",
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default defineAction({
|
|
61
|
+
description:
|
|
62
|
+
"Import a folder-backed agent pack from Claude, Cowork, or another agent tool. The pack can include a Markdown/JSON profile, context, references, and skills. Credentials, hooks, shell commands, and local environment settings are never imported.",
|
|
63
|
+
schema,
|
|
64
|
+
run: async ({ files, scope }) => {
|
|
65
|
+
const normalized = normalizeAgentPack(files as AgentPackFileInput[]);
|
|
66
|
+
const { dispatchActions } = await import("./index.js");
|
|
67
|
+
const toolValidation = validateImportedAgentTools(
|
|
68
|
+
normalized.profile.tools,
|
|
69
|
+
availableToolNames(Object.keys(dispatchActions)),
|
|
70
|
+
);
|
|
71
|
+
const warnings = [...normalized.warnings, ...toolValidation.warnings];
|
|
72
|
+
const sourceHash = crypto
|
|
73
|
+
.createHash("sha256")
|
|
74
|
+
.update(JSON.stringify(files))
|
|
75
|
+
.digest("hex");
|
|
76
|
+
const profileContent = agentPackProfileContent({
|
|
77
|
+
profile: normalized.profile,
|
|
78
|
+
tools: toolValidation.tools,
|
|
79
|
+
sourceHash,
|
|
80
|
+
importedAt: new Date().toISOString(),
|
|
81
|
+
});
|
|
82
|
+
const root = agentPackRoot(normalized.profile.slug);
|
|
83
|
+
const inputs: WorkspaceResourceInput[] = [
|
|
84
|
+
{
|
|
85
|
+
kind: "agent",
|
|
86
|
+
name: normalized.profile.name,
|
|
87
|
+
description: normalized.profile.description,
|
|
88
|
+
path: `${root}.md`,
|
|
89
|
+
content: profileContent,
|
|
90
|
+
scope,
|
|
91
|
+
},
|
|
92
|
+
...normalized.files.map((file) => ({
|
|
93
|
+
kind: file.kind,
|
|
94
|
+
name: file.name,
|
|
95
|
+
description: file.description,
|
|
96
|
+
path: `${root}/${file.path}`,
|
|
97
|
+
content: file.content,
|
|
98
|
+
scope,
|
|
99
|
+
})),
|
|
100
|
+
];
|
|
101
|
+
const existing = await listWorkspaceResources();
|
|
102
|
+
const existingProfile = existing.find(
|
|
103
|
+
(resource) => resource.path === `${root}.md`,
|
|
104
|
+
);
|
|
105
|
+
if (existingProfile?.content.includes(`source-hash: ${sourceHash}`)) {
|
|
106
|
+
return {
|
|
107
|
+
status: "unchanged" as const,
|
|
108
|
+
resource: existingProfile,
|
|
109
|
+
files: existing.filter((resource) =>
|
|
110
|
+
resource.path.startsWith(`${root}/`),
|
|
111
|
+
),
|
|
112
|
+
warnings,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (existingProfile) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`An agent already exists at ${root}. Rename the source before importing it.`,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const policy = await getApprovalPolicy();
|
|
122
|
+
if (scope === "all" && policy.enabled) {
|
|
123
|
+
const approval = await createApprovalRequest({
|
|
124
|
+
changeType: "workspace-agent-pack.create",
|
|
125
|
+
targetType: "workspace-agent-pack",
|
|
126
|
+
summary: `Import All-app agent pack "${normalized.profile.name}"`,
|
|
127
|
+
payload: { inputs },
|
|
128
|
+
beforeValue: null,
|
|
129
|
+
afterValue: {
|
|
130
|
+
name: normalized.profile.name,
|
|
131
|
+
path: `${root}.md`,
|
|
132
|
+
fileCount: inputs.length,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
return { status: "pending-approval" as const, approval, warnings };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const created = await applyAgentPackCreate(inputs);
|
|
139
|
+
return {
|
|
140
|
+
status: "created" as const,
|
|
141
|
+
resource: created[0] ?? null,
|
|
142
|
+
files: created.slice(1),
|
|
143
|
+
warnings,
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import { defineAction } from "@agent-native/core";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
buildSimpleAgentContent,
|
|
8
|
+
normalizeImportedAgent,
|
|
9
|
+
validateImportedAgentTools,
|
|
10
|
+
} from "../lib/simple-agent-profile.js";
|
|
11
|
+
import {
|
|
12
|
+
createWorkspaceResource,
|
|
13
|
+
listWorkspaceResources,
|
|
14
|
+
} from "../server/lib/workspace-resources-store.js";
|
|
15
|
+
|
|
16
|
+
export default defineAction({
|
|
17
|
+
description:
|
|
18
|
+
"Import a Claude-style Markdown agent or a generic JSON agent definition into a reusable Dispatch agent profile. Credentials, shell commands, hooks, and local environment settings are never imported. Use connect-external-agent for an HTTP/A2A endpoint.",
|
|
19
|
+
schema: z.object({
|
|
20
|
+
source: z
|
|
21
|
+
.string()
|
|
22
|
+
.min(1)
|
|
23
|
+
.max(200_000)
|
|
24
|
+
.describe("Pasted Markdown or JSON agent definition"),
|
|
25
|
+
fileName: z
|
|
26
|
+
.string()
|
|
27
|
+
.max(512)
|
|
28
|
+
.optional()
|
|
29
|
+
.describe("Original file name, such as .claude/agents/research.md"),
|
|
30
|
+
scope: z
|
|
31
|
+
.enum(["all", "selected"])
|
|
32
|
+
.default("all")
|
|
33
|
+
.describe("Make the profile available to all apps or selected apps"),
|
|
34
|
+
}),
|
|
35
|
+
run: async ({ source, fileName, scope }) => {
|
|
36
|
+
const normalized = normalizeImportedAgent(source, fileName);
|
|
37
|
+
const { dispatchActions } = await import("./index.js");
|
|
38
|
+
const availableToolNames = new Set([
|
|
39
|
+
...Object.keys(dispatchActions),
|
|
40
|
+
"agent-teams",
|
|
41
|
+
"bash",
|
|
42
|
+
"call-agent",
|
|
43
|
+
"db-query",
|
|
44
|
+
"db-schema",
|
|
45
|
+
"refresh-screen",
|
|
46
|
+
"resources",
|
|
47
|
+
"set-search-params",
|
|
48
|
+
"set-url-path",
|
|
49
|
+
"tool-search",
|
|
50
|
+
"web-request",
|
|
51
|
+
"web-search",
|
|
52
|
+
]);
|
|
53
|
+
const toolValidation = validateImportedAgentTools(
|
|
54
|
+
normalized.tools,
|
|
55
|
+
availableToolNames,
|
|
56
|
+
);
|
|
57
|
+
const warnings = [...normalized.warnings, ...toolValidation.warnings];
|
|
58
|
+
const sourceHash = crypto.createHash("sha256").update(source).digest("hex");
|
|
59
|
+
const content = buildSimpleAgentContent({
|
|
60
|
+
...normalized,
|
|
61
|
+
tools: toolValidation.tools,
|
|
62
|
+
source: normalized.source,
|
|
63
|
+
sourcePath: normalized.sourcePath,
|
|
64
|
+
sourceHash,
|
|
65
|
+
importedAt: new Date().toISOString(),
|
|
66
|
+
});
|
|
67
|
+
const path = `agents/${normalized.slug}.md`;
|
|
68
|
+
const existing = (await listWorkspaceResources({ kind: "agent" })).find(
|
|
69
|
+
(resource) => resource.path === path,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
if (existing) {
|
|
73
|
+
if (existing.content.includes(`source-hash: ${sourceHash}`)) {
|
|
74
|
+
return {
|
|
75
|
+
status: "unchanged" as const,
|
|
76
|
+
resource: existing,
|
|
77
|
+
source: normalized.source,
|
|
78
|
+
warnings,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
throw new Error(
|
|
82
|
+
`An agent already exists at ${path}. Rename the source before importing it.`,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const resource = await createWorkspaceResource({
|
|
87
|
+
kind: "agent",
|
|
88
|
+
name: normalized.name,
|
|
89
|
+
description: normalized.description,
|
|
90
|
+
path,
|
|
91
|
+
content,
|
|
92
|
+
scope,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
status: "created" as const,
|
|
97
|
+
resource,
|
|
98
|
+
source: normalized.source,
|
|
99
|
+
warnings,
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
});
|
|
@@ -5,6 +5,8 @@ import { dispatchActions } from "./index.js";
|
|
|
5
5
|
describe("dispatch action registry", () => {
|
|
6
6
|
it("keeps workspace resources runtime-inherited instead of exposing sync actions", () => {
|
|
7
7
|
expect(dispatchActions).toHaveProperty("list-workspace-resources-for-app");
|
|
8
|
+
expect(dispatchActions).toHaveProperty("connect-external-agent");
|
|
9
|
+
expect(dispatchActions).toHaveProperty("import-agent");
|
|
8
10
|
expect(dispatchActions).toHaveProperty("list-mcp-app-access");
|
|
9
11
|
expect(dispatchActions).toHaveProperty("set-mcp-app-access");
|
|
10
12
|
expect(dispatchActions).toHaveProperty("list_apps");
|
|
@@ -12,6 +14,9 @@ describe("dispatch action registry", () => {
|
|
|
12
14
|
expect(dispatchActions).toHaveProperty("ask_app_status");
|
|
13
15
|
expect(dispatchActions).toHaveProperty("open_app");
|
|
14
16
|
expect(dispatchActions).toHaveProperty("create_embed_session");
|
|
17
|
+
expect(dispatchActions).toHaveProperty(
|
|
18
|
+
"create-workspace-app-embed-session",
|
|
19
|
+
);
|
|
15
20
|
expect(dispatchActions).toHaveProperty("read-slack-thread-context");
|
|
16
21
|
expect(dispatchActions).toHaveProperty(
|
|
17
22
|
"get-workspace-resource-effective-context",
|
|
@@ -32,6 +37,14 @@ describe("dispatch action registry", () => {
|
|
|
32
37
|
).toEqual([]);
|
|
33
38
|
});
|
|
34
39
|
|
|
40
|
+
it("exposes folder-backed agent pack actions", () => {
|
|
41
|
+
expect(dispatchActions).toHaveProperty("import-agent-pack");
|
|
42
|
+
expect(dispatchActions).toHaveProperty("list-agent-pack");
|
|
43
|
+
expect(dispatchActions["import-agent-pack"].tool.description).toContain(
|
|
44
|
+
"folder-backed agent pack",
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
35
48
|
it("distinguishes mounted workspace apps from connected A2A agents", () => {
|
|
36
49
|
expect(dispatchActions["list-workspace-apps"].tool.description).toContain(
|
|
37
50
|
"not the hosted/connected A2A agent registry",
|
package/src/actions/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import approveVaultRequest from "./approve-vault-request.js";
|
|
|
6
6
|
import archiveWorkspaceApp from "./archive-workspace-app.js";
|
|
7
7
|
import askApp from "./ask_app.js";
|
|
8
8
|
import askAppStatus from "./ask_app_status.js";
|
|
9
|
+
import connectExternalAgent from "./connect-external-agent.js";
|
|
9
10
|
import createBrowserChatSession from "./create-browser-chat-session.js";
|
|
10
11
|
import createDreamReport from "./create-dream-report.js";
|
|
11
12
|
import createLinkToken from "./create-link-token.js";
|
|
@@ -15,6 +16,7 @@ import createVaultSecret from "./create-vault-secret.js";
|
|
|
15
16
|
import createWorkspaceResourceGrant from "./create-workspace-resource-grant.js";
|
|
16
17
|
import createWorkspaceResource from "./create-workspace-resource.js";
|
|
17
18
|
import createEmbedSession from "./create_embed_session.js";
|
|
19
|
+
import createWorkspaceAppEmbedSession from "./create_workspace_app_embed_session.js";
|
|
18
20
|
import deleteDestination from "./delete-destination.js";
|
|
19
21
|
import deleteStagedDataset from "./delete-staged-dataset.js";
|
|
20
22
|
import deleteVaultSecret from "./delete-vault-secret.js";
|
|
@@ -31,6 +33,9 @@ import getWorkspaceInfo from "./get-workspace-info.js";
|
|
|
31
33
|
import getWorkspaceResourceEffectiveContext from "./get-workspace-resource-effective-context.js";
|
|
32
34
|
import grantVaultSecretsToApp from "./grant-vault-secrets-to-app.js";
|
|
33
35
|
import grantWorkspaceResourcesToApp from "./grant-workspace-resources-to-app.js";
|
|
36
|
+
import importAgentPack from "./import-agent-pack.js";
|
|
37
|
+
import importAgent from "./import-agent.js";
|
|
38
|
+
import listAgentPack from "./list-agent-pack.js";
|
|
34
39
|
import listAgentRunFailures from "./list-agent-run-failures.js";
|
|
35
40
|
import listAgentThreadSources from "./list-agent-thread-sources.js";
|
|
36
41
|
import listAvailableWorkspaceTemplates from "./list-available-workspace-templates.js";
|
|
@@ -107,6 +112,7 @@ export const dispatchActions: Record<string, ActionEntry> = {
|
|
|
107
112
|
"archive-workspace-app": archiveWorkspaceApp,
|
|
108
113
|
ask_app: askApp,
|
|
109
114
|
ask_app_status: askAppStatus,
|
|
115
|
+
"connect-external-agent": connectExternalAgent,
|
|
110
116
|
"create-link-token": createLinkToken,
|
|
111
117
|
"create-pylon-ticket": createPylonTicket,
|
|
112
118
|
"create-vault-grant": createVaultGrant,
|
|
@@ -116,6 +122,7 @@ export const dispatchActions: Record<string, ActionEntry> = {
|
|
|
116
122
|
"create-dream-report": createDreamReport,
|
|
117
123
|
"create-browser-chat-session": createBrowserChatSession,
|
|
118
124
|
create_embed_session: createEmbedSession,
|
|
125
|
+
"create-workspace-app-embed-session": createWorkspaceAppEmbedSession,
|
|
119
126
|
"delete-staged-dataset": deleteStagedDataset,
|
|
120
127
|
"delete-destination": deleteDestination,
|
|
121
128
|
"delete-vault-secret": deleteVaultSecret,
|
|
@@ -160,6 +167,9 @@ export const dispatchActions: Record<string, ActionEntry> = {
|
|
|
160
167
|
"list-workspace-resource-grants": listWorkspaceResourceGrants,
|
|
161
168
|
"list-workspace-resources-for-app": listWorkspaceResourcesForApp,
|
|
162
169
|
"list-workspace-resources": listWorkspaceResources,
|
|
170
|
+
"import-agent": importAgent,
|
|
171
|
+
"import-agent-pack": importAgentPack,
|
|
172
|
+
"list-agent-pack": listAgentPack,
|
|
163
173
|
navigate: navigate,
|
|
164
174
|
open_app: openApp,
|
|
165
175
|
"apply-dream-proposal": applyDreamProposal,
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
import { agentPackRoot } from "../lib/agent-pack.js";
|
|
5
|
+
import { listWorkspaceResources } from "../server/lib/workspace-resources-store.js";
|
|
6
|
+
|
|
7
|
+
const schema = z
|
|
8
|
+
.object({
|
|
9
|
+
agentId: z.string().trim().min(1).optional(),
|
|
10
|
+
path: z.string().trim().min(1).optional(),
|
|
11
|
+
})
|
|
12
|
+
.refine((input) => Boolean(input.agentId || input.path), {
|
|
13
|
+
message: "Provide an agentId or path.",
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export default defineAction({
|
|
17
|
+
description:
|
|
18
|
+
"List the files in a reusable agent pack, including its profile, reference files, context files, and agent-owned skills.",
|
|
19
|
+
schema,
|
|
20
|
+
http: { method: "GET" },
|
|
21
|
+
run: async ({ agentId, path }) => {
|
|
22
|
+
const resources = await listWorkspaceResources();
|
|
23
|
+
const profile = resources.find(
|
|
24
|
+
(resource) =>
|
|
25
|
+
resource.kind === "agent" &&
|
|
26
|
+
(agentId ? resource.id === agentId : resource.path === path),
|
|
27
|
+
);
|
|
28
|
+
if (!profile) throw new Error("Agent profile not found");
|
|
29
|
+
|
|
30
|
+
const root = agentPackRoot(
|
|
31
|
+
profile.path.replace(/^agents\//, "").replace(/\.md$/i, ""),
|
|
32
|
+
);
|
|
33
|
+
const files = resources.filter(
|
|
34
|
+
(resource) =>
|
|
35
|
+
resource.id !== profile.id && resource.path.startsWith(`${root}/`),
|
|
36
|
+
);
|
|
37
|
+
return {
|
|
38
|
+
profile,
|
|
39
|
+
root,
|
|
40
|
+
files,
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
});
|
|
@@ -8,7 +8,14 @@ export default defineAction({
|
|
|
8
8
|
"List lightweight workspace resource options for selectors, without returning full content.",
|
|
9
9
|
schema: z.object({
|
|
10
10
|
kind: z
|
|
11
|
-
.enum([
|
|
11
|
+
.enum([
|
|
12
|
+
"skill",
|
|
13
|
+
"instruction",
|
|
14
|
+
"agent",
|
|
15
|
+
"agent-file",
|
|
16
|
+
"knowledge",
|
|
17
|
+
"mcp-server",
|
|
18
|
+
])
|
|
12
19
|
.optional()
|
|
13
20
|
.describe("Filter by resource kind"),
|
|
14
21
|
}),
|
|
@@ -8,7 +8,14 @@ export default defineAction({
|
|
|
8
8
|
"List all workspace-wide resources (skills, instructions, agent profiles, reference resources, and MCP servers) that apps inherit at runtime.",
|
|
9
9
|
schema: z.object({
|
|
10
10
|
kind: z
|
|
11
|
-
.enum([
|
|
11
|
+
.enum([
|
|
12
|
+
"skill",
|
|
13
|
+
"instruction",
|
|
14
|
+
"agent",
|
|
15
|
+
"agent-file",
|
|
16
|
+
"knowledge",
|
|
17
|
+
"mcp-server",
|
|
18
|
+
])
|
|
12
19
|
.optional()
|
|
13
20
|
.describe("Filter by resource kind"),
|
|
14
21
|
}),
|
package/src/actions/navigate.ts
CHANGED
|
@@ -27,7 +27,7 @@ export default defineAction({
|
|
|
27
27
|
.string()
|
|
28
28
|
.optional()
|
|
29
29
|
.describe(
|
|
30
|
-
"Named dispatch view to navigate to. Built-in views include chat, overview, apps, operations (or monitoring, observability, database), metrics, new-app, vault, integrations, messaging, workspace, agents, destinations, identities, approvals, automations, audit, thread-debug, dreams, and team. Generated Dispatch extension tabs can also use their nav item id.",
|
|
30
|
+
"Named dispatch view to navigate to. Built-in views include chat, overview, apps, operations (or monitoring, observability, database), metrics, new-app, vault, integrations, messaging, workspace, agents, connected-agents, destinations, identities, approvals, automations, audit, thread-debug, dreams, and team. Generated Dispatch extension tabs can also use their nav item id.",
|
|
31
31
|
),
|
|
32
32
|
path: z.string().optional().describe("URL path to navigate to"),
|
|
33
33
|
threadId: z
|
|
@@ -4,6 +4,7 @@ const mocks = vi.hoisted(() => ({
|
|
|
4
4
|
navigation: {} as Record<string, unknown>,
|
|
5
5
|
listAgentRunFailures: vi.fn(),
|
|
6
6
|
listThreadDebugSources: vi.fn(),
|
|
7
|
+
listWorkspaceResourceOptions: vi.fn(),
|
|
7
8
|
}));
|
|
8
9
|
|
|
9
10
|
vi.mock("@agent-native/core", () => ({
|
|
@@ -46,7 +47,7 @@ vi.mock("../server/lib/vault-store.js", () => ({
|
|
|
46
47
|
}));
|
|
47
48
|
|
|
48
49
|
vi.mock("../server/lib/workspace-resources-store.js", () => ({
|
|
49
|
-
listWorkspaceResourceOptions:
|
|
50
|
+
listWorkspaceResourceOptions: mocks.listWorkspaceResourceOptions,
|
|
50
51
|
listWorkspaceResourcesForApp: vi.fn(),
|
|
51
52
|
}));
|
|
52
53
|
|
|
@@ -59,6 +60,8 @@ describe("view-screen Thread Debug summary", () => {
|
|
|
59
60
|
mocks.listAgentRunFailures.mockResolvedValue({ failures: [] });
|
|
60
61
|
mocks.listThreadDebugSources.mockReset();
|
|
61
62
|
mocks.listThreadDebugSources.mockResolvedValue({ sources: [] });
|
|
63
|
+
mocks.listWorkspaceResourceOptions.mockReset();
|
|
64
|
+
mocks.listWorkspaceResourceOptions.mockResolvedValue([]);
|
|
62
65
|
});
|
|
63
66
|
|
|
64
67
|
it("matches the UI's default 24-hour failed-run range", async () => {
|
|
@@ -89,4 +92,29 @@ describe("view-screen Thread Debug summary", () => {
|
|
|
89
92
|
}),
|
|
90
93
|
);
|
|
91
94
|
});
|
|
95
|
+
|
|
96
|
+
it("surfaces the focused simple agent on the chat screen", async () => {
|
|
97
|
+
mocks.navigation = {
|
|
98
|
+
view: "chat",
|
|
99
|
+
agentPath: "agents/research-partner.md",
|
|
100
|
+
};
|
|
101
|
+
mocks.listWorkspaceResourceOptions.mockResolvedValue([
|
|
102
|
+
{
|
|
103
|
+
id: "agent-1",
|
|
104
|
+
kind: "agent",
|
|
105
|
+
name: "Research Partner",
|
|
106
|
+
description: "Synthesizes research",
|
|
107
|
+
path: "agents/research-partner.md",
|
|
108
|
+
scope: "all",
|
|
109
|
+
updatedAt: 1,
|
|
110
|
+
},
|
|
111
|
+
]);
|
|
112
|
+
|
|
113
|
+
const result = JSON.parse(await viewScreen.run({}));
|
|
114
|
+
|
|
115
|
+
expect(result.chatSurface).toMatchObject({
|
|
116
|
+
agentPath: "agents/research-partner.md",
|
|
117
|
+
agent: { id: "agent-1", name: "Research Partner" },
|
|
118
|
+
});
|
|
119
|
+
});
|
|
92
120
|
});
|