@agent-native/core 0.131.2 → 0.131.4
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 +1 -1
- package/corpus/core/CHANGELOG.md +34 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/types.ts +6 -0
- package/corpus/core/src/action.ts +13 -0
- package/corpus/core/src/client/AgentPanel.tsx +58 -34
- package/corpus/core/src/localization/default-messages.ts +6 -0
- package/corpus/core/src/server/agent-capabilities.ts +43 -8
- package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +63 -1
- package/corpus/templates/analytics/AGENTS.md +5 -0
- package/corpus/templates/analytics/actions/hubspot-deals.ts +1 -0
- package/corpus/templates/analytics/actions/hubspot-records.ts +1 -0
- package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +2 -0
- package/corpus/templates/calendar/actions/get-event.ts +1 -0
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +1 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +7 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +14 -19
- package/corpus/templates/calendar/app/hooks/use-events.ts +7 -0
- package/corpus/templates/calendar/app/lib/event-form-utils.ts +13 -0
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +21 -14
- package/corpus/templates/calendar/changelog/2026-07-29-unnamed-events-now-use-a-title-placeholder.md +6 -0
- package/corpus/templates/calendar/server/lib/google-calendar.ts +2 -0
- package/corpus/templates/calendar/server/lib/ical-fetcher.ts +1 -0
- package/corpus/templates/calendar/shared/api.ts +2 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +3 -1
- package/corpus/templates/design/actions/get-design.ts +11 -3
- package/corpus/templates/design/actions/present-design-variants.ts +62 -5
- package/corpus/templates/design/app/components/design/BreakpointBar.tsx +64 -1
- package/corpus/templates/design/app/components/design/EditPanel.tsx +199 -25
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +160 -46
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +7 -1
- package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +59 -12
- package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +1 -1
- package/corpus/templates/design/app/components/design/edit-panel/inspector-controls.tsx +34 -29
- package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +2 -2
- package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +28 -10
- package/corpus/templates/design/app/components/design/inspector/design-icons.tsx +15 -28
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +4 -3
- package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +12 -8
- package/corpus/templates/design/app/components/design/multi-screen/culling.ts +34 -9
- package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +13 -27
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +8 -1
- package/corpus/templates/design/app/components/design/multi-screen/zoom-gesture.ts +95 -0
- package/corpus/templates/design/app/i18n-data.ts +121 -10
- package/corpus/templates/design/app/pages/design-editor/data-operations.ts +45 -0
- package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +59 -0
- package/corpus/templates/design/app/pages/design-editor/text-edit-utils.ts +115 -40
- package/corpus/templates/design/changelog/2026-07-28-generated-design-variants-no-longer-overlap-each-other-on-th.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-auto-layout-direction-icons-show-an-arrow.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-breakpoints-no-longer-overlap-neighbouring-screens.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-canvas-is-more-responsive-when-selecting-and-adding-frames.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-canvas-zoom-is-smoother-and-labels-hold-their-size.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-double-click-a-frame-now-drills-into-its-layers.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-export-preview-shows-the-real-render.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-figma-parity-shortcuts.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-more-breakpoint-width-presets.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-resize-a-selected-frame-to-a-device-preset.md +6 -0
- package/corpus/templates/design/changelog/2026-07-29-text-tool-reaches-the-right-surface.md +6 -0
- package/corpus/templates/design/shared/canvas-frames.ts +23 -0
- package/corpus/templates/design/shared/code-layer.ts +54 -2
- package/corpus/templates/design/shared/responsive-frame-layout.ts +55 -0
- package/corpus/templates/slides/.agents/skills/analytics-data-for-decks/SKILL.md +48 -0
- package/corpus/templates/slides/AGENTS.md +3 -0
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +72 -8
- package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
- package/corpus/templates/slides/changelog/2026-07-29-google-slides-exports-can-connect-your-google-account-direct.md +6 -0
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +4 -2
- package/dist/a2a/types.d.ts +6 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/action.d.ts +13 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +16 -5
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/localization/default-messages.d.ts +6 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +6 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-capabilities.d.ts.map +1 -1
- package/dist/server/agent-capabilities.js +32 -3
- package/dist/server/agent-capabilities.js.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.d.ts +17 -1
- package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.js +50 -1
- package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/package.json +1 -1
- package/src/a2a/types.ts +6 -0
- package/src/action.ts +13 -0
- package/src/client/AgentPanel.tsx +58 -34
- package/src/localization/default-messages.ts +6 -0
- package/src/server/agent-capabilities.ts +43 -8
- package/src/server/agent-chat/action-filters-a2a.ts +63 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-capabilities.js","sourceRoot":"","sources":["../../src/server/agent-capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["import { A2AClient } from \"../a2a/client.js\";\nimport type { AgentCard, AgentSkill } from \"../a2a/types.js\";\nimport { type DiscoveredAgent } from \"./agent-discovery.js\";\nimport { getRequestUserEmail } from \"./request-context.js\";\n\n/** Matches the `<available-apps>` prompt block so both surfaces agree. */\nexport const MAX_APPS = 30;\nconst MAX_SKILLS_IN_SUMMARY = 8;\nconst MAX_SKILLS_IN_DETAIL = 60;\nconst MAX_DESCRIPTION_CHARS = 240;\nconst CARD_TIMEOUT_MS = 6_000;\nconst CARD_CONCURRENCY = 8;\n\nexport interface PeerCapabilities {\n agent: DiscoveredAgent;\n /** null distinguishes an unreachable card from a peer that exposes nothing. */\n skills: AgentSkill[] | null;\n cardDescription?: string;\n error?: string;\n /**\n * The full card from this same fetch, for callers that need more than\n * skills/description (e.g. the peer-probe route's name/securitySchemes).\n * Kept optional so existing consumers of this shape are unaffected.\n */\n card?: AgentCard;\n}\n\nfunction truncate(value: string, max: number): string {\n const collapsed = value.replace(/\\s+/g, \" \").trim();\n return collapsed.length > max ? `${collapsed.slice(0, max - 1)}…` : collapsed;\n}\n\nexport async function loadCapabilities(\n agent: DiscoveredAgent,\n): Promise<PeerCapabilities> {\n try {\n // Discover as ourselves. An anonymous card lists only publicly-safe\n // actions, which never overlap the set `actions/invoke` accepts, so an\n // unauthenticated probe reports every sibling as having no callable\n // actions and pushes the caller into open-ended delegation.\n let token: string | undefined;\n try {\n const { signA2AToken } = await import(\"../a2a/client.js\");\n const email = getRequestUserEmail();\n if (email) {\n token = await signA2AToken(email, undefined, undefined, {\n preferGlobalSecret: true,\n audience: new URL(agent.url).origin,\n });\n }\n } catch {\n // No signable identity (no secret, no session) — fall back to the\n // anonymous card rather than failing discovery outright.\n }\n const card = await new A2AClient(agent.url).getAgentCard({\n timeoutMs: CARD_TIMEOUT_MS,\n ...(token ? { token } : {}),\n });\n return {\n agent,\n skills: Array.isArray(card.skills) ? card.skills : [],\n cardDescription:\n typeof card.description === \"string\" ? card.description : undefined,\n card,\n };\n } catch (error) {\n return {\n agent,\n skills: null,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function loadAllCapabilities(\n agents: DiscoveredAgent[],\n): Promise<PeerCapabilities[]> {\n const results: PeerCapabilities[] = [];\n for (let i = 0; i < agents.length; i += CARD_CONCURRENCY) {\n results.push(\n ...(await Promise.all(\n agents.slice(i, i + CARD_CONCURRENCY).map(loadCapabilities),\n )),\n );\n }\n return results;\n}\n\nexport function purposeOf(peer: PeerCapabilities): string {\n // The manifest description comes from the app's own package.json and is\n // authored; the card description is a generic template for auto-mounted\n // apps, so it is only a fallback.\n const manifest = peer.agent.description?.trim();\n if (manifest) return truncate(manifest, MAX_DESCRIPTION_CHARS);\n const card = peer.cardDescription?.trim();\n return card\n ? truncate(card, MAX_DESCRIPTION_CHARS)\n : \"(no description published)\";\n}\n\n/**\n * `detailHint` differs per surface: the agent tool tells the model to call\n * itself again with an app id, the CLI tells the reader to pass `--app`.\n */\nexport function formatCapabilitySummary(\n peers: PeerCapabilities[],\n truncated: number,\n detailHint: (appId: string) => string,\n): string {\n const lines = peers.map((peer) => {\n const header = `### ${peer.agent.name} (${peer.agent.id})\\n${purposeOf(peer)}`;\n if (peer.skills === null) {\n return `${header}\\nCapabilities: could not read agent card (${truncate(peer.error ?? \"unreachable\", 120)}). Delegate with a natural-language message instead of a direct action.`;\n }\n if (peer.skills.length === 0) {\n return `${header}\\nCapabilities: exposes no directly callable actions. Delegate with a natural-language message via call-agent.`;\n }\n const shown = peer.skills.slice(0, MAX_SKILLS_IN_SUMMARY);\n const rest = peer.skills.length - shown.length;\n return `${header}\\nCallable actions: ${shown.map((skill) => skill.id).join(\", \")}${\n rest > 0 ? ` (+${rest} more — ${detailHint(peer.agent.id)})` : \"\"\n }`;\n });\n\n return [\n `${peers.length} other app${peers.length === 1 ? \"\" : \"s\"} reachable from this one over A2A.`,\n truncated > 0\n ? `(${truncated} additional app${truncated === 1 ? \"\" : \"s\"} not shown.)`\n : \"\",\n \"\",\n lines.join(\"\\n\\n\"),\n \"\",\n \"Delegate with call-agent: pass action + input for a listed action, or message for open-ended work. Prefer the app that owns the data over rebuilding its capability here.\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nexport function formatCapabilityDetail(\n peer: PeerCapabilities,\n callHint: (appId: string) => string,\n): string {\n const header = `## ${peer.agent.name} (${peer.agent.id})\\n${purposeOf(peer)}\\nURL: ${peer.agent.url}`;\n\n if (peer.skills === null) {\n return `${header}\\n\\nIts agent card could not be read (${truncate(peer.error ?? \"unreachable\", 200)}), so its callable actions are unknown. It may still answer a natural-language call-agent message.`;\n }\n if (peer.skills.length === 0) {\n return `${header}\\n\\nIt exposes no directly callable actions. Delegate with a natural-language call-agent message.`;\n }\n\n const shown = peer.skills.slice(0, MAX_SKILLS_IN_DETAIL);\n const rest = peer.skills.length - shown.length;\n const lines = shown.map(\n (skill) =>\n `- ${skill.id}${skill.readOnly ? \"\" : \" (mutating)\"}: ${\n skill.description\n ? truncate(skill.description, MAX_DESCRIPTION_CHARS)\n : skill.name || \"(no description)\"\n }`,\n );\n\n return [\n header,\n \"\",\n \"Callable actions:\",\n lines.join(\"\\n\"),\n rest > 0 ? `(+${rest} more not shown.)` : \"\",\n \"\",\n callHint(peer.agent.id),\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agent-capabilities.js","sourceRoot":"","sources":["../../src/server/agent-capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,0EAA0E;AAC1E,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,CAAC;AAC3B,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAChC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAChC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,MAAM,eAAe,GAAG,KAAK,CAAC;AAC9B,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAgB3B,SAAS,QAAQ,CAAC,KAAa,EAAE,GAAW;IAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,OAAO,SAAS,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AAChF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAsB;IAEtB,IAAI,CAAC;QACH,oEAAoE;QACpE,uEAAuE;QACvE,oEAAoE;QACpE,4DAA4D;QAC5D,IAAI,KAAyB,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;YAC1D,MAAM,KAAK,GAAG,mBAAmB,EAAE,CAAC;YACpC,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE;oBACtD,kBAAkB,EAAE,IAAI;oBACxB,QAAQ,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM;iBACpC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;YAClE,yDAAyD;QAC3D,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC;YACvD,SAAS,EAAE,eAAe;YAC1B,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5B,CAAC,CAAC;QACH,OAAO;YACL,KAAK;YACL,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YACrD,eAAe,EACb,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;YACrE,IAAI;SACL,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,KAAK;YACL,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAyB;IAEzB,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,gBAAgB,EAAE,CAAC;QACzD,OAAO,CAAC,IAAI,CACV,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,CACnB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAC5D,CAAC,CACH,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAsB;IAC9C,wEAAwE;IACxE,wEAAwE;IACxE,kCAAkC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IAChD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC;IAC1C,OAAO,IAAI;QACT,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;QACvC,CAAC,CAAC,4BAA4B,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,KAAyB,EACzB,SAAiB,EACjB,UAAqC;IAErC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC/B,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/E,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YACzB,OAAO,GAAG,MAAM,8CAA8C,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,aAAa,EAAE,GAAG,CAAC,yEAAyE,CAAC;QACpL,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO,GAAG,MAAM,gHAAgH,CAAC;QACnI,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC/C,OAAO,GAAG,MAAM,uBAAuB,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAC9E,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,WAAW,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EACjE,EAAE,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,GAAG,KAAK,CAAC,MAAM,aAAa,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,oCAAoC;QAC7F,SAAS,GAAG,CAAC;YACX,CAAC,CAAC,IAAI,SAAS,kBAAkB,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,cAAc;YACzE,CAAC,CAAC,EAAE;QACN,EAAE;QACF,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QAClB,EAAE;QACF,2KAA2K;KAC5K;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,KAAiB;IACzC,MAAM,MAAM,GAAG,KAAK,CAAC,WAKR,CAAC;IACd,MAAM,UAAU,GAAG,MAAM,EAAE,UAAU,CAAC;IACtC,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACpE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,0BAA0B,CAAC;IAE1D,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC;QAC7B,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CACpB,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CACnD;QACH,CAAC,CAAC,EAAE,CACP,CAAC;IACF,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAChC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;QACpC,MAAM,QAAQ,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;QACzD,OAAO,GAAG,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;IACjE,CAAC,CAAC,CAAC;IACH,OAAO,eAAe,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,IAAsB,EACtB,QAAmC;IAEnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,SAAS,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IAEtG,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QACzB,OAAO,GAAG,MAAM,yCAAyC,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,aAAa,EAAE,GAAG,CAAC,oGAAoG,CAAC;IAC1M,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,GAAG,MAAM,mGAAmG,CAAC;IACtH,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAChC,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW;YAC/B,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,qBAAqB,CAAC;YACpD,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,kBAAkB,CAAC;QACrC,2EAA2E;QAC3E,2EAA2E;QAC3E,0CAA0C;QAC1C,OAAO,KAAK,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,OAAO,GACpE,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAC7B,EAAE,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,MAAM;QACN,EAAE;QACF,mBAAmB;QACnB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAChB,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,mBAAmB,CAAC,CAAC,CAAC,EAAE;QAC5C,EAAE;QACF,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;KACxB;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC","sourcesContent":["import { A2AClient } from \"../a2a/client.js\";\nimport type { AgentCard, AgentSkill } from \"../a2a/types.js\";\nimport { type DiscoveredAgent } from \"./agent-discovery.js\";\nimport { getRequestUserEmail } from \"./request-context.js\";\n\n/** Matches the `<available-apps>` prompt block so both surfaces agree. */\nexport const MAX_APPS = 30;\nconst MAX_SKILLS_IN_SUMMARY = 8;\nconst MAX_SKILLS_IN_DETAIL = 60;\nconst MAX_DESCRIPTION_CHARS = 240;\nconst CARD_TIMEOUT_MS = 6_000;\nconst CARD_CONCURRENCY = 8;\n\nexport interface PeerCapabilities {\n agent: DiscoveredAgent;\n /** null distinguishes an unreachable card from a peer that exposes nothing. */\n skills: AgentSkill[] | null;\n cardDescription?: string;\n error?: string;\n /**\n * The full card from this same fetch, for callers that need more than\n * skills/description (e.g. the peer-probe route's name/securitySchemes).\n * Kept optional so existing consumers of this shape are unaffected.\n */\n card?: AgentCard;\n}\n\nfunction truncate(value: string, max: number): string {\n const collapsed = value.replace(/\\s+/g, \" \").trim();\n return collapsed.length > max ? `${collapsed.slice(0, max - 1)}…` : collapsed;\n}\n\nexport async function loadCapabilities(\n agent: DiscoveredAgent,\n): Promise<PeerCapabilities> {\n try {\n // Discover as ourselves. An anonymous card lists only publicly-safe\n // actions, which never overlap the set `actions/invoke` accepts, so an\n // unauthenticated probe reports every sibling as having no callable\n // actions and pushes the caller into open-ended delegation.\n let token: string | undefined;\n try {\n const { signA2AToken } = await import(\"../a2a/client.js\");\n const email = getRequestUserEmail();\n if (email) {\n token = await signA2AToken(email, undefined, undefined, {\n preferGlobalSecret: true,\n audience: new URL(agent.url).origin,\n });\n }\n } catch {\n // No signable identity (no secret, no session) — fall back to the\n // anonymous card rather than failing discovery outright.\n }\n const card = await new A2AClient(agent.url).getAgentCard({\n timeoutMs: CARD_TIMEOUT_MS,\n ...(token ? { token } : {}),\n });\n return {\n agent,\n skills: Array.isArray(card.skills) ? card.skills : [],\n cardDescription:\n typeof card.description === \"string\" ? card.description : undefined,\n card,\n };\n } catch (error) {\n return {\n agent,\n skills: null,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function loadAllCapabilities(\n agents: DiscoveredAgent[],\n): Promise<PeerCapabilities[]> {\n const results: PeerCapabilities[] = [];\n for (let i = 0; i < agents.length; i += CARD_CONCURRENCY) {\n results.push(\n ...(await Promise.all(\n agents.slice(i, i + CARD_CONCURRENCY).map(loadCapabilities),\n )),\n );\n }\n return results;\n}\n\nexport function purposeOf(peer: PeerCapabilities): string {\n // The manifest description comes from the app's own package.json and is\n // authored; the card description is a generic template for auto-mounted\n // apps, so it is only a fallback.\n const manifest = peer.agent.description?.trim();\n if (manifest) return truncate(manifest, MAX_DESCRIPTION_CHARS);\n const card = peer.cardDescription?.trim();\n return card\n ? truncate(card, MAX_DESCRIPTION_CHARS)\n : \"(no description published)\";\n}\n\n/**\n * `detailHint` differs per surface: the agent tool tells the model to call\n * itself again with an app id, the CLI tells the reader to pass `--app`.\n */\nexport function formatCapabilitySummary(\n peers: PeerCapabilities[],\n truncated: number,\n detailHint: (appId: string) => string,\n): string {\n const lines = peers.map((peer) => {\n const header = `### ${peer.agent.name} (${peer.agent.id})\\n${purposeOf(peer)}`;\n if (peer.skills === null) {\n return `${header}\\nCapabilities: could not read agent card (${truncate(peer.error ?? \"unreachable\", 120)}). Delegate with a natural-language message instead of a direct action.`;\n }\n if (peer.skills.length === 0) {\n return `${header}\\nCapabilities: exposes no directly callable actions. Delegate with a natural-language message via call-agent.`;\n }\n const shown = peer.skills.slice(0, MAX_SKILLS_IN_SUMMARY);\n const rest = peer.skills.length - shown.length;\n return `${header}\\nCallable actions: ${shown.map((skill) => skill.id).join(\", \")}${\n rest > 0 ? ` (+${rest} more — ${detailHint(peer.agent.id)})` : \"\"\n }`;\n });\n\n return [\n `${peers.length} other app${peers.length === 1 ? \"\" : \"s\"} reachable from this one over A2A.`,\n truncated > 0\n ? `(${truncated} additional app${truncated === 1 ? \"\" : \"s\"} not shown.)`\n : \"\",\n \"\",\n lines.join(\"\\n\\n\"),\n \"\",\n \"Delegate with call-agent: pass action + input for a listed action, or message for open-ended work. Prefer the app that owns the data over rebuilding its capability here.\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n\n/**\n * Render a skill's `input` contract as `input: { field*: type, other?: type }`,\n * marking required fields with `*`. Returns undefined when the skill publishes\n * no schema, so callers fall back to the description alone.\n */\nfunction formatSkillInput(skill: AgentSkill): string | undefined {\n const schema = skill.inputSchema as\n | {\n properties?: Record<string, { type?: unknown }>;\n required?: unknown;\n }\n | undefined;\n const properties = schema?.properties;\n if (!properties || typeof properties !== \"object\") return undefined;\n const names = Object.keys(properties);\n if (names.length === 0) return \" — input: {} (no fields)\";\n\n const required = new Set(\n Array.isArray(schema?.required)\n ? schema.required.filter(\n (name): name is string => typeof name === \"string\",\n )\n : [],\n );\n const fields = names.map((name) => {\n const type = properties[name]?.type;\n const rendered = typeof type === \"string\" ? type : \"any\";\n return `${name}${required.has(name) ? \"*\" : \"?\"}: ${rendered}`;\n });\n return ` — input: { ${fields.join(\", \")} } (* = required)`;\n}\n\nexport function formatCapabilityDetail(\n peer: PeerCapabilities,\n callHint: (appId: string) => string,\n): string {\n const header = `## ${peer.agent.name} (${peer.agent.id})\\n${purposeOf(peer)}\\nURL: ${peer.agent.url}`;\n\n if (peer.skills === null) {\n return `${header}\\n\\nIts agent card could not be read (${truncate(peer.error ?? \"unreachable\", 200)}), so its callable actions are unknown. It may still answer a natural-language call-agent message.`;\n }\n if (peer.skills.length === 0) {\n return `${header}\\n\\nIt exposes no directly callable actions. Delegate with a natural-language call-agent message.`;\n }\n\n const shown = peer.skills.slice(0, MAX_SKILLS_IN_DETAIL);\n const rest = peer.skills.length - shown.length;\n const lines = shown.map((skill) => {\n const summary = skill.description\n ? truncate(skill.description, MAX_DESCRIPTION_CHARS)\n : skill.name || \"(no description)\";\n // Naming an action without its parameters is what makes a caller invoke it\n // with `{}` and fail on a required field, which reads as the sibling being\n // broken rather than as a malformed call.\n return `- ${skill.id}${skill.readOnly ? \"\" : \" (mutating)\"}: ${summary}${\n formatSkillInput(skill) ?? \"\"\n }`;\n });\n\n return [\n header,\n \"\",\n \"Callable actions:\",\n lines.join(\"\\n\"),\n rest > 0 ? `(+${rest} more not shown.)` : \"\",\n \"\",\n callHint(peer.agent.id),\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n"]}
|
|
@@ -12,10 +12,24 @@ export declare function filterReadOnlyActions(actions: Record<string, ActionEntr
|
|
|
12
12
|
* Default-allow: only an explicit `false` is excluded. */
|
|
13
13
|
export declare function filterAgentTools(actions: Record<string, ActionEntry>): Record<string, ActionEntry>;
|
|
14
14
|
export declare function filterPublicAgentActions(actions: Record<string, ActionEntry>): Record<string, ActionEntry>;
|
|
15
|
+
/**
|
|
16
|
+
* True when an action takes a free-form query or program as input — raw SQL, a
|
|
17
|
+
* code body, an arbitrary expression.
|
|
18
|
+
*
|
|
19
|
+
* Such an action must not be sibling-invocable over A2A. The app that owns the
|
|
20
|
+
* data owns its schema, data dictionary, skills, and reference queries; a
|
|
21
|
+
* calling app has none of that, so letting it pass SQL means every caller
|
|
22
|
+
* reimplements the owner's schema knowledge badly and silently rots when the
|
|
23
|
+
* owner's shape changes. Callers ask the owning app a question; the owner
|
|
24
|
+
* forms the query. Set `publicAgent.allowRawQueryInput` to opt a specific
|
|
25
|
+
* action out of this rule.
|
|
26
|
+
*/
|
|
27
|
+
export declare function hasRawQueryInput(entry: ActionEntry): boolean;
|
|
15
28
|
/**
|
|
16
29
|
* Direct A2A action calls share the authenticated external-agent policy with
|
|
17
30
|
* MCP, but remain stricter: only explicitly exposed, authenticated read-only
|
|
18
|
-
* actions can skip the receiver's model loop
|
|
31
|
+
* actions can skip the receiver's model loop, and never one that takes a raw
|
|
32
|
+
* query the caller wrote.
|
|
19
33
|
*/
|
|
20
34
|
export declare function filterDirectA2AActions(actions: Record<string, ActionEntry>, options: Pick<AgentChatPluginOptions, "connectorCatalog" | "externalAgents">): Record<string, ActionEntry>;
|
|
21
35
|
export declare function buildPublicAgentA2ASkills(actions: Record<string, ActionEntry>): Array<{
|
|
@@ -23,6 +37,7 @@ export declare function buildPublicAgentA2ASkills(actions: Record<string, Action
|
|
|
23
37
|
name: string;
|
|
24
38
|
description: string;
|
|
25
39
|
publicAgent: ActionEntry["publicAgent"];
|
|
40
|
+
inputSchema?: Record<string, unknown>;
|
|
26
41
|
}>;
|
|
27
42
|
/**
|
|
28
43
|
* Skills for a caller with a verified A2A identity: exactly what
|
|
@@ -37,6 +52,7 @@ export declare function buildAuthenticatedAgentA2ASkills(actions: Record<string,
|
|
|
37
52
|
name: string;
|
|
38
53
|
description: string;
|
|
39
54
|
publicAgent: ActionEntry["publicAgent"];
|
|
55
|
+
inputSchema?: Record<string, unknown>;
|
|
40
56
|
}>;
|
|
41
57
|
export declare function resolveArtifactBaseUrl(event: any | undefined): string | undefined;
|
|
42
58
|
export declare function assembleA2AFinalResponse(events: readonly AgentChatEvent[], toolResults: readonly A2AToolResultSummary[], options?: A2AArtifactResponseOptions & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-filters-a2a.d.ts","sourceRoot":"","sources":["../../../src/server/agent-chat/action-filters-a2a.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,EAC1B,MAAM,gCAAgC,CAAC;AAGxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAM3D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAQlE,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GACnC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAI7B;AAED;;;;2DAI2D;AAC3D,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GACnC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAI7B;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GACnC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAY7B;AAED
|
|
1
|
+
{"version":3,"file":"action-filters-a2a.d.ts","sourceRoot":"","sources":["../../../src/server/agent-chat/action-filters-a2a.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,10 +31,45 @@ export function filterPublicAgentActions(actions) {
|
|
|
31
31
|
config.isConsequential !== true);
|
|
32
32
|
}));
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Input fields that unambiguously carry a program the receiver executes.
|
|
36
|
+
*
|
|
37
|
+
* Deliberately excludes `query`: across the templates that field is nearly
|
|
38
|
+
* always natural-language search text (Brain's `search-everything`,
|
|
39
|
+
* `search-knowledge`), and blocking it would break exactly the ask-don't-instruct
|
|
40
|
+
* calls this rule exists to encourage.
|
|
41
|
+
*/
|
|
42
|
+
const RAW_QUERY_INPUT_FIELDS = new Set(["sql", "code", "script", "expression"]);
|
|
43
|
+
/**
|
|
44
|
+
* True when an action takes a free-form query or program as input — raw SQL, a
|
|
45
|
+
* code body, an arbitrary expression.
|
|
46
|
+
*
|
|
47
|
+
* Such an action must not be sibling-invocable over A2A. The app that owns the
|
|
48
|
+
* data owns its schema, data dictionary, skills, and reference queries; a
|
|
49
|
+
* calling app has none of that, so letting it pass SQL means every caller
|
|
50
|
+
* reimplements the owner's schema knowledge badly and silently rots when the
|
|
51
|
+
* owner's shape changes. Callers ask the owning app a question; the owner
|
|
52
|
+
* forms the query. Set `publicAgent.allowRawQueryInput` to opt a specific
|
|
53
|
+
* action out of this rule.
|
|
54
|
+
*/
|
|
55
|
+
export function hasRawQueryInput(entry) {
|
|
56
|
+
const parameters = entry.tool?.parameters;
|
|
57
|
+
const properties = parameters?.properties;
|
|
58
|
+
if (!properties || typeof properties !== "object")
|
|
59
|
+
return false;
|
|
60
|
+
return Object.entries(properties).some(([field, schema]) => {
|
|
61
|
+
const type = schema?.type;
|
|
62
|
+
const acceptsString = type === "string" ||
|
|
63
|
+
type === undefined ||
|
|
64
|
+
(Array.isArray(type) && type.includes("string"));
|
|
65
|
+
return RAW_QUERY_INPUT_FIELDS.has(field.toLowerCase()) && acceptsString;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
34
68
|
/**
|
|
35
69
|
* Direct A2A action calls share the authenticated external-agent policy with
|
|
36
70
|
* MCP, but remain stricter: only explicitly exposed, authenticated read-only
|
|
37
|
-
* actions can skip the receiver's model loop
|
|
71
|
+
* actions can skip the receiver's model loop, and never one that takes a raw
|
|
72
|
+
* query the caller wrote.
|
|
38
73
|
*/
|
|
39
74
|
export function filterDirectA2AActions(actions, options) {
|
|
40
75
|
const catalog = new Set(options.connectorCatalog ?? []);
|
|
@@ -46,7 +81,9 @@ export function filterDirectA2AActions(actions, options) {
|
|
|
46
81
|
(autoReads &&
|
|
47
82
|
isAuthenticatedReadAction(entry) &&
|
|
48
83
|
!isAutoReadExcludedActionName(name));
|
|
84
|
+
const rawQueryAllowed = !hasRawQueryInput(entry) || exposure?.allowRawQueryInput === true;
|
|
49
85
|
return (selected &&
|
|
86
|
+
rawQueryAllowed &&
|
|
50
87
|
!denied.has(name) &&
|
|
51
88
|
entry.agentTool !== false &&
|
|
52
89
|
entry.readOnly === true &&
|
|
@@ -63,6 +100,11 @@ export function buildPublicAgentA2ASkills(actions) {
|
|
|
63
100
|
name,
|
|
64
101
|
description: entry.tool.description,
|
|
65
102
|
publicAgent: entry.publicAgent,
|
|
103
|
+
...(entry.tool.parameters
|
|
104
|
+
? {
|
|
105
|
+
inputSchema: entry.tool.parameters,
|
|
106
|
+
}
|
|
107
|
+
: {}),
|
|
66
108
|
}));
|
|
67
109
|
}
|
|
68
110
|
/**
|
|
@@ -79,6 +121,13 @@ export function buildAuthenticatedAgentA2ASkills(actions, options) {
|
|
|
79
121
|
name,
|
|
80
122
|
description: entry.tool.description,
|
|
81
123
|
publicAgent: entry.publicAgent,
|
|
124
|
+
// Naming an action without its parameters is what makes a caller invoke
|
|
125
|
+
// it with `{}` and fail on a required field.
|
|
126
|
+
...(entry.tool.parameters
|
|
127
|
+
? {
|
|
128
|
+
inputSchema: entry.tool.parameters,
|
|
129
|
+
}
|
|
130
|
+
: {}),
|
|
82
131
|
}));
|
|
83
132
|
}
|
|
84
133
|
export function resolveArtifactBaseUrl(event) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-filters-a2a.js","sourceRoot":"","sources":["../../../src/server/agent-chat/action-filters-a2a.ts"],"names":[],"mappings":"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","sourcesContent":["import { getHeader } from \"h3\";\n\nimport {\n appendA2AArtifactLinks,\n type A2AArtifactResponseOptions,\n type A2AToolResultSummary,\n} from \"../../a2a/artifact-response.js\";\nimport { collectFinalResponseTextFromAgentEvents } from \"../../a2a/response-text.js\";\nimport { resolveMainChatMaxOutputTokens } from \"../../agent/engine/output-tokens.js\";\nimport type { EngineTool } from \"../../agent/engine/types.js\";\nimport {\n filterInitialEngineTools,\n resolveAgentRequestReasoningEffort,\n type ActionEntry,\n} from \"../../agent/production-agent.js\";\nimport { runAgentLoopDirectWithSoftTimeout } from \"../../agent/run-loop-with-resume.js\";\nimport type { AgentChatEvent } from \"../../agent/types.js\";\nimport {\n isAuthenticatedReadAction,\n isAutoReadExcludedActionName,\n} from \"../../mcp/build-server.js\";\nimport { withConfiguredAppBasePath } from \"../app-base-path.js\";\nimport type { AgentChatPluginOptions } from \"./plugin-options.js\";\n\n// ---------------------------------------------------------------------------\n// Action-visibility filters (read-only / agent-exposed / public-agent-safe)\n// and the A2A (agent-to-agent) final-response assembly + delegated-run\n// helpers that share those filters.\n// ---------------------------------------------------------------------------\n\nexport function filterReadOnlyActions(\n actions: Record<string, ActionEntry>,\n): Record<string, ActionEntry> {\n return Object.fromEntries(\n Object.entries(actions).filter(([, entry]) => entry.readOnly === true),\n );\n}\n\n/** Drop actions that opted out of agent exposure via `agentTool: false`. They\n * remain callable from the frontend / HTTP (mounted separately from this\n * agent tool surface — see `httpActions`) but never appear in any agent tool\n * list (in-app assistant, MCP, A2A, job/trigger runners) or actions prompt.\n * Default-allow: only an explicit `false` is excluded. */\nexport function filterAgentTools(\n actions: Record<string, ActionEntry>,\n): Record<string, ActionEntry> {\n return Object.fromEntries(\n Object.entries(actions).filter(([, entry]) => entry.agentTool !== false),\n );\n}\n\nexport function filterPublicAgentActions(\n actions: Record<string, ActionEntry>,\n): Record<string, ActionEntry> {\n return Object.fromEntries(\n Object.entries(actions).filter(([, entry]) => {\n const config = entry.publicAgent;\n return (\n config?.expose === true &&\n config.readOnly === true &&\n config.requiresAuth !== true &&\n config.isConsequential !== true\n );\n }),\n );\n}\n\n/**\n * Direct A2A action calls share the authenticated external-agent policy with\n * MCP, but remain stricter: only explicitly exposed, authenticated read-only\n * actions can skip the receiver's model loop.\n */\nexport function filterDirectA2AActions(\n actions: Record<string, ActionEntry>,\n options: Pick<AgentChatPluginOptions, \"connectorCatalog\" | \"externalAgents\">,\n): Record<string, ActionEntry> {\n const catalog = new Set(options.connectorCatalog ?? []);\n const denied = new Set(options.externalAgents?.denyActions ?? []);\n const autoReads = options.externalAgents?.authenticatedReads === \"auto\";\n\n return Object.fromEntries(\n Object.entries(actions).filter(([name, entry]) => {\n const exposure = entry.publicAgent;\n const selected =\n catalog.has(name) ||\n (autoReads &&\n isAuthenticatedReadAction(entry) &&\n !isAutoReadExcludedActionName(name));\n return (\n selected &&\n !denied.has(name) &&\n entry.agentTool !== false &&\n entry.readOnly === true &&\n exposure?.expose === true &&\n exposure.readOnly === true &&\n exposure.requiresAuth === true &&\n (entry.needsApproval === undefined || entry.needsApproval === false) &&\n exposure.isConsequential !== true\n );\n }),\n );\n}\n\nexport function buildPublicAgentA2ASkills(\n actions: Record<string, ActionEntry>,\n): Array<{\n id: string;\n name: string;\n description: string;\n publicAgent: ActionEntry[\"publicAgent\"];\n}> {\n return Object.entries(filterPublicAgentActions(actions)).map(\n ([name, entry]) => ({\n id: name,\n name,\n description: entry.tool.description,\n publicAgent: entry.publicAgent,\n }),\n );\n}\n\n/**\n * Skills for a caller with a verified A2A identity: exactly what\n * `filterDirectA2AActions` will execute. Kept separate from\n * `buildPublicAgentA2ASkills` because the public card may only name actions\n * with `requiresAuth !== true` while direct invocation requires\n * `requiresAuth === true` — advertising the public set alone tells siblings\n * an app has nothing callable when it does.\n */\nexport function buildAuthenticatedAgentA2ASkills(\n actions: Record<string, ActionEntry>,\n options: Pick<AgentChatPluginOptions, \"connectorCatalog\" | \"externalAgents\">,\n): Array<{\n id: string;\n name: string;\n description: string;\n publicAgent: ActionEntry[\"publicAgent\"];\n}> {\n return Object.entries(filterDirectA2AActions(actions, options)).map(\n ([name, entry]) => ({\n id: name,\n name,\n description: entry.tool.description,\n publicAgent: entry.publicAgent,\n }),\n );\n}\n\nexport function resolveArtifactBaseUrl(\n event: any | undefined,\n): string | undefined {\n const fromEnv =\n process.env.APP_URL ||\n process.env.URL ||\n process.env.DEPLOY_URL ||\n process.env.BETTER_AUTH_URL;\n if (fromEnv) return withConfiguredAppBasePath(String(fromEnv));\n\n try {\n const proto = getHeader(event, \"x-forwarded-proto\") || \"https\";\n const host = getHeader(event, \"host\");\n if (host) return withConfiguredAppBasePath(`${proto}://${host}`);\n } catch {}\n\n return undefined;\n}\n\nexport function assembleA2AFinalResponse(\n events: readonly AgentChatEvent[],\n toolResults: readonly A2AToolResultSummary[],\n options: A2AArtifactResponseOptions & { event?: any } = {},\n): { responseText: string; finalText: string } {\n const terminalError = getA2ATerminalErrorEvent(events);\n const responseText = collectFinalResponseTextFromAgentEvents(events, {\n fallbackToPreToolText: !terminalError,\n });\n const finalText = appendA2AArtifactLinks(responseText, [...toolResults], {\n baseUrl: options.baseUrl ?? resolveArtifactBaseUrl(options.event),\n includeReferencedArtifacts: true,\n includePersistedArtifactMarker: true,\n });\n if (terminalError && !finalText.trim()) {\n throw new Error(formatA2ATerminalError(terminalError));\n }\n return { responseText, finalText };\n}\n\nfunction getA2ATerminalErrorEvent(\n events: readonly AgentChatEvent[],\n): Extract<AgentChatEvent, { type: \"error\" }> | null {\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i];\n if (event.type === \"clear\") continue;\n if (event.type === \"done\") return null;\n if (event.type === \"error\") return event;\n if (event.type === \"auto_continue\") {\n return {\n type: \"error\",\n error: `Agent stopped before finishing (${event.reason}).`,\n errorCode: event.reason,\n recoverable: true,\n };\n }\n }\n return null;\n}\n\nfunction formatA2ATerminalError(\n event: Extract<AgentChatEvent, { type: \"error\" }>,\n): string {\n const parts = [\n event.error || \"Agent failed before producing a final response.\",\n event.errorCode ? `code: ${event.errorCode}` : \"\",\n event.details ? `details: ${event.details}` : \"\",\n ].filter(Boolean);\n return parts.join(\"\\n\");\n}\n\ntype A2AAgentLoopRunner = typeof runAgentLoopDirectWithSoftTimeout;\n\nexport interface DelegatedAgentLoopTelemetry {\n runId: string;\n threadId: string | null;\n userId: string | null;\n delegation: {\n protocol: \"a2a\" | \"mcp\";\n callerApp?: string;\n taskId?: string;\n parentRunId?: string;\n parentTurnId?: string;\n };\n}\n\ninterface DelegatedAgentLoopOptions {\n runner?: A2AAgentLoopRunner;\n telemetry?: DelegatedAgentLoopTelemetry;\n}\n\nasync function runDelegatedAgentLoop(\n runOptions: Parameters<A2AAgentLoopRunner>[0],\n pluginOptions: Pick<\n AgentChatPluginOptions,\n \"finalResponseGuard\" | \"runSoftTimeoutMs\"\n >,\n timeoutOptions: Parameters<A2AAgentLoopRunner>[2],\n options: DelegatedAgentLoopOptions,\n) {\n const runner = options.runner ?? runAgentLoopDirectWithSoftTimeout;\n const resolvedRunOptions = {\n ...runOptions,\n // Delegated runs resolve their own model and do not pass through the\n // interactive request handler's output-token setup. Use the same\n // model-aware headroom here so reasoning models (notably GPT-5.x) do\n // not spend the small internal default entirely on reasoning before\n // emitting a tool call or answer. Preserve explicit test/caller values.\n maxOutputTokens:\n runOptions.maxOutputTokens ??\n resolveMainChatMaxOutputTokens(runOptions.model),\n reasoningEffort:\n runOptions.reasoningEffort ??\n resolveAgentRequestReasoningEffort({ model: runOptions.model }),\n finalResponseGuard: pluginOptions.finalResponseGuard,\n };\n const execute = (loopOptions = resolvedRunOptions) =>\n runner(loopOptions, pluginOptions.runSoftTimeoutMs, timeoutOptions);\n\n if (!options.telemetry) return execute();\n\n let instrumented = false;\n try {\n const { getObservabilityConfig, instrumentAgentLoop } =\n await import(\"../../observability/traces.js\");\n const config = await getObservabilityConfig();\n if (config.enabled) {\n instrumented = true;\n return await instrumentAgentLoop({\n runAgentLoop: (loopOptions) =>\n execute(\n loopOptions as Parameters<A2AAgentLoopRunner>[0] &\n typeof resolvedRunOptions,\n ),\n loopOpts: resolvedRunOptions,\n runId: options.telemetry.runId,\n threadId: options.telemetry.threadId,\n userId: options.telemetry.userId,\n config,\n delegation: options.telemetry.delegation,\n });\n }\n } catch (error) {\n // Match interactive chat: setup failures fall through, but a failure from\n // inside an instrumented agent loop is the real run failure and rethrows.\n if (instrumented) throw error;\n }\n return execute();\n}\n\n/**\n * Run an A2A-delegated agent turn with the same final-response guard used by\n * the app's interactive chat surface.\n *\n * Keeping this in one helper prevents delegated calls from silently bypassing\n * template guarantees such as Analytics' requirement to query real data\n * before presenting metrics or exhaustive provider conclusions.\n */\nexport function runA2AAgentLoop(\n runOptions: Parameters<A2AAgentLoopRunner>[0],\n pluginOptions: Pick<\n AgentChatPluginOptions,\n \"finalResponseGuard\" | \"runSoftTimeoutMs\"\n >,\n timeoutOptions: Parameters<A2AAgentLoopRunner>[2],\n options: DelegatedAgentLoopOptions = {},\n) {\n return runDelegatedAgentLoop(\n runOptions,\n pluginOptions,\n timeoutOptions,\n options,\n );\n}\n\n/**\n * Run the MCP-local ask_app turn with the same app-level response guard as\n * A2A. Keeping this seam shared prevents hosted MCP callers from bypassing\n * template guarantees when the request cannot use the self-A2A route.\n */\nexport function runMCPAgentLoop(\n runOptions: Parameters<A2AAgentLoopRunner>[0],\n pluginOptions: Pick<\n AgentChatPluginOptions,\n \"finalResponseGuard\" | \"runSoftTimeoutMs\"\n >,\n timeoutOptions: Parameters<A2AAgentLoopRunner>[2],\n options: DelegatedAgentLoopOptions = {},\n) {\n return runDelegatedAgentLoop(\n runOptions,\n pluginOptions,\n timeoutOptions,\n options,\n );\n}\n\n/**\n * Keep delegated A2A turns on the same compact initial tool surface as\n * interactive chat. `tool-search` remains in the initial set, while the\n * complete registry is supplied separately so the run loop can load a matched\n * schema after a tool-search result.\n */\nexport function createA2AEngineToolSurface(\n availableTools: EngineTool[],\n initialToolNames?: string[],\n): { tools: EngineTool[]; availableTools: EngineTool[] } {\n return {\n tools: filterInitialEngineTools(availableTools, initialToolNames),\n availableTools,\n };\n}\n\nexport function resolveInitialToolNames(\n templateActions: Record<string, ActionEntry>,\n configured?: string[],\n): string[] {\n return configured ?? Object.keys(templateActions);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"action-filters-a2a.js","sourceRoot":"","sources":["../../../src/server/agent-chat/action-filters-a2a.ts"],"names":[],"mappings":"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","sourcesContent":["import { getHeader } from \"h3\";\n\nimport {\n appendA2AArtifactLinks,\n type A2AArtifactResponseOptions,\n type A2AToolResultSummary,\n} from \"../../a2a/artifact-response.js\";\nimport { collectFinalResponseTextFromAgentEvents } from \"../../a2a/response-text.js\";\nimport { resolveMainChatMaxOutputTokens } from \"../../agent/engine/output-tokens.js\";\nimport type { EngineTool } from \"../../agent/engine/types.js\";\nimport {\n filterInitialEngineTools,\n resolveAgentRequestReasoningEffort,\n type ActionEntry,\n} from \"../../agent/production-agent.js\";\nimport { runAgentLoopDirectWithSoftTimeout } from \"../../agent/run-loop-with-resume.js\";\nimport type { AgentChatEvent } from \"../../agent/types.js\";\nimport {\n isAuthenticatedReadAction,\n isAutoReadExcludedActionName,\n} from \"../../mcp/build-server.js\";\nimport { withConfiguredAppBasePath } from \"../app-base-path.js\";\nimport type { AgentChatPluginOptions } from \"./plugin-options.js\";\n\n// ---------------------------------------------------------------------------\n// Action-visibility filters (read-only / agent-exposed / public-agent-safe)\n// and the A2A (agent-to-agent) final-response assembly + delegated-run\n// helpers that share those filters.\n// ---------------------------------------------------------------------------\n\nexport function filterReadOnlyActions(\n actions: Record<string, ActionEntry>,\n): Record<string, ActionEntry> {\n return Object.fromEntries(\n Object.entries(actions).filter(([, entry]) => entry.readOnly === true),\n );\n}\n\n/** Drop actions that opted out of agent exposure via `agentTool: false`. They\n * remain callable from the frontend / HTTP (mounted separately from this\n * agent tool surface — see `httpActions`) but never appear in any agent tool\n * list (in-app assistant, MCP, A2A, job/trigger runners) or actions prompt.\n * Default-allow: only an explicit `false` is excluded. */\nexport function filterAgentTools(\n actions: Record<string, ActionEntry>,\n): Record<string, ActionEntry> {\n return Object.fromEntries(\n Object.entries(actions).filter(([, entry]) => entry.agentTool !== false),\n );\n}\n\nexport function filterPublicAgentActions(\n actions: Record<string, ActionEntry>,\n): Record<string, ActionEntry> {\n return Object.fromEntries(\n Object.entries(actions).filter(([, entry]) => {\n const config = entry.publicAgent;\n return (\n config?.expose === true &&\n config.readOnly === true &&\n config.requiresAuth !== true &&\n config.isConsequential !== true\n );\n }),\n );\n}\n\n/**\n * Input fields that unambiguously carry a program the receiver executes.\n *\n * Deliberately excludes `query`: across the templates that field is nearly\n * always natural-language search text (Brain's `search-everything`,\n * `search-knowledge`), and blocking it would break exactly the ask-don't-instruct\n * calls this rule exists to encourage.\n */\nconst RAW_QUERY_INPUT_FIELDS = new Set([\"sql\", \"code\", \"script\", \"expression\"]);\n\n/**\n * True when an action takes a free-form query or program as input — raw SQL, a\n * code body, an arbitrary expression.\n *\n * Such an action must not be sibling-invocable over A2A. The app that owns the\n * data owns its schema, data dictionary, skills, and reference queries; a\n * calling app has none of that, so letting it pass SQL means every caller\n * reimplements the owner's schema knowledge badly and silently rots when the\n * owner's shape changes. Callers ask the owning app a question; the owner\n * forms the query. Set `publicAgent.allowRawQueryInput` to opt a specific\n * action out of this rule.\n */\nexport function hasRawQueryInput(entry: ActionEntry): boolean {\n const parameters = entry.tool?.parameters as\n | { properties?: Record<string, { type?: unknown }> }\n | undefined;\n const properties = parameters?.properties;\n if (!properties || typeof properties !== \"object\") return false;\n return Object.entries(properties).some(([field, schema]) => {\n const type = schema?.type;\n const acceptsString =\n type === \"string\" ||\n type === undefined ||\n (Array.isArray(type) && type.includes(\"string\"));\n return RAW_QUERY_INPUT_FIELDS.has(field.toLowerCase()) && acceptsString;\n });\n}\n\n/**\n * Direct A2A action calls share the authenticated external-agent policy with\n * MCP, but remain stricter: only explicitly exposed, authenticated read-only\n * actions can skip the receiver's model loop, and never one that takes a raw\n * query the caller wrote.\n */\nexport function filterDirectA2AActions(\n actions: Record<string, ActionEntry>,\n options: Pick<AgentChatPluginOptions, \"connectorCatalog\" | \"externalAgents\">,\n): Record<string, ActionEntry> {\n const catalog = new Set(options.connectorCatalog ?? []);\n const denied = new Set(options.externalAgents?.denyActions ?? []);\n const autoReads = options.externalAgents?.authenticatedReads === \"auto\";\n\n return Object.fromEntries(\n Object.entries(actions).filter(([name, entry]) => {\n const exposure = entry.publicAgent;\n const selected =\n catalog.has(name) ||\n (autoReads &&\n isAuthenticatedReadAction(entry) &&\n !isAutoReadExcludedActionName(name));\n const rawQueryAllowed =\n !hasRawQueryInput(entry) || exposure?.allowRawQueryInput === true;\n return (\n selected &&\n rawQueryAllowed &&\n !denied.has(name) &&\n entry.agentTool !== false &&\n entry.readOnly === true &&\n exposure?.expose === true &&\n exposure.readOnly === true &&\n exposure.requiresAuth === true &&\n (entry.needsApproval === undefined || entry.needsApproval === false) &&\n exposure.isConsequential !== true\n );\n }),\n );\n}\n\nexport function buildPublicAgentA2ASkills(\n actions: Record<string, ActionEntry>,\n): Array<{\n id: string;\n name: string;\n description: string;\n publicAgent: ActionEntry[\"publicAgent\"];\n inputSchema?: Record<string, unknown>;\n}> {\n return Object.entries(filterPublicAgentActions(actions)).map(\n ([name, entry]) => ({\n id: name,\n name,\n description: entry.tool.description,\n publicAgent: entry.publicAgent,\n ...(entry.tool.parameters\n ? {\n inputSchema: entry.tool.parameters as unknown as Record<\n string,\n unknown\n >,\n }\n : {}),\n }),\n );\n}\n\n/**\n * Skills for a caller with a verified A2A identity: exactly what\n * `filterDirectA2AActions` will execute. Kept separate from\n * `buildPublicAgentA2ASkills` because the public card may only name actions\n * with `requiresAuth !== true` while direct invocation requires\n * `requiresAuth === true` — advertising the public set alone tells siblings\n * an app has nothing callable when it does.\n */\nexport function buildAuthenticatedAgentA2ASkills(\n actions: Record<string, ActionEntry>,\n options: Pick<AgentChatPluginOptions, \"connectorCatalog\" | \"externalAgents\">,\n): Array<{\n id: string;\n name: string;\n description: string;\n publicAgent: ActionEntry[\"publicAgent\"];\n inputSchema?: Record<string, unknown>;\n}> {\n return Object.entries(filterDirectA2AActions(actions, options)).map(\n ([name, entry]) => ({\n id: name,\n name,\n description: entry.tool.description,\n publicAgent: entry.publicAgent,\n // Naming an action without its parameters is what makes a caller invoke\n // it with `{}` and fail on a required field.\n ...(entry.tool.parameters\n ? {\n inputSchema: entry.tool.parameters as unknown as Record<\n string,\n unknown\n >,\n }\n : {}),\n }),\n );\n}\n\nexport function resolveArtifactBaseUrl(\n event: any | undefined,\n): string | undefined {\n const fromEnv =\n process.env.APP_URL ||\n process.env.URL ||\n process.env.DEPLOY_URL ||\n process.env.BETTER_AUTH_URL;\n if (fromEnv) return withConfiguredAppBasePath(String(fromEnv));\n\n try {\n const proto = getHeader(event, \"x-forwarded-proto\") || \"https\";\n const host = getHeader(event, \"host\");\n if (host) return withConfiguredAppBasePath(`${proto}://${host}`);\n } catch {}\n\n return undefined;\n}\n\nexport function assembleA2AFinalResponse(\n events: readonly AgentChatEvent[],\n toolResults: readonly A2AToolResultSummary[],\n options: A2AArtifactResponseOptions & { event?: any } = {},\n): { responseText: string; finalText: string } {\n const terminalError = getA2ATerminalErrorEvent(events);\n const responseText = collectFinalResponseTextFromAgentEvents(events, {\n fallbackToPreToolText: !terminalError,\n });\n const finalText = appendA2AArtifactLinks(responseText, [...toolResults], {\n baseUrl: options.baseUrl ?? resolveArtifactBaseUrl(options.event),\n includeReferencedArtifacts: true,\n includePersistedArtifactMarker: true,\n });\n if (terminalError && !finalText.trim()) {\n throw new Error(formatA2ATerminalError(terminalError));\n }\n return { responseText, finalText };\n}\n\nfunction getA2ATerminalErrorEvent(\n events: readonly AgentChatEvent[],\n): Extract<AgentChatEvent, { type: \"error\" }> | null {\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i];\n if (event.type === \"clear\") continue;\n if (event.type === \"done\") return null;\n if (event.type === \"error\") return event;\n if (event.type === \"auto_continue\") {\n return {\n type: \"error\",\n error: `Agent stopped before finishing (${event.reason}).`,\n errorCode: event.reason,\n recoverable: true,\n };\n }\n }\n return null;\n}\n\nfunction formatA2ATerminalError(\n event: Extract<AgentChatEvent, { type: \"error\" }>,\n): string {\n const parts = [\n event.error || \"Agent failed before producing a final response.\",\n event.errorCode ? `code: ${event.errorCode}` : \"\",\n event.details ? `details: ${event.details}` : \"\",\n ].filter(Boolean);\n return parts.join(\"\\n\");\n}\n\ntype A2AAgentLoopRunner = typeof runAgentLoopDirectWithSoftTimeout;\n\nexport interface DelegatedAgentLoopTelemetry {\n runId: string;\n threadId: string | null;\n userId: string | null;\n delegation: {\n protocol: \"a2a\" | \"mcp\";\n callerApp?: string;\n taskId?: string;\n parentRunId?: string;\n parentTurnId?: string;\n };\n}\n\ninterface DelegatedAgentLoopOptions {\n runner?: A2AAgentLoopRunner;\n telemetry?: DelegatedAgentLoopTelemetry;\n}\n\nasync function runDelegatedAgentLoop(\n runOptions: Parameters<A2AAgentLoopRunner>[0],\n pluginOptions: Pick<\n AgentChatPluginOptions,\n \"finalResponseGuard\" | \"runSoftTimeoutMs\"\n >,\n timeoutOptions: Parameters<A2AAgentLoopRunner>[2],\n options: DelegatedAgentLoopOptions,\n) {\n const runner = options.runner ?? runAgentLoopDirectWithSoftTimeout;\n const resolvedRunOptions = {\n ...runOptions,\n // Delegated runs resolve their own model and do not pass through the\n // interactive request handler's output-token setup. Use the same\n // model-aware headroom here so reasoning models (notably GPT-5.x) do\n // not spend the small internal default entirely on reasoning before\n // emitting a tool call or answer. Preserve explicit test/caller values.\n maxOutputTokens:\n runOptions.maxOutputTokens ??\n resolveMainChatMaxOutputTokens(runOptions.model),\n reasoningEffort:\n runOptions.reasoningEffort ??\n resolveAgentRequestReasoningEffort({ model: runOptions.model }),\n finalResponseGuard: pluginOptions.finalResponseGuard,\n };\n const execute = (loopOptions = resolvedRunOptions) =>\n runner(loopOptions, pluginOptions.runSoftTimeoutMs, timeoutOptions);\n\n if (!options.telemetry) return execute();\n\n let instrumented = false;\n try {\n const { getObservabilityConfig, instrumentAgentLoop } =\n await import(\"../../observability/traces.js\");\n const config = await getObservabilityConfig();\n if (config.enabled) {\n instrumented = true;\n return await instrumentAgentLoop({\n runAgentLoop: (loopOptions) =>\n execute(\n loopOptions as Parameters<A2AAgentLoopRunner>[0] &\n typeof resolvedRunOptions,\n ),\n loopOpts: resolvedRunOptions,\n runId: options.telemetry.runId,\n threadId: options.telemetry.threadId,\n userId: options.telemetry.userId,\n config,\n delegation: options.telemetry.delegation,\n });\n }\n } catch (error) {\n // Match interactive chat: setup failures fall through, but a failure from\n // inside an instrumented agent loop is the real run failure and rethrows.\n if (instrumented) throw error;\n }\n return execute();\n}\n\n/**\n * Run an A2A-delegated agent turn with the same final-response guard used by\n * the app's interactive chat surface.\n *\n * Keeping this in one helper prevents delegated calls from silently bypassing\n * template guarantees such as Analytics' requirement to query real data\n * before presenting metrics or exhaustive provider conclusions.\n */\nexport function runA2AAgentLoop(\n runOptions: Parameters<A2AAgentLoopRunner>[0],\n pluginOptions: Pick<\n AgentChatPluginOptions,\n \"finalResponseGuard\" | \"runSoftTimeoutMs\"\n >,\n timeoutOptions: Parameters<A2AAgentLoopRunner>[2],\n options: DelegatedAgentLoopOptions = {},\n) {\n return runDelegatedAgentLoop(\n runOptions,\n pluginOptions,\n timeoutOptions,\n options,\n );\n}\n\n/**\n * Run the MCP-local ask_app turn with the same app-level response guard as\n * A2A. Keeping this seam shared prevents hosted MCP callers from bypassing\n * template guarantees when the request cannot use the self-A2A route.\n */\nexport function runMCPAgentLoop(\n runOptions: Parameters<A2AAgentLoopRunner>[0],\n pluginOptions: Pick<\n AgentChatPluginOptions,\n \"finalResponseGuard\" | \"runSoftTimeoutMs\"\n >,\n timeoutOptions: Parameters<A2AAgentLoopRunner>[2],\n options: DelegatedAgentLoopOptions = {},\n) {\n return runDelegatedAgentLoop(\n runOptions,\n pluginOptions,\n timeoutOptions,\n options,\n );\n}\n\n/**\n * Keep delegated A2A turns on the same compact initial tool surface as\n * interactive chat. `tool-search` remains in the initial set, while the\n * complete registry is supplied separately so the run loop can load a matched\n * schema after a tool-search result.\n */\nexport function createA2AEngineToolSurface(\n availableTools: EngineTool[],\n initialToolNames?: string[],\n): { tools: EngineTool[]; availableTools: EngineTool[] } {\n return {\n tools: filterInitialEngineTools(availableTools, initialToolNames),\n availableTools,\n };\n}\n\nexport function resolveInitialToolNames(\n templateActions: Record<string, ActionEntry>,\n configured?: string[],\n): string[] {\n return configured ?? Object.keys(templateActions);\n}\n"]}
|
|
@@ -27,11 +27,11 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
|
|
|
27
27
|
export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
28
28
|
error: any;
|
|
29
29
|
} | {
|
|
30
|
-
error?: undefined;
|
|
31
30
|
ok: boolean;
|
|
32
31
|
key: string;
|
|
33
32
|
baseUrlKey?: string;
|
|
34
33
|
scope: AgentEngineApiKeyScope;
|
|
34
|
+
error?: undefined;
|
|
35
35
|
}>>;
|
|
36
36
|
export {};
|
|
37
37
|
//# sourceMappingURL=agent-engine-api-key-route.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.131.
|
|
3
|
+
"version": "0.131.4",
|
|
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": {
|
package/src/a2a/types.ts
CHANGED
|
@@ -85,6 +85,12 @@ export interface AgentSkill {
|
|
|
85
85
|
requiresAuth?: boolean;
|
|
86
86
|
isConsequential?: boolean;
|
|
87
87
|
publicAgent?: PublicAgentActionConfig;
|
|
88
|
+
/**
|
|
89
|
+
* JSON Schema for the action's `input`. Advertising a skill without it tells a
|
|
90
|
+
* caller the action exists but not how to call it, so callers invoke with `{}`
|
|
91
|
+
* and get a required-property error back.
|
|
92
|
+
*/
|
|
93
|
+
inputSchema?: Record<string, unknown>;
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
export interface AgentCapabilities {
|
package/src/action.ts
CHANGED
|
@@ -200,6 +200,19 @@ export interface PublicAgentActionConfig {
|
|
|
200
200
|
isConsequential?: boolean;
|
|
201
201
|
title?: string;
|
|
202
202
|
description?: string;
|
|
203
|
+
/**
|
|
204
|
+
* Allow a sibling app to invoke this action over A2A even though its input is
|
|
205
|
+
* a free-form query or program (`sql`, `query`, `code`, `script`,
|
|
206
|
+
* `expression`).
|
|
207
|
+
*
|
|
208
|
+
* Off by default and rarely correct. The app that owns the data owns its
|
|
209
|
+
* schema, data dictionary, and reference queries; a caller has none of that,
|
|
210
|
+
* so passing raw SQL across apps makes every caller reimplement the owner's
|
|
211
|
+
* schema knowledge and silently break when it changes. Prefer a semantic
|
|
212
|
+
* action the owner implements, or let the caller ask in natural language and
|
|
213
|
+
* form the query yourself.
|
|
214
|
+
*/
|
|
215
|
+
allowRawQueryInput?: boolean;
|
|
203
216
|
}
|
|
204
217
|
|
|
205
218
|
export type ActionPlanModeEffect = "read" | "write" | "unknown";
|
|
@@ -2585,47 +2585,71 @@ class AgentPanelErrorBoundary extends React.Component<
|
|
|
2585
2585
|
assistantUiRecoverableRenderErrorKind(this.state.error) &&
|
|
2586
2586
|
this.state.staleIndexRecoveryCount < 2
|
|
2587
2587
|
) {
|
|
2588
|
-
return
|
|
2589
|
-
<div className="flex h-full items-center justify-center p-6 text-center text-xs text-muted-foreground">
|
|
2590
|
-
Reloading chat UI...
|
|
2591
|
-
</div>
|
|
2592
|
-
);
|
|
2588
|
+
return <AgentPanelReloadingNotice />;
|
|
2593
2589
|
}
|
|
2594
2590
|
|
|
2595
2591
|
return (
|
|
2596
|
-
<
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
</p>
|
|
2604
|
-
</div>
|
|
2605
|
-
<button
|
|
2606
|
-
type="button"
|
|
2607
|
-
className="rounded-md border border-border bg-background px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent"
|
|
2608
|
-
onClick={() => {
|
|
2609
|
-
this.setState({ error: null, staleIndexRecoveryCount: 0 });
|
|
2610
|
-
this.props.onReset();
|
|
2611
|
-
}}
|
|
2612
|
-
>
|
|
2613
|
-
Reset agent panel
|
|
2614
|
-
</button>
|
|
2615
|
-
<ErrorReportActions
|
|
2616
|
-
appName="Agent panel"
|
|
2617
|
-
title="Agent panel UI error"
|
|
2618
|
-
details={this.state.error.message}
|
|
2619
|
-
issueTitle="Agent panel UI error"
|
|
2620
|
-
className="max-w-[260px]"
|
|
2621
|
-
feedbackClassName="h-7"
|
|
2622
|
-
githubClassName="h-7"
|
|
2623
|
-
/>
|
|
2624
|
-
</div>
|
|
2592
|
+
<AgentPanelErrorFallback
|
|
2593
|
+
details={this.state.error.message}
|
|
2594
|
+
onReset={() => {
|
|
2595
|
+
this.setState({ error: null, staleIndexRecoveryCount: 0 });
|
|
2596
|
+
this.props.onReset();
|
|
2597
|
+
}}
|
|
2598
|
+
/>
|
|
2625
2599
|
);
|
|
2626
2600
|
}
|
|
2627
2601
|
}
|
|
2628
2602
|
|
|
2603
|
+
// The boundary must stay a class (componentDidCatch), but its copy still has to
|
|
2604
|
+
// come from the catalog like every other string in this file — so the fallback
|
|
2605
|
+
// UI lives in function components that can call useT.
|
|
2606
|
+
function AgentPanelReloadingNotice() {
|
|
2607
|
+
const t = useT();
|
|
2608
|
+
return (
|
|
2609
|
+
<div className="flex h-full items-center justify-center p-6 text-center text-xs text-muted-foreground">
|
|
2610
|
+
{t("agentPanel.uiError.reloading")}
|
|
2611
|
+
</div>
|
|
2612
|
+
);
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
function AgentPanelErrorFallback({
|
|
2616
|
+
details,
|
|
2617
|
+
onReset,
|
|
2618
|
+
}: {
|
|
2619
|
+
details: string;
|
|
2620
|
+
onReset: () => void;
|
|
2621
|
+
}) {
|
|
2622
|
+
const t = useT();
|
|
2623
|
+
return (
|
|
2624
|
+
<div className="flex h-full flex-col items-center justify-center gap-3 p-6 text-center">
|
|
2625
|
+
<div className="max-w-[260px] space-y-1">
|
|
2626
|
+
<p className="text-sm font-medium text-foreground">
|
|
2627
|
+
{t("agentPanel.uiError.title")}
|
|
2628
|
+
</p>
|
|
2629
|
+
<p className="text-xs leading-relaxed text-muted-foreground">
|
|
2630
|
+
{t("agentPanel.uiError.description")}
|
|
2631
|
+
</p>
|
|
2632
|
+
</div>
|
|
2633
|
+
<button
|
|
2634
|
+
type="button"
|
|
2635
|
+
className="rounded-md border border-border bg-background px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent"
|
|
2636
|
+
onClick={onReset}
|
|
2637
|
+
>
|
|
2638
|
+
{t("agentPanel.uiError.reset")}
|
|
2639
|
+
</button>
|
|
2640
|
+
<ErrorReportActions
|
|
2641
|
+
appName="Agent panel"
|
|
2642
|
+
title={t("agentPanel.uiError.title")}
|
|
2643
|
+
details={details}
|
|
2644
|
+
issueTitle="Agent panel UI error"
|
|
2645
|
+
className="max-w-[260px]"
|
|
2646
|
+
feedbackClassName="h-7"
|
|
2647
|
+
githubClassName="h-7"
|
|
2648
|
+
/>
|
|
2649
|
+
</div>
|
|
2650
|
+
);
|
|
2651
|
+
}
|
|
2652
|
+
|
|
2629
2653
|
export function AgentPanel(props: AgentPanelProps) {
|
|
2630
2654
|
const [resetKey, setResetKey] = useState(0);
|
|
2631
2655
|
const resetPanel = useCallback(() => {
|
|
@@ -336,6 +336,12 @@ const messages = {
|
|
|
336
336
|
},
|
|
337
337
|
},
|
|
338
338
|
agentPanel: {
|
|
339
|
+
uiError: {
|
|
340
|
+
title: "Agent panel hit a glitch",
|
|
341
|
+
description: "The app's still usable. Reset to reload the chat.",
|
|
342
|
+
reset: "Reset agent panel",
|
|
343
|
+
reloading: "Reloading chat…",
|
|
344
|
+
},
|
|
339
345
|
useBuilder: "Use Builder",
|
|
340
346
|
openDesktopToEditCode: "Open Desktop to edit code",
|
|
341
347
|
codeUnavailableDescription:
|
|
@@ -136,6 +136,38 @@ export function formatCapabilitySummary(
|
|
|
136
136
|
.join("\n");
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Render a skill's `input` contract as `input: { field*: type, other?: type }`,
|
|
141
|
+
* marking required fields with `*`. Returns undefined when the skill publishes
|
|
142
|
+
* no schema, so callers fall back to the description alone.
|
|
143
|
+
*/
|
|
144
|
+
function formatSkillInput(skill: AgentSkill): string | undefined {
|
|
145
|
+
const schema = skill.inputSchema as
|
|
146
|
+
| {
|
|
147
|
+
properties?: Record<string, { type?: unknown }>;
|
|
148
|
+
required?: unknown;
|
|
149
|
+
}
|
|
150
|
+
| undefined;
|
|
151
|
+
const properties = schema?.properties;
|
|
152
|
+
if (!properties || typeof properties !== "object") return undefined;
|
|
153
|
+
const names = Object.keys(properties);
|
|
154
|
+
if (names.length === 0) return " — input: {} (no fields)";
|
|
155
|
+
|
|
156
|
+
const required = new Set(
|
|
157
|
+
Array.isArray(schema?.required)
|
|
158
|
+
? schema.required.filter(
|
|
159
|
+
(name): name is string => typeof name === "string",
|
|
160
|
+
)
|
|
161
|
+
: [],
|
|
162
|
+
);
|
|
163
|
+
const fields = names.map((name) => {
|
|
164
|
+
const type = properties[name]?.type;
|
|
165
|
+
const rendered = typeof type === "string" ? type : "any";
|
|
166
|
+
return `${name}${required.has(name) ? "*" : "?"}: ${rendered}`;
|
|
167
|
+
});
|
|
168
|
+
return ` — input: { ${fields.join(", ")} } (* = required)`;
|
|
169
|
+
}
|
|
170
|
+
|
|
139
171
|
export function formatCapabilityDetail(
|
|
140
172
|
peer: PeerCapabilities,
|
|
141
173
|
callHint: (appId: string) => string,
|
|
@@ -151,14 +183,17 @@ export function formatCapabilityDetail(
|
|
|
151
183
|
|
|
152
184
|
const shown = peer.skills.slice(0, MAX_SKILLS_IN_DETAIL);
|
|
153
185
|
const rest = peer.skills.length - shown.length;
|
|
154
|
-
const lines = shown.map(
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
186
|
+
const lines = shown.map((skill) => {
|
|
187
|
+
const summary = skill.description
|
|
188
|
+
? truncate(skill.description, MAX_DESCRIPTION_CHARS)
|
|
189
|
+
: skill.name || "(no description)";
|
|
190
|
+
// Naming an action without its parameters is what makes a caller invoke it
|
|
191
|
+
// with `{}` and fail on a required field, which reads as the sibling being
|
|
192
|
+
// broken rather than as a malformed call.
|
|
193
|
+
return `- ${skill.id}${skill.readOnly ? "" : " (mutating)"}: ${summary}${
|
|
194
|
+
formatSkillInput(skill) ?? ""
|
|
195
|
+
}`;
|
|
196
|
+
});
|
|
162
197
|
|
|
163
198
|
return [
|
|
164
199
|
header,
|