@agent-native/dispatch 0.8.17 → 0.8.18
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/dist/actions/create-workspace-resource-grant.js +1 -1
- package/dist/actions/create-workspace-resource-grant.js.map +1 -1
- package/dist/actions/create-workspace-resource.js +5 -7
- package/dist/actions/create-workspace-resource.js.map +1 -1
- package/dist/actions/grant-workspace-resources-to-app.js +1 -1
- package/dist/actions/grant-workspace-resources-to-app.js.map +1 -1
- package/dist/actions/list-workspace-resource-grants.js +1 -1
- package/dist/actions/list-workspace-resource-grants.js.map +1 -1
- package/dist/actions/list-workspace-resource-options.js +1 -1
- package/dist/actions/list-workspace-resource-options.js.map +1 -1
- package/dist/actions/list-workspace-resources.js +2 -2
- package/dist/actions/list-workspace-resources.js.map +1 -1
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/db/schema.js +2 -2
- package/dist/db/schema.js.map +1 -1
- package/dist/routes/pages/workspace.d.ts.map +1 -1
- package/dist/routes/pages/workspace.js +18 -5
- package/dist/routes/pages/workspace.js.map +1 -1
- package/dist/server/lib/workspace-resources-store.d.ts +2 -1
- package/dist/server/lib/workspace-resources-store.d.ts.map +1 -1
- package/dist/server/lib/workspace-resources-store.js +7 -1
- package/dist/server/lib/workspace-resources-store.js.map +1 -1
- package/dist/server/plugins/integrations.js +2 -2
- package/dist/server/plugins/integrations.js.map +1 -1
- package/package.json +1 -1
- package/src/actions/create-workspace-resource-grant.ts +1 -1
- package/src/actions/create-workspace-resource.ts +7 -7
- package/src/actions/grant-workspace-resources-to-app.ts +1 -1
- package/src/actions/list-workspace-resource-grants.ts +1 -1
- package/src/actions/list-workspace-resource-options.ts +1 -1
- package/src/actions/list-workspace-resources.ts +2 -2
- package/src/components/create-app-popover.tsx +1 -1
- package/src/db/schema.ts +2 -2
- package/src/routes/pages/workspace.tsx +41 -7
- package/src/server/lib/workspace-resources-store.spec.ts +2 -0
- package/src/server/lib/workspace-resources-store.ts +13 -5
- package/src/server/plugins/integrations.ts +2 -2
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
IconEdit,
|
|
12
12
|
IconFileText,
|
|
13
13
|
IconPlus,
|
|
14
|
+
IconPlugConnected,
|
|
14
15
|
IconTrash,
|
|
15
16
|
IconUser,
|
|
16
17
|
IconX,
|
|
@@ -87,6 +88,13 @@ const KIND_CONFIG = {
|
|
|
87
88
|
description:
|
|
88
89
|
"Reference resources - brand, positioning, persona, and domain context",
|
|
89
90
|
},
|
|
91
|
+
"mcp-server": {
|
|
92
|
+
label: "MCP Server",
|
|
93
|
+
icon: IconPlugConnected,
|
|
94
|
+
pathPrefix: "mcp-servers/",
|
|
95
|
+
description:
|
|
96
|
+
"HTTP MCP servers - external tools centrally granted to app agents",
|
|
97
|
+
},
|
|
90
98
|
} as const;
|
|
91
99
|
|
|
92
100
|
const STARTER_GLOBAL_CONTEXT = [
|
|
@@ -135,6 +143,7 @@ function defaultResourcePath(kind: string, name: string): string {
|
|
|
135
143
|
if (kind === "instruction") return `instructions/${slug}.md`;
|
|
136
144
|
if (kind === "agent") return `agents/${slug}.md`;
|
|
137
145
|
if (kind === "knowledge") return `context/${slug}.md`;
|
|
146
|
+
if (kind === "mcp-server") return `mcp-servers/${slug}.json`;
|
|
138
147
|
return `${slug}.md`;
|
|
139
148
|
}
|
|
140
149
|
|
|
@@ -347,8 +356,8 @@ function AddResourceDialog() {
|
|
|
347
356
|
<DialogHeader>
|
|
348
357
|
<DialogTitle>Add workspace resource</DialogTitle>
|
|
349
358
|
<DialogDescription>
|
|
350
|
-
Create a skill, instruction, agent profile,
|
|
351
|
-
that can be shared across workspace apps.
|
|
359
|
+
Create a skill, instruction, agent profile, reference resource, or
|
|
360
|
+
MCP server that can be shared across workspace apps.
|
|
352
361
|
</DialogDescription>
|
|
353
362
|
</DialogHeader>
|
|
354
363
|
<div className="space-y-4 py-2">
|
|
@@ -364,6 +373,7 @@ function AddResourceDialog() {
|
|
|
364
373
|
<SelectItem value="instruction">Instruction</SelectItem>
|
|
365
374
|
<SelectItem value="agent">Agent</SelectItem>
|
|
366
375
|
<SelectItem value="knowledge">Knowledge pack</SelectItem>
|
|
376
|
+
<SelectItem value="mcp-server">MCP server</SelectItem>
|
|
367
377
|
</SelectContent>
|
|
368
378
|
</Select>
|
|
369
379
|
</div>
|
|
@@ -390,7 +400,9 @@ function AddResourceDialog() {
|
|
|
390
400
|
? "Research Specialist"
|
|
391
401
|
: kind === "knowledge"
|
|
392
402
|
? "Core GTM Messaging"
|
|
393
|
-
:
|
|
403
|
+
: kind === "mcp-server"
|
|
404
|
+
? "Zapier MCP"
|
|
405
|
+
: "Code Style Guide"
|
|
394
406
|
}
|
|
395
407
|
value={name}
|
|
396
408
|
onChange={(e) => setName(e.target.value)}
|
|
@@ -407,7 +419,9 @@ function AddResourceDialog() {
|
|
|
407
419
|
<p className="text-xs text-muted-foreground">
|
|
408
420
|
Skills use skills/name/SKILL.md. Guardrails in AGENTS.md or
|
|
409
421
|
instructions/ auto-load in app chat. Reference resources in
|
|
410
|
-
context/ are indexed so agents can read them when relevant.
|
|
422
|
+
context/ are indexed so agents can read them when relevant. MCP
|
|
423
|
+
server resources use mcp-servers/name.json and are loaded as HTTP
|
|
424
|
+
MCP tools.
|
|
411
425
|
</p>
|
|
412
426
|
</div>
|
|
413
427
|
<div className="space-y-2">
|
|
@@ -428,7 +442,9 @@ function AddResourceDialog() {
|
|
|
428
442
|
? "---\nname: Research Specialist\ndescription: Handles research tasks\n---\n\n# Instructions\n\n..."
|
|
429
443
|
: kind === "knowledge"
|
|
430
444
|
? "# Core GTM Messaging\n\n## Positioning\n\n## ICP\n\n## Proof points\n\n## Source\n\n"
|
|
431
|
-
:
|
|
445
|
+
: kind === "mcp-server"
|
|
446
|
+
? '{\n "type": "http",\n "url": "https://example.com/mcp",\n "headers": {\n "Authorization": "Bearer ${keys.MCP_SERVER_TOKEN}"\n },\n "description": "Shared MCP tools for workspace apps"\n}\n'
|
|
447
|
+
: "# Instructions\n\nAlways-on guardrails for agents across apps..."
|
|
432
448
|
}
|
|
433
449
|
value={content}
|
|
434
450
|
onChange={(e) => setContent(e.target.value)}
|
|
@@ -447,7 +463,12 @@ function AddResourceDialog() {
|
|
|
447
463
|
<Button
|
|
448
464
|
onClick={() =>
|
|
449
465
|
create.mutate({
|
|
450
|
-
kind: kind as
|
|
466
|
+
kind: kind as
|
|
467
|
+
| "skill"
|
|
468
|
+
| "instruction"
|
|
469
|
+
| "agent"
|
|
470
|
+
| "knowledge"
|
|
471
|
+
| "mcp-server",
|
|
451
472
|
name,
|
|
452
473
|
description: description || undefined,
|
|
453
474
|
path: path || defaultResourcePath(kind, name),
|
|
@@ -1010,6 +1031,9 @@ export default function WorkspaceRoute() {
|
|
|
1010
1031
|
const knowledge = (resources || []).filter(
|
|
1011
1032
|
(r: any) => r.kind === "knowledge",
|
|
1012
1033
|
);
|
|
1034
|
+
const mcpServers = (resources || []).filter(
|
|
1035
|
+
(r: any) => r.kind === "mcp-server",
|
|
1036
|
+
);
|
|
1013
1037
|
|
|
1014
1038
|
function ResourceList({
|
|
1015
1039
|
items,
|
|
@@ -1056,7 +1080,7 @@ export default function WorkspaceRoute() {
|
|
|
1056
1080
|
return (
|
|
1057
1081
|
<DispatchShell
|
|
1058
1082
|
title="Workspace Resources"
|
|
1059
|
-
description="Manage inherited workspace skills, guardrail instructions, agent profiles, and
|
|
1083
|
+
description="Manage inherited workspace skills, guardrail instructions, agent profiles, reference resources, and MCP servers. All-app resources are available to every app without syncing."
|
|
1060
1084
|
>
|
|
1061
1085
|
<div className="flex items-center justify-between">
|
|
1062
1086
|
<div className="text-sm text-muted-foreground">
|
|
@@ -1087,6 +1111,9 @@ export default function WorkspaceRoute() {
|
|
|
1087
1111
|
<TabsTrigger value="knowledge">
|
|
1088
1112
|
Knowledge {knowledge.length > 0 && `(${knowledge.length})`}
|
|
1089
1113
|
</TabsTrigger>
|
|
1114
|
+
<TabsTrigger value="mcp">
|
|
1115
|
+
MCP {mcpServers.length > 0 && `(${mcpServers.length})`}
|
|
1116
|
+
</TabsTrigger>
|
|
1090
1117
|
</TabsList>
|
|
1091
1118
|
|
|
1092
1119
|
<TabsContent value="skills" className="mt-4">
|
|
@@ -1116,6 +1143,13 @@ export default function WorkspaceRoute() {
|
|
|
1116
1143
|
emptyText="No knowledge packs yet. Add GTM, product, or domain context that apps can reuse."
|
|
1117
1144
|
/>
|
|
1118
1145
|
</TabsContent>
|
|
1146
|
+
|
|
1147
|
+
<TabsContent value="mcp" className="mt-4">
|
|
1148
|
+
<ResourceList
|
|
1149
|
+
items={mcpServers}
|
|
1150
|
+
emptyText="No workspace MCP servers yet. Add an HTTP MCP server to share external tools across apps."
|
|
1151
|
+
/>
|
|
1152
|
+
</TabsContent>
|
|
1119
1153
|
</Tabs>
|
|
1120
1154
|
</DispatchShell>
|
|
1121
1155
|
);
|
|
@@ -703,6 +703,7 @@ describe("workspace resource materialization", () => {
|
|
|
703
703
|
expect(mocks.resourceEffectiveContext).toHaveBeenCalledWith(
|
|
704
704
|
"person@example.test",
|
|
705
705
|
"context/brand.md",
|
|
706
|
+
{ workspaceAppId: "analytics", orgId: "org_123" },
|
|
706
707
|
);
|
|
707
708
|
expect(mocks.resourcePut).toHaveBeenCalledWith(
|
|
708
709
|
"__workspace__",
|
|
@@ -899,6 +900,7 @@ describe("workspace resource materialization", () => {
|
|
|
899
900
|
expect(mocks.resourceEffectiveContext).toHaveBeenCalledWith(
|
|
900
901
|
"owner@example.test",
|
|
901
902
|
"context/analytics-launch.md",
|
|
903
|
+
{ workspaceAppId: "analytics", orgId: "org_123" },
|
|
902
904
|
);
|
|
903
905
|
});
|
|
904
906
|
|
|
@@ -186,7 +186,8 @@ export type WorkspaceResourceKind =
|
|
|
186
186
|
| "skill"
|
|
187
187
|
| "instruction"
|
|
188
188
|
| "agent"
|
|
189
|
-
| "knowledge"
|
|
189
|
+
| "knowledge"
|
|
190
|
+
| "mcp-server";
|
|
190
191
|
export type WorkspaceResourceScope = "all" | "selected";
|
|
191
192
|
|
|
192
193
|
export interface WorkspaceResourceInput {
|
|
@@ -969,10 +970,6 @@ export async function getWorkspaceResourceEffectiveContext(input: {
|
|
|
969
970
|
await materializeGlobalResource(row);
|
|
970
971
|
}
|
|
971
972
|
|
|
972
|
-
const coreContext: EffectiveResourceContext = await resourceEffectiveContext(
|
|
973
|
-
userEmail,
|
|
974
|
-
path,
|
|
975
|
-
);
|
|
976
973
|
const resource = row ? workspaceResourceOption(row) : null;
|
|
977
974
|
const activeGrant =
|
|
978
975
|
resource?.scope === "selected" && appId
|
|
@@ -985,6 +982,15 @@ export async function getWorkspaceResourceEffectiveContext(input: {
|
|
|
985
982
|
appId,
|
|
986
983
|
activeGrantId: activeGrant?.id ?? null,
|
|
987
984
|
});
|
|
985
|
+
const resolveEffectiveContext = resourceEffectiveContext as (
|
|
986
|
+
userEmail: string,
|
|
987
|
+
path: string,
|
|
988
|
+
options?: { workspaceAppId?: string | null; orgId?: string | null },
|
|
989
|
+
) => Promise<EffectiveResourceContext>;
|
|
990
|
+
const coreContext = await resolveEffectiveContext(userEmail, path, {
|
|
991
|
+
workspaceAppId: appId,
|
|
992
|
+
orgId: ctx.orgId,
|
|
993
|
+
});
|
|
988
994
|
|
|
989
995
|
return {
|
|
990
996
|
appId,
|
|
@@ -1373,6 +1379,7 @@ export async function listWorkspaceResourcesOverview() {
|
|
|
1373
1379
|
const instructions = resources.filter((r) => r.kind === "instruction");
|
|
1374
1380
|
const agents = resources.filter((r) => r.kind === "agent");
|
|
1375
1381
|
const knowledge = resources.filter((r) => r.kind === "knowledge");
|
|
1382
|
+
const mcpServers = resources.filter((r) => r.kind === "mcp-server");
|
|
1376
1383
|
const activeGrants = grants.filter((g) => g.status === "active");
|
|
1377
1384
|
|
|
1378
1385
|
return {
|
|
@@ -1380,6 +1387,7 @@ export async function listWorkspaceResourcesOverview() {
|
|
|
1380
1387
|
instructionCount: instructions.length,
|
|
1381
1388
|
agentCount: agents.length,
|
|
1382
1389
|
knowledgeCount: knowledge.length,
|
|
1390
|
+
mcpServerCount: mcpServers.length,
|
|
1383
1391
|
totalResources: resources.length,
|
|
1384
1392
|
activeGrantCount: activeGrants.length,
|
|
1385
1393
|
};
|
|
@@ -10,7 +10,7 @@ const DISPATCH_INTEGRATION_SYSTEM_PROMPT = `You are the central dispatch for thi
|
|
|
10
10
|
|
|
11
11
|
Default posture:
|
|
12
12
|
- Treat Slack, Telegram, and email as shared entrypoints into the workspace.
|
|
13
|
-
- Heavily delegate domain work to specialized agents through A2A (call-agent) when another app owns the job. Apps you can delegate to include slides (decks/presentations), analytics (data/dashboards), content (docs/articles), videos (Remotion compositions), forms (form builder), clips (screen recordings), design (visual designs), and
|
|
13
|
+
- Heavily delegate domain work to specialized agents through A2A (call-agent) when another app owns the job. Apps you can delegate to include slides (decks/presentations), analytics (data/dashboards), content (docs/articles), videos (Remotion compositions), forms (form builder), clips (screen recordings), design (visual designs), and assets (brand libraries plus generated images/videos).
|
|
14
14
|
- Use the available-apps prompt context first, then list-connected-agents when you need fresh details, to see what agents are available before assuming a request must be handled locally.
|
|
15
15
|
- When asked whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. Without that probe, missing agent-card fields mean unchecked, not unavailable.
|
|
16
16
|
- Treat first-party apps such as Mail, Calendar, Analytics, Brain, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.
|
|
@@ -18,7 +18,7 @@ Default posture:
|
|
|
18
18
|
- Reply in the originating thread unless the user explicitly asks you to send to a saved destination.
|
|
19
19
|
|
|
20
20
|
When a user asks for something:
|
|
21
|
-
- If it belongs to analytics, content, slides, videos,
|
|
21
|
+
- If it belongs to analytics, content, slides, videos, assets, etc., delegate via call-agent — do not re-implement the domain logic in dispatch.
|
|
22
22
|
- After call-agent returns an answer, RELAY IT DIRECTLY to the user with at most a one-line preface — do not rephrase, summarize, or add commentary. The downstream agent already crafted the answer; your job is delivery, not editing. This minimizes round-trips and keeps the user-visible reply fast.
|
|
23
23
|
- Exception: if the downstream agent reports a missing model/provider credential, do not name exact env vars, Vault keys, tokens, or secrets. Say the target app needs an LLM connection and recommend connecting Builder/managed LLM for that app; keep bring-your-own provider keys as a secondary option only if the user asks.
|
|
24
24
|
- If the user asks to create, build, make, scaffold, or generate an "agent" from Dispatch chat or by tagging @agent-native in Slack, email, or Telegram, first classify the ask. If it is a simple Dispatch-native behavior like a reminder, digest, monitor, routing rule, saved instruction, or recurring workflow, create or update the recurring job/resource/destination in Dispatch. If it is a robust unique product or teammate that needs its own UI, data model, actions, integrations, or domain workflow, treat it as a new workspace app and call start-workspace-app-creation.
|