@agent-native/dispatch 0.13.13 → 0.14.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/dist/actions/delete-destination.d.ts +12 -12
- package/dist/actions/navigate.js +1 -1
- package/dist/actions/navigate.js.map +1 -1
- package/dist/actions/provider-api-audit.d.ts +7 -0
- package/dist/actions/provider-api-audit.d.ts.map +1 -0
- package/dist/actions/provider-api-audit.js +74 -0
- package/dist/actions/provider-api-audit.js.map +1 -0
- package/dist/actions/provider-api-catalog.d.ts +1 -1
- package/dist/actions/provider-api-request.js +10 -0
- package/dist/actions/provider-api-request.js.map +1 -1
- package/dist/actions/send-platform-message.d.ts +1 -0
- package/dist/actions/send-platform-message.js +43 -22
- package/dist/actions/send-platform-message.js.map +1 -1
- package/dist/actions/view-screen.js +9 -0
- package/dist/actions/view-screen.js.map +1 -1
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +75 -70
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/messaging-setup-panel.d.ts.map +1 -1
- package/dist/components/messaging-setup-panel.js +203 -127
- package/dist/components/messaging-setup-panel.js.map +1 -1
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +1 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/pages/messaging.js +1 -1
- package/dist/routes/pages/messaging.js.map +1 -1
- package/dist/routes/pages/operations.d.ts +5 -0
- package/dist/routes/pages/operations.d.ts.map +1 -0
- package/dist/routes/pages/operations.js +51 -0
- package/dist/routes/pages/operations.js.map +1 -0
- package/dist/routes/pages/overview.d.ts +2 -2
- package/dist/server/lib/dispatch-integrations.d.ts +7 -1
- package/dist/server/lib/dispatch-integrations.d.ts.map +1 -1
- package/dist/server/lib/dispatch-integrations.js +178 -8
- package/dist/server/lib/dispatch-integrations.js.map +1 -1
- package/dist/server/lib/dispatch-routing.d.ts +6 -0
- package/dist/server/lib/dispatch-routing.d.ts.map +1 -0
- package/dist/server/lib/dispatch-routing.js +30 -0
- package/dist/server/lib/dispatch-routing.js.map +1 -0
- package/dist/server/lib/env-config.d.ts.map +1 -1
- package/dist/server/lib/env-config.js +50 -0
- package/dist/server/lib/env-config.js.map +1 -1
- package/dist/server/lib/onboarding-steps.d.ts.map +1 -1
- package/dist/server/lib/onboarding-steps.js +25 -0
- package/dist/server/lib/onboarding-steps.js.map +1 -1
- package/dist/server/lib/provider-api.d.ts +2 -2
- package/dist/server/lib/provider-api.d.ts.map +1 -1
- package/dist/server/plugins/integrations.d.ts.map +1 -1
- package/dist/server/plugins/integrations.js +5 -2
- package/dist/server/plugins/integrations.js.map +1 -1
- package/package.json +2 -2
- package/src/actions/navigate.ts +1 -1
- package/src/actions/provider-api-audit.spec.ts +52 -0
- package/src/actions/provider-api-audit.ts +88 -0
- package/src/actions/provider-api-request.ts +10 -0
- package/src/actions/send-platform-message.spec.ts +108 -0
- package/src/actions/send-platform-message.ts +73 -25
- package/src/actions/view-screen.ts +11 -0
- package/src/components/layout/Layout.spec.tsx +154 -0
- package/src/components/layout/Layout.tsx +196 -189
- package/src/components/messaging-setup-panel.spec.tsx +191 -0
- package/src/components/messaging-setup-panel.tsx +472 -193
- package/src/routes/index.spec.ts +23 -0
- package/src/routes/index.ts +1 -0
- package/src/routes/pages/messaging.tsx +1 -1
- package/src/routes/pages/operations.tsx +134 -0
- package/src/server/lib/dispatch-integrations.spec.ts +113 -0
- package/src/server/lib/dispatch-integrations.ts +239 -6
- package/src/server/lib/dispatch-routing.spec.ts +44 -0
- package/src/server/lib/dispatch-routing.ts +42 -0
- package/src/server/lib/env-config.ts +50 -0
- package/src/server/lib/onboarding-steps.ts +32 -0
- package/src/server/plugins/integrations.ts +5 -2
- package/src/styles/dispatch-css.spec.ts +11 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { dispatchIntegrationRoutingHint } from "./dispatch-routing.js";
|
|
4
|
+
|
|
5
|
+
describe("dispatchIntegrationRoutingHint", () => {
|
|
6
|
+
it.each([
|
|
7
|
+
"File a security review request for the platform team",
|
|
8
|
+
"Add this hiring ask to the intake board",
|
|
9
|
+
"Add two design tasks for the launch page",
|
|
10
|
+
"Create a design task for the new onboarding flow",
|
|
11
|
+
"Create a vendor request form with the required fields",
|
|
12
|
+
"What is currently in the editorial requests queue?",
|
|
13
|
+
])(
|
|
14
|
+
"resolves structured intake through workspace capabilities: %s",
|
|
15
|
+
(text) => {
|
|
16
|
+
const hint = dispatchIntegrationRoutingHint(text);
|
|
17
|
+
expect(hint?.targetAgent).toBeUndefined();
|
|
18
|
+
expect(hint?.instruction).toContain("workspace instructions/resources");
|
|
19
|
+
expect(hint?.instruction).toContain("do not assume a particular app");
|
|
20
|
+
},
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
it.each([
|
|
24
|
+
"Design a homepage for the launch",
|
|
25
|
+
"Create a visual mockup for this settings screen",
|
|
26
|
+
"Redesign the product UI",
|
|
27
|
+
])("routes visual output to Design: %s", (text) => {
|
|
28
|
+
expect(dispatchIntegrationRoutingHint(text)).toMatchObject({
|
|
29
|
+
targetAgent: "design",
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("lets unrelated domain questions use normal agent discovery", () => {
|
|
34
|
+
expect(
|
|
35
|
+
dispatchIntegrationRoutingHint(
|
|
36
|
+
"What were the reasons for closed-lost deals this quarter?",
|
|
37
|
+
),
|
|
38
|
+
).toBeUndefined();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("leaves organization-specific shorthand to learned workspace instructions", () => {
|
|
42
|
+
expect(dispatchIntegrationRoutingHint("Apoorva queue")).toBeUndefined();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const STRUCTURED_INTAKE_PATTERNS = [
|
|
2
|
+
/\b(?:file|submit|add|log|track|triage|prioriti[sz]e|create)\b.{0,64}\b(?:asks?|requests?|tickets?|tasks?|intake)\b/i,
|
|
3
|
+
/\b(?:asks?|requests?|tickets?|intake)\b.{0,64}\b(?:database|table|board|form|queue|priority|deadline|urgency)\b/i,
|
|
4
|
+
/\b(?:database|table|board|form|queue)\b.{0,64}\b(?:asks?|requests?|tickets?|intake|priority|deadline|urgency)\b/i,
|
|
5
|
+
];
|
|
6
|
+
|
|
7
|
+
const VISUAL_DESIGN_PATTERNS = [
|
|
8
|
+
/\b(?:design|redesign|create|make|generate|mock(?:\s+up)?)\b.{0,64}\b(?:visual|mockup|wireframe|screen|interface|ui|website|landing\s+page|homepage|logo|graphic|illustration)\b/i,
|
|
9
|
+
/\b(?:visual|ui|website|product|brand)\s+design\b/i,
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
export interface DispatchIntegrationRoutingHint {
|
|
13
|
+
targetAgent?: string;
|
|
14
|
+
instruction: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function dispatchIntegrationRoutingHint(
|
|
18
|
+
text: string,
|
|
19
|
+
): DispatchIntegrationRoutingHint | undefined {
|
|
20
|
+
const normalized = text.replace(/\s+/g, " ").trim();
|
|
21
|
+
if (!normalized) return undefined;
|
|
22
|
+
|
|
23
|
+
// Route by the requested artifact type, not organization-specific names.
|
|
24
|
+
// Exact destinations, schemas, and required fields come from workspace
|
|
25
|
+
// resources such as shared LEARNINGS.md rather than this classifier.
|
|
26
|
+
if (STRUCTURED_INTAKE_PATTERNS.some((pattern) => pattern.test(normalized))) {
|
|
27
|
+
return {
|
|
28
|
+
instruction:
|
|
29
|
+
"Resolve this structured-intake request from loaded workspace instructions/resources and discovered app capabilities. Follow any workspace-defined canonical destination and form contract; do not assume a particular app, database, schema, or owner. Preserve the source thread URL, submit once, verify the saved record, and return its exact link.",
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (VISUAL_DESIGN_PATTERNS.some((pattern) => pattern.test(normalized))) {
|
|
34
|
+
return {
|
|
35
|
+
targetAgent: "design",
|
|
36
|
+
instruction:
|
|
37
|
+
"Delegate to Design because the requested output is a visual design, mockup, or interface rather than an intake record.",
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
@@ -4,6 +4,16 @@ export const envKeys: EnvKeyConfig[] = [
|
|
|
4
4
|
{
|
|
5
5
|
key: "SLACK_BOT_TOKEN",
|
|
6
6
|
label: "Slack bot token",
|
|
7
|
+
required: false,
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
key: "SLACK_CLIENT_ID",
|
|
11
|
+
label: "Slack OAuth client ID",
|
|
12
|
+
required: true,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
key: "SLACK_CLIENT_SECRET",
|
|
16
|
+
label: "Slack OAuth client secret",
|
|
7
17
|
required: true,
|
|
8
18
|
},
|
|
9
19
|
{
|
|
@@ -16,6 +26,41 @@ export const envKeys: EnvKeyConfig[] = [
|
|
|
16
26
|
label: "Telegram bot token",
|
|
17
27
|
required: true,
|
|
18
28
|
},
|
|
29
|
+
{
|
|
30
|
+
key: "TELEGRAM_WEBHOOK_SECRET",
|
|
31
|
+
label: "Telegram webhook secret",
|
|
32
|
+
required: true,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
key: "MICROSOFT_TEAMS_APP_ID",
|
|
36
|
+
label: "Microsoft Bot app ID",
|
|
37
|
+
required: false,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
key: "MICROSOFT_TEAMS_APP_PASSWORD",
|
|
41
|
+
label: "Microsoft Bot client secret",
|
|
42
|
+
required: false,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
key: "MICROSOFT_TEAMS_APP_TENANT_ID",
|
|
46
|
+
label: "Microsoft Bot tenant ID",
|
|
47
|
+
required: false,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
key: "MICROSOFT_TEAMS_ALLOWED_TENANT_IDS",
|
|
51
|
+
label: "Allowed Microsoft Teams tenant IDs",
|
|
52
|
+
required: false,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
key: "DISCORD_APPLICATION_ID",
|
|
56
|
+
label: "Discord application ID",
|
|
57
|
+
required: false,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
key: "DISCORD_PUBLIC_KEY",
|
|
61
|
+
label: "Discord public key",
|
|
62
|
+
required: false,
|
|
63
|
+
},
|
|
19
64
|
{
|
|
20
65
|
key: "EMAIL_AGENT_ADDRESS",
|
|
21
66
|
label: "Agent email address",
|
|
@@ -41,6 +86,11 @@ export const envKeys: EnvKeyConfig[] = [
|
|
|
41
86
|
label: "WhatsApp phone number ID",
|
|
42
87
|
required: false,
|
|
43
88
|
},
|
|
89
|
+
{
|
|
90
|
+
key: "WHATSAPP_APP_SECRET",
|
|
91
|
+
label: "WhatsApp app secret",
|
|
92
|
+
required: false,
|
|
93
|
+
},
|
|
44
94
|
{
|
|
45
95
|
key: "PYLON_API_KEY",
|
|
46
96
|
label: "Pylon API key",
|
|
@@ -9,7 +9,12 @@
|
|
|
9
9
|
* their first workspace app first.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { listIntegrationInstallations } from "@agent-native/core/integrations";
|
|
12
13
|
import { registerOnboardingStep } from "@agent-native/core/onboarding";
|
|
14
|
+
import {
|
|
15
|
+
getRequestOrgId,
|
|
16
|
+
getRequestUserEmail,
|
|
17
|
+
} from "@agent-native/core/server/request-context";
|
|
13
18
|
|
|
14
19
|
import { listWorkspaceApps } from "./app-creation-store.js";
|
|
15
20
|
|
|
@@ -47,4 +52,31 @@ export function registerDispatchOnboardingSteps(): void {
|
|
|
47
52
|
}
|
|
48
53
|
},
|
|
49
54
|
});
|
|
55
|
+
|
|
56
|
+
registerOnboardingStep({
|
|
57
|
+
id: "dispatch:connect-slack-workspace",
|
|
58
|
+
title: "Connect a Slack workspace",
|
|
59
|
+
description:
|
|
60
|
+
"Install Agent Native with OAuth, then configure channel identities and access policies.",
|
|
61
|
+
order: 60,
|
|
62
|
+
required: false,
|
|
63
|
+
methods: [
|
|
64
|
+
{
|
|
65
|
+
id: "open-messaging",
|
|
66
|
+
kind: "link",
|
|
67
|
+
primary: true,
|
|
68
|
+
label: "Open Messaging",
|
|
69
|
+
payload: { url: "/messaging", external: false },
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
isComplete: async () => {
|
|
73
|
+
const userEmail = getRequestUserEmail();
|
|
74
|
+
if (!userEmail) return false;
|
|
75
|
+
const rows = await listIntegrationInstallations(
|
|
76
|
+
{ userEmail, orgId: getRequestOrgId() ?? null },
|
|
77
|
+
"slack",
|
|
78
|
+
).catch(() => []);
|
|
79
|
+
return rows.some((row) => row.status === "connected");
|
|
80
|
+
},
|
|
81
|
+
});
|
|
50
82
|
}
|
|
@@ -4,7 +4,7 @@ import { dispatchActions } from "../../actions/index.js";
|
|
|
4
4
|
import { getDispatchConfig } from "../index.js";
|
|
5
5
|
import {
|
|
6
6
|
beforeDispatchProcess,
|
|
7
|
-
|
|
7
|
+
resolveDispatchExecutionContext,
|
|
8
8
|
} from "../lib/dispatch-integrations.js";
|
|
9
9
|
|
|
10
10
|
const dispatchIntegrationActions = {
|
|
@@ -32,6 +32,9 @@ Default posture:
|
|
|
32
32
|
|
|
33
33
|
When a user asks for something:
|
|
34
34
|
- If it belongs to analytics, content, slides, clips, assets, etc., delegate via call-agent — do not re-implement the domain logic in dispatch.
|
|
35
|
+
- Synthetic uptime, health-check, and URL-availability monitors belong to Analytics, even when the monitored target is another app such as Clips. Delegate creation to Analytics and relay its exact monitor URL. Dispatch-native recurring jobs are for reminders, digests, and agent workflows, not HTTP uptime probes.
|
|
36
|
+
- Route by the requested artifact type, not by organization-specific names stored in code. For structured records, databases, tables, queues, boards, and intake forms, resolve the owning app and canonical destination from loaded workspace instructions/resources plus discovered app capabilities; do not assume Content, a database ID, schema, owner, or required fields. Visual designs, mockups, wireframes, screens, and interfaces belong to Design. A trusted Required target agent hint in integration context is authoritative.
|
|
37
|
+
- When delegating structured intake to the resolved owning app, preserve the exact Source thread URL and the workspace instruction context, inspect the destination's current required fields, ask only for missing values, submit once, verify the saved record, and return the exact link.
|
|
35
38
|
- In messaging integrations, use call-agent for cross-app delegation; do not use ask_app.
|
|
36
39
|
- 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.
|
|
37
40
|
- 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.
|
|
@@ -62,7 +65,7 @@ const dispatchIntegrationsPlugin = async (nitroApp: any) => {
|
|
|
62
65
|
const plugin = createIntegrationsPlugin({
|
|
63
66
|
appId: "dispatch",
|
|
64
67
|
actions: dispatchIntegrationActions,
|
|
65
|
-
|
|
68
|
+
resolveExecutionContext: resolveDispatchExecutionContext,
|
|
66
69
|
beforeProcess: beforeDispatchProcess,
|
|
67
70
|
systemPrompt,
|
|
68
71
|
// Inherit the framework default (claude-sonnet-4-6 from
|
|
@@ -62,4 +62,15 @@ describe("dispatch route shells", () => {
|
|
|
62
62
|
|
|
63
63
|
expect(chatRoute).toContain("@agent-native/dispatch/routes/pages/chat");
|
|
64
64
|
});
|
|
65
|
+
|
|
66
|
+
it("re-exports the operations console from the Dispatch template", () => {
|
|
67
|
+
const operationsRoute = fs.readFileSync(
|
|
68
|
+
path.join(repoRoot, "templates/dispatch/app/routes/operations.tsx"),
|
|
69
|
+
"utf-8",
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
expect(operationsRoute).toContain(
|
|
73
|
+
"@agent-native/dispatch/routes/pages/operations",
|
|
74
|
+
);
|
|
75
|
+
});
|
|
65
76
|
});
|