@kolisachint/hoocode-agent 0.5.30 → 0.5.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +234 -0
- package/dist/core/agent-selection-eval.d.ts +91 -0
- package/dist/core/agent-selection-eval.d.ts.map +1 -0
- package/dist/core/agent-selection-eval.js +186 -0
- package/dist/core/agent-selection-eval.js.map +1 -0
- package/dist/core/agent-session-runtime.d.ts +28 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +61 -2
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/builtin-skills.d.ts +61 -0
- package/dist/core/builtin-skills.d.ts.map +1 -0
- package/dist/core/builtin-skills.js +106 -0
- package/dist/core/builtin-skills.js.map +1 -0
- package/dist/core/extensions/plugins/default-marketplace/.agents-plugin/marketplace.json +5 -1
- package/dist/core/extensions/plugins/trigger-judge.d.ts +42 -0
- package/dist/core/extensions/plugins/trigger-judge.d.ts.map +1 -0
- package/dist/core/extensions/plugins/trigger-judge.js +121 -0
- package/dist/core/extensions/plugins/trigger-judge.js.map +1 -0
- package/dist/core/external-tools.d.ts +67 -0
- package/dist/core/external-tools.d.ts.map +1 -0
- package/dist/core/external-tools.js +120 -0
- package/dist/core/external-tools.js.map +1 -0
- package/dist/core/keybindings.d.ts +102 -30
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +123 -29
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/mode-prompts.d.ts +15 -3
- package/dist/core/mode-prompts.d.ts.map +1 -1
- package/dist/core/mode-prompts.js +17 -29
- package/dist/core/mode-prompts.js.map +1 -1
- package/dist/core/settings-defaults.d.ts +1 -1
- package/dist/core/settings-defaults.d.ts.map +1 -1
- package/dist/core/settings-defaults.js +1 -1
- package/dist/core/settings-defaults.js.map +1 -1
- package/dist/core/settings-manager.d.ts +10 -3
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +19 -8
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-types.d.ts +1 -1
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +5 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tool-output-view.d.ts +33 -0
- package/dist/core/tool-output-view.d.ts.map +1 -0
- package/dist/core/tool-output-view.js +31 -0
- package/dist/core/tool-output-view.js.map +1 -0
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +4 -0
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/propose-plugin.d.ts.map +1 -1
- package/dist/core/tools/propose-plugin.js +7 -7
- package/dist/core/tools/propose-plugin.js.map +1 -1
- package/dist/core/tools/subagent.d.ts +7 -1
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +12 -24
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/extensions/core/modes.d.ts.map +1 -1
- package/dist/extensions/core/modes.js +21 -23
- package/dist/extensions/core/modes.js.map +1 -1
- package/dist/extensions/core/scaffold.d.ts.map +1 -1
- package/dist/extensions/core/scaffold.js +28 -24
- package/dist/extensions/core/scaffold.js.map +1 -1
- package/dist/init-templates.generated.d.ts +3 -0
- package/dist/init-templates.generated.d.ts.map +1 -1
- package/dist/init-templates.generated.js +12 -0
- package/dist/init-templates.generated.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +14 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/command-executor.d.ts +20 -0
- package/dist/modes/interactive/command-executor.d.ts.map +1 -1
- package/dist/modes/interactive/command-executor.js +138 -9
- package/dist/modes/interactive/command-executor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +4 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +31 -2
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -2
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +2 -2
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +2 -2
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +10 -2
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +165 -23
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-chain-summary.d.ts +65 -0
- package/dist/modes/interactive/components/tool-chain-summary.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-chain-summary.js +216 -0
- package/dist/modes/interactive/components/tool-chain-summary.js.map +1 -0
- package/dist/modes/interactive/components/tool-chain.d.ts +61 -0
- package/dist/modes/interactive/components/tool-chain.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-chain.js +156 -0
- package/dist/modes/interactive/components/tool-chain.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +55 -9
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +173 -33
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-signal.d.ts +50 -0
- package/dist/modes/interactive/components/tool-signal.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-signal.js +151 -0
- package/dist/modes/interactive/components/tool-signal.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +50 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +244 -29
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/resource-display.d.ts +9 -0
- package/dist/modes/interactive/resource-display.d.ts.map +1 -1
- package/dist/modes/interactive/resource-display.js +13 -0
- package/dist/modes/interactive/resource-display.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +30 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +35 -0
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/modes.md +4 -0
- package/docs/plugins.md +10 -0
- package/docs/settings.md +42 -0
- package/docs/skills.md +30 -0
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +5 -4
- package/templates/prompts/grill-bridge.md +1 -0
- package/templates/prompts/grill-me.md +7 -0
- package/templates/prompts/grill-plan.md +9 -0
- package/templates/prompts/task-background-agents.md +2 -0
- package/templates/prompts/task-background-none.md +1 -0
- package/templates/prompts/task-main.md +19 -0
- package/templates/skills/plugin-authoring/SKILL.md +81 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,SAAS,EAMT,KAAK,GAAG,EAGR,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,mCAAmC,CAAC;AAM3F;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvE,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,sBAAsB,CAAC;CACtC;AA2CD,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,WAAW,CAAO;IAC1B,OAAO,CAAC,mBAAmB,CAAY;IACvC,OAAO,CAAC,qBAAqB,CAAC,CAAY;IAC1C,OAAO,CAAC,uBAAuB,CAAC,CAAY;IAC5C,OAAO,CAAC,aAAa,CAAW;IAChC,OAAO,CAAC,eAAe,CAAe;IACtC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,QAAQ,CAAS;IAIzB,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,cAAc,CAAC,CAA2B;IAClD,OAAO,CAAC,qBAAqB,CAAC,CAA2B;IACzD,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAC,CAIb;IACF,OAAO,CAAC,eAAe,CAA8D;IACrF,OAAO,CAAC,aAAa,CAAS;IAQ9B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAC,CAAW;IAC/B;uFACmF;IACnF,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,eAAe,CAAC,CAAW;IACnC,OAAO,CAAC,oBAAoB,CAAM;IAElC,YACC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,GAAG,EACT,OAAO,kCAA2B,EAClC,cAAc,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,SAAS,EACpD,EAAE,EAAE,GAAG,EACP,GAAG,EAAE,MAAM,EAiCX;IAED,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,oBAAoB;IAQ5B,UAAU,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,CAG1B;IAED,oBAAoB,IAAI,IAAI,CAI3B;IAED,eAAe,IAAI,IAAI,CAItB;IAED,YAAY,CACX,MAAM,EAAE;QACP,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAClF,OAAO,CAAC,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;KACjB,EACD,SAAS,UAAQ,GACf,IAAI,CAKN;IAED,OAAO,CAAC,0BAA0B;IAwBlC,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAMnC;IAED,eAAe,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAGnD;IAED,8EAA8E;IAC9E,OAAO,CAAC,cAAc;IAItB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAGjC;IAED,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGtC;IAEQ,UAAU,IAAI,IAAI,CAM1B;IAED;;;;OAIG;IACH,WAAW,IAAI,OAAO,CAErB;IAED;uEACmE;IACnE,MAAM,IAAI,IAAI,CAEb;IAED,OAAO,CAAC,iBAAiB;IAahB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAuBvC;IAED,OAAO,CAAC,aAAa;IAkHrB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,mBAAmB;CAc3B","sourcesContent":["import {\n\tBox,\n\ttype Component,\n\tContainer,\n\tgetCapabilities,\n\tImage,\n\tisImageLine,\n\tSpacer,\n\tText,\n\ttype TUI,\n\ttruncateToWidth,\n\tvisibleWidth,\n} from \"@kolisachint/hoocode-tui\";\nimport type { ToolDefinition, ToolRenderContext } from \"../../../core/extensions/types.js\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.js\";\nimport { getTextOutput as getRenderedTextOutput } from \"../../../core/tools/render-utils.js\";\nimport { convertToPng } from \"../../../utils/image-convert.js\";\nimport { theme } from \"../theme/theme.js\";\n\n/**\n * How a tool block's result body is displayed:\n * - \"standard\": result shown (truncated preview, expandable) — the default.\n * - \"collapsed\": result hidden; only the call line + status dot render.\n * - \"peek\": result hidden by default with a ▸ affordance; the expand key reveals it.\n */\nexport type ToolOutputDisplayLevel = \"collapsed\" | \"peek\" | \"standard\";\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n\tdisplayLevel?: ToolOutputDisplayLevel;\n}\n\n/**\n * Renders a child component and prepends a prefix (e.g. a status dot) to its\n * first line, indenting continuation lines so they align under the content.\n *\n * This keeps the dot inline with the first line instead of stacking it on its\n * own line (which happens when a Container holds the dot as a separate child).\n */\nclass PrefixFirstLine implements Component {\n\tprivate prefix: string;\n\tprivate child: Component;\n\tprivate indentWidth: number;\n\t// Keyed on the child's returned array identity so an unchanged child keeps\n\t// this wrapper reference-stable too (parents memoize flattening by ref).\n\tprivate memo?: { src: string[]; width: number; out: string[] };\n\n\tconstructor(prefix: string, child: Component) {\n\t\tthis.prefix = prefix;\n\t\tthis.child = child;\n\t\tthis.indentWidth = visibleWidth(prefix);\n\t}\n\n\tinvalidate(): void {\n\t\tthis.child.invalidate?.();\n\t\tthis.memo = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\t// Reserve room for the prefix so the child wraps within the remaining width.\n\t\tconst childWidth = Math.max(1, width - this.indentWidth);\n\t\tconst lines = this.child.render(childWidth);\n\t\tif (this.memo && this.memo.src === lines && this.memo.width === width) {\n\t\t\treturn this.memo.out;\n\t\t}\n\t\tconst indent = \" \".repeat(this.indentWidth);\n\t\tconst out =\n\t\t\tlines.length === 0 ? [this.prefix] : lines.map((line, i) => (i === 0 ? this.prefix + line : indent + line));\n\t\tthis.memo = { src: lines, width, out };\n\t\treturn out;\n\t}\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\t// Persisted display level (collapsed/peek/standard). Controls whether the\n\t// result body renders at all; `revealed` is the per-block override that the\n\t// global expand key flips for collapsed/peek blocks.\n\tprivate displayLevel: ToolOutputDisplayLevel;\n\tprivate revealed = false;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\t// Once a finished tool block has scrolled far out of view the interactive mode\n\t// freezes it (see freeze()): its already-rendered lines are captured and the\n\t// heavy source payloads (full tool result, base64 image copies, per-renderer\n\t// state, child component caches) are released. A frozen block is immutable and\n\t// no longer reflows on resize — old off-screen scrollback keeps its wrapping,\n\t// which self-heals on any full rebuild (theme toggle / session reload, both of\n\t// which reconstruct components from the intact session data).\n\tprivate frozen = false;\n\tprivate frozenLines?: string[];\n\t/** Width the frozen snapshot was captured at; a wider terminal is safe as-is,\n\t * a narrower one needs re-truncation to avoid the TUI's over-width crash guard. */\n\tprivate frozenWidth = 0;\n\tprivate frozenTruncated?: string[];\n\tprivate frozenTruncatedWidth = -1;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.displayLevel = options.displayLevel ?? \"standard\";\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\t// Boxless: no filled background — hierarchy comes from status dots + indent.\n\t\t// paddingY is 0: the single leading Spacer(1) is the only separator between\n\t\t// tool blocks, so consecutive commands don't stack 3 blank lines between them.\n\t\tthis.contentBox = new Box(1, 0);\n\t\tthis.contentText = new Text(\"\", 1, 0);\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox);\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.builtInToolDefinition !== undefined || this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(this.toolName)), 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn new Text(theme.fg(\"toolOutput\", output), 0, 0);\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (this.frozen) return;\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\t// For collapsed/peek blocks the same global toggle reveals the hidden body;\n\t\t// for standard blocks `expanded` alone switches truncated ↔ full.\n\t\tthis.revealed = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetDisplayLevel(level: ToolOutputDisplayLevel): void {\n\t\tthis.displayLevel = level;\n\t\tthis.updateDisplay();\n\t}\n\n\t/** Whether the result body should render given the level and reveal state. */\n\tprivate shouldShowBody(): boolean {\n\t\treturn this.displayLevel === \"standard\" || this.revealed;\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\t// A frozen block has released the state updateDisplay would rebuild from;\n\t\t// its captured snapshot is authoritative, so skip the rebuild entirely.\n\t\tif (this.frozen) return;\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\t/**\n\t * True when this block is a finished, visible tool result that still holds its\n\t * heavy source payloads — i.e. a candidate for freeze() once it scrolls out of\n\t * the live window. In-flight (partial) and already-frozen blocks are excluded.\n\t */\n\tisFreezable(): boolean {\n\t\treturn !this.frozen && !this.isPartial && !this.hideComponent && !!this.result;\n\t}\n\n\t/** Mark this block for freezing; the snapshot is captured on the next render\n\t * (at the real render width) and the heavy state released then. */\n\tfreeze(): void {\n\t\tif (this.isFreezable()) this.frozen = true;\n\t}\n\n\tprivate releaseHeavyState(): void {\n\t\tthis.result = undefined;\n\t\tthis.convertedImages.clear();\n\t\tthis.imageComponents = [];\n\t\tthis.imageSpacers = [];\n\t\tthis.rendererState = {};\n\t\tthis.callRendererComponent = undefined;\n\t\tthis.resultRendererComponent = undefined;\n\t\t// Drop child components so their line caches (which embed base64 image\n\t\t// payloads and full text output) become collectable.\n\t\tthis.clear();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\t\tif (this.frozenLines) {\n\t\t\t// Captured snapshot. Wider (or equal) terminal: emit as-is. Narrower:\n\t\t\t// re-truncate non-image lines to avoid the TUI's over-width crash guard,\n\t\t\t// caching the result per width so it stays O(1) on unchanged frames.\n\t\t\tif (width >= this.frozenWidth) return this.frozenLines;\n\t\t\tif (this.frozenTruncatedWidth === width && this.frozenTruncated) return this.frozenTruncated;\n\t\t\tthis.frozenTruncated = this.frozenLines.map((line) =>\n\t\t\t\tisImageLine(line) || visibleWidth(line) <= width ? line : truncateToWidth(line, width),\n\t\t\t);\n\t\t\tthis.frozenTruncatedWidth = width;\n\t\t\treturn this.frozenTruncated;\n\t\t}\n\t\tconst lines = super.render(width);\n\t\tif (this.frozen) {\n\t\t\tthis.frozenLines = lines;\n\t\t\tthis.frozenWidth = width;\n\t\t\tthis.releaseHeavyState();\n\t\t}\n\t\treturn lines;\n\t}\n\n\tprivate updateDisplay(): void {\n\t\t// Frozen blocks are immutable snapshots with their source state released.\n\t\tif (this.frozen) return;\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tconst renderContainer = this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t\t\t// Boxless: no background fill on the container.\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(undefined);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\t// Status dot prefix: green for complete success, yellow for pending/partial, red for error.\n\t\t\t// The dot is prepended to the first line of the call renderer so it stays inline\n\t\t\t// (adding it as a separate child would stack it on its own line).\n\t\t\tconst dotColor = this.result?.isError ? \"error\" : this.isPartial ? \"warning\" : \"success\";\n\t\t\t// Peek blocks advertise their hidden body with a ▸/▾ caret before the dot.\n\t\t\tconst caret = this.displayLevel === \"peek\" ? theme.fg(\"muted\", this.revealed ? \"▾ \" : \"▸ \") : \"\";\n\t\t\tconst dot = caret + theme.fg(dotColor, \"● \");\n\n\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\tif (!callRenderer) {\n\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, this.createCallFallback()));\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, component));\n\t\t\t\t\thasContent = true;\n\t\t\t\t} catch {\n\t\t\t\t\tthis.callRendererComponent = undefined;\n\t\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, this.createCallFallback()));\n\t\t\t\t\thasContent = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result && this.shouldShowBody()) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.resultRendererComponent = undefined;\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Boxless: no background fill.\n\t\t\tthis.contentText.setCustomBgFn(undefined);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tconst dotColor = this.result?.isError ? \"error\" : this.isPartial ? \"warning\" : \"success\";\n\t\tconst caret = this.displayLevel === \"peek\" ? theme.fg(\"muted\", this.revealed ? \"▾ \" : \"▸ \") : \"\";\n\t\tlet text = caret + theme.fg(dotColor, \"● \") + theme.fg(\"toolTitle\", theme.bold(this.toolName));\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.shouldShowBody() ? this.getTextOutput() : \"\";\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tool-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tBox,\n\ttype Component,\n\tContainer,\n\tgetCapabilities,\n\tImage,\n\tisImageLine,\n\tSpacer,\n\tText,\n\ttype TUI,\n\ttruncateToWidth,\n\tvisibleWidth,\n} from \"@kolisachint/hoocode-tui\";\nimport type { ToolDefinition, ToolRenderContext } from \"../../../core/extensions/types.js\";\nimport type { ToolOutputView } from \"../../../core/tool-output-view.js\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.js\";\nimport { getTextOutput as getRenderedTextOutput } from \"../../../core/tools/render-utils.js\";\nimport { convertToPng } from \"../../../utils/image-convert.js\";\nimport { theme } from \"../theme/theme.js\";\nimport type { ChainEntry } from \"./tool-chain-summary.js\";\nimport { ToolSignalComponent, toolSubject } from \"./tool-signal.js\";\n\n/**\n * Re-exported so tool-block callers keep a single import site for the view\n * dial; the type itself lives in core (the settings manager persists it).\n */\nexport type { ToolOutputView } from \"../../../core/tool-output-view.js\";\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n\tview?: ToolOutputView;\n}\n\n/**\n * Renders a child component and prepends a prefix (e.g. a status dot) to its\n * first line, indenting continuation lines so they align under the content.\n *\n * This keeps the dot inline with the first line instead of stacking it on its\n * own line (which happens when a Container holds the dot as a separate child).\n */\nclass PrefixFirstLine implements Component {\n\tprivate prefix: string;\n\tprivate child: Component;\n\tprivate indentWidth: number;\n\t// Keyed on the child's returned array identity so an unchanged child keeps\n\t// this wrapper reference-stable too (parents memoize flattening by ref).\n\tprivate memo?: { src: string[]; width: number; out: string[] };\n\n\tconstructor(prefix: string, child: Component) {\n\t\tthis.prefix = prefix;\n\t\tthis.child = child;\n\t\tthis.indentWidth = visibleWidth(prefix);\n\t}\n\n\tinvalidate(): void {\n\t\tthis.child.invalidate?.();\n\t\tthis.memo = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\t// Reserve room for the prefix so the child wraps within the remaining width.\n\t\tconst childWidth = Math.max(1, width - this.indentWidth);\n\t\tconst lines = this.child.render(childWidth);\n\t\tif (this.memo && this.memo.src === lines && this.memo.width === width) {\n\t\t\treturn this.memo.out;\n\t\t}\n\t\tconst indent = \" \".repeat(this.indentWidth);\n\t\tconst out =\n\t\t\tlines.length === 0 ? [this.prefix] : lines.map((line, i) => (i === 0 ? this.prefix + line : indent + line));\n\t\tthis.memo = { src: lines, width, out };\n\t\treturn out;\n\t}\n}\n\n/**\n * Indents every line of a child, unlike PrefixFirstLine which only offsets the\n * first. Used for a failure's body under a radar row, so the reason reads as\n * hanging off the row rather than starting a new column.\n */\nclass IndentAll implements Component {\n\tprivate child: Component;\n\tprivate indent: string;\n\tprivate memo?: { src: string[]; width: number; out: string[] };\n\n\tconstructor(child: Component, width: number) {\n\t\tthis.child = child;\n\t\tthis.indent = \" \".repeat(width);\n\t}\n\n\tinvalidate(): void {\n\t\tthis.child.invalidate?.();\n\t\tthis.memo = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines = this.child.render(Math.max(1, width - this.indent.length));\n\t\tif (this.memo && this.memo.src === lines && this.memo.width === width) return this.memo.out;\n\t\tconst out = lines.map((line) => (line.trim() === \"\" ? line : this.indent + line));\n\t\tthis.memo = { src: lines, width, out };\n\t\treturn out;\n\t}\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\t// Persisted view (radar/glance/full). Controls how the call line is drawn and\n\t// whether the result body renders at all; `revealed` is the per-block override\n\t// the global expand key flips for radar/glance blocks.\n\tprivate view: ToolOutputView;\n\tprivate revealed = false;\n\tprivate signalComponent?: ToolSignalComponent;\n\tprivate leadingSpacer: Spacer;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\t// Once a finished tool block has scrolled far out of view the interactive mode\n\t// freezes it (see freeze()): its already-rendered lines are captured and the\n\t// heavy source payloads (full tool result, base64 image copies, per-renderer\n\t// state, child component caches) are released. A frozen block is immutable and\n\t// no longer reflows on resize — old off-screen scrollback keeps its wrapping,\n\t// which self-heals on any full rebuild (theme toggle / session reload, both of\n\t// which reconstruct components from the intact session data).\n\tprivate frozen = false;\n\tprivate frozenLines?: string[];\n\t/** Width the frozen snapshot was captured at; a wider terminal is safe as-is,\n\t * a narrower one needs re-truncation to avoid the TUI's over-width crash guard. */\n\tprivate frozenWidth = 0;\n\tprivate frozenTruncated?: string[];\n\tprivate frozenTruncatedWidth = -1;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.view = options.view ?? \"glance\";\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\t// The separator between consecutive tool blocks. Radar drops it: rows that\n\t\t// are one line each only read as a map when they stack without gaps.\n\t\tthis.leadingSpacer = new Spacer(1);\n\t\tthis.addChild(this.leadingSpacer);\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\t// Boxless: no filled background — hierarchy comes from status dots + indent.\n\t\t// paddingY is 0: the single leading Spacer(1) is the only separator between\n\t\t// tool blocks, so consecutive commands don't stack 3 blank lines between them.\n\t\tthis.contentBox = new Box(1, 0);\n\t\tthis.contentText = new Text(\"\", 1, 0);\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.activeShell());\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.builtInToolDefinition !== undefined || this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(this.toolName)), 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn new Text(theme.fg(\"toolOutput\", output), 0, 0);\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (this.frozen) return;\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\t// For radar/glance blocks the same global toggle reveals the hidden body;\n\t\t// for full blocks `expanded` alone switches truncated ↔ everything.\n\t\tthis.revealed = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetView(view: ToolOutputView): void {\n\t\tthis.view = view;\n\t\tthis.updateDisplay();\n\t}\n\n\t/**\n\t * Whether this block is currently opened up.\n\t *\n\t * Read by the one-at-a-time unfold, which walks back from the newest block\n\t * to find the first one still folded.\n\t */\n\tisRevealed(): boolean {\n\t\treturn this.revealed;\n\t}\n\n\t/** This call's contribution to its chain's summary line. */\n\tchainEntry(): ChainEntry {\n\t\tconst output = this.result ? this.getTextOutput() : \"\";\n\t\treturn {\n\t\t\ttool: this.toolName,\n\t\t\tsubject: toolSubject(this.args, this.cwd),\n\t\t\tisError: this.result?.isError === true,\n\t\t\tisPartial: this.result === undefined || this.isPartial,\n\t\t\toutputLines: output.trim() ? output.split(\"\\n\").length : 0,\n\t\t};\n\t}\n\n\t/** The failure text, for a collapsed chain to print under its line. */\n\terrorText(): string {\n\t\treturn this.result?.isError ? this.getTextOutput() : \"\";\n\t}\n\n\t/**\n\t * Whether the result body should render.\n\t *\n\t * A failure always shows its reason, in every view. Everything else about\n\t * these views is a judgement about how much detail you want; why something\n\t * broke is not detail, and a red dot with no explanation was the one thing\n\t * the folded views got wrong.\n\t */\n\tprivate shouldShowBody(): boolean {\n\t\treturn this.view === \"full\" || this.revealed || this.result?.isError === true;\n\t}\n\n\t/**\n\t * Whether this block draws its radar signal line instead of the tool's own\n\t * call renderer. A revealed block leaves radar for as long as it is open, so\n\t * \"expand\" means the same thing in every view.\n\t */\n\tprivate shouldShowSignalLine(): boolean {\n\t\treturn this.view === \"radar\" && !this.revealed;\n\t}\n\n\t/**\n\t * A failure's body under a radar row hangs off the row; anywhere else it sits\n\t * directly under its own call line and needs no extra indent.\n\t */\n\tprivate indentUnderSignalRow(component: Component): Component {\n\t\treturn this.shouldShowSignalLine() ? new IndentAll(component, 3) : component;\n\t}\n\n\tprivate getSignalComponent(): ToolSignalComponent {\n\t\tconst input = {\n\t\t\ttoolName: this.toolName,\n\t\t\targs: this.args,\n\t\t\tcwd: this.cwd,\n\t\t\tresult: this.result,\n\t\t\tisPartial: this.isPartial,\n\t\t\tshowImages: this.showImages,\n\t\t};\n\t\tif (this.signalComponent) {\n\t\t\tthis.signalComponent.setInput(input);\n\t\t} else {\n\t\t\tthis.signalComponent = new ToolSignalComponent(input);\n\t\t}\n\t\treturn this.signalComponent;\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\t// A frozen block has released the state updateDisplay would rebuild from;\n\t\t// its captured snapshot is authoritative, so skip the rebuild entirely.\n\t\tif (this.frozen) return;\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\t/**\n\t * True when this block is a finished, visible tool result that still holds its\n\t * heavy source payloads — i.e. a candidate for freeze() once it scrolls out of\n\t * the live window. In-flight (partial) and already-frozen blocks are excluded.\n\t */\n\tisFreezable(): boolean {\n\t\treturn !this.frozen && !this.isPartial && !this.hideComponent && !!this.result;\n\t}\n\n\t/** Mark this block for freezing; the snapshot is captured on the next render\n\t * (at the real render width) and the heavy state released then. */\n\tfreeze(): void {\n\t\tif (this.isFreezable()) this.frozen = true;\n\t}\n\n\tprivate releaseHeavyState(): void {\n\t\tthis.result = undefined;\n\t\tthis.convertedImages.clear();\n\t\tthis.imageComponents = [];\n\t\tthis.imageSpacers = [];\n\t\tthis.rendererState = {};\n\t\tthis.callRendererComponent = undefined;\n\t\tthis.resultRendererComponent = undefined;\n\t\t// Drop child components so their line caches (which embed base64 image\n\t\t// payloads and full text output) become collectable.\n\t\tthis.clear();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\t\tif (this.frozenLines) {\n\t\t\t// Captured snapshot. Wider (or equal) terminal: emit as-is. Narrower:\n\t\t\t// re-truncate non-image lines to avoid the TUI's over-width crash guard,\n\t\t\t// caching the result per width so it stays O(1) on unchanged frames.\n\t\t\tif (width >= this.frozenWidth) return this.frozenLines;\n\t\t\tif (this.frozenTruncatedWidth === width && this.frozenTruncated) return this.frozenTruncated;\n\t\t\tthis.frozenTruncated = this.frozenLines.map((line) =>\n\t\t\t\tisImageLine(line) || visibleWidth(line) <= width ? line : truncateToWidth(line, width),\n\t\t\t);\n\t\t\tthis.frozenTruncatedWidth = width;\n\t\t\treturn this.frozenTruncated;\n\t\t}\n\t\tconst lines = super.render(width);\n\t\tif (this.frozen) {\n\t\t\tthis.frozenLines = lines;\n\t\t\tthis.frozenWidth = width;\n\t\t\tthis.releaseHeavyState();\n\t\t}\n\t\treturn lines;\n\t}\n\n\t/**\n\t * The container this block renders into.\n\t *\n\t * A self-rendering tool (`edit` draws its own framed diff) normally gets the\n\t * bare container so its frame can use the full width; everything else gets\n\t * the padded box. That only matters while the body is on screen. With the\n\t * body folded away the block is a single line, and the unpadded container\n\t * put it one column left of every other row — invisible while `peek` was an\n\t * opt-in, glaring now that `glance` is the default. So: padded box whenever\n\t * nothing is expanded, which also gives radar the uniform rows it exists for.\n\t */\n\tprivate activeShell(): Box | Container {\n\t\tif (!this.shouldShowBody()) return this.contentBox;\n\t\treturn this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t}\n\n\t/** Swap the attached shell when the view changes which one applies. */\n\tprivate syncShellChild(): void {\n\t\tconst wanted = this.activeShell();\n\t\tconst other = wanted === this.contentBox ? this.selfRenderContainer : this.contentBox;\n\t\tif (this.children.includes(wanted)) return;\n\t\tthis.removeChild(other);\n\t\tother.clear();\n\t\tthis.addChild(wanted);\n\t}\n\n\tprivate updateDisplay(): void {\n\t\t// Frozen blocks are immutable snapshots with their source state released.\n\t\tif (this.frozen) return;\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tthis.leadingSpacer.setLines(this.shouldShowSignalLine() ? 0 : 1);\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.syncShellChild();\n\t\t\tconst renderContainer = this.activeShell();\n\t\t\t// Boxless: no background fill on the container.\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(undefined);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\t// Status dot prefix: green for complete success, yellow for pending/partial, red for error.\n\t\t\t// The dot is prepended to the first line of the call renderer so it stays inline\n\t\t\t// (adding it as a separate child would stack it on its own line).\n\t\t\tconst dotColor = this.result?.isError ? \"error\" : this.isPartial ? \"warning\" : \"success\";\n\t\t\t// No disclosure caret. It is a click-target idiom in a TUI with no\n\t\t\t// pointer, it cost two columns on every row for an action that could\n\t\t\t// only ever be reached by keyboard, and reading it as \"this row opens\"\n\t\t\t// set an expectation the view does not meet.\n\t\t\tconst dot = theme.fg(dotColor, \"● \");\n\n\t\t\t// Radar replaces the tool's own call renderer with the uniform signal\n\t\t\t// row, so a screen of mixed tools lines up into one readable map.\n\t\t\tif (this.shouldShowSignalLine()) {\n\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, this.getSignalComponent()));\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\t\tif (!callRenderer) {\n\t\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, this.createCallFallback()));\n\t\t\t\t\thasContent = true;\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, component));\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.callRendererComponent = undefined;\n\t\t\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, this.createCallFallback()));\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result && this.shouldShowBody()) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(this.indentUnderSignalRow(component));\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(this.indentUnderSignalRow(component));\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.resultRendererComponent = undefined;\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Boxless: no background fill.\n\t\t\tthis.contentText.setCustomBgFn(undefined);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result && !this.shouldShowSignalLine()) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tconst dotColor = this.result?.isError ? \"error\" : this.isPartial ? \"warning\" : \"success\";\n\t\t// A tool with no renderer still gets a radar row, just without the\n\t\t// flush-right signal column (this path has no width to align against).\n\t\tif (this.shouldShowSignalLine()) {\n\t\t\tconst subject = toolSubject(this.args, this.cwd);\n\t\t\treturn (\n\t\t\t\ttheme.fg(dotColor, \"● \") +\n\t\t\t\ttheme.fg(\"toolTitle\", theme.bold(this.toolName)) +\n\t\t\t\t(subject ? ` ${theme.fg(\"toolOutput\", subject)}` : \"\")\n\t\t\t);\n\t\t}\n\t\tlet text = theme.fg(dotColor, \"● \") + theme.fg(\"toolTitle\", theme.bold(this.toolName));\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.shouldShowBody() ? this.getTextOutput() : \"\";\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
|
|
@@ -3,6 +3,7 @@ import { createAllToolDefinitions } from "../../../core/tools/index.js";
|
|
|
3
3
|
import { getTextOutput as getRenderedTextOutput } from "../../../core/tools/render-utils.js";
|
|
4
4
|
import { convertToPng } from "../../../utils/image-convert.js";
|
|
5
5
|
import { theme } from "../theme/theme.js";
|
|
6
|
+
import { ToolSignalComponent, toolSubject } from "./tool-signal.js";
|
|
6
7
|
/**
|
|
7
8
|
* Renders a child component and prepends a prefix (e.g. a status dot) to its
|
|
8
9
|
* first line, indenting continuation lines so they align under the content.
|
|
@@ -39,6 +40,32 @@ class PrefixFirstLine {
|
|
|
39
40
|
return out;
|
|
40
41
|
}
|
|
41
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Indents every line of a child, unlike PrefixFirstLine which only offsets the
|
|
45
|
+
* first. Used for a failure's body under a radar row, so the reason reads as
|
|
46
|
+
* hanging off the row rather than starting a new column.
|
|
47
|
+
*/
|
|
48
|
+
class IndentAll {
|
|
49
|
+
child;
|
|
50
|
+
indent;
|
|
51
|
+
memo;
|
|
52
|
+
constructor(child, width) {
|
|
53
|
+
this.child = child;
|
|
54
|
+
this.indent = " ".repeat(width);
|
|
55
|
+
}
|
|
56
|
+
invalidate() {
|
|
57
|
+
this.child.invalidate?.();
|
|
58
|
+
this.memo = undefined;
|
|
59
|
+
}
|
|
60
|
+
render(width) {
|
|
61
|
+
const lines = this.child.render(Math.max(1, width - this.indent.length));
|
|
62
|
+
if (this.memo && this.memo.src === lines && this.memo.width === width)
|
|
63
|
+
return this.memo.out;
|
|
64
|
+
const out = lines.map((line) => (line.trim() === "" ? line : this.indent + line));
|
|
65
|
+
this.memo = { src: lines, width, out };
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
42
69
|
export class ToolExecutionComponent extends Container {
|
|
43
70
|
contentBox;
|
|
44
71
|
contentText;
|
|
@@ -52,11 +79,13 @@ export class ToolExecutionComponent extends Container {
|
|
|
52
79
|
toolCallId;
|
|
53
80
|
args;
|
|
54
81
|
expanded = false;
|
|
55
|
-
// Persisted
|
|
56
|
-
// result body renders at all; `revealed` is the per-block override
|
|
57
|
-
// global expand key flips for
|
|
58
|
-
|
|
82
|
+
// Persisted view (radar/glance/full). Controls how the call line is drawn and
|
|
83
|
+
// whether the result body renders at all; `revealed` is the per-block override
|
|
84
|
+
// the global expand key flips for radar/glance blocks.
|
|
85
|
+
view;
|
|
59
86
|
revealed = false;
|
|
87
|
+
signalComponent;
|
|
88
|
+
leadingSpacer;
|
|
60
89
|
showImages;
|
|
61
90
|
imageWidthCells;
|
|
62
91
|
isPartial = true;
|
|
@@ -92,10 +121,13 @@ export class ToolExecutionComponent extends Container {
|
|
|
92
121
|
this.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName];
|
|
93
122
|
this.showImages = options.showImages ?? true;
|
|
94
123
|
this.imageWidthCells = options.imageWidthCells ?? 60;
|
|
95
|
-
this.
|
|
124
|
+
this.view = options.view ?? "glance";
|
|
96
125
|
this.ui = ui;
|
|
97
126
|
this.cwd = cwd;
|
|
98
|
-
|
|
127
|
+
// The separator between consecutive tool blocks. Radar drops it: rows that
|
|
128
|
+
// are one line each only read as a map when they stack without gaps.
|
|
129
|
+
this.leadingSpacer = new Spacer(1);
|
|
130
|
+
this.addChild(this.leadingSpacer);
|
|
99
131
|
// Always create all shell variants. contentBox is used for default renderer-based composition.
|
|
100
132
|
// selfRenderContainer is used when the tool renders its own framing.
|
|
101
133
|
// contentText is reserved for generic fallback rendering when no tool definition exists.
|
|
@@ -106,7 +138,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
106
138
|
this.contentText = new Text("", 1, 0);
|
|
107
139
|
this.selfRenderContainer = new Container();
|
|
108
140
|
if (this.hasRendererDefinition()) {
|
|
109
|
-
this.addChild(this.
|
|
141
|
+
this.addChild(this.activeShell());
|
|
110
142
|
}
|
|
111
143
|
else {
|
|
112
144
|
this.addChild(this.contentText);
|
|
@@ -221,18 +253,81 @@ export class ToolExecutionComponent extends Container {
|
|
|
221
253
|
}
|
|
222
254
|
setExpanded(expanded) {
|
|
223
255
|
this.expanded = expanded;
|
|
224
|
-
// For
|
|
225
|
-
// for
|
|
256
|
+
// For radar/glance blocks the same global toggle reveals the hidden body;
|
|
257
|
+
// for full blocks `expanded` alone switches truncated ↔ everything.
|
|
226
258
|
this.revealed = expanded;
|
|
227
259
|
this.updateDisplay();
|
|
228
260
|
}
|
|
229
|
-
|
|
230
|
-
this.
|
|
261
|
+
setView(view) {
|
|
262
|
+
this.view = view;
|
|
231
263
|
this.updateDisplay();
|
|
232
264
|
}
|
|
233
|
-
/**
|
|
265
|
+
/**
|
|
266
|
+
* Whether this block is currently opened up.
|
|
267
|
+
*
|
|
268
|
+
* Read by the one-at-a-time unfold, which walks back from the newest block
|
|
269
|
+
* to find the first one still folded.
|
|
270
|
+
*/
|
|
271
|
+
isRevealed() {
|
|
272
|
+
return this.revealed;
|
|
273
|
+
}
|
|
274
|
+
/** This call's contribution to its chain's summary line. */
|
|
275
|
+
chainEntry() {
|
|
276
|
+
const output = this.result ? this.getTextOutput() : "";
|
|
277
|
+
return {
|
|
278
|
+
tool: this.toolName,
|
|
279
|
+
subject: toolSubject(this.args, this.cwd),
|
|
280
|
+
isError: this.result?.isError === true,
|
|
281
|
+
isPartial: this.result === undefined || this.isPartial,
|
|
282
|
+
outputLines: output.trim() ? output.split("\n").length : 0,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/** The failure text, for a collapsed chain to print under its line. */
|
|
286
|
+
errorText() {
|
|
287
|
+
return this.result?.isError ? this.getTextOutput() : "";
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Whether the result body should render.
|
|
291
|
+
*
|
|
292
|
+
* A failure always shows its reason, in every view. Everything else about
|
|
293
|
+
* these views is a judgement about how much detail you want; why something
|
|
294
|
+
* broke is not detail, and a red dot with no explanation was the one thing
|
|
295
|
+
* the folded views got wrong.
|
|
296
|
+
*/
|
|
234
297
|
shouldShowBody() {
|
|
235
|
-
return this.
|
|
298
|
+
return this.view === "full" || this.revealed || this.result?.isError === true;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Whether this block draws its radar signal line instead of the tool's own
|
|
302
|
+
* call renderer. A revealed block leaves radar for as long as it is open, so
|
|
303
|
+
* "expand" means the same thing in every view.
|
|
304
|
+
*/
|
|
305
|
+
shouldShowSignalLine() {
|
|
306
|
+
return this.view === "radar" && !this.revealed;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* A failure's body under a radar row hangs off the row; anywhere else it sits
|
|
310
|
+
* directly under its own call line and needs no extra indent.
|
|
311
|
+
*/
|
|
312
|
+
indentUnderSignalRow(component) {
|
|
313
|
+
return this.shouldShowSignalLine() ? new IndentAll(component, 3) : component;
|
|
314
|
+
}
|
|
315
|
+
getSignalComponent() {
|
|
316
|
+
const input = {
|
|
317
|
+
toolName: this.toolName,
|
|
318
|
+
args: this.args,
|
|
319
|
+
cwd: this.cwd,
|
|
320
|
+
result: this.result,
|
|
321
|
+
isPartial: this.isPartial,
|
|
322
|
+
showImages: this.showImages,
|
|
323
|
+
};
|
|
324
|
+
if (this.signalComponent) {
|
|
325
|
+
this.signalComponent.setInput(input);
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
this.signalComponent = new ToolSignalComponent(input);
|
|
329
|
+
}
|
|
330
|
+
return this.signalComponent;
|
|
236
331
|
}
|
|
237
332
|
setShowImages(show) {
|
|
238
333
|
this.showImages = show;
|
|
@@ -300,14 +395,42 @@ export class ToolExecutionComponent extends Container {
|
|
|
300
395
|
}
|
|
301
396
|
return lines;
|
|
302
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* The container this block renders into.
|
|
400
|
+
*
|
|
401
|
+
* A self-rendering tool (`edit` draws its own framed diff) normally gets the
|
|
402
|
+
* bare container so its frame can use the full width; everything else gets
|
|
403
|
+
* the padded box. That only matters while the body is on screen. With the
|
|
404
|
+
* body folded away the block is a single line, and the unpadded container
|
|
405
|
+
* put it one column left of every other row — invisible while `peek` was an
|
|
406
|
+
* opt-in, glaring now that `glance` is the default. So: padded box whenever
|
|
407
|
+
* nothing is expanded, which also gives radar the uniform rows it exists for.
|
|
408
|
+
*/
|
|
409
|
+
activeShell() {
|
|
410
|
+
if (!this.shouldShowBody())
|
|
411
|
+
return this.contentBox;
|
|
412
|
+
return this.getRenderShell() === "self" ? this.selfRenderContainer : this.contentBox;
|
|
413
|
+
}
|
|
414
|
+
/** Swap the attached shell when the view changes which one applies. */
|
|
415
|
+
syncShellChild() {
|
|
416
|
+
const wanted = this.activeShell();
|
|
417
|
+
const other = wanted === this.contentBox ? this.selfRenderContainer : this.contentBox;
|
|
418
|
+
if (this.children.includes(wanted))
|
|
419
|
+
return;
|
|
420
|
+
this.removeChild(other);
|
|
421
|
+
other.clear();
|
|
422
|
+
this.addChild(wanted);
|
|
423
|
+
}
|
|
303
424
|
updateDisplay() {
|
|
304
425
|
// Frozen blocks are immutable snapshots with their source state released.
|
|
305
426
|
if (this.frozen)
|
|
306
427
|
return;
|
|
307
428
|
let hasContent = false;
|
|
308
429
|
this.hideComponent = false;
|
|
430
|
+
this.leadingSpacer.setLines(this.shouldShowSignalLine() ? 0 : 1);
|
|
309
431
|
if (this.hasRendererDefinition()) {
|
|
310
|
-
|
|
432
|
+
this.syncShellChild();
|
|
433
|
+
const renderContainer = this.activeShell();
|
|
311
434
|
// Boxless: no background fill on the container.
|
|
312
435
|
if (renderContainer instanceof Box) {
|
|
313
436
|
renderContainer.setBgFn(undefined);
|
|
@@ -317,33 +440,43 @@ export class ToolExecutionComponent extends Container {
|
|
|
317
440
|
// The dot is prepended to the first line of the call renderer so it stays inline
|
|
318
441
|
// (adding it as a separate child would stack it on its own line).
|
|
319
442
|
const dotColor = this.result?.isError ? "error" : this.isPartial ? "warning" : "success";
|
|
320
|
-
//
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
443
|
+
// No disclosure caret. It is a click-target idiom in a TUI with no
|
|
444
|
+
// pointer, it cost two columns on every row for an action that could
|
|
445
|
+
// only ever be reached by keyboard, and reading it as "this row opens"
|
|
446
|
+
// set an expectation the view does not meet.
|
|
447
|
+
const dot = theme.fg(dotColor, "● ");
|
|
448
|
+
// Radar replaces the tool's own call renderer with the uniform signal
|
|
449
|
+
// row, so a screen of mixed tools lines up into one readable map.
|
|
450
|
+
if (this.shouldShowSignalLine()) {
|
|
451
|
+
renderContainer.addChild(new PrefixFirstLine(dot, this.getSignalComponent()));
|
|
326
452
|
hasContent = true;
|
|
327
453
|
}
|
|
328
454
|
else {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
this.callRendererComponent = component;
|
|
332
|
-
renderContainer.addChild(new PrefixFirstLine(dot, component));
|
|
333
|
-
hasContent = true;
|
|
334
|
-
}
|
|
335
|
-
catch {
|
|
336
|
-
this.callRendererComponent = undefined;
|
|
455
|
+
const callRenderer = this.getCallRenderer();
|
|
456
|
+
if (!callRenderer) {
|
|
337
457
|
renderContainer.addChild(new PrefixFirstLine(dot, this.createCallFallback()));
|
|
338
458
|
hasContent = true;
|
|
339
459
|
}
|
|
460
|
+
else {
|
|
461
|
+
try {
|
|
462
|
+
const component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));
|
|
463
|
+
this.callRendererComponent = component;
|
|
464
|
+
renderContainer.addChild(new PrefixFirstLine(dot, component));
|
|
465
|
+
hasContent = true;
|
|
466
|
+
}
|
|
467
|
+
catch {
|
|
468
|
+
this.callRendererComponent = undefined;
|
|
469
|
+
renderContainer.addChild(new PrefixFirstLine(dot, this.createCallFallback()));
|
|
470
|
+
hasContent = true;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
340
473
|
}
|
|
341
474
|
if (this.result && this.shouldShowBody()) {
|
|
342
475
|
const resultRenderer = this.getResultRenderer();
|
|
343
476
|
if (!resultRenderer) {
|
|
344
477
|
const component = this.createResultFallback();
|
|
345
478
|
if (component) {
|
|
346
|
-
renderContainer.addChild(component);
|
|
479
|
+
renderContainer.addChild(this.indentUnderSignalRow(component));
|
|
347
480
|
hasContent = true;
|
|
348
481
|
}
|
|
349
482
|
}
|
|
@@ -351,7 +484,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
351
484
|
try {
|
|
352
485
|
const component = resultRenderer({ content: this.result.content, details: this.result.details }, { expanded: this.expanded, isPartial: this.isPartial }, theme, this.getRenderContext(this.resultRendererComponent));
|
|
353
486
|
this.resultRendererComponent = component;
|
|
354
|
-
renderContainer.addChild(component);
|
|
487
|
+
renderContainer.addChild(this.indentUnderSignalRow(component));
|
|
355
488
|
hasContent = true;
|
|
356
489
|
}
|
|
357
490
|
catch {
|
|
@@ -379,7 +512,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
379
512
|
this.removeChild(spacer);
|
|
380
513
|
}
|
|
381
514
|
this.imageSpacers = [];
|
|
382
|
-
if (this.result) {
|
|
515
|
+
if (this.result && !this.shouldShowSignalLine()) {
|
|
383
516
|
const imageBlocks = this.result.content.filter((c) => c.type === "image");
|
|
384
517
|
const caps = getCapabilities();
|
|
385
518
|
for (let i = 0; i < imageBlocks.length; i++) {
|
|
@@ -408,8 +541,15 @@ export class ToolExecutionComponent extends Container {
|
|
|
408
541
|
}
|
|
409
542
|
formatToolExecution() {
|
|
410
543
|
const dotColor = this.result?.isError ? "error" : this.isPartial ? "warning" : "success";
|
|
411
|
-
|
|
412
|
-
|
|
544
|
+
// A tool with no renderer still gets a radar row, just without the
|
|
545
|
+
// flush-right signal column (this path has no width to align against).
|
|
546
|
+
if (this.shouldShowSignalLine()) {
|
|
547
|
+
const subject = toolSubject(this.args, this.cwd);
|
|
548
|
+
return (theme.fg(dotColor, "● ") +
|
|
549
|
+
theme.fg("toolTitle", theme.bold(this.toolName)) +
|
|
550
|
+
(subject ? ` ${theme.fg("toolOutput", subject)}` : ""));
|
|
551
|
+
}
|
|
552
|
+
let text = theme.fg(dotColor, "● ") + theme.fg("toolTitle", theme.bold(this.toolName));
|
|
413
553
|
const content = JSON.stringify(this.args, null, 2);
|
|
414
554
|
if (content) {
|
|
415
555
|
text += `\n\n${content}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-execution.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,GAAG,EAEH,SAAS,EACT,eAAe,EACf,KAAK,EACL,WAAW,EACX,MAAM,EACN,IAAI,EAEJ,eAAe,EACf,YAAY,GACZ,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,wBAAwB,EAAiB,MAAM,8BAA8B,CAAC;AACvF,OAAO,EAAE,aAAa,IAAI,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAgB1C;;;;;;GAMG;AACH,MAAM,eAAe;IACZ,MAAM,CAAS;IACf,KAAK,CAAY;IACjB,WAAW,CAAS;IAC5B,2EAA2E;IAC3E,yEAAyE;IACjE,IAAI,CAAmD;IAE/D,YAAY,MAAc,EAAE,KAAgB,EAAE;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAAA,CACxC;IAED,UAAU,GAAS;QAClB,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;IAAA,CACtB;IAED,MAAM,CAAC,KAAa,EAAY;QAC/B,6EAA6E;QAC7E,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YACvE,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QACtB,CAAC;QACD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5C,MAAM,GAAG,GACR,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;QAC7G,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QACvC,OAAO,GAAG,CAAC;IAAA,CACX;CACD;AAED,MAAM,OAAO,sBAAuB,SAAQ,SAAS;IAC5C,UAAU,CAAM;IAChB,WAAW,CAAO;IAClB,mBAAmB,CAAY;IAC/B,qBAAqB,CAAa;IAClC,uBAAuB,CAAa;IACpC,aAAa,GAAQ,EAAE,CAAC;IACxB,eAAe,GAAY,EAAE,CAAC;IAC9B,YAAY,GAAa,EAAE,CAAC;IAC5B,QAAQ,CAAS;IACjB,UAAU,CAAS;IACnB,IAAI,CAAM;IACV,QAAQ,GAAG,KAAK,CAAC;IACzB,0EAA0E;IAC1E,4EAA4E;IAC5E,qDAAqD;IAC7C,YAAY,CAAyB;IACrC,QAAQ,GAAG,KAAK,CAAC;IACjB,UAAU,CAAU;IACpB,eAAe,CAAS;IACxB,SAAS,GAAG,IAAI,CAAC;IACjB,cAAc,CAA4B;IAC1C,qBAAqB,CAA4B;IACjD,EAAE,CAAM;IACR,GAAG,CAAS;IACZ,gBAAgB,GAAG,KAAK,CAAC;IACzB,YAAY,GAAG,KAAK,CAAC;IACrB,MAAM,CAIZ;IACM,eAAe,GAAoD,IAAI,GAAG,EAAE,CAAC;IAC7E,aAAa,GAAG,KAAK,CAAC;IAC9B,+EAA+E;IAC/E,6EAA6E;IAC7E,6EAA6E;IAC7E,+EAA+E;IAC/E,gFAA8E;IAC9E,+EAA+E;IAC/E,8DAA8D;IACtD,MAAM,GAAG,KAAK,CAAC;IACf,WAAW,CAAY;IAC/B;uFACmF;IAC3E,WAAW,GAAG,CAAC,CAAC;IAChB,eAAe,CAAY;IAC3B,oBAAoB,GAAG,CAAC,CAAC,CAAC;IAElC,YACC,QAAgB,EAChB,UAAkB,EAClB,IAAS,EACT,OAAO,GAAyB,EAAE,EAClC,cAAoD,EACpD,EAAO,EACP,GAAW,EACV;QACD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,qBAAqB,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC,QAAoB,CAAC,CAAC;QACjF,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;QAC7C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC;QACrD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,UAAU,CAAC;QACvD,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QAEf,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7B,+FAA+F;QAC/F,qEAAqE;QACrE,yFAAyF;QACzF,+EAA6E;QAC7E,4EAA4E;QAC5E,+EAA+E;QAC/E,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,WAAW,GAAG,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,mBAAmB,GAAG,IAAI,SAAS,EAAE,CAAC;QAE3C,IAAI,IAAI,CAAC,qBAAqB,EAAE,EAAE,CAAC;YAClC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9F,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAEO,eAAe,GAAuD;QAC7E,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC;QACxC,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC;QAC9C,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,UAAU,IAAI,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC;IAAA,CAC/E;IAEO,iBAAiB,GAAyD;QACjF,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC;QAC1C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,qBAAqB,CAAC,YAAY,CAAC;QAChD,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,YAAY,IAAI,IAAI,CAAC,qBAAqB,CAAC,YAAY,CAAC;IAAA,CACnF;IAEO,qBAAqB,GAAY;QACxC,OAAO,IAAI,CAAC,qBAAqB,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,CAAC;IAAA,CACrF;IAEO,cAAc,GAAuB;QAC5C,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,cAAc,EAAE,WAAW,IAAI,SAAS,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,qBAAqB,CAAC,WAAW,IAAI,SAAS,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,WAAW,IAAI,IAAI,CAAC,qBAAqB,CAAC,WAAW,IAAI,SAAS,CAAC;IAAA,CAC9F;IAEO,gBAAgB,CAAC,aAAoC,EAAqB;QACjF,OAAO;YACN,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,UAAU,EAAE,GAAG,EAAE,CAAC;gBACjB,IAAI,CAAC,UAAU,EAAE,CAAC;gBAClB,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;YAAA,CACxB;YACD,aAAa;YACb,KAAK,EAAE,IAAI,CAAC,aAAa;YACzB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,KAAK;SACtC,CAAC;IAAA,CACF;IAEO,kBAAkB,GAAc;QACvC,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAAA,CACxE;IAEO,oBAAoB,GAA0B;QACrD,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAAA,CACtD;IAED,UAAU,CAAC,IAAS,EAAQ;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAED,oBAAoB,GAAS;QAC5B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;IAAA,CACxB;IAED,eAAe,GAAS;QACvB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;IAAA,CACxB;IAED,YAAY,CACX,MAIC,EACD,SAAS,GAAG,KAAK,EACV;QACP,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,0BAA0B,EAAE,CAAC;IAAA,CAClC;IAEO,0BAA0B,GAAS;QAC1C,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO;YAAE,OAAO;QACpC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAEzB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QAC1E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ;gBAAE,SAAS;YACzC,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW;gBAAE,SAAS;YAC3C,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,SAAS;YAE1C,MAAM,KAAK,GAAG,CAAC,CAAC;YAChB,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC;gBACxD,IAAI,IAAI,CAAC,MAAM;oBAAE,OAAO;gBACxB,IAAI,SAAS,EAAE,CAAC;oBACf,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;oBACrB,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;gBACzB,CAAC;YAAA,CACD,CAAC,CAAC;QACJ,CAAC;IAAA,CACD;IAED,WAAW,CAAC,QAAiB,EAAQ;QACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,4EAA4E;QAC5E,oEAAkE;QAClE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAED,eAAe,CAAC,KAA6B,EAAQ;QACpD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAED,8EAA8E;IACtE,cAAc,GAAY;QACjC,OAAO,IAAI,CAAC,YAAY,KAAK,UAAU,IAAI,IAAI,CAAC,QAAQ,CAAC;IAAA,CACzD;IAED,aAAa,CAAC,IAAa,EAAQ;QAClC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAED,kBAAkB,CAAC,KAAa,EAAQ;QACvC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAEQ,UAAU,GAAS;QAC3B,0EAA0E;QAC1E,wEAAwE;QACxE,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,KAAK,CAAC,UAAU,EAAE,CAAC;QACnB,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAED;;;;OAIG;IACH,WAAW,GAAY;QACtB,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IAAA,CAC/E;IAED;uEACmE;IACnE,MAAM,GAAS;QACd,IAAI,IAAI,CAAC,WAAW,EAAE;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IAAA,CAC3C;IAEO,iBAAiB,GAAS;QACjC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;QACvC,IAAI,CAAC,uBAAuB,GAAG,SAAS,CAAC;QACzC,uEAAuE;QACvE,qDAAqD;QACrD,IAAI,CAAC,KAAK,EAAE,CAAC;IAAA,CACb;IAEQ,MAAM,CAAC,KAAa,EAAY;QACxC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,OAAO,EAAE,CAAC;QACX,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,sEAAsE;YACtE,yEAAyE;YACzE,qEAAqE;YACrE,IAAI,KAAK,IAAI,IAAI,CAAC,WAAW;gBAAE,OAAO,IAAI,CAAC,WAAW,CAAC;YACvD,IAAI,IAAI,CAAC,oBAAoB,KAAK,KAAK,IAAI,IAAI,CAAC,eAAe;gBAAE,OAAO,IAAI,CAAC,eAAe,CAAC;YAC7F,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACpD,WAAW,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,CACtF,CAAC;YACF,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC;YAClC,OAAO,IAAI,CAAC,eAAe,CAAC;QAC7B,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC1B,CAAC;QACD,OAAO,KAAK,CAAC;IAAA,CACb;IAEO,aAAa,GAAS;QAC7B,0EAA0E;QAC1E,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,IAAI,CAAC,qBAAqB,EAAE,EAAE,CAAC;YAClC,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;YACtG,gDAAgD;YAChD,IAAI,eAAe,YAAY,GAAG,EAAE,CAAC;gBACpC,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACpC,CAAC;YACD,eAAe,CAAC,KAAK,EAAE,CAAC;YAExB,4FAA4F;YAC5F,iFAAiF;YACjF,kEAAkE;YAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;YACzF,+EAA2E;YAC3E,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAI,CAAC,CAAC,CAAC,MAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACjG,MAAM,GAAG,GAAG,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAI,CAAC,CAAC;YAE7C,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YAC5C,IAAI,CAAC,YAAY,EAAE,CAAC;gBACnB,eAAe,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;gBAC9E,UAAU,GAAG,IAAI,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC;oBACJ,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;oBACpG,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;oBACvC,eAAe,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;oBAC9D,UAAU,GAAG,IAAI,CAAC;gBACnB,CAAC;gBAAC,MAAM,CAAC;oBACR,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;oBACvC,eAAe,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;oBAC9E,UAAU,GAAG,IAAI,CAAC;gBACnB,CAAC;YACF,CAAC;YAED,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC1C,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAChD,IAAI,CAAC,cAAc,EAAE,CAAC;oBACrB,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;oBAC9C,IAAI,SAAS,EAAE,CAAC;wBACf,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;wBACpC,UAAU,GAAG,IAAI,CAAC;oBACnB,CAAC;gBACF,CAAC;qBAAM,CAAC;oBACP,IAAI,CAAC;wBACJ,MAAM,SAAS,GAAG,cAAc,CAC/B,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAc,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,EACrE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,EACtD,KAAK,EACL,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,uBAAuB,CAAC,CACnD,CAAC;wBACF,IAAI,CAAC,uBAAuB,GAAG,SAAS,CAAC;wBACzC,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;wBACpC,UAAU,GAAG,IAAI,CAAC;oBACnB,CAAC;oBAAC,MAAM,CAAC;wBACR,IAAI,CAAC,uBAAuB,GAAG,SAAS,CAAC;wBACzC,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;wBAC9C,IAAI,SAAS,EAAE,CAAC;4BACf,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;4BACpC,UAAU,GAAG,IAAI,CAAC;wBACnB,CAAC;oBACF,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;aAAM,CAAC;YACP,+BAA+B;YAC/B,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YAC1C,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC;YACrD,UAAU,GAAG,IAAI,CAAC;QACnB,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACxC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACxC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QAEvB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;YAC1E,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;YAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;gBAC3B,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;oBAChE,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBAC9C,MAAM,SAAS,GAAG,SAAS,EAAE,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC;oBAC9C,MAAM,aAAa,GAAG,SAAS,EAAE,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC;oBAC1D,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,IAAI,aAAa,KAAK,WAAW;wBAAE,SAAS;oBAEvE,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;oBAC7B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;oBACtB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAC/B,MAAM,cAAc,GAAG,IAAI,KAAK,CAC/B,SAAS,EACT,aAAa,EACb,EAAE,aAAa,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,EAC3D,EAAE,aAAa,EAAE,IAAI,CAAC,eAAe,EAAE,CACvC,CAAC;oBACF,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;oBAC1C,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;gBAC/B,CAAC;YACF,CAAC;QACF,CAAC;QAED,IAAI,IAAI,CAAC,qBAAqB,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtF,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC3B,CAAC;IAAA,CACD;IAEO,aAAa,GAAW;QAC/B,OAAO,qBAAqB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAAA,CAC3D;IAEO,mBAAmB,GAAW;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QACzF,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAI,CAAC,CAAC,CAAC,MAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjG,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAI,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/F,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACnD,IAAI,OAAO,EAAE,CAAC;YACb,IAAI,IAAI,OAAO,OAAO,EAAE,CAAC;QAC1B,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,IAAI,MAAM,EAAE,CAAC;YACZ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACvB,CAAC;QACD,OAAO,IAAI,CAAC;IAAA,CACZ;CACD","sourcesContent":["import {\n\tBox,\n\ttype Component,\n\tContainer,\n\tgetCapabilities,\n\tImage,\n\tisImageLine,\n\tSpacer,\n\tText,\n\ttype TUI,\n\ttruncateToWidth,\n\tvisibleWidth,\n} from \"@kolisachint/hoocode-tui\";\nimport type { ToolDefinition, ToolRenderContext } from \"../../../core/extensions/types.js\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.js\";\nimport { getTextOutput as getRenderedTextOutput } from \"../../../core/tools/render-utils.js\";\nimport { convertToPng } from \"../../../utils/image-convert.js\";\nimport { theme } from \"../theme/theme.js\";\n\n/**\n * How a tool block's result body is displayed:\n * - \"standard\": result shown (truncated preview, expandable) — the default.\n * - \"collapsed\": result hidden; only the call line + status dot render.\n * - \"peek\": result hidden by default with a ▸ affordance; the expand key reveals it.\n */\nexport type ToolOutputDisplayLevel = \"collapsed\" | \"peek\" | \"standard\";\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n\tdisplayLevel?: ToolOutputDisplayLevel;\n}\n\n/**\n * Renders a child component and prepends a prefix (e.g. a status dot) to its\n * first line, indenting continuation lines so they align under the content.\n *\n * This keeps the dot inline with the first line instead of stacking it on its\n * own line (which happens when a Container holds the dot as a separate child).\n */\nclass PrefixFirstLine implements Component {\n\tprivate prefix: string;\n\tprivate child: Component;\n\tprivate indentWidth: number;\n\t// Keyed on the child's returned array identity so an unchanged child keeps\n\t// this wrapper reference-stable too (parents memoize flattening by ref).\n\tprivate memo?: { src: string[]; width: number; out: string[] };\n\n\tconstructor(prefix: string, child: Component) {\n\t\tthis.prefix = prefix;\n\t\tthis.child = child;\n\t\tthis.indentWidth = visibleWidth(prefix);\n\t}\n\n\tinvalidate(): void {\n\t\tthis.child.invalidate?.();\n\t\tthis.memo = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\t// Reserve room for the prefix so the child wraps within the remaining width.\n\t\tconst childWidth = Math.max(1, width - this.indentWidth);\n\t\tconst lines = this.child.render(childWidth);\n\t\tif (this.memo && this.memo.src === lines && this.memo.width === width) {\n\t\t\treturn this.memo.out;\n\t\t}\n\t\tconst indent = \" \".repeat(this.indentWidth);\n\t\tconst out =\n\t\t\tlines.length === 0 ? [this.prefix] : lines.map((line, i) => (i === 0 ? this.prefix + line : indent + line));\n\t\tthis.memo = { src: lines, width, out };\n\t\treturn out;\n\t}\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\t// Persisted display level (collapsed/peek/standard). Controls whether the\n\t// result body renders at all; `revealed` is the per-block override that the\n\t// global expand key flips for collapsed/peek blocks.\n\tprivate displayLevel: ToolOutputDisplayLevel;\n\tprivate revealed = false;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\t// Once a finished tool block has scrolled far out of view the interactive mode\n\t// freezes it (see freeze()): its already-rendered lines are captured and the\n\t// heavy source payloads (full tool result, base64 image copies, per-renderer\n\t// state, child component caches) are released. A frozen block is immutable and\n\t// no longer reflows on resize — old off-screen scrollback keeps its wrapping,\n\t// which self-heals on any full rebuild (theme toggle / session reload, both of\n\t// which reconstruct components from the intact session data).\n\tprivate frozen = false;\n\tprivate frozenLines?: string[];\n\t/** Width the frozen snapshot was captured at; a wider terminal is safe as-is,\n\t * a narrower one needs re-truncation to avoid the TUI's over-width crash guard. */\n\tprivate frozenWidth = 0;\n\tprivate frozenTruncated?: string[];\n\tprivate frozenTruncatedWidth = -1;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.displayLevel = options.displayLevel ?? \"standard\";\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\t// Boxless: no filled background — hierarchy comes from status dots + indent.\n\t\t// paddingY is 0: the single leading Spacer(1) is the only separator between\n\t\t// tool blocks, so consecutive commands don't stack 3 blank lines between them.\n\t\tthis.contentBox = new Box(1, 0);\n\t\tthis.contentText = new Text(\"\", 1, 0);\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox);\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.builtInToolDefinition !== undefined || this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(this.toolName)), 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn new Text(theme.fg(\"toolOutput\", output), 0, 0);\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (this.frozen) return;\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\t// For collapsed/peek blocks the same global toggle reveals the hidden body;\n\t\t// for standard blocks `expanded` alone switches truncated ↔ full.\n\t\tthis.revealed = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetDisplayLevel(level: ToolOutputDisplayLevel): void {\n\t\tthis.displayLevel = level;\n\t\tthis.updateDisplay();\n\t}\n\n\t/** Whether the result body should render given the level and reveal state. */\n\tprivate shouldShowBody(): boolean {\n\t\treturn this.displayLevel === \"standard\" || this.revealed;\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\t// A frozen block has released the state updateDisplay would rebuild from;\n\t\t// its captured snapshot is authoritative, so skip the rebuild entirely.\n\t\tif (this.frozen) return;\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\t/**\n\t * True when this block is a finished, visible tool result that still holds its\n\t * heavy source payloads — i.e. a candidate for freeze() once it scrolls out of\n\t * the live window. In-flight (partial) and already-frozen blocks are excluded.\n\t */\n\tisFreezable(): boolean {\n\t\treturn !this.frozen && !this.isPartial && !this.hideComponent && !!this.result;\n\t}\n\n\t/** Mark this block for freezing; the snapshot is captured on the next render\n\t * (at the real render width) and the heavy state released then. */\n\tfreeze(): void {\n\t\tif (this.isFreezable()) this.frozen = true;\n\t}\n\n\tprivate releaseHeavyState(): void {\n\t\tthis.result = undefined;\n\t\tthis.convertedImages.clear();\n\t\tthis.imageComponents = [];\n\t\tthis.imageSpacers = [];\n\t\tthis.rendererState = {};\n\t\tthis.callRendererComponent = undefined;\n\t\tthis.resultRendererComponent = undefined;\n\t\t// Drop child components so their line caches (which embed base64 image\n\t\t// payloads and full text output) become collectable.\n\t\tthis.clear();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\t\tif (this.frozenLines) {\n\t\t\t// Captured snapshot. Wider (or equal) terminal: emit as-is. Narrower:\n\t\t\t// re-truncate non-image lines to avoid the TUI's over-width crash guard,\n\t\t\t// caching the result per width so it stays O(1) on unchanged frames.\n\t\t\tif (width >= this.frozenWidth) return this.frozenLines;\n\t\t\tif (this.frozenTruncatedWidth === width && this.frozenTruncated) return this.frozenTruncated;\n\t\t\tthis.frozenTruncated = this.frozenLines.map((line) =>\n\t\t\t\tisImageLine(line) || visibleWidth(line) <= width ? line : truncateToWidth(line, width),\n\t\t\t);\n\t\t\tthis.frozenTruncatedWidth = width;\n\t\t\treturn this.frozenTruncated;\n\t\t}\n\t\tconst lines = super.render(width);\n\t\tif (this.frozen) {\n\t\t\tthis.frozenLines = lines;\n\t\t\tthis.frozenWidth = width;\n\t\t\tthis.releaseHeavyState();\n\t\t}\n\t\treturn lines;\n\t}\n\n\tprivate updateDisplay(): void {\n\t\t// Frozen blocks are immutable snapshots with their source state released.\n\t\tif (this.frozen) return;\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tconst renderContainer = this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t\t\t// Boxless: no background fill on the container.\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(undefined);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\t// Status dot prefix: green for complete success, yellow for pending/partial, red for error.\n\t\t\t// The dot is prepended to the first line of the call renderer so it stays inline\n\t\t\t// (adding it as a separate child would stack it on its own line).\n\t\t\tconst dotColor = this.result?.isError ? \"error\" : this.isPartial ? \"warning\" : \"success\";\n\t\t\t// Peek blocks advertise their hidden body with a ▸/▾ caret before the dot.\n\t\t\tconst caret = this.displayLevel === \"peek\" ? theme.fg(\"muted\", this.revealed ? \"▾ \" : \"▸ \") : \"\";\n\t\t\tconst dot = caret + theme.fg(dotColor, \"● \");\n\n\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\tif (!callRenderer) {\n\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, this.createCallFallback()));\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, component));\n\t\t\t\t\thasContent = true;\n\t\t\t\t} catch {\n\t\t\t\t\tthis.callRendererComponent = undefined;\n\t\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, this.createCallFallback()));\n\t\t\t\t\thasContent = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result && this.shouldShowBody()) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.resultRendererComponent = undefined;\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Boxless: no background fill.\n\t\t\tthis.contentText.setCustomBgFn(undefined);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tconst dotColor = this.result?.isError ? \"error\" : this.isPartial ? \"warning\" : \"success\";\n\t\tconst caret = this.displayLevel === \"peek\" ? theme.fg(\"muted\", this.revealed ? \"▾ \" : \"▸ \") : \"\";\n\t\tlet text = caret + theme.fg(dotColor, \"● \") + theme.fg(\"toolTitle\", theme.bold(this.toolName));\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.shouldShowBody() ? this.getTextOutput() : \"\";\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tool-execution.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,GAAG,EAEH,SAAS,EACT,eAAe,EACf,KAAK,EACL,WAAW,EACX,MAAM,EACN,IAAI,EAEJ,eAAe,EACf,YAAY,GACZ,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,wBAAwB,EAAiB,MAAM,8BAA8B,CAAC;AACvF,OAAO,EAAE,aAAa,IAAI,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAcpE;;;;;;GAMG;AACH,MAAM,eAAe;IACZ,MAAM,CAAS;IACf,KAAK,CAAY;IACjB,WAAW,CAAS;IAC5B,2EAA2E;IAC3E,yEAAyE;IACjE,IAAI,CAAmD;IAE/D,YAAY,MAAc,EAAE,KAAgB,EAAE;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAAA,CACxC;IAED,UAAU,GAAS;QAClB,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;IAAA,CACtB;IAED,MAAM,CAAC,KAAa,EAAY;QAC/B,6EAA6E;QAC7E,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YACvE,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QACtB,CAAC;QACD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5C,MAAM,GAAG,GACR,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;QAC7G,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QACvC,OAAO,GAAG,CAAC;IAAA,CACX;CACD;AAED;;;;GAIG;AACH,MAAM,SAAS;IACN,KAAK,CAAY;IACjB,MAAM,CAAS;IACf,IAAI,CAAmD;IAE/D,YAAY,KAAgB,EAAE,KAAa,EAAE;QAC5C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAAA,CAChC;IAED,UAAU,GAAS;QAClB,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;IAAA,CACtB;IAED,MAAM,CAAC,KAAa,EAAY;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACzE,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QAC5F,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;QAClF,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QACvC,OAAO,GAAG,CAAC;IAAA,CACX;CACD;AAED,MAAM,OAAO,sBAAuB,SAAQ,SAAS;IAC5C,UAAU,CAAM;IAChB,WAAW,CAAO;IAClB,mBAAmB,CAAY;IAC/B,qBAAqB,CAAa;IAClC,uBAAuB,CAAa;IACpC,aAAa,GAAQ,EAAE,CAAC;IACxB,eAAe,GAAY,EAAE,CAAC;IAC9B,YAAY,GAAa,EAAE,CAAC;IAC5B,QAAQ,CAAS;IACjB,UAAU,CAAS;IACnB,IAAI,CAAM;IACV,QAAQ,GAAG,KAAK,CAAC;IACzB,8EAA8E;IAC9E,+EAA+E;IAC/E,uDAAuD;IAC/C,IAAI,CAAiB;IACrB,QAAQ,GAAG,KAAK,CAAC;IACjB,eAAe,CAAuB;IACtC,aAAa,CAAS;IACtB,UAAU,CAAU;IACpB,eAAe,CAAS;IACxB,SAAS,GAAG,IAAI,CAAC;IACjB,cAAc,CAA4B;IAC1C,qBAAqB,CAA4B;IACjD,EAAE,CAAM;IACR,GAAG,CAAS;IACZ,gBAAgB,GAAG,KAAK,CAAC;IACzB,YAAY,GAAG,KAAK,CAAC;IACrB,MAAM,CAIZ;IACM,eAAe,GAAoD,IAAI,GAAG,EAAE,CAAC;IAC7E,aAAa,GAAG,KAAK,CAAC;IAC9B,+EAA+E;IAC/E,6EAA6E;IAC7E,6EAA6E;IAC7E,+EAA+E;IAC/E,gFAA8E;IAC9E,+EAA+E;IAC/E,8DAA8D;IACtD,MAAM,GAAG,KAAK,CAAC;IACf,WAAW,CAAY;IAC/B;uFACmF;IAC3E,WAAW,GAAG,CAAC,CAAC;IAChB,eAAe,CAAY;IAC3B,oBAAoB,GAAG,CAAC,CAAC,CAAC;IAElC,YACC,QAAgB,EAChB,UAAkB,EAClB,IAAS,EACT,OAAO,GAAyB,EAAE,EAClC,cAAoD,EACpD,EAAO,EACP,GAAW,EACV;QACD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,qBAAqB,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC,QAAoB,CAAC,CAAC;QACjF,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;QAC7C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC;QACrD,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,QAAQ,CAAC;QACrC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QAEf,2EAA2E;QAC3E,qEAAqE;QACrE,IAAI,CAAC,aAAa,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAElC,+FAA+F;QAC/F,qEAAqE;QACrE,yFAAyF;QACzF,+EAA6E;QAC7E,4EAA4E;QAC5E,+EAA+E;QAC/E,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,WAAW,GAAG,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,mBAAmB,GAAG,IAAI,SAAS,EAAE,CAAC;QAE3C,IAAI,IAAI,CAAC,qBAAqB,EAAE,EAAE,CAAC;YAClC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAEO,eAAe,GAAuD;QAC7E,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC;QACxC,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC;QAC9C,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,UAAU,IAAI,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC;IAAA,CAC/E;IAEO,iBAAiB,GAAyD;QACjF,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC;QAC1C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,qBAAqB,CAAC,YAAY,CAAC;QAChD,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,YAAY,IAAI,IAAI,CAAC,qBAAqB,CAAC,YAAY,CAAC;IAAA,CACnF;IAEO,qBAAqB,GAAY;QACxC,OAAO,IAAI,CAAC,qBAAqB,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,CAAC;IAAA,CACrF;IAEO,cAAc,GAAuB;QAC5C,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,cAAc,EAAE,WAAW,IAAI,SAAS,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,qBAAqB,CAAC,WAAW,IAAI,SAAS,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,WAAW,IAAI,IAAI,CAAC,qBAAqB,CAAC,WAAW,IAAI,SAAS,CAAC;IAAA,CAC9F;IAEO,gBAAgB,CAAC,aAAoC,EAAqB;QACjF,OAAO;YACN,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,UAAU,EAAE,GAAG,EAAE,CAAC;gBACjB,IAAI,CAAC,UAAU,EAAE,CAAC;gBAClB,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;YAAA,CACxB;YACD,aAAa;YACb,KAAK,EAAE,IAAI,CAAC,aAAa;YACzB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,KAAK;SACtC,CAAC;IAAA,CACF;IAEO,kBAAkB,GAAc;QACvC,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAAA,CACxE;IAEO,oBAAoB,GAA0B;QACrD,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAAA,CACtD;IAED,UAAU,CAAC,IAAS,EAAQ;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAED,oBAAoB,GAAS;QAC5B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;IAAA,CACxB;IAED,eAAe,GAAS;QACvB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;IAAA,CACxB;IAED,YAAY,CACX,MAIC,EACD,SAAS,GAAG,KAAK,EACV;QACP,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,0BAA0B,EAAE,CAAC;IAAA,CAClC;IAEO,0BAA0B,GAAS;QAC1C,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO;YAAE,OAAO;QACpC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAEzB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QAC1E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ;gBAAE,SAAS;YACzC,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW;gBAAE,SAAS;YAC3C,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,SAAS;YAE1C,MAAM,KAAK,GAAG,CAAC,CAAC;YAChB,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC;gBACxD,IAAI,IAAI,CAAC,MAAM;oBAAE,OAAO;gBACxB,IAAI,SAAS,EAAE,CAAC;oBACf,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;oBACrB,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;gBACzB,CAAC;YAAA,CACD,CAAC,CAAC;QACJ,CAAC;IAAA,CACD;IAED,WAAW,CAAC,QAAiB,EAAQ;QACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,0EAA0E;QAC1E,sEAAoE;QACpE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAED,OAAO,CAAC,IAAoB,EAAQ;QACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAED;;;;;OAKG;IACH,UAAU,GAAY;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC;IAAA,CACrB;IAED,4DAA4D;IAC5D,UAAU,GAAe;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,OAAO;YACN,IAAI,EAAE,IAAI,CAAC,QAAQ;YACnB,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;YACzC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI;YACtC,SAAS,EAAE,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS;YACtD,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;SAC1D,CAAC;IAAA,CACF;IAED,uEAAuE;IACvE,SAAS,GAAW;QACnB,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAAA,CACxD;IAED;;;;;;;OAOG;IACK,cAAc,GAAY;QACjC,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAAA,CAC9E;IAED;;;;OAIG;IACK,oBAAoB,GAAY;QACvC,OAAO,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;IAAA,CAC/C;IAED;;;OAGG;IACK,oBAAoB,CAAC,SAAoB,EAAa;QAC7D,OAAO,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAAA,CAC7E;IAEO,kBAAkB,GAAwB;QACjD,MAAM,KAAK,GAAG;YACb,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC3B,CAAC;QACF,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,eAAe,GAAG,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,IAAI,CAAC,eAAe,CAAC;IAAA,CAC5B;IAED,aAAa,CAAC,IAAa,EAAQ;QAClC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAED,kBAAkB,CAAC,KAAa,EAAQ;QACvC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAEQ,UAAU,GAAS;QAC3B,0EAA0E;QAC1E,wEAAwE;QACxE,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,KAAK,CAAC,UAAU,EAAE,CAAC;QACnB,IAAI,CAAC,aAAa,EAAE,CAAC;IAAA,CACrB;IAED;;;;OAIG;IACH,WAAW,GAAY;QACtB,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IAAA,CAC/E;IAED;uEACmE;IACnE,MAAM,GAAS;QACd,IAAI,IAAI,CAAC,WAAW,EAAE;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IAAA,CAC3C;IAEO,iBAAiB,GAAS;QACjC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;QACvC,IAAI,CAAC,uBAAuB,GAAG,SAAS,CAAC;QACzC,uEAAuE;QACvE,qDAAqD;QACrD,IAAI,CAAC,KAAK,EAAE,CAAC;IAAA,CACb;IAEQ,MAAM,CAAC,KAAa,EAAY;QACxC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,OAAO,EAAE,CAAC;QACX,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,sEAAsE;YACtE,yEAAyE;YACzE,qEAAqE;YACrE,IAAI,KAAK,IAAI,IAAI,CAAC,WAAW;gBAAE,OAAO,IAAI,CAAC,WAAW,CAAC;YACvD,IAAI,IAAI,CAAC,oBAAoB,KAAK,KAAK,IAAI,IAAI,CAAC,eAAe;gBAAE,OAAO,IAAI,CAAC,eAAe,CAAC;YAC7F,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACpD,WAAW,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,CACtF,CAAC;YACF,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC;YAClC,OAAO,IAAI,CAAC,eAAe,CAAC;QAC7B,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC1B,CAAC;QACD,OAAO,KAAK,CAAC;IAAA,CACb;IAED;;;;;;;;;;OAUG;IACK,WAAW,GAAoB;QACtC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC;QACnD,OAAO,IAAI,CAAC,cAAc,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;IAAA,CACrF;IAED,uEAAuE;IAC/D,cAAc,GAAS;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM,KAAK,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QACtF,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO;QAC3C,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACxB,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAAA,CACtB;IAEO,aAAa,GAAS;QAC7B,0EAA0E;QAC1E,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,IAAI,IAAI,CAAC,qBAAqB,EAAE,EAAE,CAAC;YAClC,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAC3C,gDAAgD;YAChD,IAAI,eAAe,YAAY,GAAG,EAAE,CAAC;gBACpC,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACpC,CAAC;YACD,eAAe,CAAC,KAAK,EAAE,CAAC;YAExB,4FAA4F;YAC5F,iFAAiF;YACjF,kEAAkE;YAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;YACzF,mEAAmE;YACnE,qEAAqE;YACrE,uEAAuE;YACvE,6CAA6C;YAC7C,MAAM,GAAG,GAAG,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAI,CAAC,CAAC;YAErC,sEAAsE;YACtE,kEAAkE;YAClE,IAAI,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;gBACjC,eAAe,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;gBAC9E,UAAU,GAAG,IAAI,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACP,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;gBAC5C,IAAI,CAAC,YAAY,EAAE,CAAC;oBACnB,eAAe,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;oBAC9E,UAAU,GAAG,IAAI,CAAC;gBACnB,CAAC;qBAAM,CAAC;oBACP,IAAI,CAAC;wBACJ,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;wBACpG,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;wBACvC,eAAe,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;wBAC9D,UAAU,GAAG,IAAI,CAAC;oBACnB,CAAC;oBAAC,MAAM,CAAC;wBACR,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;wBACvC,eAAe,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;wBAC9E,UAAU,GAAG,IAAI,CAAC;oBACnB,CAAC;gBACF,CAAC;YACF,CAAC;YAED,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC1C,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAChD,IAAI,CAAC,cAAc,EAAE,CAAC;oBACrB,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;oBAC9C,IAAI,SAAS,EAAE,CAAC;wBACf,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,CAAC;wBAC/D,UAAU,GAAG,IAAI,CAAC;oBACnB,CAAC;gBACF,CAAC;qBAAM,CAAC;oBACP,IAAI,CAAC;wBACJ,MAAM,SAAS,GAAG,cAAc,CAC/B,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAc,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,EACrE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,EACtD,KAAK,EACL,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,uBAAuB,CAAC,CACnD,CAAC;wBACF,IAAI,CAAC,uBAAuB,GAAG,SAAS,CAAC;wBACzC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,CAAC;wBAC/D,UAAU,GAAG,IAAI,CAAC;oBACnB,CAAC;oBAAC,MAAM,CAAC;wBACR,IAAI,CAAC,uBAAuB,GAAG,SAAS,CAAC;wBACzC,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;wBAC9C,IAAI,SAAS,EAAE,CAAC;4BACf,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;4BACpC,UAAU,GAAG,IAAI,CAAC;wBACnB,CAAC;oBACF,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;aAAM,CAAC;YACP,+BAA+B;YAC/B,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YAC1C,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC;YACrD,UAAU,GAAG,IAAI,CAAC;QACnB,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACxC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACxC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QAEvB,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;YACjD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;YAC1E,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;YAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;gBAC3B,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;oBAChE,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBAC9C,MAAM,SAAS,GAAG,SAAS,EAAE,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC;oBAC9C,MAAM,aAAa,GAAG,SAAS,EAAE,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC;oBAC1D,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,IAAI,aAAa,KAAK,WAAW;wBAAE,SAAS;oBAEvE,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;oBAC7B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;oBACtB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAC/B,MAAM,cAAc,GAAG,IAAI,KAAK,CAC/B,SAAS,EACT,aAAa,EACb,EAAE,aAAa,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,EAC3D,EAAE,aAAa,EAAE,IAAI,CAAC,eAAe,EAAE,CACvC,CAAC;oBACF,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;oBAC1C,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;gBAC/B,CAAC;YACF,CAAC;QACF,CAAC;QAED,IAAI,IAAI,CAAC,qBAAqB,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtF,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC3B,CAAC;IAAA,CACD;IAEO,aAAa,GAAW;QAC/B,OAAO,qBAAqB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAAA,CAC3D;IAEO,mBAAmB,GAAW;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QACzF,mEAAmE;QACnE,uEAAuE;QACvE,IAAI,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YACjD,OAAO,CACN,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAI,CAAC;gBACxB,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAChD,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CACtD,CAAC;QACH,CAAC;QACD,IAAI,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAI,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvF,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACnD,IAAI,OAAO,EAAE,CAAC;YACb,IAAI,IAAI,OAAO,OAAO,EAAE,CAAC;QAC1B,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,IAAI,MAAM,EAAE,CAAC;YACZ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACvB,CAAC;QACD,OAAO,IAAI,CAAC;IAAA,CACZ;CACD","sourcesContent":["import {\n\tBox,\n\ttype Component,\n\tContainer,\n\tgetCapabilities,\n\tImage,\n\tisImageLine,\n\tSpacer,\n\tText,\n\ttype TUI,\n\ttruncateToWidth,\n\tvisibleWidth,\n} from \"@kolisachint/hoocode-tui\";\nimport type { ToolDefinition, ToolRenderContext } from \"../../../core/extensions/types.js\";\nimport type { ToolOutputView } from \"../../../core/tool-output-view.js\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.js\";\nimport { getTextOutput as getRenderedTextOutput } from \"../../../core/tools/render-utils.js\";\nimport { convertToPng } from \"../../../utils/image-convert.js\";\nimport { theme } from \"../theme/theme.js\";\nimport type { ChainEntry } from \"./tool-chain-summary.js\";\nimport { ToolSignalComponent, toolSubject } from \"./tool-signal.js\";\n\n/**\n * Re-exported so tool-block callers keep a single import site for the view\n * dial; the type itself lives in core (the settings manager persists it).\n */\nexport type { ToolOutputView } from \"../../../core/tool-output-view.js\";\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n\tview?: ToolOutputView;\n}\n\n/**\n * Renders a child component and prepends a prefix (e.g. a status dot) to its\n * first line, indenting continuation lines so they align under the content.\n *\n * This keeps the dot inline with the first line instead of stacking it on its\n * own line (which happens when a Container holds the dot as a separate child).\n */\nclass PrefixFirstLine implements Component {\n\tprivate prefix: string;\n\tprivate child: Component;\n\tprivate indentWidth: number;\n\t// Keyed on the child's returned array identity so an unchanged child keeps\n\t// this wrapper reference-stable too (parents memoize flattening by ref).\n\tprivate memo?: { src: string[]; width: number; out: string[] };\n\n\tconstructor(prefix: string, child: Component) {\n\t\tthis.prefix = prefix;\n\t\tthis.child = child;\n\t\tthis.indentWidth = visibleWidth(prefix);\n\t}\n\n\tinvalidate(): void {\n\t\tthis.child.invalidate?.();\n\t\tthis.memo = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\t// Reserve room for the prefix so the child wraps within the remaining width.\n\t\tconst childWidth = Math.max(1, width - this.indentWidth);\n\t\tconst lines = this.child.render(childWidth);\n\t\tif (this.memo && this.memo.src === lines && this.memo.width === width) {\n\t\t\treturn this.memo.out;\n\t\t}\n\t\tconst indent = \" \".repeat(this.indentWidth);\n\t\tconst out =\n\t\t\tlines.length === 0 ? [this.prefix] : lines.map((line, i) => (i === 0 ? this.prefix + line : indent + line));\n\t\tthis.memo = { src: lines, width, out };\n\t\treturn out;\n\t}\n}\n\n/**\n * Indents every line of a child, unlike PrefixFirstLine which only offsets the\n * first. Used for a failure's body under a radar row, so the reason reads as\n * hanging off the row rather than starting a new column.\n */\nclass IndentAll implements Component {\n\tprivate child: Component;\n\tprivate indent: string;\n\tprivate memo?: { src: string[]; width: number; out: string[] };\n\n\tconstructor(child: Component, width: number) {\n\t\tthis.child = child;\n\t\tthis.indent = \" \".repeat(width);\n\t}\n\n\tinvalidate(): void {\n\t\tthis.child.invalidate?.();\n\t\tthis.memo = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines = this.child.render(Math.max(1, width - this.indent.length));\n\t\tif (this.memo && this.memo.src === lines && this.memo.width === width) return this.memo.out;\n\t\tconst out = lines.map((line) => (line.trim() === \"\" ? line : this.indent + line));\n\t\tthis.memo = { src: lines, width, out };\n\t\treturn out;\n\t}\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\t// Persisted view (radar/glance/full). Controls how the call line is drawn and\n\t// whether the result body renders at all; `revealed` is the per-block override\n\t// the global expand key flips for radar/glance blocks.\n\tprivate view: ToolOutputView;\n\tprivate revealed = false;\n\tprivate signalComponent?: ToolSignalComponent;\n\tprivate leadingSpacer: Spacer;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\t// Once a finished tool block has scrolled far out of view the interactive mode\n\t// freezes it (see freeze()): its already-rendered lines are captured and the\n\t// heavy source payloads (full tool result, base64 image copies, per-renderer\n\t// state, child component caches) are released. A frozen block is immutable and\n\t// no longer reflows on resize — old off-screen scrollback keeps its wrapping,\n\t// which self-heals on any full rebuild (theme toggle / session reload, both of\n\t// which reconstruct components from the intact session data).\n\tprivate frozen = false;\n\tprivate frozenLines?: string[];\n\t/** Width the frozen snapshot was captured at; a wider terminal is safe as-is,\n\t * a narrower one needs re-truncation to avoid the TUI's over-width crash guard. */\n\tprivate frozenWidth = 0;\n\tprivate frozenTruncated?: string[];\n\tprivate frozenTruncatedWidth = -1;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.view = options.view ?? \"glance\";\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\t// The separator between consecutive tool blocks. Radar drops it: rows that\n\t\t// are one line each only read as a map when they stack without gaps.\n\t\tthis.leadingSpacer = new Spacer(1);\n\t\tthis.addChild(this.leadingSpacer);\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\t// Boxless: no filled background — hierarchy comes from status dots + indent.\n\t\t// paddingY is 0: the single leading Spacer(1) is the only separator between\n\t\t// tool blocks, so consecutive commands don't stack 3 blank lines between them.\n\t\tthis.contentBox = new Box(1, 0);\n\t\tthis.contentText = new Text(\"\", 1, 0);\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.activeShell());\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.builtInToolDefinition !== undefined || this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(this.toolName)), 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn new Text(theme.fg(\"toolOutput\", output), 0, 0);\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (this.frozen) return;\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\t// For radar/glance blocks the same global toggle reveals the hidden body;\n\t\t// for full blocks `expanded` alone switches truncated ↔ everything.\n\t\tthis.revealed = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetView(view: ToolOutputView): void {\n\t\tthis.view = view;\n\t\tthis.updateDisplay();\n\t}\n\n\t/**\n\t * Whether this block is currently opened up.\n\t *\n\t * Read by the one-at-a-time unfold, which walks back from the newest block\n\t * to find the first one still folded.\n\t */\n\tisRevealed(): boolean {\n\t\treturn this.revealed;\n\t}\n\n\t/** This call's contribution to its chain's summary line. */\n\tchainEntry(): ChainEntry {\n\t\tconst output = this.result ? this.getTextOutput() : \"\";\n\t\treturn {\n\t\t\ttool: this.toolName,\n\t\t\tsubject: toolSubject(this.args, this.cwd),\n\t\t\tisError: this.result?.isError === true,\n\t\t\tisPartial: this.result === undefined || this.isPartial,\n\t\t\toutputLines: output.trim() ? output.split(\"\\n\").length : 0,\n\t\t};\n\t}\n\n\t/** The failure text, for a collapsed chain to print under its line. */\n\terrorText(): string {\n\t\treturn this.result?.isError ? this.getTextOutput() : \"\";\n\t}\n\n\t/**\n\t * Whether the result body should render.\n\t *\n\t * A failure always shows its reason, in every view. Everything else about\n\t * these views is a judgement about how much detail you want; why something\n\t * broke is not detail, and a red dot with no explanation was the one thing\n\t * the folded views got wrong.\n\t */\n\tprivate shouldShowBody(): boolean {\n\t\treturn this.view === \"full\" || this.revealed || this.result?.isError === true;\n\t}\n\n\t/**\n\t * Whether this block draws its radar signal line instead of the tool's own\n\t * call renderer. A revealed block leaves radar for as long as it is open, so\n\t * \"expand\" means the same thing in every view.\n\t */\n\tprivate shouldShowSignalLine(): boolean {\n\t\treturn this.view === \"radar\" && !this.revealed;\n\t}\n\n\t/**\n\t * A failure's body under a radar row hangs off the row; anywhere else it sits\n\t * directly under its own call line and needs no extra indent.\n\t */\n\tprivate indentUnderSignalRow(component: Component): Component {\n\t\treturn this.shouldShowSignalLine() ? new IndentAll(component, 3) : component;\n\t}\n\n\tprivate getSignalComponent(): ToolSignalComponent {\n\t\tconst input = {\n\t\t\ttoolName: this.toolName,\n\t\t\targs: this.args,\n\t\t\tcwd: this.cwd,\n\t\t\tresult: this.result,\n\t\t\tisPartial: this.isPartial,\n\t\t\tshowImages: this.showImages,\n\t\t};\n\t\tif (this.signalComponent) {\n\t\t\tthis.signalComponent.setInput(input);\n\t\t} else {\n\t\t\tthis.signalComponent = new ToolSignalComponent(input);\n\t\t}\n\t\treturn this.signalComponent;\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\t// A frozen block has released the state updateDisplay would rebuild from;\n\t\t// its captured snapshot is authoritative, so skip the rebuild entirely.\n\t\tif (this.frozen) return;\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\t/**\n\t * True when this block is a finished, visible tool result that still holds its\n\t * heavy source payloads — i.e. a candidate for freeze() once it scrolls out of\n\t * the live window. In-flight (partial) and already-frozen blocks are excluded.\n\t */\n\tisFreezable(): boolean {\n\t\treturn !this.frozen && !this.isPartial && !this.hideComponent && !!this.result;\n\t}\n\n\t/** Mark this block for freezing; the snapshot is captured on the next render\n\t * (at the real render width) and the heavy state released then. */\n\tfreeze(): void {\n\t\tif (this.isFreezable()) this.frozen = true;\n\t}\n\n\tprivate releaseHeavyState(): void {\n\t\tthis.result = undefined;\n\t\tthis.convertedImages.clear();\n\t\tthis.imageComponents = [];\n\t\tthis.imageSpacers = [];\n\t\tthis.rendererState = {};\n\t\tthis.callRendererComponent = undefined;\n\t\tthis.resultRendererComponent = undefined;\n\t\t// Drop child components so their line caches (which embed base64 image\n\t\t// payloads and full text output) become collectable.\n\t\tthis.clear();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\t\tif (this.frozenLines) {\n\t\t\t// Captured snapshot. Wider (or equal) terminal: emit as-is. Narrower:\n\t\t\t// re-truncate non-image lines to avoid the TUI's over-width crash guard,\n\t\t\t// caching the result per width so it stays O(1) on unchanged frames.\n\t\t\tif (width >= this.frozenWidth) return this.frozenLines;\n\t\t\tif (this.frozenTruncatedWidth === width && this.frozenTruncated) return this.frozenTruncated;\n\t\t\tthis.frozenTruncated = this.frozenLines.map((line) =>\n\t\t\t\tisImageLine(line) || visibleWidth(line) <= width ? line : truncateToWidth(line, width),\n\t\t\t);\n\t\t\tthis.frozenTruncatedWidth = width;\n\t\t\treturn this.frozenTruncated;\n\t\t}\n\t\tconst lines = super.render(width);\n\t\tif (this.frozen) {\n\t\t\tthis.frozenLines = lines;\n\t\t\tthis.frozenWidth = width;\n\t\t\tthis.releaseHeavyState();\n\t\t}\n\t\treturn lines;\n\t}\n\n\t/**\n\t * The container this block renders into.\n\t *\n\t * A self-rendering tool (`edit` draws its own framed diff) normally gets the\n\t * bare container so its frame can use the full width; everything else gets\n\t * the padded box. That only matters while the body is on screen. With the\n\t * body folded away the block is a single line, and the unpadded container\n\t * put it one column left of every other row — invisible while `peek` was an\n\t * opt-in, glaring now that `glance` is the default. So: padded box whenever\n\t * nothing is expanded, which also gives radar the uniform rows it exists for.\n\t */\n\tprivate activeShell(): Box | Container {\n\t\tif (!this.shouldShowBody()) return this.contentBox;\n\t\treturn this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t}\n\n\t/** Swap the attached shell when the view changes which one applies. */\n\tprivate syncShellChild(): void {\n\t\tconst wanted = this.activeShell();\n\t\tconst other = wanted === this.contentBox ? this.selfRenderContainer : this.contentBox;\n\t\tif (this.children.includes(wanted)) return;\n\t\tthis.removeChild(other);\n\t\tother.clear();\n\t\tthis.addChild(wanted);\n\t}\n\n\tprivate updateDisplay(): void {\n\t\t// Frozen blocks are immutable snapshots with their source state released.\n\t\tif (this.frozen) return;\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tthis.leadingSpacer.setLines(this.shouldShowSignalLine() ? 0 : 1);\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.syncShellChild();\n\t\t\tconst renderContainer = this.activeShell();\n\t\t\t// Boxless: no background fill on the container.\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(undefined);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\t// Status dot prefix: green for complete success, yellow for pending/partial, red for error.\n\t\t\t// The dot is prepended to the first line of the call renderer so it stays inline\n\t\t\t// (adding it as a separate child would stack it on its own line).\n\t\t\tconst dotColor = this.result?.isError ? \"error\" : this.isPartial ? \"warning\" : \"success\";\n\t\t\t// No disclosure caret. It is a click-target idiom in a TUI with no\n\t\t\t// pointer, it cost two columns on every row for an action that could\n\t\t\t// only ever be reached by keyboard, and reading it as \"this row opens\"\n\t\t\t// set an expectation the view does not meet.\n\t\t\tconst dot = theme.fg(dotColor, \"● \");\n\n\t\t\t// Radar replaces the tool's own call renderer with the uniform signal\n\t\t\t// row, so a screen of mixed tools lines up into one readable map.\n\t\t\tif (this.shouldShowSignalLine()) {\n\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, this.getSignalComponent()));\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\t\tif (!callRenderer) {\n\t\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, this.createCallFallback()));\n\t\t\t\t\thasContent = true;\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, component));\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.callRendererComponent = undefined;\n\t\t\t\t\t\trenderContainer.addChild(new PrefixFirstLine(dot, this.createCallFallback()));\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result && this.shouldShowBody()) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(this.indentUnderSignalRow(component));\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(this.indentUnderSignalRow(component));\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.resultRendererComponent = undefined;\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Boxless: no background fill.\n\t\t\tthis.contentText.setCustomBgFn(undefined);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result && !this.shouldShowSignalLine()) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tconst dotColor = this.result?.isError ? \"error\" : this.isPartial ? \"warning\" : \"success\";\n\t\t// A tool with no renderer still gets a radar row, just without the\n\t\t// flush-right signal column (this path has no width to align against).\n\t\tif (this.shouldShowSignalLine()) {\n\t\t\tconst subject = toolSubject(this.args, this.cwd);\n\t\t\treturn (\n\t\t\t\ttheme.fg(dotColor, \"● \") +\n\t\t\t\ttheme.fg(\"toolTitle\", theme.bold(this.toolName)) +\n\t\t\t\t(subject ? ` ${theme.fg(\"toolOutput\", subject)}` : \"\")\n\t\t\t);\n\t\t}\n\t\tlet text = theme.fg(dotColor, \"● \") + theme.fg(\"toolTitle\", theme.bold(this.toolName));\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.shouldShowBody() ? this.getTextOutput() : \"\";\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
|