@agent-native/core 0.125.0 → 0.127.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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +79 -0
- package/corpus/core/docs/content/external-agents-catalog.mdx +14 -11
- package/corpus/core/docs/content/mcp-protocol.mdx +9 -4
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/index.ts +2 -0
- package/corpus/core/src/agent/production-agent.ts +6 -1
- package/corpus/core/src/agent/run-manager.ts +37 -0
- package/corpus/core/src/agent/run-store.ts +18 -0
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +75 -43
- package/corpus/core/src/client/agent-chat.ts +19 -1
- package/corpus/core/src/client/chat/tool-call-display.tsx +25 -0
- package/corpus/core/src/client/resources/mcp-integration-catalog.ts +23 -0
- package/corpus/core/src/client/settings/AgentsSection.tsx +565 -71
- package/corpus/core/src/client/settings/SecretsSection.tsx +71 -36
- package/corpus/core/src/client/use-chat-models.ts +54 -37
- package/corpus/core/src/localization/default-messages.ts +11 -0
- package/corpus/core/src/mcp/ask-app-task-handle.ts +183 -0
- package/corpus/core/src/mcp/builtin-tools.ts +146 -34
- package/corpus/core/src/server/agent-capabilities.ts +8 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +17 -0
- package/corpus/core/src/server/agent-discovery.ts +1 -1
- package/corpus/core/src/server/agent-peer-probe.ts +133 -0
- package/corpus/core/src/server/core-routes-plugin.ts +67 -0
- package/corpus/core/src/server/email-template.ts +13 -0
- package/corpus/core/src/server/email.ts +40 -4
- package/corpus/core/src/shared/mcp-embed-headers.ts +4 -0
- package/corpus/core/src/sharing/actions/share-resource.ts +55 -5
- package/corpus/core/src/sharing/registry.ts +41 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +159 -119
- package/corpus/templates/assets/actions/edit-image.ts +31 -18
- package/corpus/templates/assets/actions/refine-image.ts +43 -29
- package/corpus/templates/assets/actions/restyle-image.ts +30 -19
- package/corpus/templates/assets/actions/variant-slots.ts +26 -0
- package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +85 -17
- package/corpus/templates/clips/changelog/2026-07-27-share-notification-emails-now-include-a-clickable-recording-.md +6 -0
- package/corpus/templates/clips/server/db/index.ts +28 -6
- package/corpus/templates/clips/server/lib/share-email-hero.ts +105 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +100 -12
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +17 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +169 -22
- package/corpus/templates/design/app/hooks/use-question-flow.ts +21 -1
- package/corpus/templates/design/changelog/2026-07-28-the-model-you-pick-when-starting-a-new-design-is-now-used-fo.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-28-pending-apps-are-hidden-by-default-and-app-ownership-details.md +6 -0
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +5 -1
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +5 -0
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +31 -8
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +15 -0
- package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +78 -8
- package/corpus/templates/slides/app/components/presentation/PresenterView.tsx +179 -0
- package/corpus/templates/slides/app/components/presentation/present-channel.ts +15 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +10 -1
- package/corpus/templates/slides/app/lib/export-google-slides-client.ts +67 -0
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +16 -3
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +11 -0
- package/corpus/templates/slides/app/pages/Presentation.tsx +11 -3
- package/corpus/templates/slides/changelog/2026-07-28-export-to-google-slides-now-creates-the-deck-directly-in-you.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-28-opening-a-presentation-link-directly-no-longer-bounces-back-.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-28-presenter-view-open-a-second-window-while-presenting-to-see-.md +6 -0
- package/corpus/templates/slides/server/routes/api/exports/google-slides.post.ts +90 -0
- package/corpus/toolkit/CHANGELOG.md +6 -0
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/src/composer/TiptapComposer.tsx +143 -111
- package/corpus/toolkit/src/composer/runtime-adapters.tsx +2 -0
- package/dist/a2a/index.d.ts +2 -0
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +1 -0
- package/dist/a2a/index.js.map +1 -1
- package/dist/agent/production-agent.d.ts +2 -2
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +6 -3
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +11 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +34 -1
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +8 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +16 -0
- package/dist/agent/run-store.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +60 -31
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat.d.ts +6 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +13 -1
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +14 -0
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.d.ts +6 -0
- package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.js +16 -0
- package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
- package/dist/client/settings/AgentsSection.d.ts.map +1 -1
- package/dist/client/settings/AgentsSection.js +250 -30
- package/dist/client/settings/AgentsSection.js.map +1 -1
- package/dist/client/settings/SecretsSection.d.ts.map +1 -1
- package/dist/client/settings/SecretsSection.js +16 -2
- package/dist/client/settings/SecretsSection.js.map +1 -1
- package/dist/client/use-chat-models.d.ts.map +1 -1
- package/dist/client/use-chat-models.js +46 -27
- package/dist/client/use-chat-models.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/localization/default-messages.d.ts +9 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +9 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp/ask-app-task-handle.d.ts +25 -0
- package/dist/mcp/ask-app-task-handle.d.ts.map +1 -0
- package/dist/mcp/ask-app-task-handle.js +136 -0
- package/dist/mcp/ask-app-task-handle.js.map +1 -0
- package/dist/mcp/builtin-tools.d.ts +3 -3
- package/dist/mcp/builtin-tools.d.ts.map +1 -1
- package/dist/mcp/builtin-tools.js +115 -38
- package/dist/mcp/builtin-tools.js.map +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +6 -6
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-capabilities.d.ts +7 -1
- package/dist/server/agent-capabilities.d.ts.map +1 -1
- package/dist/server/agent-capabilities.js +1 -0
- package/dist/server/agent-capabilities.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +7 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +16 -1
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts +1 -0
- package/dist/server/agent-discovery.d.ts.map +1 -1
- package/dist/server/agent-discovery.js +1 -1
- package/dist/server/agent-discovery.js.map +1 -1
- package/dist/server/agent-peer-probe.d.ts +37 -0
- package/dist/server/agent-peer-probe.d.ts.map +1 -0
- package/dist/server/agent-peer-probe.js +90 -0
- package/dist/server/agent-peer-probe.js.map +1 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +53 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/email-template.d.ts +6 -0
- package/dist/server/email-template.d.ts.map +1 -1
- package/dist/server/email-template.js +6 -0
- package/dist/server/email-template.js.map +1 -1
- package/dist/server/email.d.ts +7 -0
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +31 -6
- package/dist/server/email.js.map +1 -1
- package/dist/shared/mcp-embed-headers.d.ts +1 -0
- package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
- package/dist/shared/mcp-embed-headers.js +4 -0
- package/dist/shared/mcp-embed-headers.js.map +1 -1
- package/dist/sharing/actions/share-resource.d.ts.map +1 -1
- package/dist/sharing/actions/share-resource.js +49 -5
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/sharing/registry.d.ts +40 -1
- package/dist/sharing/registry.d.ts.map +1 -1
- package/dist/sharing/registry.js.map +1 -1
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +159 -119
- package/docs/content/external-agents-catalog.mdx +14 -11
- package/docs/content/mcp-protocol.mdx +9 -4
- package/package.json +2 -2
- package/src/a2a/index.ts +2 -0
- package/src/agent/production-agent.ts +6 -1
- package/src/agent/run-manager.ts +37 -0
- package/src/agent/run-store.ts +18 -0
- package/src/client/MultiTabAssistantChat.tsx +75 -43
- package/src/client/agent-chat.ts +19 -1
- package/src/client/chat/tool-call-display.tsx +25 -0
- package/src/client/resources/mcp-integration-catalog.ts +23 -0
- package/src/client/settings/AgentsSection.tsx +565 -71
- package/src/client/settings/SecretsSection.tsx +71 -36
- package/src/client/use-chat-models.ts +54 -37
- package/src/localization/default-messages.ts +11 -0
- package/src/mcp/ask-app-task-handle.ts +183 -0
- package/src/mcp/builtin-tools.ts +146 -34
- package/src/server/agent-capabilities.ts +8 -1
- package/src/server/agent-chat-plugin.ts +17 -0
- package/src/server/agent-discovery.ts +1 -1
- package/src/server/agent-peer-probe.ts +133 -0
- package/src/server/core-routes-plugin.ts +67 -0
- package/src/server/email-template.ts +13 -0
- package/src/server/email.ts +40 -4
- package/src/shared/mcp-embed-headers.ts +4 -0
- package/src/sharing/actions/share-resource.ts +55 -5
- package/src/sharing/registry.ts +41 -1
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +159 -119
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* titleColumn: "title",
|
|
17
17
|
* });
|
|
18
18
|
*/
|
|
19
|
+
import type { UserProfile } from "../user-profile/shared.js";
|
|
19
20
|
export interface ShareableResourceRegistration {
|
|
20
21
|
/** Stable identifier used across actions, UI, and analytics. e.g. "document". */
|
|
21
22
|
type: string;
|
|
@@ -41,7 +42,45 @@ export interface ShareableResourceRegistration {
|
|
|
41
42
|
* (e.g. the sharing org's own logo), or undefined to fall back. Receives the
|
|
42
43
|
* resource row being shared so the template can scope the logo to its org.
|
|
43
44
|
*/
|
|
44
|
-
|
|
45
|
+
getLogoUrl?: (resource: any) => string | undefined | Promise<string | undefined>;
|
|
46
|
+
/**
|
|
47
|
+
* Optional resolver for the brand name shown beside the logo in the
|
|
48
|
+
* share-notification email header. Return a display name (e.g. the sharing
|
|
49
|
+
* org's name) to override the app name, or undefined to keep the default.
|
|
50
|
+
* Receives the resource row being shared.
|
|
51
|
+
*/
|
|
52
|
+
getBrandName?: (resource: any) => string | undefined | Promise<string | undefined>;
|
|
53
|
+
/**
|
|
54
|
+
* Optional resolver for who the share-notification email appears to come
|
|
55
|
+
* from. `fromName` changes only the display name and keeps the configured,
|
|
56
|
+
* domain-verified sending address (e.g. "Alice via Clips"); `replyTo` routes
|
|
57
|
+
* replies to the sharer. `ctx.sender` is the account doing the sharing, so the
|
|
58
|
+
* template decides how to present them (name, email, avatar).
|
|
59
|
+
*
|
|
60
|
+
* Do not put a user's address in the sending address itself — SPF/DKIM sign
|
|
61
|
+
* the app's domain, so recipients would bounce or spam-filter it.
|
|
62
|
+
*/
|
|
63
|
+
getSender?: (resource: any, ctx: {
|
|
64
|
+
sender: UserProfile;
|
|
65
|
+
}) => {
|
|
66
|
+
fromName?: string;
|
|
67
|
+
replyTo?: string;
|
|
68
|
+
} | undefined | Promise<{
|
|
69
|
+
fromName?: string;
|
|
70
|
+
replyTo?: string;
|
|
71
|
+
} | undefined>;
|
|
72
|
+
/**
|
|
73
|
+
* Optional resolver for a preview block shown above the CTA in the
|
|
74
|
+
* share-notification email — e.g. a recording thumbnail with a play badge.
|
|
75
|
+
* Return trusted HTML (built by template code, dynamic values escaped) that
|
|
76
|
+
* is injected verbatim, or undefined to omit it. `ctx.href` is the resolved
|
|
77
|
+
* link to the resource; `ctx.alt` is its title. The template owns the entire
|
|
78
|
+
* preview markup so the generic share action stays app-agnostic.
|
|
79
|
+
*/
|
|
80
|
+
getHeroHtml?: (resource: any, ctx: {
|
|
81
|
+
href: string;
|
|
82
|
+
alt?: string;
|
|
83
|
+
}) => string | undefined | Promise<string | undefined>;
|
|
45
84
|
/**
|
|
46
85
|
* Drizzle DB accessor from the template's server/db/index.ts. Required —
|
|
47
86
|
* the framework-level share actions and access helpers call this to reach
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/sharing/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,6BAA6B;IAC5C,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,aAAa,EAAE,GAAG,CAAC;IACnB,qDAAqD;IACrD,WAAW,EAAE,GAAG,CAAC;IACjB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,MAAM,GAAG,SAAS,CAAC;IACxD;;;;;OAKG;IACH,
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/sharing/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D,MAAM,WAAW,6BAA6B;IAC5C,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,aAAa,EAAE,GAAG,CAAC;IACnB,qDAAqD;IACrD,WAAW,EAAE,GAAG,CAAC;IACjB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,MAAM,GAAG,SAAS,CAAC;IACxD;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CACX,QAAQ,EAAE,GAAG,KACV,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CACb,QAAQ,EAAE,GAAG,KACV,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,CACV,QAAQ,EAAE,GAAG,EACb,GAAG,EAAE;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE,KAE1B;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GACvC,SAAS,GACT,OAAO,CAAC;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;IACjE;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,CACZ,QAAQ,EAAE,GAAG,EACb,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,KAChC,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,CAAC;IACjB;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;;;;;;OAYG;IACH,gBAAgB,CAAC,EACb,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,CAAC,CACC,QAAQ,EAAE,GAAG,EACb,GAAG,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAEzC,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,OAAO,CAAC,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC;IAChD;;;;;;;;;;OAUG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAC;IACxC;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK;QACtE,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF;;;;;;;OAOG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;;OAMG;IACH,aAAa,CAAC,EACV,KAAK,GACL;QACE,uEAAuE;QACvE,YAAY,EAAE,MAAM,CAAC;QACrB,qEAAqE;QACrE,cAAc,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,MAAM,GAAG,SAAS,CAAC;QACtD,uEAAuE;QACvE,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,MAAM,GAAG,SAAS,CAAC;QACpD,iEAAiE;QACjE,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACP;AAuCD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,6BAA6B,GACnC,IAAI,CAGN;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GACX,6BAA6B,GAAG,SAAS,CAE3C;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,GACX,6BAA6B,CAS/B;AAED,wBAAgB,sBAAsB,IAAI,6BAA6B,EAAE,CAExE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/sharing/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AA+HH,0EAA0E;AAC1E,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,2EAA2E;AAC3E,0EAA0E;AAC1E,8EAA8E;AAC9E,+EAA+E;AAC/E,MAAM,YAAY,GAAG,mCAAmC,CAAC;AAEzD,MAAM,cAAc,GAClB,UAAiB,CAAC;AAEpB,SAAS,aAAa;IACpB,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;QAC/B,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,MAAM;QAC7B,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,CAC3B,CAAC;AACJ,CAAC;AAED,SAAS,4BAA4B;IACnC,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;IACtC,OAAO,oEAAoE,CAAC,IAAI,CAC9E,KAAK,CACN,CAAC;AACJ,CAAC;AAED,SAAS,WAAW;IAClB,IAAI,CAAC,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IACrC,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,CAAC,GAAG,IAAI,GAAG,EAAyC,CAAC;QACrD,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,KAAoC;IAEpC,IAAI,CAAC,aAAa,EAAE,IAAI,4BAA4B,EAAE;QAAE,OAAO;IAC/D,WAAW,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,IAAY;IAEZ,OAAO,WAAW,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,IAAY;IAEZ,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,qCAAqC,IAAI,gDAAgD,CAC1F,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["/**\n * Registry of shareable resources.\n *\n * Each template registers its ownable resource(s) once on module load so the\n * framework-level share actions (`share-resource`, `list-resource-shares`,\n * etc.) can dispatch to the correct tables.\n *\n * import { registerShareableResource } from \"@agent-native/core/sharing\";\n * import * as schema from \"./schema.js\";\n *\n * registerShareableResource({\n * type: \"document\",\n * resourceTable: schema.documents,\n * sharesTable: schema.documentShares,\n * displayName: \"Document\",\n * titleColumn: \"title\",\n * });\n */\n\nexport interface ShareableResourceRegistration {\n /** Stable identifier used across actions, UI, and analytics. e.g. \"document\". */\n type: string;\n /** Drizzle table for the parent resource (must have ownableColumns()). */\n resourceTable: any;\n /** Drizzle table produced by createSharesTable(). */\n sharesTable: any;\n /** Human-readable singular label shown in the share dialog. */\n displayName: string;\n /**\n * Column on the resource table that holds a human-readable title for\n * display in the share UI. Default: \"title\".\n */\n titleColumn?: string;\n /**\n * Optional app-relative path to this resource. Used by share notifications\n * when the caller does not pass a more specific resourceUrl.\n */\n getResourcePath?: (resource: any) => string | undefined;\n /**\n * Optional resolver for the share-notification email's brand logo. Return an\n * absolute `https://` URL to override the default embedded Agent Native logo\n * (e.g. the sharing org's own logo), or undefined to fall back. Receives the\n * resource row being shared so the template can scope the logo to its org.\n */\n getShareEmailLogoUrl?: (\n resource: any,\n ) => string | undefined | Promise<string | undefined>;\n /**\n * Drizzle DB accessor from the template's server/db/index.ts. Required —\n * the framework-level share actions and access helpers call this to reach\n * the right DB instance (schema is template-specific).\n */\n getDb: () => any;\n /**\n * When `false`, `visibility: \"public\"` is rejected by `set-resource-visibility`,\n * and `accessFilter` / `resolveAccess` treat any stored public row as private\n * (defense in depth — only owner + explicit shares grant access).\n *\n * Use this for resources that execute code or expose privileged data and must\n * never be reachable by a random authenticated user. Extensions set this:\n * extension HTML runs inside an iframe that calls actions / DB / proxied APIs\n * as the *viewer*, so a public extension would be arbitrary code with the\n * viewer's credentials.\n *\n * Default: `true` (matches the historical behavior — most resources can be public).\n */\n allowPublic?: boolean;\n /**\n * Optional role granted by a public-by-link read. Most resources should omit\n * this so public visibility remains viewer-only. Use narrowly for local or\n * otherwise constrained resources where the resource owner intentionally wants\n * unauthenticated link holders to do more than view.\n *\n * When this is a function, it may read arbitrary fields on the resource row\n * (not just the ownership/visibility columns). Because of that,\n * `resolveAccess`/`assertAccess`'s opt-in `{ skipResourceBody: true }`\n * projected load (see `access.ts`) is automatically ignored for this\n * registration and always loads the full row instead — a fixed role string\n * has no such requirement and is compatible with the projection.\n */\n publicAccessRole?:\n | \"viewer\"\n | \"editor\"\n | \"admin\"\n | ((\n resource: any,\n ctx: { userEmail?: string; orgId?: string },\n ) =>\n | \"viewer\"\n | \"editor\"\n | \"admin\"\n | Promise<\"viewer\" | \"editor\" | \"admin\">);\n /**\n * When `true`, individual user shares (`principalType: \"user\"`) must target\n * an email that is already a member of the same org as the resource, OR has\n * a pending invitation to that org. Cross-org user shares are rejected.\n *\n * Pair with `allowPublic: false` for resources that need a hard \"this org\n * only\" trust boundary. Extensions set this so a malicious caller can't\n * widen reach by sharing a code-executing extension to an outsider email.\n *\n * Default: `false` (matches the historical behavior — any email can be granted).\n */\n requireOrgMemberForUserShares?: boolean;\n /**\n * Optional per-resource access-context adapter. Most resources should use the\n * request user/org unchanged. Templates with an intentional alternate local\n * identity can normalize here so the generic framework sharing actions and\n * access helpers stay in sync with template-owned actions.\n */\n resolveAccessContext?: (ctx: { userEmail?: string; orgId?: string }) => {\n userEmail?: string;\n orgId?: string;\n };\n /**\n * When true, direct ownership is recognized by owner_email regardless of the\n * caller's active org. Use this only for resource types where the template's\n * own actions already treat owner_email as the cross-org authority and list\n * views add their own org filters.\n *\n * Default: `false`.\n */\n ownerAccessIgnoresOrg?: boolean;\n /**\n * Optional external-agent read handoff. When set, the framework-level\n * `create-agent-resource-link` action can mint a short-lived, read-only\n * `agent_access` URL for this resource. The context endpoint is owned by the\n * template so it can expose the same intentionally shareable shape as the\n * public page, not a generic raw database row.\n */\n agentReadable?:\n | false\n | {\n /** Token scope. Include the app name to avoid cross-app collisions. */\n resourceKind: string;\n /** App-relative JSON endpoint that accepts `id` + `agent_access`. */\n getContextPath: (resource: any) => string | undefined;\n /** Optional override for the page URL. Defaults to getResourcePath. */\n getPagePath?: (resource: any) => string | undefined;\n /** Optional override for the default two-hour token lifetime. */\n ttlSeconds?: number;\n };\n}\n\n// Stash the registry on globalThis so it survives SSR bundle duplication.\n// Vite SSR's `noExternal: /^(?!node:)/` policy means @agent-native/core gets\n// inlined into every server bundle that imports it — and each bundle gets its\n// own module-level state. A plain `new Map()` here would create one Map per\n// bundle, so the template's `registerShareableResource()` (called from the\n// Nitro plugin graph) wouldn't be visible to the framework's auto-mounted\n// share-resource action (loaded via `import(\"../sharing/actions/...js\")` in a\n// different module instance). Using globalThis collapses them back to one Map.\nconst REGISTRY_KEY = \"__agentNativeShareableResources__\";\ntype RegistryStore = Map<string, ShareableResourceRegistration>;\nconst globalRegistry: { [K in typeof REGISTRY_KEY]?: RegistryStore } =\n globalThis as any;\n\nfunction isTestRuntime(): boolean {\n return (\n process.env.NODE_ENV === \"test\" ||\n process.env.VITEST === \"true\" ||\n process.env.VITEST === \"1\"\n );\n}\n\nfunction registrationCameFromTestFile(): boolean {\n const stack = new Error().stack ?? \"\";\n return /[./\\\\](?:[^/\\\\]+[.-])(?:test|spec)\\.[cm]?[jt]sx?(?::\\d+)?(?::\\d+)?/.test(\n stack,\n );\n}\n\nfunction getRegistry(): RegistryStore {\n let r = globalRegistry[REGISTRY_KEY];\n if (!r) {\n r = new Map<string, ShareableResourceRegistration>();\n globalRegistry[REGISTRY_KEY] = r;\n }\n return r;\n}\n\nexport function registerShareableResource(\n entry: ShareableResourceRegistration,\n): void {\n if (!isTestRuntime() && registrationCameFromTestFile()) return;\n getRegistry().set(entry.type, entry);\n}\n\nexport function getShareableResource(\n type: string,\n): ShareableResourceRegistration | undefined {\n return getRegistry().get(type);\n}\n\nexport function requireShareableResource(\n type: string,\n): ShareableResourceRegistration {\n const reg = getRegistry();\n const entry = reg.get(type);\n if (!entry) {\n throw new Error(\n `Unknown shareable resource type: \"${type}\". Did you forget registerShareableResource()?`,\n );\n }\n return entry;\n}\n\nexport function listShareableResources(): ShareableResourceRegistration[] {\n return Array.from(getRegistry().values());\n}\n"]}
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/sharing/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAuKH,0EAA0E;AAC1E,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,2EAA2E;AAC3E,0EAA0E;AAC1E,8EAA8E;AAC9E,+EAA+E;AAC/E,MAAM,YAAY,GAAG,mCAAmC,CAAC;AAEzD,MAAM,cAAc,GAClB,UAAiB,CAAC;AAEpB,SAAS,aAAa;IACpB,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;QAC/B,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,MAAM;QAC7B,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,CAC3B,CAAC;AACJ,CAAC;AAED,SAAS,4BAA4B;IACnC,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;IACtC,OAAO,oEAAoE,CAAC,IAAI,CAC9E,KAAK,CACN,CAAC;AACJ,CAAC;AAED,SAAS,WAAW;IAClB,IAAI,CAAC,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IACrC,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,CAAC,GAAG,IAAI,GAAG,EAAyC,CAAC;QACrD,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,KAAoC;IAEpC,IAAI,CAAC,aAAa,EAAE,IAAI,4BAA4B,EAAE;QAAE,OAAO;IAC/D,WAAW,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,IAAY;IAEZ,OAAO,WAAW,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,IAAY;IAEZ,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,qCAAqC,IAAI,gDAAgD,CAC1F,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["/**\n * Registry of shareable resources.\n *\n * Each template registers its ownable resource(s) once on module load so the\n * framework-level share actions (`share-resource`, `list-resource-shares`,\n * etc.) can dispatch to the correct tables.\n *\n * import { registerShareableResource } from \"@agent-native/core/sharing\";\n * import * as schema from \"./schema.js\";\n *\n * registerShareableResource({\n * type: \"document\",\n * resourceTable: schema.documents,\n * sharesTable: schema.documentShares,\n * displayName: \"Document\",\n * titleColumn: \"title\",\n * });\n */\n\nimport type { UserProfile } from \"../user-profile/shared.js\";\n\nexport interface ShareableResourceRegistration {\n /** Stable identifier used across actions, UI, and analytics. e.g. \"document\". */\n type: string;\n /** Drizzle table for the parent resource (must have ownableColumns()). */\n resourceTable: any;\n /** Drizzle table produced by createSharesTable(). */\n sharesTable: any;\n /** Human-readable singular label shown in the share dialog. */\n displayName: string;\n /**\n * Column on the resource table that holds a human-readable title for\n * display in the share UI. Default: \"title\".\n */\n titleColumn?: string;\n /**\n * Optional app-relative path to this resource. Used by share notifications\n * when the caller does not pass a more specific resourceUrl.\n */\n getResourcePath?: (resource: any) => string | undefined;\n /**\n * Optional resolver for the share-notification email's brand logo. Return an\n * absolute `https://` URL to override the default embedded Agent Native logo\n * (e.g. the sharing org's own logo), or undefined to fall back. Receives the\n * resource row being shared so the template can scope the logo to its org.\n */\n getLogoUrl?: (\n resource: any,\n ) => string | undefined | Promise<string | undefined>;\n /**\n * Optional resolver for the brand name shown beside the logo in the\n * share-notification email header. Return a display name (e.g. the sharing\n * org's name) to override the app name, or undefined to keep the default.\n * Receives the resource row being shared.\n */\n getBrandName?: (\n resource: any,\n ) => string | undefined | Promise<string | undefined>;\n /**\n * Optional resolver for who the share-notification email appears to come\n * from. `fromName` changes only the display name and keeps the configured,\n * domain-verified sending address (e.g. \"Alice via Clips\"); `replyTo` routes\n * replies to the sharer. `ctx.sender` is the account doing the sharing, so the\n * template decides how to present them (name, email, avatar).\n *\n * Do not put a user's address in the sending address itself — SPF/DKIM sign\n * the app's domain, so recipients would bounce or spam-filter it.\n */\n getSender?: (\n resource: any,\n ctx: { sender: UserProfile },\n ) =>\n | { fromName?: string; replyTo?: string }\n | undefined\n | Promise<{ fromName?: string; replyTo?: string } | undefined>;\n /**\n * Optional resolver for a preview block shown above the CTA in the\n * share-notification email — e.g. a recording thumbnail with a play badge.\n * Return trusted HTML (built by template code, dynamic values escaped) that\n * is injected verbatim, or undefined to omit it. `ctx.href` is the resolved\n * link to the resource; `ctx.alt` is its title. The template owns the entire\n * preview markup so the generic share action stays app-agnostic.\n */\n getHeroHtml?: (\n resource: any,\n ctx: { href: string; alt?: string },\n ) => string | undefined | Promise<string | undefined>;\n /**\n * Drizzle DB accessor from the template's server/db/index.ts. Required —\n * the framework-level share actions and access helpers call this to reach\n * the right DB instance (schema is template-specific).\n */\n getDb: () => any;\n /**\n * When `false`, `visibility: \"public\"` is rejected by `set-resource-visibility`,\n * and `accessFilter` / `resolveAccess` treat any stored public row as private\n * (defense in depth — only owner + explicit shares grant access).\n *\n * Use this for resources that execute code or expose privileged data and must\n * never be reachable by a random authenticated user. Extensions set this:\n * extension HTML runs inside an iframe that calls actions / DB / proxied APIs\n * as the *viewer*, so a public extension would be arbitrary code with the\n * viewer's credentials.\n *\n * Default: `true` (matches the historical behavior — most resources can be public).\n */\n allowPublic?: boolean;\n /**\n * Optional role granted by a public-by-link read. Most resources should omit\n * this so public visibility remains viewer-only. Use narrowly for local or\n * otherwise constrained resources where the resource owner intentionally wants\n * unauthenticated link holders to do more than view.\n *\n * When this is a function, it may read arbitrary fields on the resource row\n * (not just the ownership/visibility columns). Because of that,\n * `resolveAccess`/`assertAccess`'s opt-in `{ skipResourceBody: true }`\n * projected load (see `access.ts`) is automatically ignored for this\n * registration and always loads the full row instead — a fixed role string\n * has no such requirement and is compatible with the projection.\n */\n publicAccessRole?:\n | \"viewer\"\n | \"editor\"\n | \"admin\"\n | ((\n resource: any,\n ctx: { userEmail?: string; orgId?: string },\n ) =>\n | \"viewer\"\n | \"editor\"\n | \"admin\"\n | Promise<\"viewer\" | \"editor\" | \"admin\">);\n /**\n * When `true`, individual user shares (`principalType: \"user\"`) must target\n * an email that is already a member of the same org as the resource, OR has\n * a pending invitation to that org. Cross-org user shares are rejected.\n *\n * Pair with `allowPublic: false` for resources that need a hard \"this org\n * only\" trust boundary. Extensions set this so a malicious caller can't\n * widen reach by sharing a code-executing extension to an outsider email.\n *\n * Default: `false` (matches the historical behavior — any email can be granted).\n */\n requireOrgMemberForUserShares?: boolean;\n /**\n * Optional per-resource access-context adapter. Most resources should use the\n * request user/org unchanged. Templates with an intentional alternate local\n * identity can normalize here so the generic framework sharing actions and\n * access helpers stay in sync with template-owned actions.\n */\n resolveAccessContext?: (ctx: { userEmail?: string; orgId?: string }) => {\n userEmail?: string;\n orgId?: string;\n };\n /**\n * When true, direct ownership is recognized by owner_email regardless of the\n * caller's active org. Use this only for resource types where the template's\n * own actions already treat owner_email as the cross-org authority and list\n * views add their own org filters.\n *\n * Default: `false`.\n */\n ownerAccessIgnoresOrg?: boolean;\n /**\n * Optional external-agent read handoff. When set, the framework-level\n * `create-agent-resource-link` action can mint a short-lived, read-only\n * `agent_access` URL for this resource. The context endpoint is owned by the\n * template so it can expose the same intentionally shareable shape as the\n * public page, not a generic raw database row.\n */\n agentReadable?:\n | false\n | {\n /** Token scope. Include the app name to avoid cross-app collisions. */\n resourceKind: string;\n /** App-relative JSON endpoint that accepts `id` + `agent_access`. */\n getContextPath: (resource: any) => string | undefined;\n /** Optional override for the page URL. Defaults to getResourcePath. */\n getPagePath?: (resource: any) => string | undefined;\n /** Optional override for the default two-hour token lifetime. */\n ttlSeconds?: number;\n };\n}\n\n// Stash the registry on globalThis so it survives SSR bundle duplication.\n// Vite SSR's `noExternal: /^(?!node:)/` policy means @agent-native/core gets\n// inlined into every server bundle that imports it — and each bundle gets its\n// own module-level state. A plain `new Map()` here would create one Map per\n// bundle, so the template's `registerShareableResource()` (called from the\n// Nitro plugin graph) wouldn't be visible to the framework's auto-mounted\n// share-resource action (loaded via `import(\"../sharing/actions/...js\")` in a\n// different module instance). Using globalThis collapses them back to one Map.\nconst REGISTRY_KEY = \"__agentNativeShareableResources__\";\ntype RegistryStore = Map<string, ShareableResourceRegistration>;\nconst globalRegistry: { [K in typeof REGISTRY_KEY]?: RegistryStore } =\n globalThis as any;\n\nfunction isTestRuntime(): boolean {\n return (\n process.env.NODE_ENV === \"test\" ||\n process.env.VITEST === \"true\" ||\n process.env.VITEST === \"1\"\n );\n}\n\nfunction registrationCameFromTestFile(): boolean {\n const stack = new Error().stack ?? \"\";\n return /[./\\\\](?:[^/\\\\]+[.-])(?:test|spec)\\.[cm]?[jt]sx?(?::\\d+)?(?::\\d+)?/.test(\n stack,\n );\n}\n\nfunction getRegistry(): RegistryStore {\n let r = globalRegistry[REGISTRY_KEY];\n if (!r) {\n r = new Map<string, ShareableResourceRegistration>();\n globalRegistry[REGISTRY_KEY] = r;\n }\n return r;\n}\n\nexport function registerShareableResource(\n entry: ShareableResourceRegistration,\n): void {\n if (!isTestRuntime() && registrationCameFromTestFile()) return;\n getRegistry().set(entry.type, entry);\n}\n\nexport function getShareableResource(\n type: string,\n): ShareableResourceRegistration | undefined {\n return getRegistry().get(type);\n}\n\nexport function requireShareableResource(\n type: string,\n): ShareableResourceRegistration {\n const reg = getRegistry();\n const entry = reg.get(type);\n if (!entry) {\n throw new Error(\n `Unknown shareable resource type: \"${type}\". Did you forget registerShareableResource()?`,\n );\n }\n return entry;\n}\n\nexport function listShareableResources(): ShareableResourceRegistration[] {\n return Array.from(getRegistry().values());\n}\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: a2a-protocol
|
|
3
3
|
description: >-
|
|
4
|
-
How
|
|
5
|
-
Use when
|
|
6
|
-
|
|
4
|
+
How agent-native apps discover, authenticate with, and call each other over
|
|
5
|
+
A2A. Use when connecting one app to another, debugging a remote agent that
|
|
6
|
+
won't authenticate, exposing skills to peers, or calling agents from scripts.
|
|
7
7
|
scope: dev
|
|
8
8
|
metadata:
|
|
9
9
|
internal: true
|
|
@@ -13,110 +13,155 @@ metadata:
|
|
|
13
13
|
|
|
14
14
|
## Rule
|
|
15
15
|
|
|
16
|
-
Agents
|
|
16
|
+
Agents call other agents over A2A, a JSON-RPC protocol for discovery and
|
|
17
|
+
delegation. Use it when work belongs to a different agent entirely — not the
|
|
18
|
+
local agent chat.
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
Connecting app A to app B is two independent things, and both must be true:
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
1. **B is registered on A** as a `remote-agents/<id>.json` resource.
|
|
23
|
+
2. **A and B share a secret**, so A's signed JWT verifies on B.
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
Neither is a code change, and neither is symmetric. Registering B on A does not
|
|
26
|
+
let B call A.
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
## A2A is already mounted
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
import { mountA2A } from "@agent-native/core/a2a";
|
|
29
|
-
|
|
30
|
-
export default defineNitroPlugin((nitro) => {
|
|
31
|
-
const app = nitro.h3App;
|
|
32
|
-
|
|
33
|
-
mountA2A(app, {
|
|
34
|
-
name: "Analytics Agent",
|
|
35
|
-
description: "Queries analytics data across providers",
|
|
36
|
-
version: "1.0.0",
|
|
37
|
-
skills: [
|
|
38
|
-
{
|
|
39
|
-
id: "query-data",
|
|
40
|
-
name: "Query Data",
|
|
41
|
-
description: "Run analytics queries across connected data sources",
|
|
42
|
-
tags: ["analytics", "data"],
|
|
43
|
-
examples: ["What were last week's signups?", "Show conversion rates"],
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
apiKeyEnv: "A2A_API_KEY", // env var holding the bearer token
|
|
47
|
-
streaming: true, // enable message/stream method
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
This mounts the agent-native A2A endpoints:
|
|
53
|
-
|
|
54
|
-
- `GET /.well-known/agent-card.json` — public agent discovery (no auth required)
|
|
55
|
-
- `POST /_agent-native/a2a` — primary JSON-RPC endpoint (bearer token auth required)
|
|
30
|
+
`createAgentChatPlugin` calls `mountA2A` for every app, so a generated app
|
|
31
|
+
already serves:
|
|
56
32
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
`/_agent-native/a2a` endpoint.
|
|
33
|
+
- `GET /.well-known/agent-card.json` — public discovery, never authenticated
|
|
34
|
+
- `POST /_agent-native/a2a` — JSON-RPC, authenticated
|
|
60
35
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
```ts
|
|
64
|
-
interface A2AConfig {
|
|
65
|
-
name: string; // agent display name
|
|
66
|
-
description: string; // what this agent does
|
|
67
|
-
version?: string; // semver version (default: "1.0.0")
|
|
68
|
-
skills: AgentSkill[]; // capabilities this agent exposes
|
|
69
|
-
handler?: A2AHandler; // custom message handler
|
|
70
|
-
apiKeyEnv?: string; // env var name for bearer token auth
|
|
71
|
-
streaming?: boolean; // enable streaming responses
|
|
72
|
-
}
|
|
36
|
+
Do not add a `mountA2A` server plugin to enable A2A; it is on. Hand-mounting is
|
|
37
|
+
only for a bespoke card or a custom handler (see **Custom mount** below).
|
|
73
38
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
name: string; // human-readable name
|
|
77
|
-
description: string; // what this skill does
|
|
78
|
-
tags?: string[]; // categorization tags
|
|
79
|
-
examples?: string[]; // example prompts
|
|
80
|
-
}
|
|
81
|
-
```
|
|
39
|
+
The client falls back to `POST /a2a` for external peers that only expose that
|
|
40
|
+
path. New agent-native apps should call `/_agent-native/a2a`.
|
|
82
41
|
|
|
83
|
-
##
|
|
42
|
+
## Registering a remote agent
|
|
84
43
|
|
|
85
|
-
|
|
44
|
+
A remote agent is **a row in the resources table, not a file on disk**. Path
|
|
45
|
+
`remote-agents/<id>.json`, owner `SHARED_OWNER`, content:
|
|
86
46
|
|
|
87
47
|
```json
|
|
88
48
|
{
|
|
89
|
-
"
|
|
49
|
+
"id": "analytics",
|
|
50
|
+
"name": "Analytics",
|
|
90
51
|
"description": "Queries analytics data across providers",
|
|
91
52
|
"url": "https://analytics.example.com",
|
|
92
|
-
"
|
|
93
|
-
"protocolVersion": "0.3",
|
|
94
|
-
"capabilities": { "streaming": true },
|
|
95
|
-
"skills": [
|
|
96
|
-
{
|
|
97
|
-
"id": "query-data",
|
|
98
|
-
"name": "Query Data",
|
|
99
|
-
"description": "Run analytics queries across connected data sources"
|
|
100
|
-
}
|
|
101
|
-
]
|
|
53
|
+
"color": "#6B7280"
|
|
102
54
|
}
|
|
103
55
|
```
|
|
104
56
|
|
|
105
|
-
|
|
57
|
+
`url` is the only required field. `parseRemoteAgentManifest` accepts **only**
|
|
58
|
+
these five keys — there is no `apiKey`, `env`, `skills`, or `token` field, and
|
|
59
|
+
anything else is silently dropped.
|
|
60
|
+
|
|
61
|
+
Four ways to create it, all writing the same row:
|
|
62
|
+
|
|
63
|
+
| Surface | Where |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| Settings → Manage agent → Connected Agents (A2A) | any app with the settings panel |
|
|
66
|
+
| Agent page → Connections | apps mounting `AgentTabsPage` |
|
|
67
|
+
| Dispatch → Agents → Add external agent | workspace dispatch |
|
|
68
|
+
| The agent itself | `resources` tool, `action: "write"`, `--scope shared` |
|
|
69
|
+
|
|
70
|
+
The last one matters for template apps with no Code tab: "connect me to
|
|
71
|
+
https://analytics.example.com" is a complete instruction. `remote-agents/` is
|
|
72
|
+
whitelisted as a durable control path, so the write is workspace-scoped, and it
|
|
73
|
+
takes effect on the next `discoverAgents()` call with no restart.
|
|
74
|
+
|
|
75
|
+
First-party templates are seeded automatically and overlaid on top of manifests,
|
|
76
|
+
so `Mail`, `Calendar`, and friends appear without registration. In dev they
|
|
77
|
+
resolve to `http://localhost:<devPort>`; a manifest pointing at localhost is
|
|
78
|
+
ignored in production.
|
|
79
|
+
|
|
80
|
+
`call-agent` also accepts a raw URL, which skips registration entirely — useful
|
|
81
|
+
for one-off calls, useless for @-mentions.
|
|
82
|
+
|
|
83
|
+
### Checking a peer
|
|
84
|
+
|
|
85
|
+
`GET /_agent-native/agents/probe?url=<base>` reads the peer's card and makes one
|
|
86
|
+
authenticated no-op call, returning `reachable` and `authorized` as independent
|
|
87
|
+
fields. Omit `url` to probe every registered peer. Reachable-but-unauthorized is
|
|
88
|
+
the failure worth looking for: local dev runs the receiver unauthenticated, so a
|
|
89
|
+
mismatched secret only surfaces after deploy. The Connected Agents settings
|
|
90
|
+
section calls this on add and on open.
|
|
91
|
+
|
|
92
|
+
## Authentication
|
|
93
|
+
|
|
94
|
+
A2A authenticates with a **short-lived JWT the caller signs**, not a stored
|
|
95
|
+
bearer key. `Authorization: Bearer <jwt>`; claims carry the caller's email and
|
|
96
|
+
org domain; HS256; 15-minute default TTL. There is no per-peer API key
|
|
97
|
+
anywhere in the system, which is why the manifest has no field for one.
|
|
98
|
+
|
|
99
|
+
Two secrets can sign it:
|
|
100
|
+
|
|
101
|
+
| Secret | Scope | How it is set |
|
|
102
|
+
| --- | --- | --- |
|
|
103
|
+
| `A2A_SECRET` | whole deployment | env var, **never auto-generated** |
|
|
104
|
+
| org `a2a_secret` | one organization | auto-generated on org creation; Team page UI |
|
|
105
|
+
|
|
106
|
+
The org secret is the managed path: **Team page → A2A secret** (owner only)
|
|
107
|
+
reveals, copies, regenerates, and pushes it to every discovered peer. Rotation
|
|
108
|
+
is tolerated — the caller tries both secrets in order and sticks to whichever
|
|
109
|
+
worked.
|
|
110
|
+
|
|
111
|
+
`A2A_SECRET` is the deploy-level path. `workspace-deploy` refuses a production
|
|
112
|
+
workspace deploy without it and prints the generator command. Peers that must
|
|
113
|
+
trust each other need the *same* value on both sides.
|
|
114
|
+
|
|
115
|
+
With no secret configured at all:
|
|
116
|
+
|
|
117
|
+
| Runtime | Result |
|
|
118
|
+
| --- | --- |
|
|
119
|
+
| local dev | open, one-time console warning |
|
|
120
|
+
| production | `503` — "A2A authentication not configured" |
|
|
121
|
+
| production, secret set, bad/absent token | `401` |
|
|
122
|
+
|
|
123
|
+
"Production" is detected broadly (NODE_ENV, Netlify, Lambda, Vercel, Render,
|
|
124
|
+
Fly, Cloud Run, …) and unrecognized deployed hosts fail closed unless the
|
|
125
|
+
request is genuine loopback or `A2A_ALLOW_UNSIGNED_INTERNAL=1`.
|
|
126
|
+
|
|
127
|
+
`A2AConfig.apiKeyEnv` still exists for static bearer auth against non-agent-native
|
|
128
|
+
peers, but the framework's own mount never sets it. Do not reach for it when
|
|
129
|
+
debugging a connection between two agent-native apps — the answer there is
|
|
130
|
+
always the shared secret.
|
|
131
|
+
|
|
132
|
+
Never hardcode either secret in source, docs, prompts, app state, action
|
|
133
|
+
descriptions, client bundles, or examples. Read them from runtime config; never
|
|
134
|
+
log or return them.
|
|
135
|
+
|
|
136
|
+
## Advertising what this agent can do
|
|
137
|
+
|
|
138
|
+
Card `skills` are derived from actions marked `publicAgent`. An app that marks
|
|
139
|
+
none publishes `"skills": []` and peers cannot see what it offers, even though
|
|
140
|
+
delegation still works. Mark the actions a peer should be able to see and
|
|
141
|
+
invoke directly; leave the rest internal.
|
|
142
|
+
|
|
143
|
+
## Calling another agent
|
|
106
144
|
|
|
107
145
|
### Simple: `callAgent()` (text in, text out)
|
|
108
146
|
|
|
109
147
|
```ts
|
|
110
|
-
import { callAgent } from "@agent-native/core/a2a";
|
|
148
|
+
import { callAgent, resolveA2ACallerAuth } from "@agent-native/core/a2a";
|
|
111
149
|
|
|
150
|
+
const auth = await resolveA2ACallerAuth();
|
|
112
151
|
const answer = await callAgent(
|
|
113
152
|
"https://analytics.example.com",
|
|
114
153
|
"What were last week's signups?",
|
|
115
|
-
|
|
154
|
+
auth,
|
|
116
155
|
);
|
|
117
156
|
// answer is a plain string
|
|
118
157
|
```
|
|
119
158
|
|
|
159
|
+
`callAgent` signs nothing on its own — with no `userEmail`/`orgSecret` in opts
|
|
160
|
+
it calls **unauthenticated**, which silently works in local dev and 401s in
|
|
161
|
+
production. `resolveA2ACallerAuth()` pulls the authenticated email, org domain,
|
|
162
|
+
and org secret out of request context; pass them explicitly only from CLI or
|
|
163
|
+
cron, where there is no request.
|
|
164
|
+
|
|
120
165
|
### Fast bounded read: `invokeAgentAction()`
|
|
121
166
|
|
|
122
167
|
When the caller knows the exact receiver-owned read action and arguments, skip
|
|
@@ -168,12 +213,13 @@ action arguments or results.
|
|
|
168
213
|
### Advanced: `A2AClient` (full control)
|
|
169
214
|
|
|
170
215
|
```ts
|
|
171
|
-
import { A2AClient } from "@agent-native/core/a2a";
|
|
216
|
+
import { A2AClient, resolveA2ACallerAuth } from "@agent-native/core/a2a";
|
|
172
217
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
218
|
+
// The second argument is the bearer token itself, not a signing secret.
|
|
219
|
+
const { apiKey, apiKeyFallbacks } = await resolveA2ACallerAuth();
|
|
220
|
+
const client = new A2AClient("https://analytics.example.com", apiKey, {
|
|
221
|
+
fallbackApiKeys: apiKeyFallbacks,
|
|
222
|
+
});
|
|
177
223
|
|
|
178
224
|
// Discover agent capabilities
|
|
179
225
|
const card = await client.getAgentCard();
|
|
@@ -264,19 +310,6 @@ submitted → working → completed
|
|
|
264
310
|
- **canceled** — task was canceled via `tasks/cancel`
|
|
265
311
|
- **input-required** — agent needs more information from the caller
|
|
266
312
|
|
|
267
|
-
## Security
|
|
268
|
-
|
|
269
|
-
A2A uses bearer token auth. The server reads the token from the environment variable specified by `apiKeyEnv`:
|
|
270
|
-
|
|
271
|
-
- Set `A2A_API_KEY=<A2A_API_KEY_VALUE>` in the server's deployment environment
|
|
272
|
-
- Callers pass it as `Authorization: Bearer <A2A_API_KEY_VALUE>`
|
|
273
|
-
- The agent card endpoint (`/.well-known/agent-card.json`) is public — no auth needed for discovery
|
|
274
|
-
|
|
275
|
-
Never hardcode the bearer token in source, docs, prompts, app state, action
|
|
276
|
-
descriptions, client bundles, or examples. A2A tokens are deploy-level secrets
|
|
277
|
-
unless a specific app designs a scoped credential flow; read them from secure
|
|
278
|
-
runtime configuration and never log or return them.
|
|
279
|
-
|
|
280
313
|
## Message Parts
|
|
281
314
|
|
|
282
315
|
Messages contain typed parts:
|
|
@@ -287,34 +320,38 @@ Messages contain typed parts:
|
|
|
287
320
|
| `file` | `{ type: "file", file: { ... } }` | Files (bytes or URI) |
|
|
288
321
|
| `data` | `{ type: "data", data: { ... } }` | Structured JSON data |
|
|
289
322
|
|
|
290
|
-
##
|
|
323
|
+
## Custom mount
|
|
291
324
|
|
|
292
|
-
|
|
325
|
+
Only when the default card is wrong for the app — a curated skill list, a
|
|
326
|
+
non-agent handler, or static bearer auth against an external peer:
|
|
293
327
|
|
|
294
328
|
```ts
|
|
295
|
-
//
|
|
296
|
-
import {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
mode: "compose",
|
|
329
|
+
// server/plugins/a2a.ts
|
|
330
|
+
import { mountA2A } from "@agent-native/core/a2a";
|
|
331
|
+
|
|
332
|
+
export default defineNitroPlugin((nitro) => {
|
|
333
|
+
mountA2A(nitro, {
|
|
334
|
+
appId: "analytics",
|
|
335
|
+
name: "Analytics Agent",
|
|
336
|
+
description: "Queries analytics data across providers",
|
|
337
|
+
skills: [
|
|
338
|
+
{
|
|
339
|
+
id: "query-data",
|
|
340
|
+
name: "Query Data",
|
|
341
|
+
description: "Run analytics queries across connected data sources",
|
|
342
|
+
tags: ["analytics", "data"],
|
|
343
|
+
examples: ["What were last week's signups?", "Show conversion rates"],
|
|
344
|
+
},
|
|
345
|
+
],
|
|
346
|
+
streaming: true,
|
|
314
347
|
});
|
|
315
|
-
}
|
|
348
|
+
});
|
|
316
349
|
```
|
|
317
350
|
|
|
351
|
+
Config also carries `handler`, `publicSkillsOnly`, `durableBackgroundRuns`,
|
|
352
|
+
`executeReadOnlyAction`, `executeApproval`, and `apiKeyEnv`. See `A2AConfig` in
|
|
353
|
+
`@agent-native/core/a2a` for the full shape.
|
|
354
|
+
|
|
318
355
|
## All Types
|
|
319
356
|
|
|
320
357
|
All types are exported from `@agent-native/core/a2a`:
|
|
@@ -345,5 +382,8 @@ import type {
|
|
|
345
382
|
## Related Skills
|
|
346
383
|
|
|
347
384
|
- **delegate-to-agent** — For work the local agent handles. Use A2A when the work goes to a different agent.
|
|
348
|
-
- **
|
|
349
|
-
- **
|
|
385
|
+
- **authentication** — Org creation, membership, and where the org secret lives.
|
|
386
|
+
- **actions** — A2A calls typically happen inside actions; `publicAgent` marks what peers can see.
|
|
387
|
+
- **storing-data** — Results from A2A calls are stored in SQL like any other data.
|
|
388
|
+
</content>
|
|
389
|
+
</invoke>
|
|
@@ -225,13 +225,13 @@ In practice, every agent-native app should be authored with both: MCP Apps for i
|
|
|
225
225
|
|
|
226
226
|
On top of the per-action tools the MCP server exposes a stable verb set, so an external agent has a predictable surface without guessing per-app action names:
|
|
227
227
|
|
|
228
|
-
| Tool | Side effects | Returns
|
|
229
|
-
| -------------------------------------------------- | ------------ |
|
|
230
|
-
| `list_apps` | none | workspace apps + their URLs / running state
|
|
231
|
-
| `open_app({ app, view?, path?, params?, embed? })` | none | a deep link or same-origin route; `embed: true` renders the full app inline where supported
|
|
232
|
-
| `ask_app({ app, message, async?, maxWaitMs? })` | agent loop | routes a natural-language task to that app's in-app agent; long work returns a durable `taskId` for `ask_app_status` polling |
|
|
233
|
-
| `create_workspace_app({ name, template })` | scaffolds | a new app booted via the workspace path, plus its running URL + deep link
|
|
234
|
-
| `list_templates` | none | the allow-listed templates only
|
|
228
|
+
| Tool | Side effects | Returns |
|
|
229
|
+
| -------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
230
|
+
| `list_apps` | none | workspace apps + their URLs / running state |
|
|
231
|
+
| `open_app({ app, view?, path?, params?, embed? })` | none | a deep link or same-origin route; `embed: true` renders the full app inline where supported |
|
|
232
|
+
| `ask_app({ app, message, async?, maxWaitMs? })` | agent loop | routes a natural-language task to that app's in-app agent; long work returns a durable `taskHandle` plus a legacy `taskId` for `ask_app_status` polling |
|
|
233
|
+
| `create_workspace_app({ name, template })` | scaffolds | a new app booted via the workspace path, plus its running URL + deep link |
|
|
234
|
+
| `list_templates` | none | the allow-listed templates only |
|
|
235
235
|
|
|
236
236
|
`create_workspace_app` rejects any non-allow-listed template — the public template allow-list in `packages/shared-app-config/templates.ts` is authoritative and CI-guarded; an external agent cannot widen it. A same-named template action overrides a builtin (template-over-core precedence). Disable the whole set with `MCPConfig.builtinCrossAppTools: false`.
|
|
237
237
|
|
|
@@ -244,9 +244,10 @@ For fast ChatGPT/Claude handoffs, the ideal path is direct: call the action that
|
|
|
244
244
|
MCP hosts and gateways do not share one long tool-call timeout; some enforce a
|
|
245
245
|
five-minute ceiling and others are configurable. Do not design an external
|
|
246
246
|
agent integration around a ten-minute blocking `tools/call`. `ask-agent` and
|
|
247
|
-
`ask_app` acknowledge hosted work quickly, then return a durable `
|
|
248
|
-
the inline wait expires. Poll with `ask_app_status`
|
|
249
|
-
|
|
247
|
+
`ask_app` acknowledge hosted work quickly, then return a durable `taskHandle`
|
|
248
|
+
plus a legacy `taskId` when the inline wait expires. Poll with `ask_app_status`
|
|
249
|
+
by replaying the returned `poll.arguments` unchanged, especially the
|
|
250
|
+
`taskHandle`; the result includes `pollAfterMs` as a host-friendly interval.
|
|
250
251
|
The task must be created before the first response can time out, so a polling
|
|
251
252
|
URL returned only after a long call is not a reliable recovery contract.
|
|
252
253
|
|
|
@@ -254,7 +255,9 @@ If a bounded transient status read is unavailable, `ask_app_status` can return
|
|
|
254
255
|
`status: "unknown"`, `statusRead: "unavailable"`, `retryable: true`, the
|
|
255
256
|
original `app` and `taskId`, and `pollAfterMs` / `poll`. This means the status
|
|
256
257
|
read is unavailable—not that the durable task failed. Retry `ask_app_status`
|
|
257
|
-
with
|
|
258
|
+
with the exact returned `poll.arguments`, including `taskHandle` when present;
|
|
259
|
+
legacy results without a handle must reuse the same `app` and `taskId`. Never
|
|
260
|
+
resubmit `ask_app` to recover, because
|
|
258
261
|
submission can duplicate work. Permanent authentication, not-found, and
|
|
259
262
|
protocol failures remain errors.
|
|
260
263
|
|
|
@@ -235,7 +235,11 @@ The agent runs the same loop as the interactive chat — it can call multiple to
|
|
|
235
235
|
{
|
|
236
236
|
"poll": {
|
|
237
237
|
"tool": "ask_app_status",
|
|
238
|
-
"arguments": {
|
|
238
|
+
"arguments": {
|
|
239
|
+
"app": "mail",
|
|
240
|
+
"taskId": "task_123",
|
|
241
|
+
"taskHandle": "opaque_handle"
|
|
242
|
+
}
|
|
239
243
|
}
|
|
240
244
|
}
|
|
241
245
|
```
|
|
@@ -248,9 +252,10 @@ If a bounded transient status read is unavailable, `ask_app_status` can return
|
|
|
248
252
|
`status: "unknown"`, `statusRead: "unavailable"`, `retryable: true`, the
|
|
249
253
|
original `app` and `taskId`, and `pollAfterMs` / `poll`. This means the status
|
|
250
254
|
read is unavailable—not that the durable task failed. Retry `ask_app_status`
|
|
251
|
-
with
|
|
252
|
-
|
|
253
|
-
|
|
255
|
+
with the returned `poll.arguments` unchanged, including `taskHandle` when
|
|
256
|
+
present; legacy results without a handle must reuse the same `app` and `taskId`.
|
|
257
|
+
Never resubmit `ask_app` to recover, because submission can duplicate work.
|
|
258
|
+
Permanent authentication, not-found, and protocol failures remain errors.
|
|
254
259
|
|
|
255
260
|
## Authentication {#authentication}
|
|
256
261
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.127.1",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -389,7 +389,7 @@
|
|
|
389
389
|
"yjs": "^13.6.31",
|
|
390
390
|
"zod": "^4.3.6",
|
|
391
391
|
"@agent-native/recap-cli": "0.5.1",
|
|
392
|
-
"@agent-native/toolkit": "^0.10.
|
|
392
|
+
"@agent-native/toolkit": "^0.10.9"
|
|
393
393
|
},
|
|
394
394
|
"devDependencies": {
|
|
395
395
|
"@ai-sdk/anthropic": "^3.0.71",
|
package/src/a2a/index.ts
CHANGED
|
@@ -21,6 +21,8 @@ export {
|
|
|
21
21
|
|
|
22
22
|
// Client
|
|
23
23
|
export { A2AClient, callAction, callAgent, signA2AToken } from "./client.js";
|
|
24
|
+
export { resolveA2ACallerAuth } from "./caller-auth.js";
|
|
25
|
+
export type { A2ACallerAuth } from "./caller-auth.js";
|
|
24
26
|
export {
|
|
25
27
|
AgentInvocationError,
|
|
26
28
|
buildAgentInvocationPrompt,
|
|
@@ -141,6 +141,7 @@ import {
|
|
|
141
141
|
getRun,
|
|
142
142
|
abortRun,
|
|
143
143
|
abortRunDurably,
|
|
144
|
+
abortTurnDurably,
|
|
144
145
|
tryClaimRunSlot,
|
|
145
146
|
isHostedRuntime,
|
|
146
147
|
resolveRunSoftTimeoutMs,
|
|
@@ -7409,8 +7410,11 @@ export function createProductionAgentHandler(
|
|
|
7409
7410
|
// sent from the model picker; `engine.name` is what resolveEngine picked.
|
|
7410
7411
|
// Divergence between them is the usual cause of "status says builder but
|
|
7411
7412
|
// no [builder-engine] log lines appear" confusion.
|
|
7413
|
+
// `requestModel` differing from `model` means normalizeModelForEngine
|
|
7414
|
+
// substituted the engine default — otherwise indistinguishable from the
|
|
7415
|
+
// client never asking for one.
|
|
7412
7416
|
console.log(
|
|
7413
|
-
`[agent-chat] resolved engine=${engine.name} model=${effectiveModel} requestEngine=${requestEngine ?? "(none)"} modelSource=${modelSelectionSource}`,
|
|
7417
|
+
`[agent-chat] resolved engine=${engine.name} model=${effectiveModel} requestModel=${requestModel ?? "(none)"} requestEngine=${requestEngine ?? "(none)"} modelSource=${modelSelectionSource} turnId=${requestTurnId ?? "(none)"}`,
|
|
7414
7418
|
);
|
|
7415
7419
|
|
|
7416
7420
|
if (
|
|
@@ -9020,5 +9024,6 @@ export {
|
|
|
9020
9024
|
getRun,
|
|
9021
9025
|
abortRun,
|
|
9022
9026
|
abortRunDurably,
|
|
9027
|
+
abortTurnDurably,
|
|
9023
9028
|
subscribeToRun,
|
|
9024
9029
|
};
|