@agent-native/dispatch 0.40.11 → 0.40.12-nightly-20261002213029
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/CHANGELOG.md +20 -0
- package/dist/components/create-app-popover.d.ts.map +1 -1
- package/dist/components/create-app-popover.js +3 -1
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/server/lib/app-creation-store.d.ts.map +1 -1
- package/dist/server/lib/app-creation-store.js +11 -5
- package/dist/server/lib/app-creation-store.js.map +1 -1
- package/dist/server/lib/dreams-store.js +1 -1
- package/dist/server/lib/dreams-store.js.map +1 -1
- package/dist/server/plugins/integrations.js +1 -1
- package/dist/server/plugins/integrations.js.map +1 -1
- package/package.json +4 -4
- package/src/components/create-app-popover.spec.tsx +8 -10
- package/src/components/create-app-popover.tsx +3 -1
- package/src/server/lib/app-creation-store.spec.ts +40 -19
- package/src/server/lib/app-creation-store.ts +28 -19
- package/src/server/lib/dreams-store.ts +1 -1
- package/src/server/plugins/integrations.ts +1 -1
|
@@ -29,7 +29,7 @@ When a user asks for something:
|
|
|
29
29
|
- 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.
|
|
30
30
|
- In messaging integrations, use call-agent for cross-app delegation; do not use ask_app.
|
|
31
31
|
- 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.
|
|
32
|
-
- 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
|
|
32
|
+
- 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 using Builder/managed LLM for that app; keep bring-your-own provider keys as a secondary option only if the user asks.
|
|
33
33
|
- 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.
|
|
34
34
|
- If a user asks to rename an existing workspace app or change its Dispatch title/description, call update-workspace-app-metadata with the existing appId from list-workspace-apps. Do not call start-workspace-app-creation for a metadata-only edit because that starts a new app and Builder branch.
|
|
35
35
|
- If a new-app prompt asks for access to Mail, Calendar, Analytics, Brain, Assets, or similar first-party app data/agents, keep using the existing hosted/connected app and A2A path. Do not ask Builder to scaffold those apps as children of the new app unless the user explicitly asks for a customized app from that template.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,qBAAqB,EACrB,+BAA+B,GAChC,MAAM,iCAAiC,CAAC;AAEzC,MAAM,0BAA0B,GAAG;IACjC,GAAG,eAAe;IAClB,OAAO,EAAE;QACP,GAAG,eAAe,CAAC,OAAO;QAC1B,SAAS,EAAE,KAAK;KACjB;CACF,CAAC;AAEF,MAAM,kCAAkC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4FA6BiD,CAAC;AAE7F,MAAM,0BAA0B,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE;IACzD,MAAM,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAClD,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,CAAC;IACjD,MAAM,YAAY,GAChB,OAAO,cAAc,KAAK,QAAQ;QAChC,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,OAAO,cAAc,KAAK,UAAU;YACpC,CAAC,CAAC,cAAc,CAAC,kCAAkC,CAAC;YACpD,CAAC,CAAC,kCAAkC,CAAC;IAE3C,MAAM,MAAM,GAAG,wBAAwB,CAAC;QACtC,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,0BAA0B;QACnC,uBAAuB,EAAE,+BAA+B;QACxD,aAAa,EAAE,qBAAqB;QACpC,YAAY;QACZ,wDAAwD;QACxD,yEAAyE;QACzE,+DAA+D;QAC/D,6EAA6E;KAC9E,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF,eAAe,0BAA0B,CAAC","sourcesContent":["import { createIntegrationsPlugin } from \"@agent-native/core/server\";\n\nimport { dispatchActions } from \"../../actions/index.js\";\nimport { getDispatchConfig } from \"../index.js\";\nimport {\n beforeDispatchProcess,\n resolveDispatchExecutionContext,\n} from \"../lib/dispatch-integrations.js\";\n\nconst dispatchIntegrationActions = {\n ...dispatchActions,\n ask_app: {\n ...dispatchActions.ask_app,\n agentTool: false,\n },\n};\n\nconst DISPATCH_INTEGRATION_SYSTEM_PROMPT = `You are the central dispatch for this workspace, responding via a messaging platform integration (Slack, Telegram, email, etc.).\n\nDefault posture:\n- Treat Slack, Telegram, and email as shared entrypoints into the workspace.\n- 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), forms (form builder), clips (screen recordings), design (visual designs), and assets (brand libraries plus generated images/videos).\n- 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.\n- Hosted/connected A2A neighbors such as Analytics and Content come from the available-apps context or list-connected-agents. list-workspace-apps only inventories apps mounted inside this workspace deployment; never use a missing row there to conclude that a connected agent is unavailable.\n- When asked whether a mounted workspace app exposes an agent card or A2A endpoint, call list-workspace-apps with includeAgentCards=true. Without that probe, missing agent-card fields mean unchecked, not unavailable.\n- Treat first-party apps such as Mail, Calendar, Analytics, Brain, Assets, 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.\n- Integration grants are not provider capability limits. For ad hoc provider inspection, querying, reporting, or troubleshooting, call provider-api-catalog/provider-api-docs, then provider-api-request against the provider's real HTTP API. Use connectionId for a specific shared grant and accountId for a specific OAuth account. Never expose secret values or silently widen app access while doing this.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Reply in the originating thread unless the user explicitly asks you to send to a saved destination.\n\nWhen a user asks for something:\n- If it belongs to analytics, content, slides, clips, assets, etc., delegate via call-agent — do not re-implement the domain logic in dispatch.\n- 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.\n- 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.\n- 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.\n- In messaging integrations, use call-agent for cross-app delegation; do not use ask_app.\n- 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.\n- 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.\n- 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.\n- If a user asks to rename an existing workspace app or change its Dispatch title/description, call update-workspace-app-metadata with the existing appId from list-workspace-apps. Do not call start-workspace-app-creation for a metadata-only edit because that starts a new app and Builder branch.\n- If a new-app prompt asks for access to Mail, Calendar, Analytics, Brain, Assets, or similar first-party app data/agents, keep using the existing hosted/connected app and A2A path. Do not ask Builder to scaffold those apps as children of the new app unless the user explicitly asks for a customized app from that template.\n- If the chat template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible \"Chat\", \"Starter\", \"Blank app\", or \"New app\" UI behind.\n- If the user explicitly asks for a new app or workspace app, call start-workspace-app-creation with their prompt and include a concise generated description by default. Do not satisfy a new-app request by adding a route, page, component, or file inside apps/chat or another existing app unless the user explicitly asks to modify that existing app. When the prompt contains a source brief or concrete repeatable workflow, choose recommended defaults and do not ask non-blocking product or UX questions; ask only for authorization, credentials, a destructive action, an ambiguous target workspace, or a genuinely missing workflow. If the request is too vague to classify, ask one concise follow-up. If the action returns mode \"builder\", reply with the Builder branch URL; Builder is responsible for creating the separate workspace app under apps/<app-id>, mounting it at /<app-id>, ensuring apps/<app-id>/package.json exists with name/displayName and description so Dispatch discovers it, using relative /<app-id> links instead of hardcoded localhost/dev ports, and preserving APP_BASE_PATH/VITE_APP_BASE_PATH in the React Router client entry. The new app lives at the workspace root /<app-id>, NOT under /dispatch/<app-id>, /apps/<app-id>, or any other Dispatch tab — when telling the user where to find it, link to /<app-id> only. There is no separate workspace app registry to edit. If it returns mode \"local-agent\", tell the user it is ready for the local code agent and include the returned app path/prompt summary. Dispatch reuses the connected workspace Builder project or provisions it through the Builder Projects API when an organization owner/admin starts the first app; members need an owner/admin to configure the project first. Do not ask the user to use Builder org/beta settings. If it returns mode \"builder-unavailable\", the action also returns a \\`reason\\` code plus a user-facing \\`message\\` and (for some reasons) an operator-facing \\`detail\\`. Relay the \\`message\\` to the user as-is; only surface \\`detail\\` when the user is clearly an operator debugging the deployment (e.g. troubleshooting a broken Builder connection for the workspace), never as routine detail for an end user. If it returns mode \"app-id-taken\", the app id is already in use: \\`conflict\\` is \"registered\" for a live app or \"pending\" for a creation in flight, and \\`owner\\` names who started it. Relay the \\`message\\` and propose a different app id; never retry the same id.\n- For digests, reminders, or saved behavior, prefer recurring jobs, resources, or destinations over chat replies.\n- Keep responses concise and operational — messaging platforms have character limits.\n- Use markdown sparingly (bold and lists are fine, avoid complex formatting).\n- If a task requires many steps, summarize what you did rather than streaming every detail.`;\n\nconst dispatchIntegrationsPlugin = async (nitroApp: any) => {\n const { integrations = {} } = getDispatchConfig();\n const promptOverride = integrations.systemPrompt;\n const systemPrompt =\n typeof promptOverride === \"string\"\n ? promptOverride\n : typeof promptOverride === \"function\"\n ? promptOverride(DISPATCH_INTEGRATION_SYSTEM_PROMPT)\n : DISPATCH_INTEGRATION_SYSTEM_PROMPT;\n\n const plugin = createIntegrationsPlugin({\n appId: \"dispatch\",\n actions: dispatchIntegrationActions,\n resolveExecutionContext: resolveDispatchExecutionContext,\n beforeProcess: beforeDispatchProcess,\n systemPrompt,\n // Inherit the framework default (claude-sonnet-4-6 from\n // packages/core/src/integrations/plugin.ts). Haiku was tried for latency\n // but hallucinated URLs/IDs after delegated call-agent results\n // (e.g. inventing `https://slides.workspace.com/deck/builder-io-deck-2024`).\n });\n\n return plugin(nitroApp);\n};\n\nexport default dispatchIntegrationsPlugin;\n"]}
|
|
1
|
+
{"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,qBAAqB,EACrB,+BAA+B,GAChC,MAAM,iCAAiC,CAAC;AAEzC,MAAM,0BAA0B,GAAG;IACjC,GAAG,eAAe;IAClB,OAAO,EAAE;QACP,GAAG,eAAe,CAAC,OAAO;QAC1B,SAAS,EAAE,KAAK;KACjB;CACF,CAAC;AAEF,MAAM,kCAAkC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4FA6BiD,CAAC;AAE7F,MAAM,0BAA0B,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE;IACzD,MAAM,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAClD,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,CAAC;IACjD,MAAM,YAAY,GAChB,OAAO,cAAc,KAAK,QAAQ;QAChC,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,OAAO,cAAc,KAAK,UAAU;YACpC,CAAC,CAAC,cAAc,CAAC,kCAAkC,CAAC;YACpD,CAAC,CAAC,kCAAkC,CAAC;IAE3C,MAAM,MAAM,GAAG,wBAAwB,CAAC;QACtC,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,0BAA0B;QACnC,uBAAuB,EAAE,+BAA+B;QACxD,aAAa,EAAE,qBAAqB;QACpC,YAAY;QACZ,wDAAwD;QACxD,yEAAyE;QACzE,+DAA+D;QAC/D,6EAA6E;KAC9E,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF,eAAe,0BAA0B,CAAC","sourcesContent":["import { createIntegrationsPlugin } from \"@agent-native/core/server\";\n\nimport { dispatchActions } from \"../../actions/index.js\";\nimport { getDispatchConfig } from \"../index.js\";\nimport {\n beforeDispatchProcess,\n resolveDispatchExecutionContext,\n} from \"../lib/dispatch-integrations.js\";\n\nconst dispatchIntegrationActions = {\n ...dispatchActions,\n ask_app: {\n ...dispatchActions.ask_app,\n agentTool: false,\n },\n};\n\nconst DISPATCH_INTEGRATION_SYSTEM_PROMPT = `You are the central dispatch for this workspace, responding via a messaging platform integration (Slack, Telegram, email, etc.).\n\nDefault posture:\n- Treat Slack, Telegram, and email as shared entrypoints into the workspace.\n- 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), forms (form builder), clips (screen recordings), design (visual designs), and assets (brand libraries plus generated images/videos).\n- 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.\n- Hosted/connected A2A neighbors such as Analytics and Content come from the available-apps context or list-connected-agents. list-workspace-apps only inventories apps mounted inside this workspace deployment; never use a missing row there to conclude that a connected agent is unavailable.\n- When asked whether a mounted workspace app exposes an agent card or A2A endpoint, call list-workspace-apps with includeAgentCards=true. Without that probe, missing agent-card fields mean unchecked, not unavailable.\n- Treat first-party apps such as Mail, Calendar, Analytics, Brain, Assets, 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.\n- Integration grants are not provider capability limits. For ad hoc provider inspection, querying, reporting, or troubleshooting, call provider-api-catalog/provider-api-docs, then provider-api-request against the provider's real HTTP API. Use connectionId for a specific shared grant and accountId for a specific OAuth account. Never expose secret values or silently widen app access while doing this.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Reply in the originating thread unless the user explicitly asks you to send to a saved destination.\n\nWhen a user asks for something:\n- If it belongs to analytics, content, slides, clips, assets, etc., delegate via call-agent — do not re-implement the domain logic in dispatch.\n- 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.\n- 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.\n- 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.\n- In messaging integrations, use call-agent for cross-app delegation; do not use ask_app.\n- 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.\n- 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 using Builder/managed LLM for that app; keep bring-your-own provider keys as a secondary option only if the user asks.\n- 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.\n- If a user asks to rename an existing workspace app or change its Dispatch title/description, call update-workspace-app-metadata with the existing appId from list-workspace-apps. Do not call start-workspace-app-creation for a metadata-only edit because that starts a new app and Builder branch.\n- If a new-app prompt asks for access to Mail, Calendar, Analytics, Brain, Assets, or similar first-party app data/agents, keep using the existing hosted/connected app and A2A path. Do not ask Builder to scaffold those apps as children of the new app unless the user explicitly asks for a customized app from that template.\n- If the chat template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible \"Chat\", \"Starter\", \"Blank app\", or \"New app\" UI behind.\n- If the user explicitly asks for a new app or workspace app, call start-workspace-app-creation with their prompt and include a concise generated description by default. Do not satisfy a new-app request by adding a route, page, component, or file inside apps/chat or another existing app unless the user explicitly asks to modify that existing app. When the prompt contains a source brief or concrete repeatable workflow, choose recommended defaults and do not ask non-blocking product or UX questions; ask only for authorization, credentials, a destructive action, an ambiguous target workspace, or a genuinely missing workflow. If the request is too vague to classify, ask one concise follow-up. If the action returns mode \"builder\", reply with the Builder branch URL; Builder is responsible for creating the separate workspace app under apps/<app-id>, mounting it at /<app-id>, ensuring apps/<app-id>/package.json exists with name/displayName and description so Dispatch discovers it, using relative /<app-id> links instead of hardcoded localhost/dev ports, and preserving APP_BASE_PATH/VITE_APP_BASE_PATH in the React Router client entry. The new app lives at the workspace root /<app-id>, NOT under /dispatch/<app-id>, /apps/<app-id>, or any other Dispatch tab — when telling the user where to find it, link to /<app-id> only. There is no separate workspace app registry to edit. If it returns mode \"local-agent\", tell the user it is ready for the local code agent and include the returned app path/prompt summary. Dispatch reuses the connected workspace Builder project or provisions it through the Builder Projects API when an organization owner/admin starts the first app; members need an owner/admin to configure the project first. Do not ask the user to use Builder org/beta settings. If it returns mode \"builder-unavailable\", the action also returns a \\`reason\\` code plus a user-facing \\`message\\` and (for some reasons) an operator-facing \\`detail\\`. Relay the \\`message\\` to the user as-is; only surface \\`detail\\` when the user is clearly an operator debugging the deployment (e.g. troubleshooting a broken Builder connection for the workspace), never as routine detail for an end user. If it returns mode \"app-id-taken\", the app id is already in use: \\`conflict\\` is \"registered\" for a live app or \"pending\" for a creation in flight, and \\`owner\\` names who started it. Relay the \\`message\\` and propose a different app id; never retry the same id.\n- For digests, reminders, or saved behavior, prefer recurring jobs, resources, or destinations over chat replies.\n- Keep responses concise and operational — messaging platforms have character limits.\n- Use markdown sparingly (bold and lists are fine, avoid complex formatting).\n- If a task requires many steps, summarize what you did rather than streaming every detail.`;\n\nconst dispatchIntegrationsPlugin = async (nitroApp: any) => {\n const { integrations = {} } = getDispatchConfig();\n const promptOverride = integrations.systemPrompt;\n const systemPrompt =\n typeof promptOverride === \"string\"\n ? promptOverride\n : typeof promptOverride === \"function\"\n ? promptOverride(DISPATCH_INTEGRATION_SYSTEM_PROMPT)\n : DISPATCH_INTEGRATION_SYSTEM_PROMPT;\n\n const plugin = createIntegrationsPlugin({\n appId: \"dispatch\",\n actions: dispatchIntegrationActions,\n resolveExecutionContext: resolveDispatchExecutionContext,\n beforeProcess: beforeDispatchProcess,\n systemPrompt,\n // Inherit the framework default (claude-sonnet-4-6 from\n // packages/core/src/integrations/plugin.ts). Haiku was tried for latency\n // but hallucinated URLs/IDs after delegated call-agent results\n // (e.g. inventing `https://slides.workspace.com/deck/builder-io-deck-2024`).\n });\n\n return plugin(nitroApp);\n};\n\nexport default dispatchIntegrationsPlugin;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/dispatch",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.12-nightly-20261002213029",
|
|
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": {
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"tailwind-merge": "^3.5.0",
|
|
90
90
|
"vaul": "^1.1.2",
|
|
91
91
|
"zod": "^4.3.6",
|
|
92
|
-
"@agent-native/toolkit": "0.200.
|
|
92
|
+
"@agent-native/toolkit": "0.200.1-nightly-20261002213029"
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
95
|
"@react-router/dev": "^8.1.0",
|
|
@@ -103,10 +103,10 @@
|
|
|
103
103
|
"typescript-7": "npm:typescript@^7.0.2",
|
|
104
104
|
"vite": "8.1.0",
|
|
105
105
|
"vitest": "^4.1.5",
|
|
106
|
-
"@agent-native/core": "0.200.
|
|
106
|
+
"@agent-native/core": "0.200.1-nightly-20261002213029"
|
|
107
107
|
},
|
|
108
108
|
"peerDependencies": {
|
|
109
|
-
"@agent-native/core": "
|
|
109
|
+
"@agent-native/core": "0.200.1-nightly-20261002213029",
|
|
110
110
|
"react": ">=19.2.7",
|
|
111
111
|
"react-dom": ">=19.2.7",
|
|
112
112
|
"react-router": ">=8"
|
|
@@ -177,24 +177,22 @@ describe("CreateAppFlow", () => {
|
|
|
177
177
|
});
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
it("renders a
|
|
180
|
+
it("renders a Use Builder.io control when Builder is not connected", async () => {
|
|
181
181
|
startWorkspaceAppCreationResponse.result = {
|
|
182
182
|
mode: "builder-unavailable",
|
|
183
183
|
reason: "builder-not-connected",
|
|
184
|
-
message: "
|
|
184
|
+
message: "Use Builder.io for this user",
|
|
185
185
|
appId: "quality",
|
|
186
186
|
};
|
|
187
187
|
await renderAndSubmit("Build a quality dashboard");
|
|
188
188
|
|
|
189
189
|
await act(async () => {
|
|
190
190
|
await vi.waitFor(() =>
|
|
191
|
-
expect(container.textContent).toContain(
|
|
192
|
-
"Connect Builder for this user",
|
|
193
|
-
),
|
|
191
|
+
expect(container.textContent).toContain("Use Builder.io for this user"),
|
|
194
192
|
);
|
|
195
193
|
});
|
|
196
194
|
|
|
197
|
-
const connectButton = findButton(container, "
|
|
195
|
+
const connectButton = findButton(container, "Use Builder.io");
|
|
198
196
|
act(() => {
|
|
199
197
|
connectButton.click();
|
|
200
198
|
});
|
|
@@ -272,7 +270,7 @@ describe("CreateAppFlow", () => {
|
|
|
272
270
|
expect(onCreated).toHaveBeenCalledTimes(1);
|
|
273
271
|
});
|
|
274
272
|
|
|
275
|
-
it("renders the error affordance and a Try again control for builder-error, without a
|
|
273
|
+
it("renders the error affordance and a Try again control for builder-error, without a Builder setup control", async () => {
|
|
276
274
|
startWorkspaceAppCreationResponse.result = {
|
|
277
275
|
mode: "builder-unavailable",
|
|
278
276
|
reason: "builder-error",
|
|
@@ -298,11 +296,11 @@ describe("CreateAppFlow", () => {
|
|
|
298
296
|
matchingDivs.some((el) => el.className.includes("border-destructive")),
|
|
299
297
|
).toBe(true);
|
|
300
298
|
|
|
301
|
-
expect(() => findButton(container, "
|
|
299
|
+
expect(() => findButton(container, "Use Builder.io")).toThrow();
|
|
302
300
|
expect(findButton(container, "Try again")).toBeTruthy();
|
|
303
301
|
});
|
|
304
302
|
|
|
305
|
-
it("renders coming-soon messages neutrally with no
|
|
303
|
+
it("renders coming-soon messages neutrally with no Builder setup control", async () => {
|
|
306
304
|
startWorkspaceAppCreationResponse.result = {
|
|
307
305
|
mode: "coming-soon",
|
|
308
306
|
message: "This template is coming soon.",
|
|
@@ -324,7 +322,7 @@ describe("CreateAppFlow", () => {
|
|
|
324
322
|
expect(
|
|
325
323
|
matchingDivs.some((el) => el.className.includes("border-destructive")),
|
|
326
324
|
).toBe(false);
|
|
327
|
-
expect(() => findButton(container, "
|
|
325
|
+
expect(() => findButton(container, "Use Builder.io")).toThrow();
|
|
328
326
|
expect(() => findButton(container, "Try again")).toThrow();
|
|
329
327
|
});
|
|
330
328
|
|
|
@@ -595,7 +595,9 @@ export function CreateAppFlow({
|
|
|
595
595
|
disabled={connectFlow.connecting}
|
|
596
596
|
className="w-fit"
|
|
597
597
|
>
|
|
598
|
-
{connectFlow.connecting
|
|
598
|
+
{connectFlow.connecting
|
|
599
|
+
? "Setting up Builder.io…"
|
|
600
|
+
: "Use Builder.io"}
|
|
599
601
|
</Button>
|
|
600
602
|
</BuilderConnectPopover>
|
|
601
603
|
<a
|
|
@@ -527,24 +527,45 @@ describe("listWorkspaceApps", () => {
|
|
|
527
527
|
warn.mockRestore();
|
|
528
528
|
});
|
|
529
529
|
|
|
530
|
-
it
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
530
|
+
it("still rejects a registry read denied for this deployment's credentials when no manifest can answer (401)", async () => {
|
|
531
|
+
const fetchMock = vi.fn(
|
|
532
|
+
async () => new Response("denied", { status: 401 }),
|
|
533
|
+
);
|
|
534
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
535
|
+
vi.stubEnv("A2A_SECRET", "test-a2a-secret");
|
|
536
|
+
vi.stubEnv("WORKSPACE_GATEWAY_URL", "https://agent-workspace.builder.io");
|
|
537
|
+
vi.stubEnv("AGENT_NATIVE_WORKSPACE_APPS_JSON", "");
|
|
538
538
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
539
|
+
await expect(
|
|
540
|
+
runWithRequestContext({ userEmail: "dev@example.test" }, () =>
|
|
541
|
+
listWorkspaceApps({ includeAgentCards: false }),
|
|
542
|
+
),
|
|
543
|
+
).rejects.toThrow(
|
|
544
|
+
"Workspace apps gateway rejected the request with HTTP 401.",
|
|
545
|
+
);
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
it("serves the deployment's own app list when the registry refuses this reader (403)", async () => {
|
|
549
|
+
const fetchMock = vi.fn(
|
|
550
|
+
async () => new Response("denied", { status: 403 }),
|
|
551
|
+
);
|
|
552
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
553
|
+
vi.stubEnv("A2A_SECRET", "test-a2a-secret");
|
|
554
|
+
vi.stubEnv("WORKSPACE_GATEWAY_URL", "https://agent-workspace.builder.io");
|
|
555
|
+
vi.stubEnv("AGENT_NATIVE_WORKSPACE_APPS_JSON", "");
|
|
556
|
+
const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
557
|
+
|
|
558
|
+
const apps = await runWithRequestContext(
|
|
559
|
+
{ userEmail: "dev@example.test" },
|
|
560
|
+
() => listWorkspaceApps({ includeAgentCards: false }),
|
|
561
|
+
);
|
|
562
|
+
|
|
563
|
+
expect(apps.map((app) => app.id)).toEqual(["dispatch"]);
|
|
564
|
+
expect(warn).toHaveBeenCalledWith(
|
|
565
|
+
expect.stringContaining("denied the registry read with HTTP 403"),
|
|
566
|
+
);
|
|
567
|
+
warn.mockRestore();
|
|
568
|
+
});
|
|
548
569
|
|
|
549
570
|
it("falls back to local manifests when the hosted registry route is missing", async () => {
|
|
550
571
|
const fetchMock = vi.fn(
|
|
@@ -1799,7 +1820,7 @@ describe("startWorkspaceAppCreation", () => {
|
|
|
1799
1820
|
providerLabel: "Builder.io",
|
|
1800
1821
|
});
|
|
1801
1822
|
expect(result.message).toContain("Builder.io is not connected");
|
|
1802
|
-
expect(result.message).toContain("
|
|
1823
|
+
expect(result.message).toContain("Use Builder.io");
|
|
1803
1824
|
expect(result.message).not.toContain("try again");
|
|
1804
1825
|
});
|
|
1805
1826
|
|
|
@@ -1880,7 +1901,7 @@ describe("startWorkspaceAppCreation", () => {
|
|
|
1880
1901
|
|
|
1881
1902
|
expect(result.mode).toBe("builder");
|
|
1882
1903
|
expect(result.connectRequired).toBeUndefined();
|
|
1883
|
-
expect(result.message).not.toContain("
|
|
1904
|
+
expect(result.message).not.toContain("Use Builder.io");
|
|
1884
1905
|
});
|
|
1885
1906
|
|
|
1886
1907
|
it("provisions and remembers the workspace Builder project when none is configured", async () => {
|
|
@@ -2063,29 +2063,38 @@ export async function listWorkspaceApps(
|
|
|
2063
2063
|
return finalize(manifestApps, { persist: !unverified });
|
|
2064
2064
|
}
|
|
2065
2065
|
|
|
2066
|
-
|
|
2066
|
+
// With no local filesystem or manifest to answer, a 401 means this
|
|
2067
|
+
// deployment's own credentials are wrong, which someone has to see. A 403
|
|
2068
|
+
// means the registry will not show this reader its apps, so they get the
|
|
2069
|
+
// deployment's own list instead, and none of it is recorded. (A manifest
|
|
2070
|
+
// answers earlier for both, with the warning above.)
|
|
2071
|
+
if (gatewayDenial?.statusCode === 401) throw gatewayDenial;
|
|
2072
|
+
warnWorkspaceAppsGatewayDenial(gatewayDenial, "deployment's own app list");
|
|
2067
2073
|
|
|
2068
2074
|
if (!workspaceRoot) {
|
|
2069
|
-
return finalize(
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2075
|
+
return finalize(
|
|
2076
|
+
[
|
|
2077
|
+
{
|
|
2078
|
+
id: "dispatch",
|
|
2079
|
+
name: "Dispatch",
|
|
2080
|
+
description: "Workspace control plane",
|
|
2081
|
+
path: "/dispatch",
|
|
2082
|
+
homePath: "/home",
|
|
2083
|
+
url: workspaceAppUrl("/dispatch"),
|
|
2084
|
+
isDispatch: true,
|
|
2085
|
+
audience: DEFAULT_WORKSPACE_APP_AUDIENCE,
|
|
2086
|
+
publicPaths: [],
|
|
2087
|
+
protectedPaths: [],
|
|
2088
|
+
status: "ready",
|
|
2089
|
+
},
|
|
2090
|
+
],
|
|
2091
|
+
{ persist: !unverified },
|
|
2092
|
+
);
|
|
2084
2093
|
}
|
|
2085
2094
|
|
|
2086
2095
|
const apps = await readWorkspaceAppsFromFilesystem(workspaceRoot);
|
|
2087
|
-
if (apps) return finalize(apps);
|
|
2088
|
-
return finalize([]);
|
|
2096
|
+
if (apps) return finalize(apps, { persist: !unverified });
|
|
2097
|
+
return finalize([], { persist: !unverified });
|
|
2089
2098
|
}
|
|
2090
2099
|
|
|
2091
2100
|
const ADDABLE_TEMPLATES: AvailableWorkspaceTemplate[] = [
|
|
@@ -2667,7 +2676,7 @@ function buildWorkspaceAppPrompt(input: {
|
|
|
2667
2676
|
"- Use Tabler Icons (@tabler/icons-react) for every icon. Never use emojis as icons.",
|
|
2668
2677
|
`- Expose what the user is looking at via application_state (navigation.view, selection, etc.) so the agent has live context. Mirror the patterns in templates/mail or templates/slides.`,
|
|
2669
2678
|
"- Optimistic UI for every mutation: update the React Query cache immediately, navigate immediately, run the mutation in the background, roll back on error. Don't await a server round-trip before re-rendering.",
|
|
2670
|
-
`- Commit an agent-native.json at apps/${appId}/agent-native.json with { "version": 1, "onboarding": { "firstRun": { "development": "connect", "production": "connect-and-integrations" } } }. Keep the shared
|
|
2679
|
+
`- Commit an agent-native.json at apps/${appId}/agent-native.json with { "version": 1, "onboarding": { "firstRun": { "development": "connect", "production": "connect-and-integrations" } } }. Keep the shared Use Builder.io / Add your own keys onboarding visible; never build a second, custom credential form or hardcode a provider key.`,
|
|
2671
2680
|
"- Every AI-labeled button must call sendToAgentChat with openSidebar: true — plus submit: true for one-click work, or submit: false when the user should review/edit the proposed prompt first. Keep follow-ups in that same sidebar thread; don't add a second freeform input beside the result. Never use sparkle, wand, magic, robot, or other decorative AI icons on those buttons — a message or neutral action icon, or no icon, instead.",
|
|
2672
2681
|
"- Choose a named visual direction in DESIGN.md before styling the first screen and build to it. Don't inherit a sibling app's palette unbuilt.",
|
|
2673
2682
|
'- Left navigation must name real domain destinations, not "Chat" as the only or default entry.',
|
|
@@ -1560,7 +1560,7 @@ function looksLikeSingleAppUiWordingCorrection(
|
|
|
1560
1560
|
}
|
|
1561
1561
|
|
|
1562
1562
|
const NON_DURABLE_FAILURE_TERMS =
|
|
1563
|
-
/\b(credits[- ]?limit|daily ai credits|current plan|missing[_ -]?credentials|no llm provider|provider key|connect builder\.io|email[_ -]?verification[_ -]?required|verify their email|gateway)\b/i;
|
|
1563
|
+
/\b(credits[- ]?limit|daily ai credits|current plan|missing[_ -]?credentials|no llm provider|provider key|(?:connect|use) builder\.io|email[_ -]?verification[_ -]?required|verify their email|gateway)\b/i;
|
|
1564
1564
|
|
|
1565
1565
|
function isDurableFailureEvidence(entry: DreamEvidence): boolean {
|
|
1566
1566
|
if (entry.kind === "eval-failure") return false;
|
|
@@ -35,7 +35,7 @@ When a user asks for something:
|
|
|
35
35
|
- 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.
|
|
36
36
|
- In messaging integrations, use call-agent for cross-app delegation; do not use ask_app.
|
|
37
37
|
- 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.
|
|
38
|
-
- 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
|
|
38
|
+
- 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 using Builder/managed LLM for that app; keep bring-your-own provider keys as a secondary option only if the user asks.
|
|
39
39
|
- 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.
|
|
40
40
|
- If a user asks to rename an existing workspace app or change its Dispatch title/description, call update-workspace-app-metadata with the existing appId from list-workspace-apps. Do not call start-workspace-app-creation for a metadata-only edit because that starts a new app and Builder branch.
|
|
41
41
|
- If a new-app prompt asks for access to Mail, Calendar, Analytics, Brain, Assets, or similar first-party app data/agents, keep using the existing hosted/connected app and A2A path. Do not ask Builder to scaffold those apps as children of the new app unless the user explicitly asks for a customized app from that template.
|