@kolisachint/hoocode-agent 0.4.23 → 0.4.25
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 +28 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +13 -4
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +41 -3
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +23 -0
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +48 -11
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-health.d.ts +36 -0
- package/dist/core/provider-health.d.ts.map +1 -0
- package/dist/core/provider-health.js +54 -0
- package/dist/core/provider-health.js.map +1 -0
- package/dist/core/resource-loader.d.ts +5 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +40 -5
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-defaults.d.ts +1 -0
- package/dist/core/settings-defaults.d.ts.map +1 -1
- package/dist/core/settings-defaults.js +1 -0
- package/dist/core/settings-defaults.js.map +1 -1
- package/dist/core/settings-manager.d.ts +4 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +14 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/subagent-pool.d.ts +6 -0
- package/dist/core/subagent-pool.d.ts.map +1 -1
- package/dist/core/subagent-pool.js +28 -0
- package/dist/core/subagent-pool.js.map +1 -1
- package/dist/core/subagent-result.d.ts.map +1 -1
- package/dist/core/subagent-result.js +32 -2
- package/dist/core/subagent-result.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +1 -1
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/subagent.d.ts +1 -1
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +27 -1
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/extensions/core/hoo-core.d.ts.map +1 -1
- package/dist/extensions/core/hoo-core.js +4 -1
- package/dist/extensions/core/hoo-core.js.map +1 -1
- package/dist/init-templates.generated.d.ts.map +1 -1
- package/dist/init-templates.generated.js +1 -1
- package/dist/init-templates.generated.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +4 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/command-executor.d.ts +64 -0
- package/dist/modes/interactive/command-executor.d.ts.map +1 -0
- package/dist/modes/interactive/command-executor.js +547 -0
- package/dist/modes/interactive/command-executor.js.map +1 -0
- package/dist/modes/interactive/components/ask-options.d.ts.map +1 -1
- package/dist/modes/interactive/components/ask-options.js +2 -0
- package/dist/modes/interactive/components/ask-options.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +9 -20
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +86 -552
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/prompt-templates.md +34 -2
- 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/examples/sdk/08-prompt-templates.ts +1 -0
- package/package.json +4 -4
- package/templates/agents/general-purpose.md +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask-options.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EACN,KAAK,SAAS,EACd,KAAK,SAAS,EAMd,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAGrE,qBAAa,mBAAoB,YAAW,SAAS,EAAE,SAAS;IAC/D,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,gBAAgB,CAAa;IAErC,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IAED,YAAY,SAAS,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,EAIhG;IAED,UAAU,IAAI,IAAI,CAAG;IAErB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,WAAW;IAgBnB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"ask-options.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EACN,KAAK,SAAS,EACd,KAAK,SAAS,EAMd,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAGrE,qBAAa,mBAAoB,YAAW,SAAS,EAAE,SAAS;IAC/D,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,gBAAgB,CAAa;IAErC,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IAED,YAAY,SAAS,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,EAIhG;IAED,UAAU,IAAI,IAAI,CAAG;IAErB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,WAAW;IAgBnB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAmE9B;IAED,OAAO,CAAC,OAAO;IAmBf,OAAO,CAAC,IAAI;IAOZ,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CA0C9B;CACD","sourcesContent":["/**\n * Options pane — the agent asking the USER for a decision before it acts.\n *\n * Rendered inline in the transcript (never a modal), in the same boxless\n * language as the other selectors: blue rules top & bottom, a cyan\n * \"INPUT NEEDED\" label, and the active row marked with the accent cursor.\n *\n * One decision per step:\n * - tui.select.up / down move between options (wraps)\n * - tui.select.next (→) confirm the highlighted option and advance; on the\n * last step it submits every answer\n * - tui.select.back (←) step back to the previous decision\n * - 1-9 quick-pick an option\n * - drop onto the custom row and type a free-form answer when none fit\n * - tui.select.cancel (esc) skips the whole sequence\n *\n * Answered steps stay on screen as a deterministic breadcrumb so you always\n * see what you've already committed to.\n */\n\nimport {\n\ttype Component,\n\ttype Focusable,\n\tgetKeybindings,\n\tInput,\n\ttype Keybinding,\n\ttruncateToWidth,\n\tvisibleWidth,\n} from \"@kolisachint/hoocode-tui\";\nimport type { AskQuestion } from \"../../../core/extensions/types.js\";\nimport { theme } from \"../theme/theme.js\";\n\nexport class AskOptionsComponent implements Component, Focusable {\n\tprivate questions: AskQuestion[];\n\tprivate step = 0;\n\tprivate index = 0;\n\tprivate answers: string[] = [];\n\tprivate customInput = new Input();\n\tprivate onSubmitCallback: (answers: string[]) => void;\n\tprivate onCancelCallback: () => void;\n\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.customInput.focused = value;\n\t}\n\n\tconstructor(questions: AskQuestion[], onSubmit: (answers: string[]) => void, onCancel: () => void) {\n\t\tthis.questions = questions;\n\t\tthis.onSubmitCallback = onSubmit;\n\t\tthis.onCancelCallback = onCancel;\n\t}\n\n\tinvalidate(): void {}\n\n\tprivate rowCount(q: AskQuestion): number {\n\t\treturn q.options.length + (q.allowCustom ? 1 : 0);\n\t}\n\n\tprivate isOnCustomRow(q: AskQuestion): boolean {\n\t\treturn !!q.allowCustom && this.index === q.options.length;\n\t}\n\n\tprivate spread(left: string, right: string, width: number): string {\n\t\tconst gap = Math.max(1, width - visibleWidth(left) - visibleWidth(right));\n\t\treturn truncateToWidth(`${left}${\" \".repeat(gap)}${right}`, width, \"\");\n\t}\n\n\tprivate renderHints(last: boolean): string {\n\t\tconst kb = getKeybindings();\n\t\tconst sep = theme.fg(\"muted\", \" · \");\n\t\tconst hint = (keys: string, desc: string) => theme.fg(\"dim\", keys) + theme.fg(\"muted\", ` ${desc}`);\n\t\tconst upDown = `${kb.getKeys(\"tui.select.up\").join(\"/\")}/${kb.getKeys(\"tui.select.down\").join(\"/\")}`;\n\t\tconst parts = [\n\t\t\thint(upDown, \"move\"),\n\t\t\thint(kb.getKeys(\"app.options.next\" as Keybinding).join(\"/\"), last ? \"submit\" : \"next\"),\n\t\t];\n\t\tif (this.step > 0) {\n\t\t\tparts.push(hint(kb.getKeys(\"app.options.back\" as Keybinding).join(\"/\"), \"back\"));\n\t\t}\n\t\tparts.push(hint(kb.getKeys(\"tui.select.cancel\").join(\"/\"), \"skip\"));\n\t\treturn parts.join(sep);\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst rule = theme.fg(\"borderAccent\", \"─\".repeat(Math.max(1, width)));\n\t\tconst cur = this.questions[this.step];\n\t\tconst last = this.step === this.questions.length - 1;\n\n\t\tlines.push(rule);\n\n\t\t// Header: \"INPUT NEEDED\" on the left, key hints on the right.\n\t\tconst title = theme.bold(theme.fg(\"borderAccent\", \"INPUT NEEDED\"));\n\t\tlines.push(this.spread(title, this.renderHints(last), width));\n\n\t\t// Answered-step breadcrumb.\n\t\tfor (let i = 0; i < this.step; i++) {\n\t\t\tconst q = this.questions[i];\n\t\t\tconst check = theme.fg(\"success\", \"✓\");\n\t\t\tconst label = theme.fg(\"dim\", q.short ?? q.question);\n\t\t\tconst arrow = theme.fg(\"dim\", \"→ \");\n\t\t\tconst answer = theme.fg(\"accent\", this.answers[i] ?? \"\");\n\t\t\tlines.push(truncateToWidth(`${check} ${label} ${arrow}${answer}`, width, \"...\"));\n\t\t}\n\t\tif (this.step > 0) lines.push(\"\");\n\n\t\t// Current question.\n\t\tconst stepLabel = theme.fg(\"dim\", `${this.step + 1}/${this.questions.length}`);\n\t\tlines.push(truncateToWidth(`${stepLabel} ${theme.bold(cur.question)}`, width, \"...\"));\n\t\tif (cur.detail) lines.push(truncateToWidth(theme.fg(\"muted\", ` ${cur.detail}`), width, \"...\"));\n\t\tlines.push(\"\");\n\n\t\t// Options.\n\t\tfor (let i = 0; i < cur.options.length; i++) {\n\t\t\tconst o = cur.options[i];\n\t\t\tconst active = i === this.index;\n\t\t\tconst cursor = theme.fg(\"accent\", active ? \">\" : \" \");\n\t\t\tconst num = theme.fg(active ? \"accent\" : \"dim\", String(i + 1));\n\t\t\tconst label = active ? theme.bold(o.label) : o.label;\n\t\t\tlet line = `${cursor} ${num} ${label}`;\n\t\t\tif (o.recommended) line += theme.fg(\"success\", \" (recommended)\");\n\t\t\tif (o.description) line += theme.fg(\"muted\", ` ${o.description}`);\n\t\t\tlines.push(truncateToWidth(line, width, \"...\"));\n\t\t}\n\n\t\t// Custom row.\n\t\tif (cur.allowCustom) {\n\t\t\tconst customIndex = cur.options.length;\n\t\t\tconst active = this.index === customIndex;\n\t\t\tconst cursor = theme.fg(\"accent\", active ? \">\" : \" \");\n\t\t\tconst plus = theme.fg(active ? \"accent\" : \"dim\", \"+\");\n\t\t\tif (active) {\n\t\t\t\tconst value = this.customInput.getValue();\n\t\t\t\tconst prompt = theme.fg(\"accent\", \">\");\n\t\t\t\tconst caret = this._focused ? theme.fg(\"accent\", \"▏\") : \"\";\n\t\t\t\tconst body = value\n\t\t\t\t\t? `${theme.fg(\"text\", value)}${caret}`\n\t\t\t\t\t: `${caret}${theme.fg(\"dim\", \"type your own answer\")}`;\n\t\t\t\tlines.push(truncateToWidth(`${cursor} ${plus} ${prompt} ${body}`, width, \"...\"));\n\t\t\t} else {\n\t\t\t\tconst label = theme.fg(\"muted\", \"custom answer\");\n\t\t\t\tconst desc = theme.fg(\"dim\", \"type your own\");\n\t\t\t\tlines.push(truncateToWidth(`${cursor} ${plus} ${label} ${desc}`, width, \"...\"));\n\t\t\t}\n\t\t}\n\n\t\t// Count.\n\t\tlines.push(theme.fg(\"dim\", `(${this.index + 1}/${this.rowCount(cur)})`));\n\t\tlines.push(rule);\n\t\treturn lines;\n\t}\n\n\tprivate confirm(): void {\n\t\tconst cur = this.questions[this.step];\n\t\tlet value: string;\n\t\tif (this.isOnCustomRow(cur)) {\n\t\t\tvalue = this.customInput.getValue().trim();\n\t\t\tif (!value) return; // can't submit an empty custom answer\n\t\t} else {\n\t\t\tvalue = cur.options[this.index].label;\n\t\t}\n\t\tthis.answers[this.step] = value;\n\t\tif (this.step < this.questions.length - 1) {\n\t\t\tthis.step += 1;\n\t\t\tthis.index = 0;\n\t\t\tthis.customInput.setValue(\"\");\n\t\t} else {\n\t\t\tthis.onSubmitCallback(this.answers.slice());\n\t\t}\n\t}\n\n\tprivate back(): void {\n\t\tif (this.step === 0) return;\n\t\tthis.step -= 1;\n\t\tthis.index = 0;\n\t\tthis.customInput.setValue(\"\");\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\t\tconst cur = this.questions[this.step];\n\t\tconst rows = this.rowCount(cur);\n\t\tconst onCustom = this.isOnCustomRow(cur);\n\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tthis.index = this.index === 0 ? rows - 1 : this.index - 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tthis.index = this.index === rows - 1 ? 0 : this.index + 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"app.options.back\" as Keybinding)) {\n\t\t\tthis.back();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"app.options.next\" as Keybinding) || kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tthis.confirm();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t\treturn;\n\t\t}\n\n\t\tif (onCustom) {\n\t\t\t// Delegate free-form typing (insert, backspace, paste, word-delete)\n\t\t\t// to a hidden Input buffer; the value is rendered inline above.\n\t\t\tthis.customInput.handleInput(data);\n\t\t\treturn;\n\t\t}\n\n\t\t// Number quick-pick for the listed options (not the custom row).\n\t\tif (/^[1-9]$/.test(data)) {\n\t\t\tconst n = Number(data) - 1;\n\t\t\tif (n < cur.options.length) {\n\t\t\t\tthis.index = n;\n\t\t\t\tthis.confirm();\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -100,6 +100,8 @@ export class AskOptionsComponent {
|
|
|
100
100
|
const num = theme.fg(active ? "accent" : "dim", String(i + 1));
|
|
101
101
|
const label = active ? theme.bold(o.label) : o.label;
|
|
102
102
|
let line = `${cursor} ${num} ${label}`;
|
|
103
|
+
if (o.recommended)
|
|
104
|
+
line += theme.fg("success", " (recommended)");
|
|
103
105
|
if (o.description)
|
|
104
106
|
line += theme.fg("muted", ` ${o.description}`);
|
|
105
107
|
lines.push(truncateToWidth(line, width, "..."));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask-options.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-options.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Options pane — the agent asking the USER for a decision before it acts.\n *\n * Rendered inline in the transcript (never a modal), in the same boxless\n * language as the other selectors: blue rules top & bottom, a cyan\n * \"INPUT NEEDED\" label, and the active row marked with the accent cursor.\n *\n * One decision per step:\n * - tui.select.up / down move between options (wraps)\n * - tui.select.next (→) confirm the highlighted option and advance; on the\n * last step it submits every answer\n * - tui.select.back (←) step back to the previous decision\n * - 1-9 quick-pick an option\n * - drop onto the custom row and type a free-form answer when none fit\n * - tui.select.cancel (esc) skips the whole sequence\n *\n * Answered steps stay on screen as a deterministic breadcrumb so you always\n * see what you've already committed to.\n */\n\nimport {\n\ttype Component,\n\ttype Focusable,\n\tgetKeybindings,\n\tInput,\n\ttype Keybinding,\n\ttruncateToWidth,\n\tvisibleWidth,\n} from \"@kolisachint/hoocode-tui\";\nimport type { AskQuestion } from \"../../../core/extensions/types.js\";\nimport { theme } from \"../theme/theme.js\";\n\nexport class AskOptionsComponent implements Component, Focusable {\n\tprivate questions: AskQuestion[];\n\tprivate step = 0;\n\tprivate index = 0;\n\tprivate answers: string[] = [];\n\tprivate customInput = new Input();\n\tprivate onSubmitCallback: (answers: string[]) => void;\n\tprivate onCancelCallback: () => void;\n\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.customInput.focused = value;\n\t}\n\n\tconstructor(questions: AskQuestion[], onSubmit: (answers: string[]) => void, onCancel: () => void) {\n\t\tthis.questions = questions;\n\t\tthis.onSubmitCallback = onSubmit;\n\t\tthis.onCancelCallback = onCancel;\n\t}\n\n\tinvalidate(): void {}\n\n\tprivate rowCount(q: AskQuestion): number {\n\t\treturn q.options.length + (q.allowCustom ? 1 : 0);\n\t}\n\n\tprivate isOnCustomRow(q: AskQuestion): boolean {\n\t\treturn !!q.allowCustom && this.index === q.options.length;\n\t}\n\n\tprivate spread(left: string, right: string, width: number): string {\n\t\tconst gap = Math.max(1, width - visibleWidth(left) - visibleWidth(right));\n\t\treturn truncateToWidth(`${left}${\" \".repeat(gap)}${right}`, width, \"\");\n\t}\n\n\tprivate renderHints(last: boolean): string {\n\t\tconst kb = getKeybindings();\n\t\tconst sep = theme.fg(\"muted\", \" · \");\n\t\tconst hint = (keys: string, desc: string) => theme.fg(\"dim\", keys) + theme.fg(\"muted\", ` ${desc}`);\n\t\tconst upDown = `${kb.getKeys(\"tui.select.up\").join(\"/\")}/${kb.getKeys(\"tui.select.down\").join(\"/\")}`;\n\t\tconst parts = [\n\t\t\thint(upDown, \"move\"),\n\t\t\thint(kb.getKeys(\"app.options.next\" as Keybinding).join(\"/\"), last ? \"submit\" : \"next\"),\n\t\t];\n\t\tif (this.step > 0) {\n\t\t\tparts.push(hint(kb.getKeys(\"app.options.back\" as Keybinding).join(\"/\"), \"back\"));\n\t\t}\n\t\tparts.push(hint(kb.getKeys(\"tui.select.cancel\").join(\"/\"), \"skip\"));\n\t\treturn parts.join(sep);\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst rule = theme.fg(\"borderAccent\", \"─\".repeat(Math.max(1, width)));\n\t\tconst cur = this.questions[this.step];\n\t\tconst last = this.step === this.questions.length - 1;\n\n\t\tlines.push(rule);\n\n\t\t// Header: \"INPUT NEEDED\" on the left, key hints on the right.\n\t\tconst title = theme.bold(theme.fg(\"borderAccent\", \"INPUT NEEDED\"));\n\t\tlines.push(this.spread(title, this.renderHints(last), width));\n\n\t\t// Answered-step breadcrumb.\n\t\tfor (let i = 0; i < this.step; i++) {\n\t\t\tconst q = this.questions[i];\n\t\t\tconst check = theme.fg(\"success\", \"✓\");\n\t\t\tconst label = theme.fg(\"dim\", q.short ?? q.question);\n\t\t\tconst arrow = theme.fg(\"dim\", \"→ \");\n\t\t\tconst answer = theme.fg(\"accent\", this.answers[i] ?? \"\");\n\t\t\tlines.push(truncateToWidth(`${check} ${label} ${arrow}${answer}`, width, \"...\"));\n\t\t}\n\t\tif (this.step > 0) lines.push(\"\");\n\n\t\t// Current question.\n\t\tconst stepLabel = theme.fg(\"dim\", `${this.step + 1}/${this.questions.length}`);\n\t\tlines.push(truncateToWidth(`${stepLabel} ${theme.bold(cur.question)}`, width, \"...\"));\n\t\tif (cur.detail) lines.push(truncateToWidth(theme.fg(\"muted\", ` ${cur.detail}`), width, \"...\"));\n\t\tlines.push(\"\");\n\n\t\t// Options.\n\t\tfor (let i = 0; i < cur.options.length; i++) {\n\t\t\tconst o = cur.options[i];\n\t\t\tconst active = i === this.index;\n\t\t\tconst cursor = theme.fg(\"accent\", active ? \">\" : \" \");\n\t\t\tconst num = theme.fg(active ? \"accent\" : \"dim\", String(i + 1));\n\t\t\tconst label = active ? theme.bold(o.label) : o.label;\n\t\t\tlet line = `${cursor} ${num} ${label}`;\n\t\t\tif (o.description) line += theme.fg(\"muted\", ` ${o.description}`);\n\t\t\tlines.push(truncateToWidth(line, width, \"...\"));\n\t\t}\n\n\t\t// Custom row.\n\t\tif (cur.allowCustom) {\n\t\t\tconst customIndex = cur.options.length;\n\t\t\tconst active = this.index === customIndex;\n\t\t\tconst cursor = theme.fg(\"accent\", active ? \">\" : \" \");\n\t\t\tconst plus = theme.fg(active ? \"accent\" : \"dim\", \"+\");\n\t\t\tif (active) {\n\t\t\t\tconst value = this.customInput.getValue();\n\t\t\t\tconst prompt = theme.fg(\"accent\", \">\");\n\t\t\t\tconst caret = this._focused ? theme.fg(\"accent\", \"▏\") : \"\";\n\t\t\t\tconst body = value\n\t\t\t\t\t? `${theme.fg(\"text\", value)}${caret}`\n\t\t\t\t\t: `${caret}${theme.fg(\"dim\", \"type your own answer\")}`;\n\t\t\t\tlines.push(truncateToWidth(`${cursor} ${plus} ${prompt} ${body}`, width, \"...\"));\n\t\t\t} else {\n\t\t\t\tconst label = theme.fg(\"muted\", \"custom answer\");\n\t\t\t\tconst desc = theme.fg(\"dim\", \"type your own\");\n\t\t\t\tlines.push(truncateToWidth(`${cursor} ${plus} ${label} ${desc}`, width, \"...\"));\n\t\t\t}\n\t\t}\n\n\t\t// Count.\n\t\tlines.push(theme.fg(\"dim\", `(${this.index + 1}/${this.rowCount(cur)})`));\n\t\tlines.push(rule);\n\t\treturn lines;\n\t}\n\n\tprivate confirm(): void {\n\t\tconst cur = this.questions[this.step];\n\t\tlet value: string;\n\t\tif (this.isOnCustomRow(cur)) {\n\t\t\tvalue = this.customInput.getValue().trim();\n\t\t\tif (!value) return; // can't submit an empty custom answer\n\t\t} else {\n\t\t\tvalue = cur.options[this.index].label;\n\t\t}\n\t\tthis.answers[this.step] = value;\n\t\tif (this.step < this.questions.length - 1) {\n\t\t\tthis.step += 1;\n\t\t\tthis.index = 0;\n\t\t\tthis.customInput.setValue(\"\");\n\t\t} else {\n\t\t\tthis.onSubmitCallback(this.answers.slice());\n\t\t}\n\t}\n\n\tprivate back(): void {\n\t\tif (this.step === 0) return;\n\t\tthis.step -= 1;\n\t\tthis.index = 0;\n\t\tthis.customInput.setValue(\"\");\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\t\tconst cur = this.questions[this.step];\n\t\tconst rows = this.rowCount(cur);\n\t\tconst onCustom = this.isOnCustomRow(cur);\n\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tthis.index = this.index === 0 ? rows - 1 : this.index - 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tthis.index = this.index === rows - 1 ? 0 : this.index + 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"app.options.back\" as Keybinding)) {\n\t\t\tthis.back();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"app.options.next\" as Keybinding) || kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tthis.confirm();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t\treturn;\n\t\t}\n\n\t\tif (onCustom) {\n\t\t\t// Delegate free-form typing (insert, backspace, paste, word-delete)\n\t\t\t// to a hidden Input buffer; the value is rendered inline above.\n\t\t\tthis.customInput.handleInput(data);\n\t\t\treturn;\n\t\t}\n\n\t\t// Number quick-pick for the listed options (not the custom row).\n\t\tif (/^[1-9]$/.test(data)) {\n\t\t\tconst n = Number(data) - 1;\n\t\t\tif (n < cur.options.length) {\n\t\t\t\tthis.index = n;\n\t\t\t\tthis.confirm();\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ask-options.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-options.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Options pane — the agent asking the USER for a decision before it acts.\n *\n * Rendered inline in the transcript (never a modal), in the same boxless\n * language as the other selectors: blue rules top & bottom, a cyan\n * \"INPUT NEEDED\" label, and the active row marked with the accent cursor.\n *\n * One decision per step:\n * - tui.select.up / down move between options (wraps)\n * - tui.select.next (→) confirm the highlighted option and advance; on the\n * last step it submits every answer\n * - tui.select.back (←) step back to the previous decision\n * - 1-9 quick-pick an option\n * - drop onto the custom row and type a free-form answer when none fit\n * - tui.select.cancel (esc) skips the whole sequence\n *\n * Answered steps stay on screen as a deterministic breadcrumb so you always\n * see what you've already committed to.\n */\n\nimport {\n\ttype Component,\n\ttype Focusable,\n\tgetKeybindings,\n\tInput,\n\ttype Keybinding,\n\ttruncateToWidth,\n\tvisibleWidth,\n} from \"@kolisachint/hoocode-tui\";\nimport type { AskQuestion } from \"../../../core/extensions/types.js\";\nimport { theme } from \"../theme/theme.js\";\n\nexport class AskOptionsComponent implements Component, Focusable {\n\tprivate questions: AskQuestion[];\n\tprivate step = 0;\n\tprivate index = 0;\n\tprivate answers: string[] = [];\n\tprivate customInput = new Input();\n\tprivate onSubmitCallback: (answers: string[]) => void;\n\tprivate onCancelCallback: () => void;\n\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.customInput.focused = value;\n\t}\n\n\tconstructor(questions: AskQuestion[], onSubmit: (answers: string[]) => void, onCancel: () => void) {\n\t\tthis.questions = questions;\n\t\tthis.onSubmitCallback = onSubmit;\n\t\tthis.onCancelCallback = onCancel;\n\t}\n\n\tinvalidate(): void {}\n\n\tprivate rowCount(q: AskQuestion): number {\n\t\treturn q.options.length + (q.allowCustom ? 1 : 0);\n\t}\n\n\tprivate isOnCustomRow(q: AskQuestion): boolean {\n\t\treturn !!q.allowCustom && this.index === q.options.length;\n\t}\n\n\tprivate spread(left: string, right: string, width: number): string {\n\t\tconst gap = Math.max(1, width - visibleWidth(left) - visibleWidth(right));\n\t\treturn truncateToWidth(`${left}${\" \".repeat(gap)}${right}`, width, \"\");\n\t}\n\n\tprivate renderHints(last: boolean): string {\n\t\tconst kb = getKeybindings();\n\t\tconst sep = theme.fg(\"muted\", \" · \");\n\t\tconst hint = (keys: string, desc: string) => theme.fg(\"dim\", keys) + theme.fg(\"muted\", ` ${desc}`);\n\t\tconst upDown = `${kb.getKeys(\"tui.select.up\").join(\"/\")}/${kb.getKeys(\"tui.select.down\").join(\"/\")}`;\n\t\tconst parts = [\n\t\t\thint(upDown, \"move\"),\n\t\t\thint(kb.getKeys(\"app.options.next\" as Keybinding).join(\"/\"), last ? \"submit\" : \"next\"),\n\t\t];\n\t\tif (this.step > 0) {\n\t\t\tparts.push(hint(kb.getKeys(\"app.options.back\" as Keybinding).join(\"/\"), \"back\"));\n\t\t}\n\t\tparts.push(hint(kb.getKeys(\"tui.select.cancel\").join(\"/\"), \"skip\"));\n\t\treturn parts.join(sep);\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst rule = theme.fg(\"borderAccent\", \"─\".repeat(Math.max(1, width)));\n\t\tconst cur = this.questions[this.step];\n\t\tconst last = this.step === this.questions.length - 1;\n\n\t\tlines.push(rule);\n\n\t\t// Header: \"INPUT NEEDED\" on the left, key hints on the right.\n\t\tconst title = theme.bold(theme.fg(\"borderAccent\", \"INPUT NEEDED\"));\n\t\tlines.push(this.spread(title, this.renderHints(last), width));\n\n\t\t// Answered-step breadcrumb.\n\t\tfor (let i = 0; i < this.step; i++) {\n\t\t\tconst q = this.questions[i];\n\t\t\tconst check = theme.fg(\"success\", \"✓\");\n\t\t\tconst label = theme.fg(\"dim\", q.short ?? q.question);\n\t\t\tconst arrow = theme.fg(\"dim\", \"→ \");\n\t\t\tconst answer = theme.fg(\"accent\", this.answers[i] ?? \"\");\n\t\t\tlines.push(truncateToWidth(`${check} ${label} ${arrow}${answer}`, width, \"...\"));\n\t\t}\n\t\tif (this.step > 0) lines.push(\"\");\n\n\t\t// Current question.\n\t\tconst stepLabel = theme.fg(\"dim\", `${this.step + 1}/${this.questions.length}`);\n\t\tlines.push(truncateToWidth(`${stepLabel} ${theme.bold(cur.question)}`, width, \"...\"));\n\t\tif (cur.detail) lines.push(truncateToWidth(theme.fg(\"muted\", ` ${cur.detail}`), width, \"...\"));\n\t\tlines.push(\"\");\n\n\t\t// Options.\n\t\tfor (let i = 0; i < cur.options.length; i++) {\n\t\t\tconst o = cur.options[i];\n\t\t\tconst active = i === this.index;\n\t\t\tconst cursor = theme.fg(\"accent\", active ? \">\" : \" \");\n\t\t\tconst num = theme.fg(active ? \"accent\" : \"dim\", String(i + 1));\n\t\t\tconst label = active ? theme.bold(o.label) : o.label;\n\t\t\tlet line = `${cursor} ${num} ${label}`;\n\t\t\tif (o.recommended) line += theme.fg(\"success\", \" (recommended)\");\n\t\t\tif (o.description) line += theme.fg(\"muted\", ` ${o.description}`);\n\t\t\tlines.push(truncateToWidth(line, width, \"...\"));\n\t\t}\n\n\t\t// Custom row.\n\t\tif (cur.allowCustom) {\n\t\t\tconst customIndex = cur.options.length;\n\t\t\tconst active = this.index === customIndex;\n\t\t\tconst cursor = theme.fg(\"accent\", active ? \">\" : \" \");\n\t\t\tconst plus = theme.fg(active ? \"accent\" : \"dim\", \"+\");\n\t\t\tif (active) {\n\t\t\t\tconst value = this.customInput.getValue();\n\t\t\t\tconst prompt = theme.fg(\"accent\", \">\");\n\t\t\t\tconst caret = this._focused ? theme.fg(\"accent\", \"▏\") : \"\";\n\t\t\t\tconst body = value\n\t\t\t\t\t? `${theme.fg(\"text\", value)}${caret}`\n\t\t\t\t\t: `${caret}${theme.fg(\"dim\", \"type your own answer\")}`;\n\t\t\t\tlines.push(truncateToWidth(`${cursor} ${plus} ${prompt} ${body}`, width, \"...\"));\n\t\t\t} else {\n\t\t\t\tconst label = theme.fg(\"muted\", \"custom answer\");\n\t\t\t\tconst desc = theme.fg(\"dim\", \"type your own\");\n\t\t\t\tlines.push(truncateToWidth(`${cursor} ${plus} ${label} ${desc}`, width, \"...\"));\n\t\t\t}\n\t\t}\n\n\t\t// Count.\n\t\tlines.push(theme.fg(\"dim\", `(${this.index + 1}/${this.rowCount(cur)})`));\n\t\tlines.push(rule);\n\t\treturn lines;\n\t}\n\n\tprivate confirm(): void {\n\t\tconst cur = this.questions[this.step];\n\t\tlet value: string;\n\t\tif (this.isOnCustomRow(cur)) {\n\t\t\tvalue = this.customInput.getValue().trim();\n\t\t\tif (!value) return; // can't submit an empty custom answer\n\t\t} else {\n\t\t\tvalue = cur.options[this.index].label;\n\t\t}\n\t\tthis.answers[this.step] = value;\n\t\tif (this.step < this.questions.length - 1) {\n\t\t\tthis.step += 1;\n\t\t\tthis.index = 0;\n\t\t\tthis.customInput.setValue(\"\");\n\t\t} else {\n\t\t\tthis.onSubmitCallback(this.answers.slice());\n\t\t}\n\t}\n\n\tprivate back(): void {\n\t\tif (this.step === 0) return;\n\t\tthis.step -= 1;\n\t\tthis.index = 0;\n\t\tthis.customInput.setValue(\"\");\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\t\tconst cur = this.questions[this.step];\n\t\tconst rows = this.rowCount(cur);\n\t\tconst onCustom = this.isOnCustomRow(cur);\n\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tthis.index = this.index === 0 ? rows - 1 : this.index - 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tthis.index = this.index === rows - 1 ? 0 : this.index + 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"app.options.back\" as Keybinding)) {\n\t\t\tthis.back();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"app.options.next\" as Keybinding) || kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tthis.confirm();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t\treturn;\n\t\t}\n\n\t\tif (onCustom) {\n\t\t\t// Delegate free-form typing (insert, backspace, paste, word-delete)\n\t\t\t// to a hidden Input buffer; the value is rendered inline above.\n\t\t\tthis.customInput.handleInput(data);\n\t\t\treturn;\n\t\t}\n\n\t\t// Number quick-pick for the listed options (not the custom row).\n\t\tif (/^[1-9]$/.test(data)) {\n\t\t\tconst n = Number(data) - 1;\n\t\t\tif (n < cur.options.length) {\n\t\t\t\tthis.index = n;\n\t\t\t\tthis.confirm();\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Handles TUI rendering and user interaction, delegating business logic to AgentSession.
|
|
4
4
|
*/
|
|
5
5
|
import { type ImageContent } from "@kolisachint/hoocode-ai";
|
|
6
|
-
import {
|
|
6
|
+
import type { AgentSessionRuntime } from "../../core/agent-session-runtime.js";
|
|
7
7
|
export declare function isApiKeyLoginProvider(providerId: string, oauthProviderIds: ReadonlySet<string>, builtInProviderIds?: ReadonlySet<string>): boolean;
|
|
8
8
|
/**
|
|
9
9
|
* Options for InteractiveMode initialization.
|
|
@@ -90,6 +90,14 @@ export declare class InteractiveMode {
|
|
|
90
90
|
private builtInHeader;
|
|
91
91
|
private customHeader;
|
|
92
92
|
private get session();
|
|
93
|
+
private _commandExecutor?;
|
|
94
|
+
/**
|
|
95
|
+
* Lazily-built command executor. The context uses getters for mutable
|
|
96
|
+
* dependencies (e.g. the active session) so handlers always operate on the
|
|
97
|
+
* current state even after a session switch.
|
|
98
|
+
*/
|
|
99
|
+
private get commandExecutor();
|
|
100
|
+
private stopLoadingAnimation;
|
|
93
101
|
private get agent();
|
|
94
102
|
private get sessionManager();
|
|
95
103
|
private get settingsManager();
|
|
@@ -317,7 +325,6 @@ export declare class InteractiveMode {
|
|
|
317
325
|
*/
|
|
318
326
|
private showSelector;
|
|
319
327
|
private showSettingsSelector;
|
|
320
|
-
private handleModelCommand;
|
|
321
328
|
private findExactModelMatch;
|
|
322
329
|
private getModelCandidates;
|
|
323
330
|
private updateAvailableProviderCount;
|
|
@@ -325,8 +332,6 @@ export declare class InteractiveMode {
|
|
|
325
332
|
private showModelSelector;
|
|
326
333
|
private showModelsSelector;
|
|
327
334
|
private showUserMessageSelector;
|
|
328
|
-
private handleCloneCommand;
|
|
329
|
-
private handleSubagentCommand;
|
|
330
335
|
private showTreeSelector;
|
|
331
336
|
private showSessionSelector;
|
|
332
337
|
private handleResumeSession;
|
|
@@ -341,26 +346,10 @@ export declare class InteractiveMode {
|
|
|
341
346
|
private showOAuthLoginSelect;
|
|
342
347
|
private showLoginDialog;
|
|
343
348
|
private handleReloadCommand;
|
|
344
|
-
private handleExportCommand;
|
|
345
|
-
private getPathCommandArgument;
|
|
346
|
-
private handleImportCommand;
|
|
347
|
-
private handleShareCommand;
|
|
348
|
-
private handleCopyCommand;
|
|
349
|
-
private handleNameCommand;
|
|
350
|
-
private handleSessionCommand;
|
|
351
|
-
private handleChangelogCommand;
|
|
352
349
|
/**
|
|
353
350
|
* Get capitalized display string for an app keybinding action.
|
|
354
351
|
*/
|
|
355
352
|
private getAppKeyDisplay;
|
|
356
|
-
/**
|
|
357
|
-
* Get capitalized display string for an editor keybinding action.
|
|
358
|
-
*/
|
|
359
|
-
private getEditorKeyDisplay;
|
|
360
|
-
private handleHotkeysCommand;
|
|
361
|
-
private handleClearCommand;
|
|
362
|
-
private handleDebugCommand;
|
|
363
|
-
private handleArminSaysHi;
|
|
364
353
|
private handleDaxnuts;
|
|
365
354
|
private checkDaxnutsEasterEgg;
|
|
366
355
|
private handleBashCommand;
|