@truefoundry/trueforge-core 0.2.0-rc.6 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-session/SessionHandle.d.ts +1 -0
- package/dist/agent-session/SessionHandle.d.ts.map +1 -1
- package/dist/agent-session/SessionHandle.js +1 -0
- package/dist/agent-session/SessionHandle.js.map +1 -1
- package/dist/agent-session/SessionHandle.mjs +1 -0
- package/dist/agent-session/SessionHandle.mjs.map +1 -1
- package/dist/agent-session/models/TurnRecord.d.ts +1 -0
- package/dist/agent-session/models/TurnRecord.d.ts.map +1 -1
- package/dist/agent-session/models/TurnRecord.js.map +1 -1
- package/dist/agent-session/models/TurnRecord.mjs.map +1 -1
- package/dist/core/capabilities/builtins/OpenUI.d.ts.map +1 -1
- package/dist/core/capabilities/builtins/OpenUI.js +4 -2
- package/dist/core/capabilities/builtins/OpenUI.js.map +1 -1
- package/dist/core/capabilities/builtins/OpenUI.mjs +4 -2
- package/dist/core/capabilities/builtins/OpenUI.mjs.map +1 -1
- package/dist/core/runtime/DeferredTool.d.ts.map +1 -1
- package/dist/core/runtime/DeferredTool.js +3 -1
- package/dist/core/runtime/DeferredTool.js.map +1 -1
- package/dist/core/runtime/DeferredTool.mjs +3 -1
- package/dist/core/runtime/DeferredTool.mjs.map +1 -1
- package/dist/core/sandbox/Sandbox.d.ts.map +1 -1
- package/dist/core/sandbox/Sandbox.js +4 -1
- package/dist/core/sandbox/Sandbox.js.map +1 -1
- package/dist/core/sandbox/Sandbox.mjs +4 -1
- package/dist/core/sandbox/Sandbox.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/capabilities/builtins/OpenUI.ts"],"sourcesContent":["import dedent from 'dedent';\nimport { z } from 'zod';\nimport { InstructionBuilder } from '../../InstructionBuilder';\nimport { toolResultResponse } from '../../mcp/IMCPServer';\nimport { defineTool, LocalToolMCP, type ToolDefinition } from '../../mcp/LocalToolMCP';\nimport type { AgentTracing } from '../../tracing/AgentTracing';\nimport { NOOP_AGENT_TRACING } from '../../tracing/NoopAgentTracing';\nimport type { AgentCapability } from '../AgentCapability';\n\nexport const OPENUI_SERVER_ID = 'openui';\nexport const GET_OPENUI_INSTRUCTIONS_TOOL_NAME = 'get_openui_instructions';\n\nconst getOpenUIInstructionsInputSchema = z.object({}).strict();\n\nexport const OPENUI_SECTION_TAG = 'openui';\nexport const OPENUI_MARKDOWN_FENCING_TAG = 'openui-markdown-fencing';\nexport const OPENUI_SYNTAX_RULES_TAG = 'openui-syntax-rules';\nexport const OPENUI_COMPONENT_SIGNATURES_TAG = 'openui-component-signatures';\nexport const OPENUI_BUILTIN_FUNCTIONS_TAG = 'openui-builtin-functions';\nexport const OPENUI_HOISTING_AND_STREAMING_TAG = 'openui-hoisting-and-streaming';\nexport const OPENUI_EXAMPLES_TAG = 'openui-examples';\nexport const OPENUI_IMPORTANT_RULES_TAG = 'openui-important-rules';\nexport const OPENUI_FINAL_VERIFICATION_TAG = 'openui-final-verification';\nexport const OPENUI_USER_INTERACTION_CHECKLIST_TAG = 'openui-user-interaction-checklist';\n\nexport function buildOpenUIInstruction(builder: InstructionBuilder): void {\n const openui = builder.beginSection(OPENUI_SECTION_TAG);\n\n openui.addSection(\n OPENUI_MARKDOWN_FENCING_TAG,\n dedent`\n All openui, code must be fenced within openui block.\n \\`\\`\\`openui\n code\n \\`\\`\\``,\n );\n\n openui.addSection(\n OPENUI_SYNTAX_RULES_TAG,\n dedent`\n 1. Each statement is on its own line: \\`identifier = Expression\\`\n 2. \\`root\\` is the entry point — every program must define \\`root = Stack(...)\\`\n 3. Expressions are: strings (\"...\"), numbers, booleans (true/false), null, arrays ([...]), objects ({...}), or component calls TypeName(arg1, arg2, ...)\n 4. Use references for readability: define \\`name = ...\\` on one line, then use \\`name\\` later\n 5. EVERY variable (except root) MUST be referenced by at least one other variable. Unreferenced variables are silently dropped and will NOT render. Always include defined variables in their parent's children/items array.\n 6. Arguments are POSITIONAL (order matters, not names). Write \\`Stack([children], \"row\", \"l\")\\` NOT \\`Stack([children], direction: \"row\", gap: \"l\")\\` — colon syntax is NOT supported and silently breaks\n 7. Optional arguments can be omitted from the end\n - Strings use double quotes with backslash escaping`,\n );\n\n openui.addSection(\n OPENUI_COMPONENT_SIGNATURES_TAG,\n dedent`\n Arguments marked with ? are optional. Sub-components can be inline or referenced; prefer references for better streaming.\n Props typed \\`ActionExpression\\` accept an Action([@steps...]) expression. See the Action section for available steps (@ToAssistant, @OpenUrl).\n Props marked \\`$binding<type>\\` accept a \\`$variable\\` reference for two-way binding.\n\n Layout:\n Stack([children], direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean) — Flex container. direction: \"row\"|\"column\" (default \"column\"). gap: \"none\"|\"xs\"|\"s\"|\"m\"|\"l\"|\"xl\"|\"2xl\" (default \"m\"). align: \"start\"|\"center\"|\"end\"|\"stretch\"|\"baseline\". justify: \"start\"|\"center\"|\"end\"|\"between\"|\"around\"|\"evenly\".\n Tabs(items: TabItem[]) — Tabbed container\n TabItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[]) — value is unique id, trigger is tab label, content is array of components\n Accordion(items: AccordionItem[]) — Collapsible sections\n AccordionItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[]) — value is unique id, trigger is section title\n Steps(items: StepsItem[]) — Step-by-step guide\n StepsItem(title: string, details: string) — title and details text for one step\n Carousel(children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[][], variant?: \"card\" | \"sunk\") — Horizontal scrollable carousel\n Separator(orientation?: \"horizontal\" | \"vertical\", decorative?: boolean) — Visual divider between content sections\n Modal(title: string, open?: $binding<boolean>, children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[], size?: \"sm\" | \"md\" | \"lg\") — Modal dialog. open is a reactive $boolean binding — set to true to open, X/Escape/backdrop auto-closes. Put Form with buttons inside children.\n - For grid-like layouts, use Stack with direction \"row\" and wrap set to true.\n - Prefer justify \"start\" (or omit justify) with wrap=true for stable columns instead of uneven gutters.\n - Use nested Stacks when you need explicit rows/sections.\n - Show/hide sections: $editId != \"\" ? Card([editForm]) : null\n - Modal: Modal(\"Title\", $showModal, [content]) — $showModal is boolean, X/Escape auto-closes. Put Form with its own buttons inside children.\n - Use Tabs for alternative views (chart types, data sections) — no $variable needed\n - Shared filter across Tabs: same $days binding in Query args works across all TabItems\n\n Content:\n Card(children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps | Tabs | Carousel | Stack)[], variant?: \"card\" | \"sunk\" | \"clear\", direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean) — Styled container. variant: \"card\" (default, elevated) | \"sunk\" (recessed) | \"clear\" (transparent). Always full width. Accepts all Stack flex params (default: direction \"column\"). Cards flex to share space in row/wrap layouts.\n CardHeader(title?: string, subtitle?: string) — Header with optional title and subtitle\n TextContent(text: string, size?: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\") — Text block. Supports markdown. Optional size: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\".\n MarkDownRenderer(textMarkdown: string, variant?: \"clear\" | \"card\" | \"sunk\") — Renders markdown text with optional container variant\n Callout(variant: \"info\" | \"warning\" | \"error\" | \"success\" | \"neutral\", title: string, description: string, visible?: $binding<boolean>) — Callout banner. Optional visible is a reactive $boolean — auto-dismisses after 3s by setting $visible to false.\n TextCallout(variant?: \"neutral\" | \"info\" | \"warning\" | \"success\" | \"danger\", title?: string, description?: string) — Text callout with variant, title, and description\n Image(alt: string, src?: string) — Image with alt text and optional URL\n ImageBlock(src: string, alt?: string) — Image block with loading state\n ImageGallery(images: {src: string, alt?: string, details?: string}[]) — Gallery grid of images with modal preview\n CodeBlock(language: string, codeString: string) — Syntax-highlighted code block\n - Use Cards to group related KPIs or sections. Stack with direction \"row\" for side-by-side layouts.\n - Success toast: Callout(\"success\", \"Saved\", \"Done.\", $showSuccess) — use @Set($showSuccess, true) in save action, auto-dismisses after 3s. For errors: result.status == \"error\" ? Callout(\"error\", \"Failed\", result.error) : null\n - KPI card: Card([TextContent(\"Label\", \"small\"), TextContent(\"\" + @Count(@Filter(data.rows, \"field\", \"==\", \"value\")), \"large-heavy\")])\n\n Tables:\n Table(columns: Col[]) — Data table — column-oriented. Each Col holds its own data array.\n Col(label: string, data, type?: \"string\" | \"number\" | \"action\") — Column definition — holds label + data array\n - Table is COLUMN-oriented: Table([Col(\"Label\", dataArray), Col(\"Count\", countArray, \"number\")]). Use array pluck for data: data.rows.fieldName\n - Col data can be component arrays for styled cells: Col(\"Status\", @Each(data.rows, \"item\", Tag(item.status, null, \"sm\", item.status == \"open\" ? \"success\" : \"danger\")))\n - Row actions: Col(\"Actions\", @Each(data.rows, \"t\", Button(\"Edit\", Action([@Set($showEdit, true), @Set($editId, t.id)]))))\n - Sortable: sorted = @Sort(data.rows, $sortField, \"desc\"). Bind $sortField to Select. Use sorted.fieldName for Col data\n - Searchable: filtered = @Filter(data.rows, \"title\", \"contains\", $search). Bind $search to Input\n - Chain sort + filter: filtered = @Filter(...) then sorted = @Sort(filtered, ...) — use sorted for both Table and Charts\n - Empty state: @Count(data.rows) > 0 ? Table([...]) : TextContent(\"No data yet\")\n\n Charts (2D):\n BarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string) — Vertical bars; use for comparing values across categories with one or more series\n LineChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string) — Lines over categories; use for trends and continuous data over time\n AreaChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string) — Filled area under lines; use for cumulative totals or volume trends over time\n RadarChart(labels: string[], series: Series[]) — Spider/web chart; use for comparing multiple variables across one or more entities\n HorizontalBarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string) — Horizontal bars; prefer when category labels are long or for ranked lists\n Series(category: string, values: number[]) — One data series\n - Charts accept column arrays: LineChart(labels, [Series(\"Name\", values)]). Use array pluck: LineChart(data.rows.day, [Series(\"Views\", data.rows.views)])\n - Use Cards to wrap charts with CardHeader for titled sections\n - Chart + Table from same source: use @Sort or @Filter result for both LineChart and Table Col data\n - Multiple chart views: use Tabs — Tabs([TabItem(\"line\", \"Line\", [LineChart(...)]), TabItem(\"bar\", \"Bar\", [BarChart(...)])])\n\n Charts (1D):\n PieChart(labels: string[], values: number[], variant?: \"pie\" | \"donut\") — Circular slices; use plucked arrays: PieChart(data.categories, data.values)\n RadialChart(labels: string[], values: number[]) — Radial bars; use plucked arrays: RadialChart(data.categories, data.values)\n SingleStackedBarChart(labels: string[], values: number[]) — Single horizontal stacked bar; use plucked arrays: SingleStackedBarChart(data.categories, data.values)\n Slice(category: string, value: number) — One slice with label and numeric value\n - PieChart and BarChart need NUMBERS, not objects. For list data, use @Count(@Filter(...)) to aggregate:\n - PieChart from list: \\`PieChart([\"Low\", \"Med\", \"High\"], [@Count(@Filter(data.rows, \"priority\", \"==\", \"low\")), @Count(@Filter(data.rows, \"priority\", \"==\", \"medium\")), @Count(@Filter(data.rows, \"priority\", \"==\", \"high\"))], \"donut\")\\`\n - KPI from count: \\`TextContent(\"\" + @Count(@Filter(data.rows, \"status\", \"==\", \"open\")), \"large-heavy\")\\`\n\n Charts (Scatter):\n ScatterChart(datasets: ScatterSeries[], xLabel?: string, yLabel?: string) — X/Y scatter plot; use for correlations, distributions, and clustering\n ScatterSeries(name: string, points: Point[]) — Named dataset\n Point(x: number, y: number, z?: number) — Data point with numeric coordinates\n\n Data Display:\n TagBlock(tags: string[]) — tags is an array of strings\n Tag(text: string, icon?: string, size?: \"sm\" | \"md\" | \"lg\", variant?: \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\") — Styled tag/badge with optional icon and variant\n - Color-mapped Tag: Tag(value, null, \"sm\", value == \"high\" ? \"danger\" : value == \"medium\" ? \"warning\" : \"neutral\")`,\n );\n\n openui.addSection(\n OPENUI_BUILTIN_FUNCTIONS_TAG,\n dedent`\n Data functions prefixed with \\`@\\` to distinguish from components. These are the ONLY functions available — do NOT invent new ones.\n Use @-prefixed built-in functions (@Count, @Sum, @Avg, @Min, @Max, @Round) on Query results — do NOT hardcode computed values.\n\n @Count(array) → number — Returns array length\n @First(array) → element — Returns first element of array\n @Last(array) → element — Returns last element of array\n @Sum(numbers[]) → number — Sum of numeric array\n @Avg(numbers[]) → number — Average of numeric array\n @Min(numbers[]) → number — Minimum value in array\n @Max(numbers[]) → number — Maximum value in array\n @Sort(array, field, direction?) → sorted array — Sort array by field. Direction: \"asc\" (default) or \"desc\"\n @Filter(array, field, operator: \"==\" | \"!=\" | \">\" | \"<\" | \">=\" | \"<=\" | \"contains\", value) → filtered array — Filter array by field value\n @Round(number, decimals?) → number — Round to N decimal places (default 0)\n @Abs(number) → number — Absolute value\n @Floor(number) → number — Round down to nearest integer\n @Ceil(number) → number — Round up to nearest integer\n @Each(array, varName, template) — Evaluate template for each element. varName is the loop variable — use it ONLY inside the template expression (inline). Do NOT create a separate statement for the template.\n\n Builtins compose — output of one is input to the next:\n \\`@Count(@Filter(data.rows, \"field\", \"==\", \"val\"))\\` for KPIs/chart values, \\`@Round(@Avg(data.rows.score), 1)\\`, \\`@Each(data.rows, \"item\", Comp(item.field))\\` for per-item rendering.\n Array pluck: \\`data.rows.field\\` extracts a field from every row → use with @Sum, @Avg, charts, tables.\n\n IMPORTANT @Each rule: The loop variable (e.g. \"item\") is ONLY available inside the @Each template expression. Always inline the template — do NOT extract it to a separate statement.\n CORRECT: \\`Col(\"Actions\", @Each(rows, \"t\", Button(\"Edit\", Action([@Set($id, t.id)]))))\\`\n WRONG: \\`myBtn = Button(\"Edit\", Action([@Set($id, t.id)]))\\` then \\`Col(\"Actions\", @Each(rows, \"t\", myBtn))\\` — t is undefined in myBtn.`,\n );\n\n openui.addSection(\n OPENUI_HOISTING_AND_STREAMING_TAG,\n dedent`\n openui-lang supports hoisting: a reference can be used BEFORE it is defined. The parser resolves all references after the full input is parsed.\n\n During streaming, the output is re-parsed on every chunk. Undefined references are temporarily unresolved and appear once their definitions stream in. This creates a progressive top-down reveal — structure first, then data fills in.\n\n Recommended statement order for optimal streaming:\n 1. \\`root = Stack(...)\\` — UI shell appears immediately\n 2. $variable declarations — state ready for bindings\n 3. Query statements — defaults resolve immediately so components render with data\n 4. Component definitions — fill in with data already available\n 5. Data values — leaf content last\n\n Always write the root = Stack(...) statement first so the UI shell appears immediately, even before child data has streamed in.`,\n );\n\n openui.addSection(\n OPENUI_EXAMPLES_TAG,\n dedent`\n Example 1 — Table (column-oriented):\n\n root = Stack([title, tbl])\n title = TextContent(\"Top Languages\", \"large-heavy\")\n tbl = Table([Col(\"Language\", langs), Col(\"Users (M)\", users), Col(\"Year\", years)])\n langs = [\"Python\", \"JavaScript\", \"Java\", \"TypeScript\", \"Go\"]\n users = [15.7, 14.2, 12.1, 8.5, 5.2]\n years = [1991, 1995, 1995, 2012, 2009]\n\n Example 2 — Bar chart:\n\n root = Stack([title, chart])\n title = TextContent(\"Q4 Revenue\", \"large-heavy\")\n chart = BarChart(labels, [s1, s2], \"grouped\")\n labels = [\"Oct\", \"Nov\", \"Dec\"]\n s1 = Series(\"Product A\", [120, 150, 180])\n s2 = Series(\"Product B\", [90, 110, 140])\n\n Example 3 — Form with validation:\n\n root = Stack([title, form])\n title = TextContent(\"Contact Us\", \"large-heavy\")\n form = Form(\"contact\", btns, [nameField, emailField, countryField, msgField])\n nameField = FormControl(\"Name\", Input(\"name\", \"Your name\", \"text\", { required: true, minLength: 2 }))\n emailField = FormControl(\"Email\", Input(\"email\", \"you@example.com\", \"email\", { required: true, email: true }))\n countryField = FormControl(\"Country\", Select(\"country\", countryOpts, \"Select...\", { required: true }))\n msgField = FormControl(\"Message\", TextArea(\"message\", \"Tell us more...\", 4, { required: true, minLength: 10 }))\n countryOpts = [SelectItem(\"us\", \"United States\"), SelectItem(\"uk\", \"United Kingdom\"), SelectItem(\"de\", \"Germany\")]\n btns = Buttons([Button(\"Submit\", Action([@ToAssistant(\"Submit\")]), \"primary\"), Button(\"Cancel\", Action([@ToAssistant(\"Cancel\")]), \"secondary\")])\n\n Example 4 — Tabs with mixed content:\n\n root = Stack([title, tabs])\n title = TextContent(\"React vs Vue\", \"large-heavy\")\n tabs = Tabs([tabReact, tabVue])\n tabReact = TabItem(\"react\", \"React\", reactContent)\n tabVue = TabItem(\"vue\", \"Vue\", vueContent)\n reactContent = [TextContent(\"React is a library by Meta for building UIs.\"), Callout(\"info\", \"Note\", \"React uses JSX syntax.\")]\n vueContent = [TextContent(\"Vue is a progressive framework by Evan You.\"), Callout(\"success\", \"Tip\", \"Vue has a gentle learning curve.\")]`,\n );\n\n openui.addSection(\n OPENUI_IMPORTANT_RULES_TAG,\n dedent`\n - When asked about data, generate realistic/plausible data\n - Choose components that best represent the content (tables for comparisons, charts for trends, forms for input, etc.)\n - When you render data in an openui block (tables, charts, KPI cards), do NOT repeat the same numbers/facts in the markdown text outside the block.\n - Text outside the openui block can optionally include:\n 1. **Qualitative insights** — patterns, anomalies, or recommendations that aren't obvious from the visual (e.g. \"the high input-to-output ratio suggests document processing\")\n 2. **Actionable next steps** — what the user can do next\n 3. **Caveats/context** — things the data doesn't show\n - If all the information is already visible in the openui components, a brief one-line summary is sufficient — do not enumerate the same values again.`,\n );\n\n openui.addSection(\n OPENUI_FINAL_VERIFICATION_TAG,\n dedent`\n Before finishing, walk your output and verify:\n 1. root = Stack(...) is the FIRST line (for optimal streaming).\n 2. Every referenced name is defined. Every defined name (other than root) is reachable from root.\n\n - For grid-like layouts, use Stack with direction \"row\" and wrap=true. Avoid justify=\"between\" unless you specifically want large gutters.\n - For forms, define one FormControl reference per field so controls can stream progressively.\n - For forms, always provide the second Form argument with Buttons(...) actions: Form(name, buttons, fields).\n - Never nest Form inside Form.\n - Use @Reset($var1, $var2) after form submit to restore defaults — not @Set($var, \"\")\n - Multi-query refresh: Action([@Run(mutation), @Run(query1), @Run(query2), @Reset(...)])\n - $variables are reactive: changing via Select or @Set re-evaluates all Queries and expressions referencing them\n - Use existing components (Tabs, Accordion, Modal) before inventing ternary show/hide patterns`,\n );\n\n openui.addSection(\n OPENUI_USER_INTERACTION_CHECKLIST_TAG,\n dedent`\n 1. Will the response be UI heavy and will contain components which are not supported by markdown? Use openui if the answer is yes.\n 2. \\`\\`\\`openui\\`\\`\\` fencing must be closed.`,\n );\n}\n\n/** Renders the existing OpenUI prompt tree without duplicating section bodies. */\nexport function renderOpenUIPrompt(): string {\n const root = new InstructionBuilder('_openui_render');\n buildOpenUIInstruction(root);\n const wrapped = root.build();\n const openTag = `<${OPENUI_SECTION_TAG}>`;\n const closeTag = `</${OPENUI_SECTION_TAG}>`;\n const start = wrapped.indexOf(openTag);\n const end = wrapped.lastIndexOf(closeTag);\n if (start === -1 || end === -1) {\n throw new Error('Failed to render OpenUI prompt from buildOpenUIInstruction');\n }\n return wrapped.slice(start, end + closeTag.length);\n}\n\nfunction buildOpenUIDeferredInstruction(builder: InstructionBuilder): void {\n builder.addSection(\n OPENUI_SECTION_TAG,\n dedent`\n The Agent can render interactive UI that markdown cannot express by emitting a fenced \\`\\`\\`openui block.\n\n Before writing any \\`\\`\\`openui fence, the Agent MUST call ${GET_OPENUI_INSTRUCTIONS_TOOL_NAME} with arguments {}.\n Do not invent OpenUI syntax or component APIs without loading those instructions.\n\n Use OpenUI only when the response is UI-heavy and needs components markdown does not support.\n `.trim(),\n );\n}\n\nexport class OpenUIInstructions extends LocalToolMCP {\n readonly name = OPENUI_SERVER_ID;\n readonly displayName = 'OpenUI';\n\n constructor(tracing: AgentTracing) {\n super({ tracing });\n }\n\n private tools: ToolDefinition[] = [\n defineTool({\n name: GET_OPENUI_INSTRUCTIONS_TOOL_NAME,\n description: [\n 'Load the full OpenUI generative-UI authoring instructions (syntax, components, builtins, examples, rules).',\n 'Call this before emitting any ```openui fenced block. Pass an empty object as arguments: {}.',\n ].join(' '),\n schema: getOpenUIInstructionsInputSchema,\n handler: () => Promise.resolve(toolResultResponse({ text: renderOpenUIPrompt() })),\n }),\n ];\n\n protected getTools(): ToolDefinition[] {\n return this.tools;\n }\n}\n\nexport function openUI(options?: { preload?: boolean; tracing?: AgentTracing }): AgentCapability {\n const preload = options?.preload ?? true;\n if (preload) {\n return {\n instructionBuilders: [buildOpenUIInstruction],\n };\n }\n return {\n systemToolSets: [new OpenUIInstructions(options?.tracing ?? NOOP_AGENT_TRACING)],\n instructionBuilders: [buildOpenUIDeferredInstruction],\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/capabilities/builtins/OpenUI.ts"],"sourcesContent":["import dedent from 'dedent';\nimport { z } from 'zod';\nimport { InstructionBuilder } from '../../InstructionBuilder';\nimport { toolResultResponse } from '../../mcp/IMCPServer';\nimport { defineTool, LocalToolMCP, type ToolDefinition } from '../../mcp/LocalToolMCP';\nimport type { AgentTracing } from '../../tracing/AgentTracing';\nimport { NOOP_AGENT_TRACING } from '../../tracing/NoopAgentTracing';\nimport type { AgentCapability } from '../AgentCapability';\n\nexport const OPENUI_SERVER_ID = 'openui';\nexport const GET_OPENUI_INSTRUCTIONS_TOOL_NAME = 'get_openui_instructions';\n\nconst getOpenUIInstructionsInputSchema = z.object({}).strict();\n\nexport const OPENUI_SECTION_TAG = 'openui';\nexport const OPENUI_MARKDOWN_FENCING_TAG = 'openui-markdown-fencing';\nexport const OPENUI_SYNTAX_RULES_TAG = 'openui-syntax-rules';\nexport const OPENUI_COMPONENT_SIGNATURES_TAG = 'openui-component-signatures';\nexport const OPENUI_BUILTIN_FUNCTIONS_TAG = 'openui-builtin-functions';\nexport const OPENUI_HOISTING_AND_STREAMING_TAG = 'openui-hoisting-and-streaming';\nexport const OPENUI_EXAMPLES_TAG = 'openui-examples';\nexport const OPENUI_IMPORTANT_RULES_TAG = 'openui-important-rules';\nexport const OPENUI_FINAL_VERIFICATION_TAG = 'openui-final-verification';\nexport const OPENUI_USER_INTERACTION_CHECKLIST_TAG = 'openui-user-interaction-checklist';\n\nexport function buildOpenUIInstruction(builder: InstructionBuilder): void {\n const openui = builder.beginSection(OPENUI_SECTION_TAG);\n\n openui.addSection(\n OPENUI_MARKDOWN_FENCING_TAG,\n dedent`\n All openui, code must be fenced within openui block.\n \\`\\`\\`openui\n code\n \\`\\`\\``,\n );\n\n openui.addSection(\n OPENUI_SYNTAX_RULES_TAG,\n dedent`\n 1. Each statement is on its own line: \\`identifier = Expression\\`\n 2. \\`root\\` is the entry point — every program must define \\`root = Stack(...)\\`\n 3. Expressions are: strings (\"...\"), numbers, booleans (true/false), null, arrays ([...]), objects ({...}), or component calls TypeName(arg1, arg2, ...)\n 4. Use references for readability: define \\`name = ...\\` on one line, then use \\`name\\` later\n 5. EVERY variable (except root) MUST be referenced by at least one other variable. Unreferenced variables are silently dropped and will NOT render. Always include defined variables in their parent's children/items array.\n 6. Arguments are POSITIONAL (order matters, not names). Write \\`Stack([children], \"row\", \"l\")\\` NOT \\`Stack([children], direction: \"row\", gap: \"l\")\\` — colon syntax is NOT supported and silently breaks\n 7. Optional arguments can be omitted from the end\n - Strings use double quotes with backslash escaping`,\n );\n\n openui.addSection(\n OPENUI_COMPONENT_SIGNATURES_TAG,\n dedent`\n Arguments marked with ? are optional. Sub-components can be inline or referenced; prefer references for better streaming.\n Props typed \\`ActionExpression\\` accept an Action([@steps...]) expression. See the Action section for available steps (@ToAssistant, @OpenUrl).\n Props marked \\`$binding<type>\\` accept a \\`$variable\\` reference for two-way binding.\n\n Layout:\n Stack([children], direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean) — Flex container. direction: \"row\"|\"column\" (default \"column\"). gap: \"none\"|\"xs\"|\"s\"|\"m\"|\"l\"|\"xl\"|\"2xl\" (default \"m\"). align: \"start\"|\"center\"|\"end\"|\"stretch\"|\"baseline\". justify: \"start\"|\"center\"|\"end\"|\"between\"|\"around\"|\"evenly\".\n Tabs(items: TabItem[]) — Tabbed container\n TabItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[]) — value is unique id, trigger is tab label, content is array of components\n Accordion(items: AccordionItem[]) — Collapsible sections\n AccordionItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[]) — value is unique id, trigger is section title\n Steps(items: StepsItem[]) — Step-by-step guide\n StepsItem(title: string, details: string) — title and details text for one step\n Carousel(children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[][], variant?: \"card\" | \"sunk\") — Horizontal scrollable carousel\n Separator(orientation?: \"horizontal\" | \"vertical\", decorative?: boolean) — Visual divider between content sections\n Modal(title: string, open?: $binding<boolean>, children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[], size?: \"sm\" | \"md\" | \"lg\") — Modal dialog. open is a reactive $boolean binding — set to true to open, X/Escape/backdrop auto-closes. Put Form with buttons inside children.\n - For grid-like layouts, use Stack with direction \"row\" and wrap set to true.\n - Prefer justify \"start\" (or omit justify) with wrap=true for stable columns instead of uneven gutters.\n - Use nested Stacks when you need explicit rows/sections.\n - Show/hide sections: $editId != \"\" ? Card([editForm]) : null\n - Modal: Modal(\"Title\", $showModal, [content]) — $showModal is boolean, X/Escape auto-closes. Put Form with its own buttons inside children.\n - Use Tabs for alternative views (chart types, data sections) — no $variable needed\n - Shared filter across Tabs: same $days binding in Query args works across all TabItems\n\n Content:\n Card(children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps | Tabs | Carousel | Stack)[], variant?: \"card\" | \"sunk\" | \"clear\", direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean) — Styled container. variant: \"card\" (default, elevated) | \"sunk\" (recessed) | \"clear\" (transparent). Always full width. Accepts all Stack flex params (default: direction \"column\"). Cards flex to share space in row/wrap layouts.\n CardHeader(title?: string, subtitle?: string) — Header with optional title and subtitle\n TextContent(text: string, size?: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\") — Text block. Supports markdown. Optional size: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\".\n MarkDownRenderer(textMarkdown: string, variant?: \"clear\" | \"card\" | \"sunk\") — Renders markdown text with optional container variant\n Callout(variant: \"info\" | \"warning\" | \"error\" | \"success\" | \"neutral\", title: string, description: string, visible?: $binding<boolean>) — Callout banner. Optional visible is a reactive $boolean — auto-dismisses after 3s by setting $visible to false.\n TextCallout(variant?: \"neutral\" | \"info\" | \"warning\" | \"success\" | \"danger\", title?: string, description?: string) — Text callout with variant, title, and description\n Image(alt: string, src?: string) — Image with alt text and optional URL\n ImageBlock(src: string, alt?: string) — Image block with loading state\n ImageGallery(images: {src: string, alt?: string, details?: string}[]) — Gallery grid of images with modal preview\n CodeBlock(language: string, codeString: string) — Syntax-highlighted code block\n - Use Cards to group related KPIs or sections. Stack with direction \"row\" for side-by-side layouts.\n - Success toast: Callout(\"success\", \"Saved\", \"Done.\", $showSuccess) — use @Set($showSuccess, true) in save action, auto-dismisses after 3s. For errors: result.status == \"error\" ? Callout(\"error\", \"Failed\", result.error) : null\n - KPI card: Card([TextContent(\"Label\", \"small\"), TextContent(\"\" + @Count(@Filter(data.rows, \"field\", \"==\", \"value\")), \"large-heavy\")])\n\n Tables:\n Table(columns: Col[]) — Data table — column-oriented. Each Col holds its own data array.\n Col(label: string, data, type?: \"string\" | \"number\" | \"action\") — Column definition — holds label + data array\n - Table is COLUMN-oriented: Table([Col(\"Label\", dataArray), Col(\"Count\", countArray, \"number\")]). Use array pluck for data: data.rows.fieldName\n - Col data can be component arrays for styled cells: Col(\"Status\", @Each(data.rows, \"item\", Tag(item.status, null, \"sm\", item.status == \"open\" ? \"success\" : \"danger\")))\n - Row actions: Col(\"Actions\", @Each(data.rows, \"t\", Button(\"Edit\", Action([@Set($showEdit, true), @Set($editId, t.id)]))))\n - Sortable: sorted = @Sort(data.rows, $sortField, \"desc\"). Bind $sortField to Select. Use sorted.fieldName for Col data\n - Searchable: filtered = @Filter(data.rows, \"title\", \"contains\", $search). Bind $search to Input\n - Chain sort + filter: filtered = @Filter(...) then sorted = @Sort(filtered, ...) — use sorted for both Table and Charts\n - Empty state: @Count(data.rows) > 0 ? Table([...]) : TextContent(\"No data yet\")\n\n Charts (2D):\n BarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string) — Vertical bars; use for comparing values across categories with one or more series\n LineChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string) — Lines over categories; use for trends and continuous data over time\n AreaChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string) — Filled area under lines; use for cumulative totals or volume trends over time\n RadarChart(labels: string[], series: Series[]) — Spider/web chart; use for comparing multiple variables across one or more entities\n HorizontalBarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string) — Horizontal bars; prefer when category labels are long or for ranked lists\n Series(category: string, values: number[]) — One data series\n - Charts accept column arrays: LineChart(labels, [Series(\"Name\", values)]). Use array pluck: LineChart(data.rows.day, [Series(\"Views\", data.rows.views)])\n - Use Cards to wrap charts with CardHeader for titled sections\n - Chart + Table from same source: use @Sort or @Filter result for both LineChart and Table Col data\n - Multiple chart views: use Tabs — Tabs([TabItem(\"line\", \"Line\", [LineChart(...)]), TabItem(\"bar\", \"Bar\", [BarChart(...)])])\n\n Charts (1D):\n PieChart(labels: string[], values: number[], variant?: \"pie\" | \"donut\") — Circular slices; use plucked arrays: PieChart(data.categories, data.values)\n RadialChart(labels: string[], values: number[]) — Radial bars; use plucked arrays: RadialChart(data.categories, data.values)\n SingleStackedBarChart(labels: string[], values: number[]) — Single horizontal stacked bar; use plucked arrays: SingleStackedBarChart(data.categories, data.values)\n Slice(category: string, value: number) — One slice with label and numeric value\n - PieChart and BarChart need NUMBERS, not objects. For list data, use @Count(@Filter(...)) to aggregate:\n - PieChart from list: \\`PieChart([\"Low\", \"Med\", \"High\"], [@Count(@Filter(data.rows, \"priority\", \"==\", \"low\")), @Count(@Filter(data.rows, \"priority\", \"==\", \"medium\")), @Count(@Filter(data.rows, \"priority\", \"==\", \"high\"))], \"donut\")\\`\n - KPI from count: \\`TextContent(\"\" + @Count(@Filter(data.rows, \"status\", \"==\", \"open\")), \"large-heavy\")\\`\n\n Charts (Scatter):\n ScatterChart(datasets: ScatterSeries[], xLabel?: string, yLabel?: string) — X/Y scatter plot; use for correlations, distributions, and clustering\n ScatterSeries(name: string, points: Point[]) — Named dataset\n Point(x: number, y: number, z?: number) — Data point with numeric coordinates\n\n Data Display:\n TagBlock(tags: string[]) — tags is an array of strings\n Tag(text: string, icon?: string, size?: \"sm\" | \"md\" | \"lg\", variant?: \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\") — Styled tag/badge with optional icon and variant\n - Color-mapped Tag: Tag(value, null, \"sm\", value == \"high\" ? \"danger\" : value == \"medium\" ? \"warning\" : \"neutral\")`,\n );\n\n openui.addSection(\n OPENUI_BUILTIN_FUNCTIONS_TAG,\n dedent`\n Data functions prefixed with \\`@\\` to distinguish from components. These are the ONLY functions available — do NOT invent new ones.\n Use @-prefixed built-in functions (@Count, @Sum, @Avg, @Min, @Max, @Round) on Query results — do NOT hardcode computed values.\n\n @Count(array) → number — Returns array length\n @First(array) → element — Returns first element of array\n @Last(array) → element — Returns last element of array\n @Sum(numbers[]) → number — Sum of numeric array\n @Avg(numbers[]) → number — Average of numeric array\n @Min(numbers[]) → number — Minimum value in array\n @Max(numbers[]) → number — Maximum value in array\n @Sort(array, field, direction?) → sorted array — Sort array by field. Direction: \"asc\" (default) or \"desc\"\n @Filter(array, field, operator: \"==\" | \"!=\" | \">\" | \"<\" | \">=\" | \"<=\" | \"contains\", value) → filtered array — Filter array by field value\n @Round(number, decimals?) → number — Round to N decimal places (default 0)\n @Abs(number) → number — Absolute value\n @Floor(number) → number — Round down to nearest integer\n @Ceil(number) → number — Round up to nearest integer\n @Each(array, varName, template) — Evaluate template for each element. varName is the loop variable — use it ONLY inside the template expression (inline). Do NOT create a separate statement for the template.\n\n Builtins compose — output of one is input to the next:\n \\`@Count(@Filter(data.rows, \"field\", \"==\", \"val\"))\\` for KPIs/chart values, \\`@Round(@Avg(data.rows.score), 1)\\`, \\`@Each(data.rows, \"item\", Comp(item.field))\\` for per-item rendering.\n Array pluck: \\`data.rows.field\\` extracts a field from every row → use with @Sum, @Avg, charts, tables.\n\n IMPORTANT @Each rule: The loop variable (e.g. \"item\") is ONLY available inside the @Each template expression. Always inline the template — do NOT extract it to a separate statement.\n CORRECT: \\`Col(\"Actions\", @Each(rows, \"t\", Button(\"Edit\", Action([@Set($id, t.id)]))))\\`\n WRONG: \\`myBtn = Button(\"Edit\", Action([@Set($id, t.id)]))\\` then \\`Col(\"Actions\", @Each(rows, \"t\", myBtn))\\` — t is undefined in myBtn.`,\n );\n\n openui.addSection(\n OPENUI_HOISTING_AND_STREAMING_TAG,\n dedent`\n openui-lang supports hoisting: a reference can be used BEFORE it is defined. The parser resolves all references after the full input is parsed.\n\n During streaming, the output is re-parsed on every chunk. Undefined references are temporarily unresolved and appear once their definitions stream in. This creates a progressive top-down reveal — structure first, then data fills in.\n\n Recommended statement order for optimal streaming:\n 1. \\`root = Stack(...)\\` — UI shell appears immediately\n 2. $variable declarations — state ready for bindings\n 3. Query statements — defaults resolve immediately so components render with data\n 4. Component definitions — fill in with data already available\n 5. Data values — leaf content last\n\n Always write the root = Stack(...) statement first so the UI shell appears immediately, even before child data has streamed in.`,\n );\n\n openui.addSection(\n OPENUI_EXAMPLES_TAG,\n dedent`\n Example 1 — Table (column-oriented):\n\n root = Stack([title, tbl])\n title = TextContent(\"Top Languages\", \"large-heavy\")\n tbl = Table([Col(\"Language\", langs), Col(\"Users (M)\", users), Col(\"Year\", years)])\n langs = [\"Python\", \"JavaScript\", \"Java\", \"TypeScript\", \"Go\"]\n users = [15.7, 14.2, 12.1, 8.5, 5.2]\n years = [1991, 1995, 1995, 2012, 2009]\n\n Example 2 — Bar chart:\n\n root = Stack([title, chart])\n title = TextContent(\"Q4 Revenue\", \"large-heavy\")\n chart = BarChart(labels, [s1, s2], \"grouped\")\n labels = [\"Oct\", \"Nov\", \"Dec\"]\n s1 = Series(\"Product A\", [120, 150, 180])\n s2 = Series(\"Product B\", [90, 110, 140])\n\n Example 3 — Form with validation:\n\n root = Stack([title, form])\n title = TextContent(\"Contact Us\", \"large-heavy\")\n form = Form(\"contact\", btns, [nameField, emailField, countryField, msgField])\n nameField = FormControl(\"Name\", Input(\"name\", \"Your name\", \"text\", { required: true, minLength: 2 }))\n emailField = FormControl(\"Email\", Input(\"email\", \"you@example.com\", \"email\", { required: true, email: true }))\n countryField = FormControl(\"Country\", Select(\"country\", countryOpts, \"Select...\", { required: true }))\n msgField = FormControl(\"Message\", TextArea(\"message\", \"Tell us more...\", 4, { required: true, minLength: 10 }))\n countryOpts = [SelectItem(\"us\", \"United States\"), SelectItem(\"uk\", \"United Kingdom\"), SelectItem(\"de\", \"Germany\")]\n btns = Buttons([Button(\"Submit\", Action([@ToAssistant(\"Submit\")]), \"primary\"), Button(\"Cancel\", Action([@ToAssistant(\"Cancel\")]), \"secondary\")])\n\n Example 4 — Tabs with mixed content:\n\n root = Stack([title, tabs])\n title = TextContent(\"React vs Vue\", \"large-heavy\")\n tabs = Tabs([tabReact, tabVue])\n tabReact = TabItem(\"react\", \"React\", reactContent)\n tabVue = TabItem(\"vue\", \"Vue\", vueContent)\n reactContent = [TextContent(\"React is a library by Meta for building UIs.\"), Callout(\"info\", \"Note\", \"React uses JSX syntax.\")]\n vueContent = [TextContent(\"Vue is a progressive framework by Evan You.\"), Callout(\"success\", \"Tip\", \"Vue has a gentle learning curve.\")]`,\n );\n\n openui.addSection(\n OPENUI_IMPORTANT_RULES_TAG,\n dedent`\n - When asked about data, generate realistic/plausible data\n - Prefer OpenUI charts for plot/chart/visualize; images only if downloadable\n - Choose components that best represent the content (tables for comparisons, charts for trends, forms for input, etc.)\n - When you render data in an openui block (tables, charts, KPI cards), do NOT repeat the same numbers/facts in the markdown text outside the block.\n - Text outside the openui block can optionally include:\n 1. **Qualitative insights** — patterns, anomalies, or recommendations that aren't obvious from the visual (e.g. \"the high input-to-output ratio suggests document processing\")\n 2. **Actionable next steps** — what the user can do next\n 3. **Caveats/context** — things the data doesn't show\n - If all the information is already visible in the openui components, a brief one-line summary is sufficient — do not enumerate the same values again.`,\n );\n\n openui.addSection(\n OPENUI_FINAL_VERIFICATION_TAG,\n dedent`\n Before finishing, walk your output and verify:\n 1. root = Stack(...) is the FIRST line (for optimal streaming).\n 2. Every referenced name is defined. Every defined name (other than root) is reachable from root.\n\n - For grid-like layouts, use Stack with direction \"row\" and wrap=true. Avoid justify=\"between\" unless you specifically want large gutters.\n - For forms, define one FormControl reference per field so controls can stream progressively.\n - For forms, always provide the second Form argument with Buttons(...) actions: Form(name, buttons, fields).\n - Never nest Form inside Form.\n - Use @Reset($var1, $var2) after form submit to restore defaults — not @Set($var, \"\")\n - Multi-query refresh: Action([@Run(mutation), @Run(query1), @Run(query2), @Reset(...)])\n - $variables are reactive: changing via Select or @Set re-evaluates all Queries and expressions referencing them\n - Use existing components (Tabs, Accordion, Modal) before inventing ternary show/hide patterns`,\n );\n\n openui.addSection(\n OPENUI_USER_INTERACTION_CHECKLIST_TAG,\n dedent`\n 1. Plot/chart/visualize or UI-heavy beyond markdown? Use openui.\n 2. \\`\\`\\`openui\\`\\`\\` fencing must be closed.`,\n );\n}\n\n/** Renders the existing OpenUI prompt tree without duplicating section bodies. */\nexport function renderOpenUIPrompt(): string {\n const root = new InstructionBuilder('_openui_render');\n buildOpenUIInstruction(root);\n const wrapped = root.build();\n const openTag = `<${OPENUI_SECTION_TAG}>`;\n const closeTag = `</${OPENUI_SECTION_TAG}>`;\n const start = wrapped.indexOf(openTag);\n const end = wrapped.lastIndexOf(closeTag);\n if (start === -1 || end === -1) {\n throw new Error('Failed to render OpenUI prompt from buildOpenUIInstruction');\n }\n return wrapped.slice(start, end + closeTag.length);\n}\n\nfunction buildOpenUIDeferredInstruction(builder: InstructionBuilder): void {\n builder.addSection(\n OPENUI_SECTION_TAG,\n dedent`\n The Agent can render interactive UI that markdown cannot express by emitting a fenced \\`\\`\\`openui block.\n\n Before writing any \\`\\`\\`openui fence, the Agent MUST call ${GET_OPENUI_INSTRUCTIONS_TOOL_NAME} with arguments {}.\n Do not invent OpenUI syntax or component APIs without loading those instructions.\n\n Prefer OpenUI for plot/chart/visualize over sandbox code; sandbox images only for downloads.\n Otherwise use OpenUI only when UI-heavy beyond markdown.\n `.trim(),\n );\n}\n\nexport class OpenUIInstructions extends LocalToolMCP {\n readonly name = OPENUI_SERVER_ID;\n readonly displayName = 'OpenUI';\n\n constructor(tracing: AgentTracing) {\n super({ tracing });\n }\n\n private tools: ToolDefinition[] = [\n defineTool({\n name: GET_OPENUI_INSTRUCTIONS_TOOL_NAME,\n description: [\n 'Load the full OpenUI generative-UI authoring instructions (syntax, components, builtins, examples, rules).',\n 'Call this before emitting any ```openui fenced block. Pass an empty object as arguments: {}.',\n ].join(' '),\n schema: getOpenUIInstructionsInputSchema,\n handler: () => Promise.resolve(toolResultResponse({ text: renderOpenUIPrompt() })),\n }),\n ];\n\n protected getTools(): ToolDefinition[] {\n return this.tools;\n }\n}\n\nexport function openUI(options?: { preload?: boolean; tracing?: AgentTracing }): AgentCapability {\n const preload = options?.preload ?? true;\n if (preload) {\n return {\n instructionBuilders: [buildOpenUIInstruction],\n };\n }\n return {\n systemToolSets: [new OpenUIInstructions(options?.tracing ?? NOOP_AGENT_TRACING)],\n instructionBuilders: [buildOpenUIDeferredInstruction],\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeferredTool.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/DeferredTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAE1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAML,KAAK,QAAQ,EAGd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAc,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AAEzD,eAAO,MAAM,eAAe,eAAe,CAAC;AAC5C,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,2BAA2B,2BAA2B,CAAC;AAkCpE,qBAAa,YAAa,SAAQ,YAAY;IAC5C,QAAQ,CAAC,IAAI,oBAA4B;IACzC,QAAQ,CAAC,WAAW,mBAAmB;IACvC,SAAkB,WAAW,gDAAgD;IAE7E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,YACE,OAAO,EAAE,SAAS,QAAQ,EAAE,EAC5B,OAAO,EAAE;QACP,OAAO,EAAE,YAAY,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;KAChB,EAMF;IAED,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAuBlD;IAED,SAAS,CAAC,QAAQ,IAAI,cAAc,EAAE,CAErC;IAEc,YAAY,CACzB,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,EACjC,qBAAqB,CAAC,EAAE,OAAO,GAC9B,OAAO,CAAC,oBAAoB,CAAC,CA8B/B;IAED,OAAO,CAAC,aAAa;YAIP,kBAAkB;IAiBhC,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,cAAc;
|
|
1
|
+
{"version":3,"file":"DeferredTool.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/DeferredTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAE1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAML,KAAK,QAAQ,EAGd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAc,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AAEzD,eAAO,MAAM,eAAe,eAAe,CAAC;AAC5C,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,2BAA2B,2BAA2B,CAAC;AAkCpE,qBAAa,YAAa,SAAQ,YAAY;IAC5C,QAAQ,CAAC,IAAI,oBAA4B;IACzC,QAAQ,CAAC,WAAW,mBAAmB;IACvC,SAAkB,WAAW,gDAAgD;IAE7E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,YACE,OAAO,EAAE,SAAS,QAAQ,EAAE,EAC5B,OAAO,EAAE;QACP,OAAO,EAAE,YAAY,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;KAChB,EAMF;IAED,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAuBlD;IAED,SAAS,CAAC,QAAQ,IAAI,cAAc,EAAE,CAErC;IAEc,YAAY,CACzB,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,EACjC,qBAAqB,CAAC,EAAE,OAAO,GAC9B,OAAO,CAAC,oBAAoB,CAAC,CA8B/B;IAED,OAAO,CAAC,aAAa;YAIP,kBAAkB;IAiBhC,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,cAAc;IAkCtB,OAAO,CAAC,gBAAgB;IAiDxB,OAAO,CAAC,wBAAwB;IAgDhC,OAAO,CAAC,aAAa;CAiDtB"}
|
|
@@ -178,7 +178,9 @@ var DeferredTool = class extends import_LocalToolMCP.LocalToolMCP {
|
|
|
178
178
|
mcpServer: input.mcp_server
|
|
179
179
|
});
|
|
180
180
|
return (0, import_IMCPServer.toolResultResponse)({
|
|
181
|
-
text: JSON.stringify({
|
|
181
|
+
text: JSON.stringify({
|
|
182
|
+
error: `Failed to list tools for '${input.mcp_server}': ${error instanceof Error ? error.message : "unknown"}`
|
|
183
|
+
}),
|
|
182
184
|
isError: true
|
|
183
185
|
});
|
|
184
186
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/runtime/DeferredTool.ts"],"sourcesContent":["import type { CallToolRequest } from '@modelcontextprotocol/sdk/types.js';\nimport dedent from 'dedent';\nimport type { Logger } from 'winston';\nimport { z } from 'zod';\nimport type { ApprovalDecision } from '../events/schema';\nimport { InstructionBuilder } from '../InstructionBuilder';\nimport type { InternalToolCallInfo } from '../llm/LLMTypes';\nimport {\n type AgentToolSchema,\n type CallToolResponse,\n isApprovalRequiredResponse,\n isAuthRequired,\n isCallToolResponseResult,\n type IToolSet,\n type ListToolsResolvedResponse,\n toolResultResponse,\n} from '../mcp/IMCPServer';\nimport { defineTool, LocalToolMCP, type ToolDefinition } from '../mcp/LocalToolMCP';\nimport type { AgentTracing } from '../tracing/AgentTracing';\nimport { extractErrorLogFields } from '../util/errorLogFields';\n\nexport const DEFERRED_TOOLS_SERVER_ID = 'deferred-tools';\nconst DEFERRED_TOOLS_INSTRUCTION = 'deferred-tools-instructions';\nexport const LIST_TOOLS_NAME = 'list_tools';\nexport const GET_TOOL_INFO_NAME = 'get_tool_info';\nexport const GET_TOOL_OUTPUT_SCHEMA_NAME = 'get_tool_output_schema';\nconst CALL_TOOL_NAME = 'call_tool';\nconst MAX_DESCRIPTION_LENGTH = 200;\n\nconst listToolsSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server to list tools for.'),\n});\n\nconst getToolInfoSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to inspect.'),\n});\n\nconst getToolOutputSchemaSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to get output schema for.'),\n});\n\nconst callToolSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to call.'),\n input: z.record(z.string(), z.unknown()).default({}).describe('Arguments to pass to the tool.'),\n});\n\ninterface ResolvedServerTools {\n server: IToolSet;\n tools: AgentToolSchema[];\n metadata: Omit<ListToolsResolvedResponse, 'result'>;\n}\n\nfunction isResolvedServerTools(result: CallToolResponse | ResolvedServerTools): result is ResolvedServerTools {\n return 'tools' in result;\n}\n\nexport class DeferredTool extends LocalToolMCP {\n readonly name = DEFERRED_TOOLS_SERVER_ID;\n readonly displayName = 'DeferredTools';\n override readonly description = 'Deferred tool loading for user MCP servers';\n\n private readonly serverMap: Map<string, IToolSet>;\n private readonly tools: ToolDefinition[];\n private readonly logger: Logger;\n\n constructor(\n servers: readonly IToolSet[],\n options: {\n tracing: AgentTracing;\n logger: Logger;\n },\n ) {\n super({ tracing: options.tracing });\n this.logger = options.logger.child({ module: 'DeferredTool' });\n this.serverMap = new Map(servers.map(s => [s.name, s]));\n this.tools = this.buildTools();\n }\n\n buildInstruction(builder: InstructionBuilder): void {\n const servers = [...this.serverMap.values()];\n\n // Membership follows `preload` only (origin/main). Selective `preload_tools` /\n // `hasPreloadedTools` must not hide a server from deferred discovery instructions.\n const deferredServers = servers.filter(s => !s.preload);\n\n if (deferredServers.length === 0) {\n return;\n }\n\n const deferredList = deferredServers\n .map(s => (s.description ? `- ${s.name}: \"${s.description.slice(0, MAX_DESCRIPTION_LENGTH)}\"` : `- ${s.name}`))\n .join('\\n');\n\n builder.addSection(\n DEFERRED_TOOLS_INSTRUCTION,\n dedent`\n The following MCP servers have deferred tool loading. Their tools are NOT pre-loaded.\n ${deferredList}\n\n The Agent MUST use ${LIST_TOOLS_NAME} and ${GET_TOOL_INFO_NAME} to discover tools before calling them.`,\n );\n }\n\n protected getTools(): ToolDefinition[] {\n return this.tools;\n }\n\n override async toolCallInfo(\n params: CallToolRequest['params'],\n resolveUnderlyingTool?: boolean,\n ): Promise<InternalToolCallInfo> {\n if (params.name !== CALL_TOOL_NAME) {\n return super.toolCallInfo(params, resolveUnderlyingTool);\n }\n if (resolveUnderlyingTool === false) {\n const base = await super.toolCallInfo(params, resolveUnderlyingTool);\n return { ...base, is_deferred: true };\n }\n const parsed = callToolSchema.safeParse(params.arguments);\n if (!parsed.success) {\n this.logger.warn(`Failed to parse call_tool arguments`, {\n tool: params.name,\n errors: parsed.error.issues,\n });\n return { ...(await super.toolCallInfo(params)), is_deferred: true };\n }\n const server = this.resolveServer(parsed.data.mcp_server);\n if (!server) {\n this.logger.warn(`Server not found for toolCallInfo`, {\n mcpServer: parsed.data.mcp_server,\n toolName: parsed.data.tool_name,\n availableServers: [...this.serverMap.keys()],\n });\n return { ...(await super.toolCallInfo(params)), is_deferred: true };\n }\n const underlying = await server.toolCallInfo({\n name: parsed.data.tool_name,\n arguments: parsed.data.input,\n });\n return { ...underlying, is_deferred: true };\n }\n\n private resolveServer(name: string): IToolSet | undefined {\n return this.serverMap.get(name);\n }\n\n private async resolveServerTools(mcpServer: string): Promise<CallToolResponse | ResolvedServerTools> {\n const server = this.resolveServer(mcpServer);\n if (!server) {\n return toolResultResponse({\n text: JSON.stringify({ error: `MCP server '${mcpServer}' not found` }),\n isError: true,\n });\n }\n\n const listResponse = await server.listTools();\n if (isAuthRequired(listResponse)) {\n return listResponse;\n }\n const { result, ...metadata } = listResponse;\n return { server, tools: result.tools, metadata };\n }\n\n private buildTools(): ToolDefinition[] {\n return [this.buildListTools(), this.buildGetToolInfo(), this.buildGetToolOutputSchema(), this.buildCallTool()];\n }\n\n private buildListTools(): ToolDefinition {\n return defineTool({\n name: LIST_TOOLS_NAME,\n description: dedent`\n List tool names available on an MCP server.\n Returns tool names only — use ${GET_TOOL_INFO_NAME} to get full details before calling a tool.`,\n schema: listToolsSchema,\n handler: async (input: { mcp_server: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { server, tools, metadata } = resolved;\n return toolResultResponse({\n text: `${server.name}:\\n ${tools.map(t => t.name).join(', ')}`,\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('list_tools failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n });\n return toolResultResponse({\n text: JSON.stringify({ error: `Failed to list tools for '${input.mcp_server}'.` }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildGetToolInfo(): ToolDefinition {\n return defineTool({\n name: GET_TOOL_INFO_NAME,\n description: dedent`\n Get description, inputSchema and outputSchema for a specific tool on an MCP server.\n If outputSchema is null, it will NOT be present in ${GET_TOOL_OUTPUT_SCHEMA_NAME} as well.\n The Agent MUST call ${LIST_TOOLS_NAME} first to know which tools are available.`,\n schema: getToolInfoSchema,\n handler: async (input: { mcp_server: string; tool_name: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { tools, metadata } = resolved;\n const tool = tools.find(t => t.name === input.tool_name);\n if (!tool) {\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool '${input.tool_name}' not found on server '${input.mcp_server}'` }),\n overrides: metadata,\n isError: true,\n });\n }\n\n return toolResultResponse({\n text: JSON.stringify({\n description: tool.description,\n inputSchema: tool.inputSchema,\n outputSchema: tool.outputSchema ?? null,\n }),\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('get_tool_info failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({\n error: `Failed to get tool info: ${error instanceof Error ? error.message : 'unknown'}`,\n }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildGetToolOutputSchema(): ToolDefinition {\n return defineTool({\n name: GET_TOOL_OUTPUT_SCHEMA_NAME,\n description: dedent`\n Get the outputSchema for a specific tool on an MCP server.\n The Agent MUST not call ${GET_TOOL_OUTPUT_SCHEMA_NAME} and ${GET_TOOL_INFO_NAME} for the same tool.\n The Agent MUST either call ${GET_TOOL_OUTPUT_SCHEMA_NAME} or ${GET_TOOL_INFO_NAME} before entering Code Mode.\n The Agent must NOT assume the structure of a tool's response from its name or description alone.`,\n schema: getToolOutputSchemaSchema,\n handler: async (input: { mcp_server: string; tool_name: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { tools, metadata } = resolved;\n const tool = tools.find(t => t.name === input.tool_name);\n if (!tool) {\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool '${input.tool_name}' not found on server '${input.mcp_server}'` }),\n overrides: metadata,\n isError: true,\n });\n }\n\n return toolResultResponse({\n text: JSON.stringify({\n outputSchema: tool.outputSchema ?? null,\n }),\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('get_tool_output_schema failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({\n error: `Failed to get output schema: ${error instanceof Error ? error.message : 'unknown'}`,\n }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildCallTool(): ToolDefinition {\n return defineTool({\n name: CALL_TOOL_NAME,\n description: dedent`\n Call a tool on an MCP server.\n The Agent MUST call ${LIST_TOOLS_NAME} and ${GET_TOOL_INFO_NAME} before calling a tool.`,\n schema: callToolSchema,\n handler: async (\n input: { mcp_server: string; tool_name: string; input: Record<string, unknown> },\n approvalDecision?: ApprovalDecision,\n ) => {\n const server = this.resolveServer(input.mcp_server);\n if (!server) {\n return toolResultResponse({\n text: JSON.stringify({ error: `MCP server '${input.mcp_server}' not found` }),\n isError: true,\n });\n }\n\n try {\n const response = await server.callTool({ name: input.tool_name, arguments: input.input }, approvalDecision);\n\n if (isAuthRequired(response)) {\n return response;\n }\n\n if (isApprovalRequiredResponse(response)) {\n return response;\n }\n\n if (!isCallToolResponseResult(response)) {\n throw new Error('Tool call returned an unexpected sub-agent response');\n }\n\n return response;\n } catch (error) {\n this.logger.error('call_tool failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool call failed: ${error instanceof Error ? error.message : 'unknown'}` }),\n isError: true,\n });\n }\n },\n });\n }\n}\n"],"mappings":"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","names":["dedent"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/core/runtime/DeferredTool.ts"],"sourcesContent":["import type { CallToolRequest } from '@modelcontextprotocol/sdk/types.js';\nimport dedent from 'dedent';\nimport type { Logger } from 'winston';\nimport { z } from 'zod';\nimport type { ApprovalDecision } from '../events/schema';\nimport { InstructionBuilder } from '../InstructionBuilder';\nimport type { InternalToolCallInfo } from '../llm/LLMTypes';\nimport {\n type AgentToolSchema,\n type CallToolResponse,\n isApprovalRequiredResponse,\n isAuthRequired,\n isCallToolResponseResult,\n type IToolSet,\n type ListToolsResolvedResponse,\n toolResultResponse,\n} from '../mcp/IMCPServer';\nimport { defineTool, LocalToolMCP, type ToolDefinition } from '../mcp/LocalToolMCP';\nimport type { AgentTracing } from '../tracing/AgentTracing';\nimport { extractErrorLogFields } from '../util/errorLogFields';\n\nexport const DEFERRED_TOOLS_SERVER_ID = 'deferred-tools';\nconst DEFERRED_TOOLS_INSTRUCTION = 'deferred-tools-instructions';\nexport const LIST_TOOLS_NAME = 'list_tools';\nexport const GET_TOOL_INFO_NAME = 'get_tool_info';\nexport const GET_TOOL_OUTPUT_SCHEMA_NAME = 'get_tool_output_schema';\nconst CALL_TOOL_NAME = 'call_tool';\nconst MAX_DESCRIPTION_LENGTH = 200;\n\nconst listToolsSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server to list tools for.'),\n});\n\nconst getToolInfoSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to inspect.'),\n});\n\nconst getToolOutputSchemaSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to get output schema for.'),\n});\n\nconst callToolSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to call.'),\n input: z.record(z.string(), z.unknown()).default({}).describe('Arguments to pass to the tool.'),\n});\n\ninterface ResolvedServerTools {\n server: IToolSet;\n tools: AgentToolSchema[];\n metadata: Omit<ListToolsResolvedResponse, 'result'>;\n}\n\nfunction isResolvedServerTools(result: CallToolResponse | ResolvedServerTools): result is ResolvedServerTools {\n return 'tools' in result;\n}\n\nexport class DeferredTool extends LocalToolMCP {\n readonly name = DEFERRED_TOOLS_SERVER_ID;\n readonly displayName = 'DeferredTools';\n override readonly description = 'Deferred tool loading for user MCP servers';\n\n private readonly serverMap: Map<string, IToolSet>;\n private readonly tools: ToolDefinition[];\n private readonly logger: Logger;\n\n constructor(\n servers: readonly IToolSet[],\n options: {\n tracing: AgentTracing;\n logger: Logger;\n },\n ) {\n super({ tracing: options.tracing });\n this.logger = options.logger.child({ module: 'DeferredTool' });\n this.serverMap = new Map(servers.map(s => [s.name, s]));\n this.tools = this.buildTools();\n }\n\n buildInstruction(builder: InstructionBuilder): void {\n const servers = [...this.serverMap.values()];\n\n // Membership follows `preload` only (origin/main). Selective `preload_tools` /\n // `hasPreloadedTools` must not hide a server from deferred discovery instructions.\n const deferredServers = servers.filter(s => !s.preload);\n\n if (deferredServers.length === 0) {\n return;\n }\n\n const deferredList = deferredServers\n .map(s => (s.description ? `- ${s.name}: \"${s.description.slice(0, MAX_DESCRIPTION_LENGTH)}\"` : `- ${s.name}`))\n .join('\\n');\n\n builder.addSection(\n DEFERRED_TOOLS_INSTRUCTION,\n dedent`\n The following MCP servers have deferred tool loading. Their tools are NOT pre-loaded.\n ${deferredList}\n\n The Agent MUST use ${LIST_TOOLS_NAME} and ${GET_TOOL_INFO_NAME} to discover tools before calling them.`,\n );\n }\n\n protected getTools(): ToolDefinition[] {\n return this.tools;\n }\n\n override async toolCallInfo(\n params: CallToolRequest['params'],\n resolveUnderlyingTool?: boolean,\n ): Promise<InternalToolCallInfo> {\n if (params.name !== CALL_TOOL_NAME) {\n return super.toolCallInfo(params, resolveUnderlyingTool);\n }\n if (resolveUnderlyingTool === false) {\n const base = await super.toolCallInfo(params, resolveUnderlyingTool);\n return { ...base, is_deferred: true };\n }\n const parsed = callToolSchema.safeParse(params.arguments);\n if (!parsed.success) {\n this.logger.warn(`Failed to parse call_tool arguments`, {\n tool: params.name,\n errors: parsed.error.issues,\n });\n return { ...(await super.toolCallInfo(params)), is_deferred: true };\n }\n const server = this.resolveServer(parsed.data.mcp_server);\n if (!server) {\n this.logger.warn(`Server not found for toolCallInfo`, {\n mcpServer: parsed.data.mcp_server,\n toolName: parsed.data.tool_name,\n availableServers: [...this.serverMap.keys()],\n });\n return { ...(await super.toolCallInfo(params)), is_deferred: true };\n }\n const underlying = await server.toolCallInfo({\n name: parsed.data.tool_name,\n arguments: parsed.data.input,\n });\n return { ...underlying, is_deferred: true };\n }\n\n private resolveServer(name: string): IToolSet | undefined {\n return this.serverMap.get(name);\n }\n\n private async resolveServerTools(mcpServer: string): Promise<CallToolResponse | ResolvedServerTools> {\n const server = this.resolveServer(mcpServer);\n if (!server) {\n return toolResultResponse({\n text: JSON.stringify({ error: `MCP server '${mcpServer}' not found` }),\n isError: true,\n });\n }\n\n const listResponse = await server.listTools();\n if (isAuthRequired(listResponse)) {\n return listResponse;\n }\n const { result, ...metadata } = listResponse;\n return { server, tools: result.tools, metadata };\n }\n\n private buildTools(): ToolDefinition[] {\n return [this.buildListTools(), this.buildGetToolInfo(), this.buildGetToolOutputSchema(), this.buildCallTool()];\n }\n\n private buildListTools(): ToolDefinition {\n return defineTool({\n name: LIST_TOOLS_NAME,\n description: dedent`\n List tool names available on an MCP server.\n Returns tool names only — use ${GET_TOOL_INFO_NAME} to get full details before calling a tool.`,\n schema: listToolsSchema,\n handler: async (input: { mcp_server: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { server, tools, metadata } = resolved;\n return toolResultResponse({\n text: `${server.name}:\\n ${tools.map(t => t.name).join(', ')}`,\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('list_tools failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n });\n return toolResultResponse({\n text: JSON.stringify({\n error: `Failed to list tools for '${input.mcp_server}': ${error instanceof Error ? error.message : 'unknown'}`,\n }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildGetToolInfo(): ToolDefinition {\n return defineTool({\n name: GET_TOOL_INFO_NAME,\n description: dedent`\n Get description, inputSchema and outputSchema for a specific tool on an MCP server.\n If outputSchema is null, it will NOT be present in ${GET_TOOL_OUTPUT_SCHEMA_NAME} as well.\n The Agent MUST call ${LIST_TOOLS_NAME} first to know which tools are available.`,\n schema: getToolInfoSchema,\n handler: async (input: { mcp_server: string; tool_name: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { tools, metadata } = resolved;\n const tool = tools.find(t => t.name === input.tool_name);\n if (!tool) {\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool '${input.tool_name}' not found on server '${input.mcp_server}'` }),\n overrides: metadata,\n isError: true,\n });\n }\n\n return toolResultResponse({\n text: JSON.stringify({\n description: tool.description,\n inputSchema: tool.inputSchema,\n outputSchema: tool.outputSchema ?? null,\n }),\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('get_tool_info failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({\n error: `Failed to get tool info: ${error instanceof Error ? error.message : 'unknown'}`,\n }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildGetToolOutputSchema(): ToolDefinition {\n return defineTool({\n name: GET_TOOL_OUTPUT_SCHEMA_NAME,\n description: dedent`\n Get the outputSchema for a specific tool on an MCP server.\n The Agent MUST not call ${GET_TOOL_OUTPUT_SCHEMA_NAME} and ${GET_TOOL_INFO_NAME} for the same tool.\n The Agent MUST either call ${GET_TOOL_OUTPUT_SCHEMA_NAME} or ${GET_TOOL_INFO_NAME} before entering Code Mode.\n The Agent must NOT assume the structure of a tool's response from its name or description alone.`,\n schema: getToolOutputSchemaSchema,\n handler: async (input: { mcp_server: string; tool_name: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { tools, metadata } = resolved;\n const tool = tools.find(t => t.name === input.tool_name);\n if (!tool) {\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool '${input.tool_name}' not found on server '${input.mcp_server}'` }),\n overrides: metadata,\n isError: true,\n });\n }\n\n return toolResultResponse({\n text: JSON.stringify({\n outputSchema: tool.outputSchema ?? null,\n }),\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('get_tool_output_schema failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({\n error: `Failed to get output schema: ${error instanceof Error ? error.message : 'unknown'}`,\n }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildCallTool(): ToolDefinition {\n return defineTool({\n name: CALL_TOOL_NAME,\n description: dedent`\n Call a tool on an MCP server.\n The Agent MUST call ${LIST_TOOLS_NAME} and ${GET_TOOL_INFO_NAME} before calling a tool.`,\n schema: callToolSchema,\n handler: async (\n input: { mcp_server: string; tool_name: string; input: Record<string, unknown> },\n approvalDecision?: ApprovalDecision,\n ) => {\n const server = this.resolveServer(input.mcp_server);\n if (!server) {\n return toolResultResponse({\n text: JSON.stringify({ error: `MCP server '${input.mcp_server}' not found` }),\n isError: true,\n });\n }\n\n try {\n const response = await server.callTool({ name: input.tool_name, arguments: input.input }, approvalDecision);\n\n if (isAuthRequired(response)) {\n return response;\n }\n\n if (isApprovalRequiredResponse(response)) {\n return response;\n }\n\n if (!isCallToolResponseResult(response)) {\n throw new Error('Tool call returned an unexpected sub-agent response');\n }\n\n return response;\n } catch (error) {\n this.logger.error('call_tool failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool call failed: ${error instanceof Error ? error.message : 'unknown'}` }),\n isError: true,\n });\n }\n },\n });\n }\n}\n"],"mappings":"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","names":["dedent"]}
|
|
@@ -145,7 +145,9 @@ var DeferredTool = class extends LocalToolMCP {
|
|
|
145
145
|
mcpServer: input.mcp_server
|
|
146
146
|
});
|
|
147
147
|
return toolResultResponse({
|
|
148
|
-
text: JSON.stringify({
|
|
148
|
+
text: JSON.stringify({
|
|
149
|
+
error: `Failed to list tools for '${input.mcp_server}': ${error instanceof Error ? error.message : "unknown"}`
|
|
150
|
+
}),
|
|
149
151
|
isError: true
|
|
150
152
|
});
|
|
151
153
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/runtime/DeferredTool.ts"],"sourcesContent":["import type { CallToolRequest } from '@modelcontextprotocol/sdk/types.js';\nimport dedent from 'dedent';\nimport type { Logger } from 'winston';\nimport { z } from 'zod';\nimport type { ApprovalDecision } from '../events/schema';\nimport { InstructionBuilder } from '../InstructionBuilder';\nimport type { InternalToolCallInfo } from '../llm/LLMTypes';\nimport {\n type AgentToolSchema,\n type CallToolResponse,\n isApprovalRequiredResponse,\n isAuthRequired,\n isCallToolResponseResult,\n type IToolSet,\n type ListToolsResolvedResponse,\n toolResultResponse,\n} from '../mcp/IMCPServer';\nimport { defineTool, LocalToolMCP, type ToolDefinition } from '../mcp/LocalToolMCP';\nimport type { AgentTracing } from '../tracing/AgentTracing';\nimport { extractErrorLogFields } from '../util/errorLogFields';\n\nexport const DEFERRED_TOOLS_SERVER_ID = 'deferred-tools';\nconst DEFERRED_TOOLS_INSTRUCTION = 'deferred-tools-instructions';\nexport const LIST_TOOLS_NAME = 'list_tools';\nexport const GET_TOOL_INFO_NAME = 'get_tool_info';\nexport const GET_TOOL_OUTPUT_SCHEMA_NAME = 'get_tool_output_schema';\nconst CALL_TOOL_NAME = 'call_tool';\nconst MAX_DESCRIPTION_LENGTH = 200;\n\nconst listToolsSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server to list tools for.'),\n});\n\nconst getToolInfoSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to inspect.'),\n});\n\nconst getToolOutputSchemaSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to get output schema for.'),\n});\n\nconst callToolSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to call.'),\n input: z.record(z.string(), z.unknown()).default({}).describe('Arguments to pass to the tool.'),\n});\n\ninterface ResolvedServerTools {\n server: IToolSet;\n tools: AgentToolSchema[];\n metadata: Omit<ListToolsResolvedResponse, 'result'>;\n}\n\nfunction isResolvedServerTools(result: CallToolResponse | ResolvedServerTools): result is ResolvedServerTools {\n return 'tools' in result;\n}\n\nexport class DeferredTool extends LocalToolMCP {\n readonly name = DEFERRED_TOOLS_SERVER_ID;\n readonly displayName = 'DeferredTools';\n override readonly description = 'Deferred tool loading for user MCP servers';\n\n private readonly serverMap: Map<string, IToolSet>;\n private readonly tools: ToolDefinition[];\n private readonly logger: Logger;\n\n constructor(\n servers: readonly IToolSet[],\n options: {\n tracing: AgentTracing;\n logger: Logger;\n },\n ) {\n super({ tracing: options.tracing });\n this.logger = options.logger.child({ module: 'DeferredTool' });\n this.serverMap = new Map(servers.map(s => [s.name, s]));\n this.tools = this.buildTools();\n }\n\n buildInstruction(builder: InstructionBuilder): void {\n const servers = [...this.serverMap.values()];\n\n // Membership follows `preload` only (origin/main). Selective `preload_tools` /\n // `hasPreloadedTools` must not hide a server from deferred discovery instructions.\n const deferredServers = servers.filter(s => !s.preload);\n\n if (deferredServers.length === 0) {\n return;\n }\n\n const deferredList = deferredServers\n .map(s => (s.description ? `- ${s.name}: \"${s.description.slice(0, MAX_DESCRIPTION_LENGTH)}\"` : `- ${s.name}`))\n .join('\\n');\n\n builder.addSection(\n DEFERRED_TOOLS_INSTRUCTION,\n dedent`\n The following MCP servers have deferred tool loading. Their tools are NOT pre-loaded.\n ${deferredList}\n\n The Agent MUST use ${LIST_TOOLS_NAME} and ${GET_TOOL_INFO_NAME} to discover tools before calling them.`,\n );\n }\n\n protected getTools(): ToolDefinition[] {\n return this.tools;\n }\n\n override async toolCallInfo(\n params: CallToolRequest['params'],\n resolveUnderlyingTool?: boolean,\n ): Promise<InternalToolCallInfo> {\n if (params.name !== CALL_TOOL_NAME) {\n return super.toolCallInfo(params, resolveUnderlyingTool);\n }\n if (resolveUnderlyingTool === false) {\n const base = await super.toolCallInfo(params, resolveUnderlyingTool);\n return { ...base, is_deferred: true };\n }\n const parsed = callToolSchema.safeParse(params.arguments);\n if (!parsed.success) {\n this.logger.warn(`Failed to parse call_tool arguments`, {\n tool: params.name,\n errors: parsed.error.issues,\n });\n return { ...(await super.toolCallInfo(params)), is_deferred: true };\n }\n const server = this.resolveServer(parsed.data.mcp_server);\n if (!server) {\n this.logger.warn(`Server not found for toolCallInfo`, {\n mcpServer: parsed.data.mcp_server,\n toolName: parsed.data.tool_name,\n availableServers: [...this.serverMap.keys()],\n });\n return { ...(await super.toolCallInfo(params)), is_deferred: true };\n }\n const underlying = await server.toolCallInfo({\n name: parsed.data.tool_name,\n arguments: parsed.data.input,\n });\n return { ...underlying, is_deferred: true };\n }\n\n private resolveServer(name: string): IToolSet | undefined {\n return this.serverMap.get(name);\n }\n\n private async resolveServerTools(mcpServer: string): Promise<CallToolResponse | ResolvedServerTools> {\n const server = this.resolveServer(mcpServer);\n if (!server) {\n return toolResultResponse({\n text: JSON.stringify({ error: `MCP server '${mcpServer}' not found` }),\n isError: true,\n });\n }\n\n const listResponse = await server.listTools();\n if (isAuthRequired(listResponse)) {\n return listResponse;\n }\n const { result, ...metadata } = listResponse;\n return { server, tools: result.tools, metadata };\n }\n\n private buildTools(): ToolDefinition[] {\n return [this.buildListTools(), this.buildGetToolInfo(), this.buildGetToolOutputSchema(), this.buildCallTool()];\n }\n\n private buildListTools(): ToolDefinition {\n return defineTool({\n name: LIST_TOOLS_NAME,\n description: dedent`\n List tool names available on an MCP server.\n Returns tool names only — use ${GET_TOOL_INFO_NAME} to get full details before calling a tool.`,\n schema: listToolsSchema,\n handler: async (input: { mcp_server: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { server, tools, metadata } = resolved;\n return toolResultResponse({\n text: `${server.name}:\\n ${tools.map(t => t.name).join(', ')}`,\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('list_tools failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n });\n return toolResultResponse({\n text: JSON.stringify({ error: `Failed to list tools for '${input.mcp_server}'.` }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildGetToolInfo(): ToolDefinition {\n return defineTool({\n name: GET_TOOL_INFO_NAME,\n description: dedent`\n Get description, inputSchema and outputSchema for a specific tool on an MCP server.\n If outputSchema is null, it will NOT be present in ${GET_TOOL_OUTPUT_SCHEMA_NAME} as well.\n The Agent MUST call ${LIST_TOOLS_NAME} first to know which tools are available.`,\n schema: getToolInfoSchema,\n handler: async (input: { mcp_server: string; tool_name: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { tools, metadata } = resolved;\n const tool = tools.find(t => t.name === input.tool_name);\n if (!tool) {\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool '${input.tool_name}' not found on server '${input.mcp_server}'` }),\n overrides: metadata,\n isError: true,\n });\n }\n\n return toolResultResponse({\n text: JSON.stringify({\n description: tool.description,\n inputSchema: tool.inputSchema,\n outputSchema: tool.outputSchema ?? null,\n }),\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('get_tool_info failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({\n error: `Failed to get tool info: ${error instanceof Error ? error.message : 'unknown'}`,\n }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildGetToolOutputSchema(): ToolDefinition {\n return defineTool({\n name: GET_TOOL_OUTPUT_SCHEMA_NAME,\n description: dedent`\n Get the outputSchema for a specific tool on an MCP server.\n The Agent MUST not call ${GET_TOOL_OUTPUT_SCHEMA_NAME} and ${GET_TOOL_INFO_NAME} for the same tool.\n The Agent MUST either call ${GET_TOOL_OUTPUT_SCHEMA_NAME} or ${GET_TOOL_INFO_NAME} before entering Code Mode.\n The Agent must NOT assume the structure of a tool's response from its name or description alone.`,\n schema: getToolOutputSchemaSchema,\n handler: async (input: { mcp_server: string; tool_name: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { tools, metadata } = resolved;\n const tool = tools.find(t => t.name === input.tool_name);\n if (!tool) {\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool '${input.tool_name}' not found on server '${input.mcp_server}'` }),\n overrides: metadata,\n isError: true,\n });\n }\n\n return toolResultResponse({\n text: JSON.stringify({\n outputSchema: tool.outputSchema ?? null,\n }),\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('get_tool_output_schema failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({\n error: `Failed to get output schema: ${error instanceof Error ? error.message : 'unknown'}`,\n }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildCallTool(): ToolDefinition {\n return defineTool({\n name: CALL_TOOL_NAME,\n description: dedent`\n Call a tool on an MCP server.\n The Agent MUST call ${LIST_TOOLS_NAME} and ${GET_TOOL_INFO_NAME} before calling a tool.`,\n schema: callToolSchema,\n handler: async (\n input: { mcp_server: string; tool_name: string; input: Record<string, unknown> },\n approvalDecision?: ApprovalDecision,\n ) => {\n const server = this.resolveServer(input.mcp_server);\n if (!server) {\n return toolResultResponse({\n text: JSON.stringify({ error: `MCP server '${input.mcp_server}' not found` }),\n isError: true,\n });\n }\n\n try {\n const response = await server.callTool({ name: input.tool_name, arguments: input.input }, approvalDecision);\n\n if (isAuthRequired(response)) {\n return response;\n }\n\n if (isApprovalRequiredResponse(response)) {\n return response;\n }\n\n if (!isCallToolResponseResult(response)) {\n throw new Error('Tool call returned an unexpected sub-agent response');\n }\n\n return response;\n } catch (error) {\n this.logger.error('call_tool failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool call failed: ${error instanceof Error ? error.message : 'unknown'}` }),\n isError: true,\n });\n }\n },\n });\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/core/runtime/DeferredTool.ts"],"sourcesContent":["import type { CallToolRequest } from '@modelcontextprotocol/sdk/types.js';\nimport dedent from 'dedent';\nimport type { Logger } from 'winston';\nimport { z } from 'zod';\nimport type { ApprovalDecision } from '../events/schema';\nimport { InstructionBuilder } from '../InstructionBuilder';\nimport type { InternalToolCallInfo } from '../llm/LLMTypes';\nimport {\n type AgentToolSchema,\n type CallToolResponse,\n isApprovalRequiredResponse,\n isAuthRequired,\n isCallToolResponseResult,\n type IToolSet,\n type ListToolsResolvedResponse,\n toolResultResponse,\n} from '../mcp/IMCPServer';\nimport { defineTool, LocalToolMCP, type ToolDefinition } from '../mcp/LocalToolMCP';\nimport type { AgentTracing } from '../tracing/AgentTracing';\nimport { extractErrorLogFields } from '../util/errorLogFields';\n\nexport const DEFERRED_TOOLS_SERVER_ID = 'deferred-tools';\nconst DEFERRED_TOOLS_INSTRUCTION = 'deferred-tools-instructions';\nexport const LIST_TOOLS_NAME = 'list_tools';\nexport const GET_TOOL_INFO_NAME = 'get_tool_info';\nexport const GET_TOOL_OUTPUT_SCHEMA_NAME = 'get_tool_output_schema';\nconst CALL_TOOL_NAME = 'call_tool';\nconst MAX_DESCRIPTION_LENGTH = 200;\n\nconst listToolsSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server to list tools for.'),\n});\n\nconst getToolInfoSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to inspect.'),\n});\n\nconst getToolOutputSchemaSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to get output schema for.'),\n});\n\nconst callToolSchema = z.object({\n mcp_server: z.string().describe('Name of the MCP server.'),\n tool_name: z.string().describe('Name of the tool to call.'),\n input: z.record(z.string(), z.unknown()).default({}).describe('Arguments to pass to the tool.'),\n});\n\ninterface ResolvedServerTools {\n server: IToolSet;\n tools: AgentToolSchema[];\n metadata: Omit<ListToolsResolvedResponse, 'result'>;\n}\n\nfunction isResolvedServerTools(result: CallToolResponse | ResolvedServerTools): result is ResolvedServerTools {\n return 'tools' in result;\n}\n\nexport class DeferredTool extends LocalToolMCP {\n readonly name = DEFERRED_TOOLS_SERVER_ID;\n readonly displayName = 'DeferredTools';\n override readonly description = 'Deferred tool loading for user MCP servers';\n\n private readonly serverMap: Map<string, IToolSet>;\n private readonly tools: ToolDefinition[];\n private readonly logger: Logger;\n\n constructor(\n servers: readonly IToolSet[],\n options: {\n tracing: AgentTracing;\n logger: Logger;\n },\n ) {\n super({ tracing: options.tracing });\n this.logger = options.logger.child({ module: 'DeferredTool' });\n this.serverMap = new Map(servers.map(s => [s.name, s]));\n this.tools = this.buildTools();\n }\n\n buildInstruction(builder: InstructionBuilder): void {\n const servers = [...this.serverMap.values()];\n\n // Membership follows `preload` only (origin/main). Selective `preload_tools` /\n // `hasPreloadedTools` must not hide a server from deferred discovery instructions.\n const deferredServers = servers.filter(s => !s.preload);\n\n if (deferredServers.length === 0) {\n return;\n }\n\n const deferredList = deferredServers\n .map(s => (s.description ? `- ${s.name}: \"${s.description.slice(0, MAX_DESCRIPTION_LENGTH)}\"` : `- ${s.name}`))\n .join('\\n');\n\n builder.addSection(\n DEFERRED_TOOLS_INSTRUCTION,\n dedent`\n The following MCP servers have deferred tool loading. Their tools are NOT pre-loaded.\n ${deferredList}\n\n The Agent MUST use ${LIST_TOOLS_NAME} and ${GET_TOOL_INFO_NAME} to discover tools before calling them.`,\n );\n }\n\n protected getTools(): ToolDefinition[] {\n return this.tools;\n }\n\n override async toolCallInfo(\n params: CallToolRequest['params'],\n resolveUnderlyingTool?: boolean,\n ): Promise<InternalToolCallInfo> {\n if (params.name !== CALL_TOOL_NAME) {\n return super.toolCallInfo(params, resolveUnderlyingTool);\n }\n if (resolveUnderlyingTool === false) {\n const base = await super.toolCallInfo(params, resolveUnderlyingTool);\n return { ...base, is_deferred: true };\n }\n const parsed = callToolSchema.safeParse(params.arguments);\n if (!parsed.success) {\n this.logger.warn(`Failed to parse call_tool arguments`, {\n tool: params.name,\n errors: parsed.error.issues,\n });\n return { ...(await super.toolCallInfo(params)), is_deferred: true };\n }\n const server = this.resolveServer(parsed.data.mcp_server);\n if (!server) {\n this.logger.warn(`Server not found for toolCallInfo`, {\n mcpServer: parsed.data.mcp_server,\n toolName: parsed.data.tool_name,\n availableServers: [...this.serverMap.keys()],\n });\n return { ...(await super.toolCallInfo(params)), is_deferred: true };\n }\n const underlying = await server.toolCallInfo({\n name: parsed.data.tool_name,\n arguments: parsed.data.input,\n });\n return { ...underlying, is_deferred: true };\n }\n\n private resolveServer(name: string): IToolSet | undefined {\n return this.serverMap.get(name);\n }\n\n private async resolveServerTools(mcpServer: string): Promise<CallToolResponse | ResolvedServerTools> {\n const server = this.resolveServer(mcpServer);\n if (!server) {\n return toolResultResponse({\n text: JSON.stringify({ error: `MCP server '${mcpServer}' not found` }),\n isError: true,\n });\n }\n\n const listResponse = await server.listTools();\n if (isAuthRequired(listResponse)) {\n return listResponse;\n }\n const { result, ...metadata } = listResponse;\n return { server, tools: result.tools, metadata };\n }\n\n private buildTools(): ToolDefinition[] {\n return [this.buildListTools(), this.buildGetToolInfo(), this.buildGetToolOutputSchema(), this.buildCallTool()];\n }\n\n private buildListTools(): ToolDefinition {\n return defineTool({\n name: LIST_TOOLS_NAME,\n description: dedent`\n List tool names available on an MCP server.\n Returns tool names only — use ${GET_TOOL_INFO_NAME} to get full details before calling a tool.`,\n schema: listToolsSchema,\n handler: async (input: { mcp_server: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { server, tools, metadata } = resolved;\n return toolResultResponse({\n text: `${server.name}:\\n ${tools.map(t => t.name).join(', ')}`,\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('list_tools failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n });\n return toolResultResponse({\n text: JSON.stringify({\n error: `Failed to list tools for '${input.mcp_server}': ${error instanceof Error ? error.message : 'unknown'}`,\n }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildGetToolInfo(): ToolDefinition {\n return defineTool({\n name: GET_TOOL_INFO_NAME,\n description: dedent`\n Get description, inputSchema and outputSchema for a specific tool on an MCP server.\n If outputSchema is null, it will NOT be present in ${GET_TOOL_OUTPUT_SCHEMA_NAME} as well.\n The Agent MUST call ${LIST_TOOLS_NAME} first to know which tools are available.`,\n schema: getToolInfoSchema,\n handler: async (input: { mcp_server: string; tool_name: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { tools, metadata } = resolved;\n const tool = tools.find(t => t.name === input.tool_name);\n if (!tool) {\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool '${input.tool_name}' not found on server '${input.mcp_server}'` }),\n overrides: metadata,\n isError: true,\n });\n }\n\n return toolResultResponse({\n text: JSON.stringify({\n description: tool.description,\n inputSchema: tool.inputSchema,\n outputSchema: tool.outputSchema ?? null,\n }),\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('get_tool_info failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({\n error: `Failed to get tool info: ${error instanceof Error ? error.message : 'unknown'}`,\n }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildGetToolOutputSchema(): ToolDefinition {\n return defineTool({\n name: GET_TOOL_OUTPUT_SCHEMA_NAME,\n description: dedent`\n Get the outputSchema for a specific tool on an MCP server.\n The Agent MUST not call ${GET_TOOL_OUTPUT_SCHEMA_NAME} and ${GET_TOOL_INFO_NAME} for the same tool.\n The Agent MUST either call ${GET_TOOL_OUTPUT_SCHEMA_NAME} or ${GET_TOOL_INFO_NAME} before entering Code Mode.\n The Agent must NOT assume the structure of a tool's response from its name or description alone.`,\n schema: getToolOutputSchemaSchema,\n handler: async (input: { mcp_server: string; tool_name: string }) => {\n try {\n const resolved = await this.resolveServerTools(input.mcp_server);\n if (!isResolvedServerTools(resolved)) {\n return resolved;\n }\n const { tools, metadata } = resolved;\n const tool = tools.find(t => t.name === input.tool_name);\n if (!tool) {\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool '${input.tool_name}' not found on server '${input.mcp_server}'` }),\n overrides: metadata,\n isError: true,\n });\n }\n\n return toolResultResponse({\n text: JSON.stringify({\n outputSchema: tool.outputSchema ?? null,\n }),\n overrides: metadata,\n });\n } catch (error) {\n this.logger.error('get_tool_output_schema failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({\n error: `Failed to get output schema: ${error instanceof Error ? error.message : 'unknown'}`,\n }),\n isError: true,\n });\n }\n },\n });\n }\n\n private buildCallTool(): ToolDefinition {\n return defineTool({\n name: CALL_TOOL_NAME,\n description: dedent`\n Call a tool on an MCP server.\n The Agent MUST call ${LIST_TOOLS_NAME} and ${GET_TOOL_INFO_NAME} before calling a tool.`,\n schema: callToolSchema,\n handler: async (\n input: { mcp_server: string; tool_name: string; input: Record<string, unknown> },\n approvalDecision?: ApprovalDecision,\n ) => {\n const server = this.resolveServer(input.mcp_server);\n if (!server) {\n return toolResultResponse({\n text: JSON.stringify({ error: `MCP server '${input.mcp_server}' not found` }),\n isError: true,\n });\n }\n\n try {\n const response = await server.callTool({ name: input.tool_name, arguments: input.input }, approvalDecision);\n\n if (isAuthRequired(response)) {\n return response;\n }\n\n if (isApprovalRequiredResponse(response)) {\n return response;\n }\n\n if (!isCallToolResponseResult(response)) {\n throw new Error('Tool call returned an unexpected sub-agent response');\n }\n\n return response;\n } catch (error) {\n this.logger.error('call_tool failed', {\n ...extractErrorLogFields(error),\n mcpServer: input.mcp_server,\n toolName: input.tool_name,\n });\n return toolResultResponse({\n text: JSON.stringify({ error: `Tool call failed: ${error instanceof Error ? error.message : 'unknown'}` }),\n isError: true,\n });\n }\n },\n });\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sandbox.d.ts","sourceRoot":"","sources":["../../../src/core/sandbox/Sandbox.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"Sandbox.d.ts","sourceRoot":"","sources":["../../../src/core/sandbox/Sandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -236,6 +236,9 @@ var Sandbox = class extends import_LocalToolMCP.LocalToolMCP {
|
|
|
236
236
|
const sandboxInstructions = builder.beginSection("sandbox");
|
|
237
237
|
sandboxInstructions.addContent("The Agent has access to a persistent sandbox environment for executing code.");
|
|
238
238
|
sandboxInstructions.addContent("The Agent must NOT read or modify any git credential files.");
|
|
239
|
+
sandboxInstructions.addContent(
|
|
240
|
+
"Prefer OpenUI for inline charts when available; sandbox chart images only for downloads."
|
|
241
|
+
);
|
|
239
242
|
this.buildSchemaSection(sandboxInstructions);
|
|
240
243
|
this.buildSkillsSection(sandboxInstructions);
|
|
241
244
|
this.buildMCPSection(sandboxInstructions);
|
|
@@ -280,7 +283,7 @@ var Sandbox = class extends import_LocalToolMCP.LocalToolMCP {
|
|
|
280
283
|
[Human-readable label](/absolute/path/to/file.ext)
|
|
281
284
|
\`\`\`
|
|
282
285
|
|
|
283
|
-
For large outputs or
|
|
286
|
+
For large outputs or downloadable artifacts that can be generated through code, prefer writing to a file and emitting the sandbox_artifacts block.
|
|
284
287
|
|
|
285
288
|
Rules:
|
|
286
289
|
- Use absolute paths, not ~/ or relative paths.
|