@dreb/coding-agent 2.70.0 → 2.70.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/core/tools/ask-user.d.ts +7 -3
- package/dist/core/tools/ask-user.d.ts.map +1 -1
- package/dist/core/tools/ask-user.js +69 -17
- package/dist/core/tools/ask-user.js.map +1 -1
- package/dist/core/tools/index.d.ts +7 -3
- package/dist/core/tools/index.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -678,7 +678,7 @@ cat README.md | dreb -p "Summarize this text"
|
|
|
678
678
|
|
|
679
679
|
Available standard tools: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`, `web_search`, `web_fetch`, `subagent`, `wait`, `watch_github_ci`, `ask_user`
|
|
680
680
|
|
|
681
|
-
`ask_user` pauses the turn and asks you one or more structured clarifying questions in a single call — batched together and answered as one wizard. Each question has Markdown-formatted question text, optional 2-4 multiple-choice options (single- or multi-select), and a "type your own answer" field — rendered natively in the TUI and the Dashboard, and over RPC. Submitting sends the whole batch of structured answers back at once; choosing **Stop agent** or pressing `Esc` aborts the whole current turn rather than continuing without an answer. Options must contain nonblank text. When a question has no options its free-text field is always shown, so every question is answerable. Unanswered questions come back flagged as skipped rather than blocking the turn. An optional `timeoutSeconds` auto-stops the turn after the given number of seconds with a live countdown on every surface; recovered Dashboard sessions retain the original deadline rather than restarting it. Tool abort, timeout, host teardown, and headless/no-UI modes settle cleanly, so the agent never deadlocks waiting on an absent user. UI or response-protocol failures remain distinct from question closure. In the TUI: `↑`/`↓` move between questions, their options, and the free-text fields, `Space` toggles a checkbox (multi-select), `Enter` submits the batch, and `Esc` stops the turn. In the Dashboard: native radios/checkboxes plus a text field per question, an in-card **Stop agent** button that remains accessible on mobile, and `Esc` to stop.
|
|
681
|
+
`ask_user` pauses the turn and asks you one or more structured clarifying questions in a single call — batched together and answered as one wizard. Each question has Markdown-formatted question text, optional 2-4 multiple-choice options (single- or multi-select), and a "type your own answer" field — rendered natively in the TUI and the Dashboard, and over RPC. Submitting sends the whole batch of structured answers back at once; choosing **Stop agent** or pressing `Esc` aborts the whole current turn rather than continuing without an answer. Options must contain nonblank text. Options may also be sent as `{label, description}` objects (shown as `label — description`), `header` is accepted in place of a question's `title`, and `questions` may arrive as a JSON-encoded string; all are converted to the standard shape before display. When a question has no options its free-text field is always shown, so every question is answerable. Unanswered questions come back flagged as skipped rather than blocking the turn. An optional `timeoutSeconds` auto-stops the turn after the given number of seconds with a live countdown on every surface; recovered Dashboard sessions retain the original deadline rather than restarting it. Tool abort, timeout, host teardown, and headless/no-UI modes settle cleanly, so the agent never deadlocks waiting on an absent user. UI or response-protocol failures remain distinct from question closure. In the TUI: `↑`/`↓` move between questions, their options, and the free-text fields, `Space` toggles a checkbox (multi-select), `Enter` submits the batch, and `Esc` stops the turn. In the Dashboard: native radios/checkboxes plus a text field per question, an in-card **Stop agent** button that remains accessible on mobile, and `Esc` to stop.
|
|
682
682
|
|
|
683
683
|
Three additional tools are always active and don't need to appear in `--tools`:
|
|
684
684
|
- `search` — semantic codebase search
|
|
@@ -30,14 +30,18 @@ export interface AskUserDetails {
|
|
|
30
30
|
failed?: boolean;
|
|
31
31
|
}
|
|
32
32
|
declare const askUserSchema: import("@sinclair/typebox").TObject<{
|
|
33
|
-
questions: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
33
|
+
questions: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
34
34
|
question: import("@sinclair/typebox").TString;
|
|
35
35
|
title: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
36
|
-
|
|
36
|
+
header: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
37
|
+
options: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TObject<{
|
|
38
|
+
label: import("@sinclair/typebox").TString;
|
|
39
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
40
|
+
}>]>>>;
|
|
37
41
|
allowFreeText: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
38
42
|
multiSelect: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
39
43
|
multiline: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
40
|
-
}
|
|
44
|
+
}>>, import("@sinclair/typebox").TString]>;
|
|
41
45
|
timeoutSeconds: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
42
46
|
}>;
|
|
43
47
|
export type AskUserInput = Static<typeof askUserSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask-user.d.ts","sourceRoot":"","sources":["../../../src/core/tools/ask-user.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAwD,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAKnH,mEAAmE;AACnE,MAAM,WAAW,mBAAmB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC9B,8CAA8C;IAC9C,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,uEAAuE;IACvE,WAAW,EAAE,OAAO,CAAC;IACrB,yDAAyD;IACzD,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAsCD,QAAA,MAAM,aAAa;;;;;;;;;;EAiBjB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAiIxD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,IAAI,cAAc,CAAC,OAAO,aAAa,EAAE,cAAc,GAAG,SAAS,CAAC,CAsE9G","sourcesContent":["/**\n * ask_user tool.\n *\n * Lets the agent pause and ask the user one or more structured clarifying\n * questions in a single call — each with optional multiple-choice options,\n * single- or multi-select, and a \"type your own answer\" free-text field —\n * rendered natively as a wizard in the TUI, the Dashboard, and over RPC. The\n * whole batch is answered together and returned as one result. Answering,\n * stopping the turn, aborting, or timing out always settles cleanly so the\n * agent never deadlocks on an absent user. Unanswered questions come back\n * flagged as skipped rather than blocking the turn.\n */\n\nimport { Text } from \"@dreb/tui\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport type { AskQuestion, AskRequest, AskResult, ExtensionContext, ToolDefinition } from \"../extensions/types.js\";\n\n// ============================================================================\n// Types\n\n/** One question's outcome, surfaced in the tool result details. */\nexport interface AskUserAnswerDetail {\n\tquestion: string;\n\ttitle?: string;\n\tselected: string[];\n\tcustomText?: string;\n\t/** True when this question closed without an answer. */\n\tskipped: boolean;\n}\n\nexport interface AskUserDetails {\n\t/** One entry per question asked, in order. */\n\tanswers: AskUserAnswerDetail[];\n\t/** True when no interactive UI was available (headless/print mode). */\n\tunavailable: boolean;\n\t/** True when the UI host or response protocol failed. */\n\tfailed?: boolean;\n}\n\n// ============================================================================\n// Schema\n\nconst questionSchema = Type.Object({\n\tquestion: Type.String({\n\t\tdescription: \"The Markdown-formatted question to ask the user. Be specific about what you need to decide.\",\n\t}),\n\ttitle: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Short bold header shown above this question.\",\n\t\t}),\n\t),\n\toptions: Type.Optional(\n\t\tType.Array(Type.String({ minLength: 1, pattern: \"^.*[^ \\\\t\\\\r\\\\n].*$\" }), {\n\t\t\tminItems: 2,\n\t\t\tmaxItems: 4,\n\t\t\tdescription: \"2-4 nonblank suggested answers the user can pick from.\",\n\t\t}),\n\t),\n\tallowFreeText: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Offer a 'type your own answer' field. Defaults to true.\",\n\t\t}),\n\t),\n\tmultiSelect: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Allow selecting multiple options (checkboxes). Only meaningful with options.\",\n\t\t}),\n\t),\n\tmultiline: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Use a large multi-line text area for open-ended answers.\",\n\t\t}),\n\t),\n});\n\nconst askUserSchema = Type.Object({\n\tquestions: Type.Array(questionSchema, {\n\t\tminItems: 1,\n\t\tmaxItems: 10,\n\t\tdescription:\n\t\t\t\"One or more clarifying questions to ask together in a single wizard. \" +\n\t\t\t\"Batch every question you need answered in one call — the user answers them all and submits once.\",\n\t}),\n\ttimeoutSeconds: Type.Optional(\n\t\tType.Number({\n\t\t\tminimum: 5,\n\t\t\tmaximum: 3600,\n\t\t\tdescription:\n\t\t\t\t\"Optional: stop the current agent turn after this many seconds if the user does not respond. \" +\n\t\t\t\t\"Shows a live countdown. Omit to wait indefinitely.\",\n\t\t}),\n\t),\n});\n\nexport type AskUserInput = Static<typeof askUserSchema>;\ntype AskUserQuestion = Static<typeof questionSchema>;\n\n// ============================================================================\n// Normalization\n\n/**\n * Normalize a single question so every rendered surface has at least one usable\n * answer control and no impossible flag combinations survive.\n */\nfunction normalizeQuestion(q: AskUserQuestion): AskQuestion {\n\tconst hasOptions = (q.options?.length ?? 0) > 0;\n\treturn {\n\t\tquestion: q.question,\n\t\ttitle: q.title,\n\t\toptions: q.options,\n\t\t// Guarantee at least one answer control: with no options, free text must\n\t\t// be offered regardless of the requested flag, otherwise a question would\n\t\t// render only a Skip control and no way to answer.\n\t\tallowFreeText: hasOptions ? q.allowFreeText : true,\n\t\t// multiSelect is only meaningful with options; multiline only with free\n\t\t// text — normalize away impossible combinations.\n\t\tmultiSelect: hasOptions ? q.multiSelect : undefined,\n\t\tmultiline: hasOptions ? (q.allowFreeText === false ? undefined : q.multiline) : q.multiline,\n\t};\n}\n\n// ============================================================================\n// Result helpers\n\nfunction textResult(text: string, details: AskUserDetails) {\n\treturn {\n\t\tcontent: [{ type: \"text\" as const, text }],\n\t\tdetails,\n\t};\n}\n\nfunction skippedAnswer(q: AskQuestion): AskUserAnswerDetail {\n\treturn { question: q.question, title: q.title, selected: [], skipped: true };\n}\n\nfunction unavailableResult(questions: AskQuestion[]) {\n\treturn textResult(\n\t\t\"The ask_user tool requires an interactive UI, which is not available in this mode. \" +\n\t\t\t\"Proceed using your best judgment without waiting for an answer.\",\n\t\t{ answers: questions.map(skippedAnswer), unavailable: true },\n\t);\n}\n\nfunction unansweredResult(questions: AskQuestion[]) {\n\treturn textResult(\"The questions closed without an answer.\", {\n\t\tanswers: questions.map(skippedAnswer),\n\t\tunavailable: false,\n\t});\n}\n\nfunction failedResult(questions: AskQuestion[]) {\n\treturn textResult(\n\t\t\"The questions could not be delivered because the interactive UI or response protocol failed. \" +\n\t\t\t\"Continue without this input.\",\n\t\t{ answers: questions.map(skippedAnswer), unavailable: false, failed: true },\n\t);\n}\n\n/** Build a per-question detail entry from the user's answer. */\nfunction toAnswerDetail(q: AskQuestion, answer: AskResult[\"answers\"][number] | undefined): AskUserAnswerDetail {\n\tif (!answer || answer.skipped) return skippedAnswer(q);\n\tconst customText = answer.customText?.trim() || undefined;\n\tconst selected = answer.selected ?? [];\n\tif (selected.length === 0 && !customText) return skippedAnswer(q);\n\treturn { question: q.question, title: q.title, selected, customText, skipped: false };\n}\n\n/** Compose the model-facing summary, one block per question. */\nfunction summarizeAnswers(details: AskUserAnswerDetail[]): string {\n\tconst blocks = details.map((d) => {\n\t\tconst heading = (d.title || d.question || \"\").replace(/\\s+/g, \" \").trim();\n\t\tif (d.skipped) return `**${heading}** → (no answer)`;\n\t\tconst parts: string[] = [];\n\t\tif (d.selected.length > 0) parts.push(`Selected: ${d.selected.join(\", \")}`);\n\t\tif (d.customText) parts.push(`wrote: \"${d.customText}\"`);\n\t\treturn `**${heading}** → ${parts.join(\" / \")}`;\n\t});\n\treturn blocks.join(\"\\n\");\n}\n\nfunction answeredResult(questions: AskQuestion[], result: AskResult) {\n\tconst details = questions.map((q, i) => toAnswerDetail(q, result.answers[i]));\n\treturn textResult(summarizeAnswers(details), { answers: details, unavailable: false });\n}\n\n// ============================================================================\n// Render helpers\n\nfunction callLabel(args: { questions?: Array<{ title?: string; question?: string }> } | undefined): string {\n\tconst questions = args?.questions ?? [];\n\tconst count = questions.length;\n\tif (count === 1) {\n\t\tconst first = questions[0];\n\t\tconst label = (first?.title || first?.question || \"\").replace(/\\s+/g, \" \").trim();\n\t\treturn label.length > 80 ? `${label.slice(0, 79)}…` : label;\n\t}\n\treturn `${count} questions`;\n}\n\nfunction formatCall(\n\targs: { questions?: Array<{ title?: string; question?: string }> } | undefined,\n\ttheme: any,\n): string {\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"ask_user\"))} ${theme.fg(\"accent\", callLabel(args))}`;\n}\n\nfunction formatResult(details: AskUserDetails, theme: any): string {\n\tif (details.unavailable) return theme.fg(\"toolOutput\", \"no interactive UI — continued without asking\");\n\tif (details.failed) return theme.fg(\"toolOutput\", \"interactive UI failed — continued without an answer\");\n\tconst answered = details.answers.filter((a) => !a.skipped);\n\tif (answered.length === 0) return theme.fg(\"toolOutput\", \"closed without an answer\");\n\tif (details.answers.length === 1) {\n\t\tconst parts: string[] = [];\n\t\tif (answered[0].selected.length > 0) parts.push(answered[0].selected.join(\", \"));\n\t\tif (answered[0].customText) parts.push(`\"${answered[0].customText}\"`);\n\t\treturn theme.fg(\"toolOutput\", `→ ${parts.join(\" + \")}`);\n\t}\n\treturn theme.fg(\"toolOutput\", `→ answered ${answered.length} of ${details.answers.length}`);\n}\n\n// ============================================================================\n// Tool definition factory\n\n/**\n * Create an `ask_user` tool definition.\n *\n * One call carries one or more questions, collected together in a single\n * wizard and returned as a batch of answers. Every path — answer, skip, abort,\n * timeout, or host failure — settles gracefully and never orphans a promise.\n */\nexport function createAskUserToolDefinition(): ToolDefinition<typeof askUserSchema, AskUserDetails | undefined> {\n\treturn {\n\t\tname: \"ask_user\",\n\t\tlabel: \"ask_user\",\n\t\tdescription:\n\t\t\t\"Pause and ask the user one or more structured clarifying questions in a single call, each with \" +\n\t\t\t\"optional multiple-choice options and a free-text answer. The questions are shown together as one \" +\n\t\t\t\"wizard and answered as a batch. Use only when genuinely blocked by ambiguity with multiple viable \" +\n\t\t\t\"paths — not for routine confirmation.\",\n\n\t\tparameters: askUserSchema,\n\n\t\tpromptSnippet:\n\t\t\t\"Ask the user one or more clarifying questions with optional multiple-choice options and free text\",\n\n\t\tpromptGuidelines: [\n\t\t\t\"Call ask_user ONLY when you are genuinely blocked by ambiguity and there are multiple viable paths forward\",\n\t\t\t\"Do NOT use it for routine confirmation, permission, or things you can reasonably decide yourself\",\n\t\t\t\"Batch everything you need in ONE call: put each distinct decision in the `questions` array — the user answers them all and submits once\",\n\t\t\t\"Provide 2-4 concrete `options` per question when there are clear candidate answers; the user can always type their own\",\n\t\t\t\"Set `multiSelect: true` when several options can be combined; `multiline: true` for open-ended answers\",\n\t\t\t\"The user may stop the current turn instead of answering; never treat that as an answer, and unanswered questions come back as skipped\",\n\t\t],\n\n\t\tasync execute(_toolCallId, input: AskUserInput, signal, _onUpdate, ctx?: ExtensionContext) {\n\t\t\tconst questions = input.questions.map(normalizeQuestion);\n\t\t\tconst request: AskRequest = { questions };\n\n\t\t\t// Optional auto-stop timeout, forwarded to every UI surface (TUI\n\t\t\t// countdown, RPC/Dashboard). Model-facing units are seconds.\n\t\t\tconst timeout = input.timeoutSeconds && input.timeoutSeconds > 0 ? input.timeoutSeconds * 1000 : undefined;\n\n\t\t\t// Headless / print / no-host modes: never block on an unreachable UI.\n\t\t\tif (!ctx?.hasUI) {\n\t\t\t\treturn unavailableResult(questions);\n\t\t\t}\n\n\t\t\t// A call whose signal already aborted settles without ever opening the\n\t\t\t// UI; the parent turn is already stopping.\n\t\t\tif (signal?.aborted) return unansweredResult(questions);\n\n\t\t\ttry {\n\t\t\t\tconst answer = await ctx.ui.ask(request, { signal, timeout });\n\t\t\t\tif (!answer) return unansweredResult(questions);\n\t\t\t\treturn answeredResult(questions, answer);\n\t\t\t} catch {\n\t\t\t\t// Host/protocol failure must still settle and never deadlock, but it\n\t\t\t\t// must not masquerade as an intentional user skip.\n\t\t\t\treturn failedResult(questions);\n\t\t\t}\n\t\t},\n\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0, undefined, true);\n\t\t\ttext.setText(formatCall(args, theme));\n\t\t\treturn text;\n\t\t},\n\n\t\trenderResult(result, _options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0, undefined, true);\n\t\t\tconst details = (result as any).details as AskUserDetails | undefined;\n\t\t\tif (details) {\n\t\t\t\ttext.setText(formatResult(details, theme));\n\t\t\t} else {\n\t\t\t\tconst content = result.content?.[0];\n\t\t\t\ttext.setText(theme.fg(\"toolOutput\", content?.type === \"text\" ? content.text : \"\"));\n\t\t\t}\n\t\t\treturn text;\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ask-user.d.ts","sourceRoot":"","sources":["../../../src/core/tools/ask-user.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAEtD,OAAO,KAAK,EAAwD,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAKnH,mEAAmE;AACnE,MAAM,WAAW,mBAAmB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC9B,8CAA8C;IAC9C,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,uEAAuE;IACvE,WAAW,EAAE,OAAO,CAAC;IACrB,yDAAyD;IACzD,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAkED,QAAA,MAAM,aAAa;;;;;;;;;;;;;;EAajB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAqKxD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,IAAI,cAAc,CAAC,OAAO,aAAa,EAAE,cAAc,GAAG,SAAS,CAAC,CAsE9G","sourcesContent":["/**\n * ask_user tool.\n *\n * Lets the agent pause and ask the user one or more structured clarifying\n * questions in a single call — each with optional multiple-choice options,\n * single- or multi-select, and a \"type your own answer\" free-text field —\n * rendered natively as a wizard in the TUI, the Dashboard, and over RPC. The\n * whole batch is answered together and returned as one result. Answering,\n * stopping the turn, aborting, or timing out always settles cleanly so the\n * agent never deadlocks on an absent user. Unanswered questions come back\n * flagged as skipped rather than blocking the turn.\n */\n\nimport { Text } from \"@dreb/tui\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { Value } from \"@sinclair/typebox/value\";\nimport type { AskQuestion, AskRequest, AskResult, ExtensionContext, ToolDefinition } from \"../extensions/types.js\";\n\n// ============================================================================\n// Types\n\n/** One question's outcome, surfaced in the tool result details. */\nexport interface AskUserAnswerDetail {\n\tquestion: string;\n\ttitle?: string;\n\tselected: string[];\n\tcustomText?: string;\n\t/** True when this question closed without an answer. */\n\tskipped: boolean;\n}\n\nexport interface AskUserDetails {\n\t/** One entry per question asked, in order. */\n\tanswers: AskUserAnswerDetail[];\n\t/** True when no interactive UI was available (headless/print mode). */\n\tunavailable: boolean;\n\t/** True when the UI host or response protocol failed. */\n\tfailed?: boolean;\n}\n\n// ============================================================================\n// Schema\n\n/** Nonblank text: at least one non-whitespace character (llama.cpp-parseable pattern). */\nconst NONBLANK_PATTERN = \"^.*[^ \\\\t\\\\r\\\\n].*$\";\n\n/**\n * One option: plain text, or a labeled object (the shape many models are\n * trained on). Objects are folded back to plain text before reaching any UI.\n */\nconst optionSchema = Type.Union([\n\tType.String({ minLength: 1, pattern: NONBLANK_PATTERN }),\n\tType.Object({\n\t\tlabel: Type.String({ minLength: 1, pattern: NONBLANK_PATTERN }),\n\t\tdescription: Type.Optional(Type.String()),\n\t}),\n]);\n\nconst questionSchema = Type.Object({\n\tquestion: Type.String({\n\t\tdescription: \"The Markdown-formatted question to ask the user. Be specific about what you need to decide.\",\n\t}),\n\ttitle: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Short bold title shown above this question.\",\n\t\t}),\n\t),\n\theader: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Alias for title; title wins when both are given.\",\n\t\t}),\n\t),\n\toptions: Type.Optional(\n\t\tType.Array(optionSchema, {\n\t\t\tminItems: 2,\n\t\t\tmaxItems: 4,\n\t\t\tdescription: \"2-4 nonblank suggested answers the user can pick from.\",\n\t\t}),\n\t),\n\tallowFreeText: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Offer a 'type your own answer' field. Defaults to true.\",\n\t\t}),\n\t),\n\tmultiSelect: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Allow selecting multiple options (checkboxes). Only meaningful with options.\",\n\t\t}),\n\t),\n\tmultiline: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Use a large multi-line text area for open-ended answers.\",\n\t\t}),\n\t),\n});\n\nconst questionsArraySchema = Type.Array(questionSchema, {\n\tminItems: 1,\n\tmaxItems: 10,\n\tdescription:\n\t\t\"One or more clarifying questions to ask together in a single wizard. \" +\n\t\t\"Batch every question you need answered in one call — the user answers them all and submits once.\",\n});\n\nconst askUserSchema = Type.Object({\n\t// A JSON-encoded string of the array is also accepted; it is parsed and\n\t// checked against the same array schema in execute.\n\tquestions: Type.Union([questionsArraySchema, Type.String()]),\n\ttimeoutSeconds: Type.Optional(\n\t\tType.Number({\n\t\t\tminimum: 5,\n\t\t\tmaximum: 3600,\n\t\t\tdescription:\n\t\t\t\t\"Optional: stop the current agent turn after this many seconds if the user does not respond. \" +\n\t\t\t\t\"Shows a live countdown. Omit to wait indefinitely.\",\n\t\t}),\n\t),\n});\n\nexport type AskUserInput = Static<typeof askUserSchema>;\ntype AskUserQuestion = Static<typeof questionSchema>;\ntype AskUserOption = Static<typeof optionSchema>;\n\n// ============================================================================\n// Normalization\n\n/** Fold an option to plain text: \"label\" or \"label — description\". */\nfunction optionText(option: AskUserOption): string {\n\tif (typeof option === \"string\") return option;\n\tconst description = option.description?.trim();\n\treturn description ? `${option.label} — ${description}` : option.label;\n}\n\n/**\n * Resolve `questions` to an array. A JSON-encoded string is parsed and checked\n * against the same schema as a real array; anything invalid throws.\n */\nfunction resolveQuestions(questions: AskUserInput[\"questions\"]): AskUserQuestion[] {\n\tif (typeof questions !== \"string\") return questions;\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(questions);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`ask_user: \\`questions\\` was a string but not valid JSON (${error instanceof Error ? error.message : String(error)}). Pass \\`questions\\` as an array of question objects.`,\n\t\t);\n\t}\n\tif (!Value.Check(questionsArraySchema, parsed)) {\n\t\tconst errors = [...Value.Errors(questionsArraySchema, parsed)]\n\t\t\t.slice(0, 10)\n\t\t\t.map((e) => ` - ${e.path || \"questions\"}: ${e.message}`)\n\t\t\t.join(\"\\n\");\n\t\tthrow new Error(\n\t\t\t`ask_user: \\`questions\\` was a JSON string that is not a valid questions array:\\n${errors}\\nPass \\`questions\\` as an array of question objects.`,\n\t\t);\n\t}\n\treturn parsed;\n}\n\n/**\n * Normalize a single question so every rendered surface has at least one usable\n * answer control and no impossible flag combinations survive.\n */\nfunction normalizeQuestion(q: AskUserQuestion): AskQuestion {\n\tconst options = q.options?.map(optionText);\n\tconst hasOptions = (options?.length ?? 0) > 0;\n\treturn {\n\t\tquestion: q.question,\n\t\ttitle: q.title ?? q.header,\n\t\toptions,\n\t\t// Guarantee at least one answer control: with no options, free text must\n\t\t// be offered regardless of the requested flag, otherwise a question would\n\t\t// render only a Skip control and no way to answer.\n\t\tallowFreeText: hasOptions ? q.allowFreeText : true,\n\t\t// multiSelect is only meaningful with options; multiline only with free\n\t\t// text — normalize away impossible combinations.\n\t\tmultiSelect: hasOptions ? q.multiSelect : undefined,\n\t\tmultiline: hasOptions ? (q.allowFreeText === false ? undefined : q.multiline) : q.multiline,\n\t};\n}\n\n// ============================================================================\n// Result helpers\n\nfunction textResult(text: string, details: AskUserDetails) {\n\treturn {\n\t\tcontent: [{ type: \"text\" as const, text }],\n\t\tdetails,\n\t};\n}\n\nfunction skippedAnswer(q: AskQuestion): AskUserAnswerDetail {\n\treturn { question: q.question, title: q.title, selected: [], skipped: true };\n}\n\nfunction unavailableResult(questions: AskQuestion[]) {\n\treturn textResult(\n\t\t\"The ask_user tool requires an interactive UI, which is not available in this mode. \" +\n\t\t\t\"Proceed using your best judgment without waiting for an answer.\",\n\t\t{ answers: questions.map(skippedAnswer), unavailable: true },\n\t);\n}\n\nfunction unansweredResult(questions: AskQuestion[]) {\n\treturn textResult(\"The questions closed without an answer.\", {\n\t\tanswers: questions.map(skippedAnswer),\n\t\tunavailable: false,\n\t});\n}\n\nfunction failedResult(questions: AskQuestion[]) {\n\treturn textResult(\n\t\t\"The questions could not be delivered because the interactive UI or response protocol failed. \" +\n\t\t\t\"Continue without this input.\",\n\t\t{ answers: questions.map(skippedAnswer), unavailable: false, failed: true },\n\t);\n}\n\n/** Build a per-question detail entry from the user's answer. */\nfunction toAnswerDetail(q: AskQuestion, answer: AskResult[\"answers\"][number] | undefined): AskUserAnswerDetail {\n\tif (!answer || answer.skipped) return skippedAnswer(q);\n\tconst customText = answer.customText?.trim() || undefined;\n\tconst selected = answer.selected ?? [];\n\tif (selected.length === 0 && !customText) return skippedAnswer(q);\n\treturn { question: q.question, title: q.title, selected, customText, skipped: false };\n}\n\n/** Compose the model-facing summary, one block per question. */\nfunction summarizeAnswers(details: AskUserAnswerDetail[]): string {\n\tconst blocks = details.map((d) => {\n\t\tconst heading = (d.title || d.question || \"\").replace(/\\s+/g, \" \").trim();\n\t\tif (d.skipped) return `**${heading}** → (no answer)`;\n\t\tconst parts: string[] = [];\n\t\tif (d.selected.length > 0) parts.push(`Selected: ${d.selected.join(\", \")}`);\n\t\tif (d.customText) parts.push(`wrote: \"${d.customText}\"`);\n\t\treturn `**${heading}** → ${parts.join(\" / \")}`;\n\t});\n\treturn blocks.join(\"\\n\");\n}\n\nfunction answeredResult(questions: AskQuestion[], result: AskResult) {\n\tconst details = questions.map((q, i) => toAnswerDetail(q, result.answers[i]));\n\treturn textResult(summarizeAnswers(details), { answers: details, unavailable: false });\n}\n\n// ============================================================================\n// Render helpers\n\ntype CallArgs = { questions?: Array<{ title?: string; header?: string; question?: string }> | string } | undefined;\n\nfunction callLabel(args: CallArgs): string {\n\t// While streaming (or for a JSON-string batch) questions may not be an array yet.\n\tconst questions = Array.isArray(args?.questions) ? args.questions : [];\n\tif (typeof args?.questions === \"string\") return \"questions\";\n\tconst count = questions.length;\n\tif (count === 1) {\n\t\tconst first = questions[0];\n\t\tconst label = (first?.title || first?.header || first?.question || \"\").replace(/\\s+/g, \" \").trim();\n\t\treturn label.length > 80 ? `${label.slice(0, 79)}…` : label;\n\t}\n\treturn `${count} questions`;\n}\n\nfunction formatCall(args: CallArgs, theme: any): string {\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"ask_user\"))} ${theme.fg(\"accent\", callLabel(args))}`;\n}\n\nfunction formatResult(details: AskUserDetails, theme: any): string {\n\tif (details.unavailable) return theme.fg(\"toolOutput\", \"no interactive UI — continued without asking\");\n\tif (details.failed) return theme.fg(\"toolOutput\", \"interactive UI failed — continued without an answer\");\n\tconst answered = details.answers.filter((a) => !a.skipped);\n\tif (answered.length === 0) return theme.fg(\"toolOutput\", \"closed without an answer\");\n\tif (details.answers.length === 1) {\n\t\tconst parts: string[] = [];\n\t\tif (answered[0].selected.length > 0) parts.push(answered[0].selected.join(\", \"));\n\t\tif (answered[0].customText) parts.push(`\"${answered[0].customText}\"`);\n\t\treturn theme.fg(\"toolOutput\", `→ ${parts.join(\" + \")}`);\n\t}\n\treturn theme.fg(\"toolOutput\", `→ answered ${answered.length} of ${details.answers.length}`);\n}\n\n// ============================================================================\n// Tool definition factory\n\n/**\n * Create an `ask_user` tool definition.\n *\n * One call carries one or more questions, collected together in a single\n * wizard and returned as a batch of answers. Every path — answer, skip, abort,\n * timeout, or host failure — settles gracefully and never orphans a promise.\n */\nexport function createAskUserToolDefinition(): ToolDefinition<typeof askUserSchema, AskUserDetails | undefined> {\n\treturn {\n\t\tname: \"ask_user\",\n\t\tlabel: \"ask_user\",\n\t\tdescription:\n\t\t\t\"Pause and ask the user one or more structured clarifying questions in a single call, each with \" +\n\t\t\t\"optional multiple-choice options and a free-text answer. The questions are shown together as one \" +\n\t\t\t\"wizard and answered as a batch. Use only when genuinely blocked by ambiguity with multiple viable \" +\n\t\t\t\"paths — not for routine confirmation.\",\n\n\t\tparameters: askUserSchema,\n\n\t\tpromptSnippet:\n\t\t\t\"Ask the user one or more clarifying questions with optional multiple-choice options and free text\",\n\n\t\tpromptGuidelines: [\n\t\t\t\"Call ask_user ONLY when you are genuinely blocked by ambiguity and there are multiple viable paths forward\",\n\t\t\t\"Do NOT use it for routine confirmation, permission, or things you can reasonably decide yourself\",\n\t\t\t\"Batch everything you need in ONE call: put each distinct decision in the `questions` array — the user answers them all and submits once\",\n\t\t\t\"Provide 2-4 concrete `options` per question (plain strings) when there are clear candidate answers; the user can always type their own\",\n\t\t\t\"Set `multiSelect: true` when several options can be combined; `multiline: true` for open-ended answers\",\n\t\t\t\"The user may stop the current turn instead of answering; never treat that as an answer, and unanswered questions come back as skipped\",\n\t\t],\n\n\t\tasync execute(_toolCallId, input: AskUserInput, signal, _onUpdate, ctx?: ExtensionContext) {\n\t\t\tconst questions = resolveQuestions(input.questions).map(normalizeQuestion);\n\t\t\tconst request: AskRequest = { questions };\n\n\t\t\t// Optional auto-stop timeout, forwarded to every UI surface (TUI\n\t\t\t// countdown, RPC/Dashboard). Model-facing units are seconds.\n\t\t\tconst timeout = input.timeoutSeconds && input.timeoutSeconds > 0 ? input.timeoutSeconds * 1000 : undefined;\n\n\t\t\t// Headless / print / no-host modes: never block on an unreachable UI.\n\t\t\tif (!ctx?.hasUI) {\n\t\t\t\treturn unavailableResult(questions);\n\t\t\t}\n\n\t\t\t// A call whose signal already aborted settles without ever opening the\n\t\t\t// UI; the parent turn is already stopping.\n\t\t\tif (signal?.aborted) return unansweredResult(questions);\n\n\t\t\ttry {\n\t\t\t\tconst answer = await ctx.ui.ask(request, { signal, timeout });\n\t\t\t\tif (!answer) return unansweredResult(questions);\n\t\t\t\treturn answeredResult(questions, answer);\n\t\t\t} catch {\n\t\t\t\t// Host/protocol failure must still settle and never deadlock, but it\n\t\t\t\t// must not masquerade as an intentional user skip.\n\t\t\t\treturn failedResult(questions);\n\t\t\t}\n\t\t},\n\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0, undefined, true);\n\t\t\ttext.setText(formatCall(args, theme));\n\t\t\treturn text;\n\t\t},\n\n\t\trenderResult(result, _options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0, undefined, true);\n\t\t\tconst details = (result as any).details as AskUserDetails | undefined;\n\t\t\tif (details) {\n\t\t\t\ttext.setText(formatResult(details, theme));\n\t\t\t} else {\n\t\t\t\tconst content = result.content?.[0];\n\t\t\t\ttext.setText(theme.fg(\"toolOutput\", content?.type === \"text\" ? content.text : \"\"));\n\t\t\t}\n\t\t\treturn text;\n\t\t},\n\t};\n}\n"]}
|
|
@@ -12,16 +12,33 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { Text } from "@dreb/tui";
|
|
14
14
|
import { Type } from "@sinclair/typebox";
|
|
15
|
+
import { Value } from "@sinclair/typebox/value";
|
|
15
16
|
// ============================================================================
|
|
16
17
|
// Schema
|
|
18
|
+
/** Nonblank text: at least one non-whitespace character (llama.cpp-parseable pattern). */
|
|
19
|
+
const NONBLANK_PATTERN = "^.*[^ \\t\\r\\n].*$";
|
|
20
|
+
/**
|
|
21
|
+
* One option: plain text, or a labeled object (the shape many models are
|
|
22
|
+
* trained on). Objects are folded back to plain text before reaching any UI.
|
|
23
|
+
*/
|
|
24
|
+
const optionSchema = Type.Union([
|
|
25
|
+
Type.String({ minLength: 1, pattern: NONBLANK_PATTERN }),
|
|
26
|
+
Type.Object({
|
|
27
|
+
label: Type.String({ minLength: 1, pattern: NONBLANK_PATTERN }),
|
|
28
|
+
description: Type.Optional(Type.String()),
|
|
29
|
+
}),
|
|
30
|
+
]);
|
|
17
31
|
const questionSchema = Type.Object({
|
|
18
32
|
question: Type.String({
|
|
19
33
|
description: "The Markdown-formatted question to ask the user. Be specific about what you need to decide.",
|
|
20
34
|
}),
|
|
21
35
|
title: Type.Optional(Type.String({
|
|
22
|
-
description: "Short bold
|
|
36
|
+
description: "Short bold title shown above this question.",
|
|
37
|
+
})),
|
|
38
|
+
header: Type.Optional(Type.String({
|
|
39
|
+
description: "Alias for title; title wins when both are given.",
|
|
23
40
|
})),
|
|
24
|
-
options: Type.Optional(Type.Array(
|
|
41
|
+
options: Type.Optional(Type.Array(optionSchema, {
|
|
25
42
|
minItems: 2,
|
|
26
43
|
maxItems: 4,
|
|
27
44
|
description: "2-4 nonblank suggested answers the user can pick from.",
|
|
@@ -36,13 +53,16 @@ const questionSchema = Type.Object({
|
|
|
36
53
|
description: "Use a large multi-line text area for open-ended answers.",
|
|
37
54
|
})),
|
|
38
55
|
});
|
|
56
|
+
const questionsArraySchema = Type.Array(questionSchema, {
|
|
57
|
+
minItems: 1,
|
|
58
|
+
maxItems: 10,
|
|
59
|
+
description: "One or more clarifying questions to ask together in a single wizard. " +
|
|
60
|
+
"Batch every question you need answered in one call — the user answers them all and submits once.",
|
|
61
|
+
});
|
|
39
62
|
const askUserSchema = Type.Object({
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
description: "One or more clarifying questions to ask together in a single wizard. " +
|
|
44
|
-
"Batch every question you need answered in one call — the user answers them all and submits once.",
|
|
45
|
-
}),
|
|
63
|
+
// A JSON-encoded string of the array is also accepted; it is parsed and
|
|
64
|
+
// checked against the same array schema in execute.
|
|
65
|
+
questions: Type.Union([questionsArraySchema, Type.String()]),
|
|
46
66
|
timeoutSeconds: Type.Optional(Type.Number({
|
|
47
67
|
minimum: 5,
|
|
48
68
|
maximum: 3600,
|
|
@@ -52,16 +72,47 @@ const askUserSchema = Type.Object({
|
|
|
52
72
|
});
|
|
53
73
|
// ============================================================================
|
|
54
74
|
// Normalization
|
|
75
|
+
/** Fold an option to plain text: "label" or "label — description". */
|
|
76
|
+
function optionText(option) {
|
|
77
|
+
if (typeof option === "string")
|
|
78
|
+
return option;
|
|
79
|
+
const description = option.description?.trim();
|
|
80
|
+
return description ? `${option.label} — ${description}` : option.label;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resolve `questions` to an array. A JSON-encoded string is parsed and checked
|
|
84
|
+
* against the same schema as a real array; anything invalid throws.
|
|
85
|
+
*/
|
|
86
|
+
function resolveQuestions(questions) {
|
|
87
|
+
if (typeof questions !== "string")
|
|
88
|
+
return questions;
|
|
89
|
+
let parsed;
|
|
90
|
+
try {
|
|
91
|
+
parsed = JSON.parse(questions);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
throw new Error(`ask_user: \`questions\` was a string but not valid JSON (${error instanceof Error ? error.message : String(error)}). Pass \`questions\` as an array of question objects.`);
|
|
95
|
+
}
|
|
96
|
+
if (!Value.Check(questionsArraySchema, parsed)) {
|
|
97
|
+
const errors = [...Value.Errors(questionsArraySchema, parsed)]
|
|
98
|
+
.slice(0, 10)
|
|
99
|
+
.map((e) => ` - ${e.path || "questions"}: ${e.message}`)
|
|
100
|
+
.join("\n");
|
|
101
|
+
throw new Error(`ask_user: \`questions\` was a JSON string that is not a valid questions array:\n${errors}\nPass \`questions\` as an array of question objects.`);
|
|
102
|
+
}
|
|
103
|
+
return parsed;
|
|
104
|
+
}
|
|
55
105
|
/**
|
|
56
106
|
* Normalize a single question so every rendered surface has at least one usable
|
|
57
107
|
* answer control and no impossible flag combinations survive.
|
|
58
108
|
*/
|
|
59
109
|
function normalizeQuestion(q) {
|
|
60
|
-
const
|
|
110
|
+
const options = q.options?.map(optionText);
|
|
111
|
+
const hasOptions = (options?.length ?? 0) > 0;
|
|
61
112
|
return {
|
|
62
113
|
question: q.question,
|
|
63
|
-
title: q.title,
|
|
64
|
-
options
|
|
114
|
+
title: q.title ?? q.header,
|
|
115
|
+
options,
|
|
65
116
|
// Guarantee at least one answer control: with no options, free text must
|
|
66
117
|
// be offered regardless of the requested flag, otherwise a question would
|
|
67
118
|
// render only a Skip control and no way to answer.
|
|
@@ -126,14 +177,15 @@ function answeredResult(questions, result) {
|
|
|
126
177
|
const details = questions.map((q, i) => toAnswerDetail(q, result.answers[i]));
|
|
127
178
|
return textResult(summarizeAnswers(details), { answers: details, unavailable: false });
|
|
128
179
|
}
|
|
129
|
-
// ============================================================================
|
|
130
|
-
// Render helpers
|
|
131
180
|
function callLabel(args) {
|
|
132
|
-
|
|
181
|
+
// While streaming (or for a JSON-string batch) questions may not be an array yet.
|
|
182
|
+
const questions = Array.isArray(args?.questions) ? args.questions : [];
|
|
183
|
+
if (typeof args?.questions === "string")
|
|
184
|
+
return "questions";
|
|
133
185
|
const count = questions.length;
|
|
134
186
|
if (count === 1) {
|
|
135
187
|
const first = questions[0];
|
|
136
|
-
const label = (first?.title || first?.question || "").replace(/\s+/g, " ").trim();
|
|
188
|
+
const label = (first?.title || first?.header || first?.question || "").replace(/\s+/g, " ").trim();
|
|
137
189
|
return label.length > 80 ? `${label.slice(0, 79)}…` : label;
|
|
138
190
|
}
|
|
139
191
|
return `${count} questions`;
|
|
@@ -182,12 +234,12 @@ export function createAskUserToolDefinition() {
|
|
|
182
234
|
"Call ask_user ONLY when you are genuinely blocked by ambiguity and there are multiple viable paths forward",
|
|
183
235
|
"Do NOT use it for routine confirmation, permission, or things you can reasonably decide yourself",
|
|
184
236
|
"Batch everything you need in ONE call: put each distinct decision in the `questions` array — the user answers them all and submits once",
|
|
185
|
-
"Provide 2-4 concrete `options` per question when there are clear candidate answers; the user can always type their own",
|
|
237
|
+
"Provide 2-4 concrete `options` per question (plain strings) when there are clear candidate answers; the user can always type their own",
|
|
186
238
|
"Set `multiSelect: true` when several options can be combined; `multiline: true` for open-ended answers",
|
|
187
239
|
"The user may stop the current turn instead of answering; never treat that as an answer, and unanswered questions come back as skipped",
|
|
188
240
|
],
|
|
189
241
|
async execute(_toolCallId, input, signal, _onUpdate, ctx) {
|
|
190
|
-
const questions = input.questions.map(normalizeQuestion);
|
|
242
|
+
const questions = resolveQuestions(input.questions).map(normalizeQuestion);
|
|
191
243
|
const request = { questions };
|
|
192
244
|
// Optional auto-stop timeout, forwarded to every UI surface (TUI
|
|
193
245
|
// countdown, RPC/Dashboard). Model-facing units are seconds.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask-user.js","sourceRoot":"","sources":["../../../src/core/tools/ask-user.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ask_user tool.\n *\n * Lets the agent pause and ask the user one or more structured clarifying\n * questions in a single call — each with optional multiple-choice options,\n * single- or multi-select, and a \"type your own answer\" free-text field —\n * rendered natively as a wizard in the TUI, the Dashboard, and over RPC. The\n * whole batch is answered together and returned as one result. Answering,\n * stopping the turn, aborting, or timing out always settles cleanly so the\n * agent never deadlocks on an absent user. Unanswered questions come back\n * flagged as skipped rather than blocking the turn.\n */\n\nimport { Text } from \"@dreb/tui\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport type { AskQuestion, AskRequest, AskResult, ExtensionContext, ToolDefinition } from \"../extensions/types.js\";\n\n// ============================================================================\n// Types\n\n/** One question's outcome, surfaced in the tool result details. */\nexport interface AskUserAnswerDetail {\n\tquestion: string;\n\ttitle?: string;\n\tselected: string[];\n\tcustomText?: string;\n\t/** True when this question closed without an answer. */\n\tskipped: boolean;\n}\n\nexport interface AskUserDetails {\n\t/** One entry per question asked, in order. */\n\tanswers: AskUserAnswerDetail[];\n\t/** True when no interactive UI was available (headless/print mode). */\n\tunavailable: boolean;\n\t/** True when the UI host or response protocol failed. */\n\tfailed?: boolean;\n}\n\n// ============================================================================\n// Schema\n\nconst questionSchema = Type.Object({\n\tquestion: Type.String({\n\t\tdescription: \"The Markdown-formatted question to ask the user. Be specific about what you need to decide.\",\n\t}),\n\ttitle: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Short bold header shown above this question.\",\n\t\t}),\n\t),\n\toptions: Type.Optional(\n\t\tType.Array(Type.String({ minLength: 1, pattern: \"^.*[^ \\\\t\\\\r\\\\n].*$\" }), {\n\t\t\tminItems: 2,\n\t\t\tmaxItems: 4,\n\t\t\tdescription: \"2-4 nonblank suggested answers the user can pick from.\",\n\t\t}),\n\t),\n\tallowFreeText: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Offer a 'type your own answer' field. Defaults to true.\",\n\t\t}),\n\t),\n\tmultiSelect: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Allow selecting multiple options (checkboxes). Only meaningful with options.\",\n\t\t}),\n\t),\n\tmultiline: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Use a large multi-line text area for open-ended answers.\",\n\t\t}),\n\t),\n});\n\nconst askUserSchema = Type.Object({\n\tquestions: Type.Array(questionSchema, {\n\t\tminItems: 1,\n\t\tmaxItems: 10,\n\t\tdescription:\n\t\t\t\"One or more clarifying questions to ask together in a single wizard. \" +\n\t\t\t\"Batch every question you need answered in one call — the user answers them all and submits once.\",\n\t}),\n\ttimeoutSeconds: Type.Optional(\n\t\tType.Number({\n\t\t\tminimum: 5,\n\t\t\tmaximum: 3600,\n\t\t\tdescription:\n\t\t\t\t\"Optional: stop the current agent turn after this many seconds if the user does not respond. \" +\n\t\t\t\t\"Shows a live countdown. Omit to wait indefinitely.\",\n\t\t}),\n\t),\n});\n\nexport type AskUserInput = Static<typeof askUserSchema>;\ntype AskUserQuestion = Static<typeof questionSchema>;\n\n// ============================================================================\n// Normalization\n\n/**\n * Normalize a single question so every rendered surface has at least one usable\n * answer control and no impossible flag combinations survive.\n */\nfunction normalizeQuestion(q: AskUserQuestion): AskQuestion {\n\tconst hasOptions = (q.options?.length ?? 0) > 0;\n\treturn {\n\t\tquestion: q.question,\n\t\ttitle: q.title,\n\t\toptions: q.options,\n\t\t// Guarantee at least one answer control: with no options, free text must\n\t\t// be offered regardless of the requested flag, otherwise a question would\n\t\t// render only a Skip control and no way to answer.\n\t\tallowFreeText: hasOptions ? q.allowFreeText : true,\n\t\t// multiSelect is only meaningful with options; multiline only with free\n\t\t// text — normalize away impossible combinations.\n\t\tmultiSelect: hasOptions ? q.multiSelect : undefined,\n\t\tmultiline: hasOptions ? (q.allowFreeText === false ? undefined : q.multiline) : q.multiline,\n\t};\n}\n\n// ============================================================================\n// Result helpers\n\nfunction textResult(text: string, details: AskUserDetails) {\n\treturn {\n\t\tcontent: [{ type: \"text\" as const, text }],\n\t\tdetails,\n\t};\n}\n\nfunction skippedAnswer(q: AskQuestion): AskUserAnswerDetail {\n\treturn { question: q.question, title: q.title, selected: [], skipped: true };\n}\n\nfunction unavailableResult(questions: AskQuestion[]) {\n\treturn textResult(\n\t\t\"The ask_user tool requires an interactive UI, which is not available in this mode. \" +\n\t\t\t\"Proceed using your best judgment without waiting for an answer.\",\n\t\t{ answers: questions.map(skippedAnswer), unavailable: true },\n\t);\n}\n\nfunction unansweredResult(questions: AskQuestion[]) {\n\treturn textResult(\"The questions closed without an answer.\", {\n\t\tanswers: questions.map(skippedAnswer),\n\t\tunavailable: false,\n\t});\n}\n\nfunction failedResult(questions: AskQuestion[]) {\n\treturn textResult(\n\t\t\"The questions could not be delivered because the interactive UI or response protocol failed. \" +\n\t\t\t\"Continue without this input.\",\n\t\t{ answers: questions.map(skippedAnswer), unavailable: false, failed: true },\n\t);\n}\n\n/** Build a per-question detail entry from the user's answer. */\nfunction toAnswerDetail(q: AskQuestion, answer: AskResult[\"answers\"][number] | undefined): AskUserAnswerDetail {\n\tif (!answer || answer.skipped) return skippedAnswer(q);\n\tconst customText = answer.customText?.trim() || undefined;\n\tconst selected = answer.selected ?? [];\n\tif (selected.length === 0 && !customText) return skippedAnswer(q);\n\treturn { question: q.question, title: q.title, selected, customText, skipped: false };\n}\n\n/** Compose the model-facing summary, one block per question. */\nfunction summarizeAnswers(details: AskUserAnswerDetail[]): string {\n\tconst blocks = details.map((d) => {\n\t\tconst heading = (d.title || d.question || \"\").replace(/\\s+/g, \" \").trim();\n\t\tif (d.skipped) return `**${heading}** → (no answer)`;\n\t\tconst parts: string[] = [];\n\t\tif (d.selected.length > 0) parts.push(`Selected: ${d.selected.join(\", \")}`);\n\t\tif (d.customText) parts.push(`wrote: \"${d.customText}\"`);\n\t\treturn `**${heading}** → ${parts.join(\" / \")}`;\n\t});\n\treturn blocks.join(\"\\n\");\n}\n\nfunction answeredResult(questions: AskQuestion[], result: AskResult) {\n\tconst details = questions.map((q, i) => toAnswerDetail(q, result.answers[i]));\n\treturn textResult(summarizeAnswers(details), { answers: details, unavailable: false });\n}\n\n// ============================================================================\n// Render helpers\n\nfunction callLabel(args: { questions?: Array<{ title?: string; question?: string }> } | undefined): string {\n\tconst questions = args?.questions ?? [];\n\tconst count = questions.length;\n\tif (count === 1) {\n\t\tconst first = questions[0];\n\t\tconst label = (first?.title || first?.question || \"\").replace(/\\s+/g, \" \").trim();\n\t\treturn label.length > 80 ? `${label.slice(0, 79)}…` : label;\n\t}\n\treturn `${count} questions`;\n}\n\nfunction formatCall(\n\targs: { questions?: Array<{ title?: string; question?: string }> } | undefined,\n\ttheme: any,\n): string {\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"ask_user\"))} ${theme.fg(\"accent\", callLabel(args))}`;\n}\n\nfunction formatResult(details: AskUserDetails, theme: any): string {\n\tif (details.unavailable) return theme.fg(\"toolOutput\", \"no interactive UI — continued without asking\");\n\tif (details.failed) return theme.fg(\"toolOutput\", \"interactive UI failed — continued without an answer\");\n\tconst answered = details.answers.filter((a) => !a.skipped);\n\tif (answered.length === 0) return theme.fg(\"toolOutput\", \"closed without an answer\");\n\tif (details.answers.length === 1) {\n\t\tconst parts: string[] = [];\n\t\tif (answered[0].selected.length > 0) parts.push(answered[0].selected.join(\", \"));\n\t\tif (answered[0].customText) parts.push(`\"${answered[0].customText}\"`);\n\t\treturn theme.fg(\"toolOutput\", `→ ${parts.join(\" + \")}`);\n\t}\n\treturn theme.fg(\"toolOutput\", `→ answered ${answered.length} of ${details.answers.length}`);\n}\n\n// ============================================================================\n// Tool definition factory\n\n/**\n * Create an `ask_user` tool definition.\n *\n * One call carries one or more questions, collected together in a single\n * wizard and returned as a batch of answers. Every path — answer, skip, abort,\n * timeout, or host failure — settles gracefully and never orphans a promise.\n */\nexport function createAskUserToolDefinition(): ToolDefinition<typeof askUserSchema, AskUserDetails | undefined> {\n\treturn {\n\t\tname: \"ask_user\",\n\t\tlabel: \"ask_user\",\n\t\tdescription:\n\t\t\t\"Pause and ask the user one or more structured clarifying questions in a single call, each with \" +\n\t\t\t\"optional multiple-choice options and a free-text answer. The questions are shown together as one \" +\n\t\t\t\"wizard and answered as a batch. Use only when genuinely blocked by ambiguity with multiple viable \" +\n\t\t\t\"paths — not for routine confirmation.\",\n\n\t\tparameters: askUserSchema,\n\n\t\tpromptSnippet:\n\t\t\t\"Ask the user one or more clarifying questions with optional multiple-choice options and free text\",\n\n\t\tpromptGuidelines: [\n\t\t\t\"Call ask_user ONLY when you are genuinely blocked by ambiguity and there are multiple viable paths forward\",\n\t\t\t\"Do NOT use it for routine confirmation, permission, or things you can reasonably decide yourself\",\n\t\t\t\"Batch everything you need in ONE call: put each distinct decision in the `questions` array — the user answers them all and submits once\",\n\t\t\t\"Provide 2-4 concrete `options` per question when there are clear candidate answers; the user can always type their own\",\n\t\t\t\"Set `multiSelect: true` when several options can be combined; `multiline: true` for open-ended answers\",\n\t\t\t\"The user may stop the current turn instead of answering; never treat that as an answer, and unanswered questions come back as skipped\",\n\t\t],\n\n\t\tasync execute(_toolCallId, input: AskUserInput, signal, _onUpdate, ctx?: ExtensionContext) {\n\t\t\tconst questions = input.questions.map(normalizeQuestion);\n\t\t\tconst request: AskRequest = { questions };\n\n\t\t\t// Optional auto-stop timeout, forwarded to every UI surface (TUI\n\t\t\t// countdown, RPC/Dashboard). Model-facing units are seconds.\n\t\t\tconst timeout = input.timeoutSeconds && input.timeoutSeconds > 0 ? input.timeoutSeconds * 1000 : undefined;\n\n\t\t\t// Headless / print / no-host modes: never block on an unreachable UI.\n\t\t\tif (!ctx?.hasUI) {\n\t\t\t\treturn unavailableResult(questions);\n\t\t\t}\n\n\t\t\t// A call whose signal already aborted settles without ever opening the\n\t\t\t// UI; the parent turn is already stopping.\n\t\t\tif (signal?.aborted) return unansweredResult(questions);\n\n\t\t\ttry {\n\t\t\t\tconst answer = await ctx.ui.ask(request, { signal, timeout });\n\t\t\t\tif (!answer) return unansweredResult(questions);\n\t\t\t\treturn answeredResult(questions, answer);\n\t\t\t} catch {\n\t\t\t\t// Host/protocol failure must still settle and never deadlock, but it\n\t\t\t\t// must not masquerade as an intentional user skip.\n\t\t\t\treturn failedResult(questions);\n\t\t\t}\n\t\t},\n\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0, undefined, true);\n\t\t\ttext.setText(formatCall(args, theme));\n\t\t\treturn text;\n\t\t},\n\n\t\trenderResult(result, _options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0, undefined, true);\n\t\t\tconst details = (result as any).details as AskUserDetails | undefined;\n\t\t\tif (details) {\n\t\t\t\ttext.setText(formatResult(details, theme));\n\t\t\t} else {\n\t\t\t\tconst content = result.content?.[0];\n\t\t\t\ttext.setText(theme.fg(\"toolOutput\", content?.type === \"text\" ? content.text : \"\"));\n\t\t\t}\n\t\t\treturn text;\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ask-user.js","sourceRoot":"","sources":["../../../src/core/tools/ask-user.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ask_user tool.\n *\n * Lets the agent pause and ask the user one or more structured clarifying\n * questions in a single call — each with optional multiple-choice options,\n * single- or multi-select, and a \"type your own answer\" free-text field —\n * rendered natively as a wizard in the TUI, the Dashboard, and over RPC. The\n * whole batch is answered together and returned as one result. Answering,\n * stopping the turn, aborting, or timing out always settles cleanly so the\n * agent never deadlocks on an absent user. Unanswered questions come back\n * flagged as skipped rather than blocking the turn.\n */\n\nimport { Text } from \"@dreb/tui\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { Value } from \"@sinclair/typebox/value\";\nimport type { AskQuestion, AskRequest, AskResult, ExtensionContext, ToolDefinition } from \"../extensions/types.js\";\n\n// ============================================================================\n// Types\n\n/** One question's outcome, surfaced in the tool result details. */\nexport interface AskUserAnswerDetail {\n\tquestion: string;\n\ttitle?: string;\n\tselected: string[];\n\tcustomText?: string;\n\t/** True when this question closed without an answer. */\n\tskipped: boolean;\n}\n\nexport interface AskUserDetails {\n\t/** One entry per question asked, in order. */\n\tanswers: AskUserAnswerDetail[];\n\t/** True when no interactive UI was available (headless/print mode). */\n\tunavailable: boolean;\n\t/** True when the UI host or response protocol failed. */\n\tfailed?: boolean;\n}\n\n// ============================================================================\n// Schema\n\n/** Nonblank text: at least one non-whitespace character (llama.cpp-parseable pattern). */\nconst NONBLANK_PATTERN = \"^.*[^ \\\\t\\\\r\\\\n].*$\";\n\n/**\n * One option: plain text, or a labeled object (the shape many models are\n * trained on). Objects are folded back to plain text before reaching any UI.\n */\nconst optionSchema = Type.Union([\n\tType.String({ minLength: 1, pattern: NONBLANK_PATTERN }),\n\tType.Object({\n\t\tlabel: Type.String({ minLength: 1, pattern: NONBLANK_PATTERN }),\n\t\tdescription: Type.Optional(Type.String()),\n\t}),\n]);\n\nconst questionSchema = Type.Object({\n\tquestion: Type.String({\n\t\tdescription: \"The Markdown-formatted question to ask the user. Be specific about what you need to decide.\",\n\t}),\n\ttitle: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Short bold title shown above this question.\",\n\t\t}),\n\t),\n\theader: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Alias for title; title wins when both are given.\",\n\t\t}),\n\t),\n\toptions: Type.Optional(\n\t\tType.Array(optionSchema, {\n\t\t\tminItems: 2,\n\t\t\tmaxItems: 4,\n\t\t\tdescription: \"2-4 nonblank suggested answers the user can pick from.\",\n\t\t}),\n\t),\n\tallowFreeText: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Offer a 'type your own answer' field. Defaults to true.\",\n\t\t}),\n\t),\n\tmultiSelect: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Allow selecting multiple options (checkboxes). Only meaningful with options.\",\n\t\t}),\n\t),\n\tmultiline: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription: \"Use a large multi-line text area for open-ended answers.\",\n\t\t}),\n\t),\n});\n\nconst questionsArraySchema = Type.Array(questionSchema, {\n\tminItems: 1,\n\tmaxItems: 10,\n\tdescription:\n\t\t\"One or more clarifying questions to ask together in a single wizard. \" +\n\t\t\"Batch every question you need answered in one call — the user answers them all and submits once.\",\n});\n\nconst askUserSchema = Type.Object({\n\t// A JSON-encoded string of the array is also accepted; it is parsed and\n\t// checked against the same array schema in execute.\n\tquestions: Type.Union([questionsArraySchema, Type.String()]),\n\ttimeoutSeconds: Type.Optional(\n\t\tType.Number({\n\t\t\tminimum: 5,\n\t\t\tmaximum: 3600,\n\t\t\tdescription:\n\t\t\t\t\"Optional: stop the current agent turn after this many seconds if the user does not respond. \" +\n\t\t\t\t\"Shows a live countdown. Omit to wait indefinitely.\",\n\t\t}),\n\t),\n});\n\nexport type AskUserInput = Static<typeof askUserSchema>;\ntype AskUserQuestion = Static<typeof questionSchema>;\ntype AskUserOption = Static<typeof optionSchema>;\n\n// ============================================================================\n// Normalization\n\n/** Fold an option to plain text: \"label\" or \"label — description\". */\nfunction optionText(option: AskUserOption): string {\n\tif (typeof option === \"string\") return option;\n\tconst description = option.description?.trim();\n\treturn description ? `${option.label} — ${description}` : option.label;\n}\n\n/**\n * Resolve `questions` to an array. A JSON-encoded string is parsed and checked\n * against the same schema as a real array; anything invalid throws.\n */\nfunction resolveQuestions(questions: AskUserInput[\"questions\"]): AskUserQuestion[] {\n\tif (typeof questions !== \"string\") return questions;\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(questions);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`ask_user: \\`questions\\` was a string but not valid JSON (${error instanceof Error ? error.message : String(error)}). Pass \\`questions\\` as an array of question objects.`,\n\t\t);\n\t}\n\tif (!Value.Check(questionsArraySchema, parsed)) {\n\t\tconst errors = [...Value.Errors(questionsArraySchema, parsed)]\n\t\t\t.slice(0, 10)\n\t\t\t.map((e) => ` - ${e.path || \"questions\"}: ${e.message}`)\n\t\t\t.join(\"\\n\");\n\t\tthrow new Error(\n\t\t\t`ask_user: \\`questions\\` was a JSON string that is not a valid questions array:\\n${errors}\\nPass \\`questions\\` as an array of question objects.`,\n\t\t);\n\t}\n\treturn parsed;\n}\n\n/**\n * Normalize a single question so every rendered surface has at least one usable\n * answer control and no impossible flag combinations survive.\n */\nfunction normalizeQuestion(q: AskUserQuestion): AskQuestion {\n\tconst options = q.options?.map(optionText);\n\tconst hasOptions = (options?.length ?? 0) > 0;\n\treturn {\n\t\tquestion: q.question,\n\t\ttitle: q.title ?? q.header,\n\t\toptions,\n\t\t// Guarantee at least one answer control: with no options, free text must\n\t\t// be offered regardless of the requested flag, otherwise a question would\n\t\t// render only a Skip control and no way to answer.\n\t\tallowFreeText: hasOptions ? q.allowFreeText : true,\n\t\t// multiSelect is only meaningful with options; multiline only with free\n\t\t// text — normalize away impossible combinations.\n\t\tmultiSelect: hasOptions ? q.multiSelect : undefined,\n\t\tmultiline: hasOptions ? (q.allowFreeText === false ? undefined : q.multiline) : q.multiline,\n\t};\n}\n\n// ============================================================================\n// Result helpers\n\nfunction textResult(text: string, details: AskUserDetails) {\n\treturn {\n\t\tcontent: [{ type: \"text\" as const, text }],\n\t\tdetails,\n\t};\n}\n\nfunction skippedAnswer(q: AskQuestion): AskUserAnswerDetail {\n\treturn { question: q.question, title: q.title, selected: [], skipped: true };\n}\n\nfunction unavailableResult(questions: AskQuestion[]) {\n\treturn textResult(\n\t\t\"The ask_user tool requires an interactive UI, which is not available in this mode. \" +\n\t\t\t\"Proceed using your best judgment without waiting for an answer.\",\n\t\t{ answers: questions.map(skippedAnswer), unavailable: true },\n\t);\n}\n\nfunction unansweredResult(questions: AskQuestion[]) {\n\treturn textResult(\"The questions closed without an answer.\", {\n\t\tanswers: questions.map(skippedAnswer),\n\t\tunavailable: false,\n\t});\n}\n\nfunction failedResult(questions: AskQuestion[]) {\n\treturn textResult(\n\t\t\"The questions could not be delivered because the interactive UI or response protocol failed. \" +\n\t\t\t\"Continue without this input.\",\n\t\t{ answers: questions.map(skippedAnswer), unavailable: false, failed: true },\n\t);\n}\n\n/** Build a per-question detail entry from the user's answer. */\nfunction toAnswerDetail(q: AskQuestion, answer: AskResult[\"answers\"][number] | undefined): AskUserAnswerDetail {\n\tif (!answer || answer.skipped) return skippedAnswer(q);\n\tconst customText = answer.customText?.trim() || undefined;\n\tconst selected = answer.selected ?? [];\n\tif (selected.length === 0 && !customText) return skippedAnswer(q);\n\treturn { question: q.question, title: q.title, selected, customText, skipped: false };\n}\n\n/** Compose the model-facing summary, one block per question. */\nfunction summarizeAnswers(details: AskUserAnswerDetail[]): string {\n\tconst blocks = details.map((d) => {\n\t\tconst heading = (d.title || d.question || \"\").replace(/\\s+/g, \" \").trim();\n\t\tif (d.skipped) return `**${heading}** → (no answer)`;\n\t\tconst parts: string[] = [];\n\t\tif (d.selected.length > 0) parts.push(`Selected: ${d.selected.join(\", \")}`);\n\t\tif (d.customText) parts.push(`wrote: \"${d.customText}\"`);\n\t\treturn `**${heading}** → ${parts.join(\" / \")}`;\n\t});\n\treturn blocks.join(\"\\n\");\n}\n\nfunction answeredResult(questions: AskQuestion[], result: AskResult) {\n\tconst details = questions.map((q, i) => toAnswerDetail(q, result.answers[i]));\n\treturn textResult(summarizeAnswers(details), { answers: details, unavailable: false });\n}\n\n// ============================================================================\n// Render helpers\n\ntype CallArgs = { questions?: Array<{ title?: string; header?: string; question?: string }> | string } | undefined;\n\nfunction callLabel(args: CallArgs): string {\n\t// While streaming (or for a JSON-string batch) questions may not be an array yet.\n\tconst questions = Array.isArray(args?.questions) ? args.questions : [];\n\tif (typeof args?.questions === \"string\") return \"questions\";\n\tconst count = questions.length;\n\tif (count === 1) {\n\t\tconst first = questions[0];\n\t\tconst label = (first?.title || first?.header || first?.question || \"\").replace(/\\s+/g, \" \").trim();\n\t\treturn label.length > 80 ? `${label.slice(0, 79)}…` : label;\n\t}\n\treturn `${count} questions`;\n}\n\nfunction formatCall(args: CallArgs, theme: any): string {\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"ask_user\"))} ${theme.fg(\"accent\", callLabel(args))}`;\n}\n\nfunction formatResult(details: AskUserDetails, theme: any): string {\n\tif (details.unavailable) return theme.fg(\"toolOutput\", \"no interactive UI — continued without asking\");\n\tif (details.failed) return theme.fg(\"toolOutput\", \"interactive UI failed — continued without an answer\");\n\tconst answered = details.answers.filter((a) => !a.skipped);\n\tif (answered.length === 0) return theme.fg(\"toolOutput\", \"closed without an answer\");\n\tif (details.answers.length === 1) {\n\t\tconst parts: string[] = [];\n\t\tif (answered[0].selected.length > 0) parts.push(answered[0].selected.join(\", \"));\n\t\tif (answered[0].customText) parts.push(`\"${answered[0].customText}\"`);\n\t\treturn theme.fg(\"toolOutput\", `→ ${parts.join(\" + \")}`);\n\t}\n\treturn theme.fg(\"toolOutput\", `→ answered ${answered.length} of ${details.answers.length}`);\n}\n\n// ============================================================================\n// Tool definition factory\n\n/**\n * Create an `ask_user` tool definition.\n *\n * One call carries one or more questions, collected together in a single\n * wizard and returned as a batch of answers. Every path — answer, skip, abort,\n * timeout, or host failure — settles gracefully and never orphans a promise.\n */\nexport function createAskUserToolDefinition(): ToolDefinition<typeof askUserSchema, AskUserDetails | undefined> {\n\treturn {\n\t\tname: \"ask_user\",\n\t\tlabel: \"ask_user\",\n\t\tdescription:\n\t\t\t\"Pause and ask the user one or more structured clarifying questions in a single call, each with \" +\n\t\t\t\"optional multiple-choice options and a free-text answer. The questions are shown together as one \" +\n\t\t\t\"wizard and answered as a batch. Use only when genuinely blocked by ambiguity with multiple viable \" +\n\t\t\t\"paths — not for routine confirmation.\",\n\n\t\tparameters: askUserSchema,\n\n\t\tpromptSnippet:\n\t\t\t\"Ask the user one or more clarifying questions with optional multiple-choice options and free text\",\n\n\t\tpromptGuidelines: [\n\t\t\t\"Call ask_user ONLY when you are genuinely blocked by ambiguity and there are multiple viable paths forward\",\n\t\t\t\"Do NOT use it for routine confirmation, permission, or things you can reasonably decide yourself\",\n\t\t\t\"Batch everything you need in ONE call: put each distinct decision in the `questions` array — the user answers them all and submits once\",\n\t\t\t\"Provide 2-4 concrete `options` per question (plain strings) when there are clear candidate answers; the user can always type their own\",\n\t\t\t\"Set `multiSelect: true` when several options can be combined; `multiline: true` for open-ended answers\",\n\t\t\t\"The user may stop the current turn instead of answering; never treat that as an answer, and unanswered questions come back as skipped\",\n\t\t],\n\n\t\tasync execute(_toolCallId, input: AskUserInput, signal, _onUpdate, ctx?: ExtensionContext) {\n\t\t\tconst questions = resolveQuestions(input.questions).map(normalizeQuestion);\n\t\t\tconst request: AskRequest = { questions };\n\n\t\t\t// Optional auto-stop timeout, forwarded to every UI surface (TUI\n\t\t\t// countdown, RPC/Dashboard). Model-facing units are seconds.\n\t\t\tconst timeout = input.timeoutSeconds && input.timeoutSeconds > 0 ? input.timeoutSeconds * 1000 : undefined;\n\n\t\t\t// Headless / print / no-host modes: never block on an unreachable UI.\n\t\t\tif (!ctx?.hasUI) {\n\t\t\t\treturn unavailableResult(questions);\n\t\t\t}\n\n\t\t\t// A call whose signal already aborted settles without ever opening the\n\t\t\t// UI; the parent turn is already stopping.\n\t\t\tif (signal?.aborted) return unansweredResult(questions);\n\n\t\t\ttry {\n\t\t\t\tconst answer = await ctx.ui.ask(request, { signal, timeout });\n\t\t\t\tif (!answer) return unansweredResult(questions);\n\t\t\t\treturn answeredResult(questions, answer);\n\t\t\t} catch {\n\t\t\t\t// Host/protocol failure must still settle and never deadlock, but it\n\t\t\t\t// must not masquerade as an intentional user skip.\n\t\t\t\treturn failedResult(questions);\n\t\t\t}\n\t\t},\n\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0, undefined, true);\n\t\t\ttext.setText(formatCall(args, theme));\n\t\t\treturn text;\n\t\t},\n\n\t\trenderResult(result, _options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0, undefined, true);\n\t\t\tconst details = (result as any).details as AskUserDetails | undefined;\n\t\t\tif (details) {\n\t\t\t\ttext.setText(formatResult(details, theme));\n\t\t\t} else {\n\t\t\t\tconst content = result.content?.[0];\n\t\t\t\ttext.setText(theme.fg(\"toolOutput\", content?.type === \"text\" ? content.text : \"\"));\n\t\t\t}\n\t\t\treturn text;\n\t\t},\n\t};\n}\n"]}
|
|
@@ -193,14 +193,18 @@ export declare const allToolDefinitions: {
|
|
|
193
193
|
rebuild: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
194
194
|
}>, import("./search.js").SearchToolDetails, any>;
|
|
195
195
|
ask_user: ToolDefinition<import("@sinclair/typebox").TObject<{
|
|
196
|
-
questions: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
196
|
+
questions: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
197
197
|
question: import("@sinclair/typebox").TString;
|
|
198
198
|
title: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
199
|
-
|
|
199
|
+
header: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
200
|
+
options: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TObject<{
|
|
201
|
+
label: import("@sinclair/typebox").TString;
|
|
202
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
203
|
+
}>]>>>;
|
|
200
204
|
allowFreeText: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
201
205
|
multiSelect: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
202
206
|
multiline: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
203
|
-
}
|
|
207
|
+
}>>, import("@sinclair/typebox").TString]>;
|
|
204
208
|
timeoutSeconds: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
205
209
|
}>, import("./ask-user.js").AskUserDetails | undefined, any>;
|
|
206
210
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/tools/index.ts"],"names":[],"mappings":"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","sourcesContent":["export {\n\ttype AskUserAnswerDetail,\n\ttype AskUserDetails,\n\ttype AskUserInput,\n\tcreateAskUserToolDefinition,\n} from \"./ask-user.js\";\nexport {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tbashTool,\n\tbashToolDefinition,\n\tcreateBashTool,\n\tcreateBashToolDefinition,\n\tcreateLocalBashOperations,\n} from \"./bash.js\";\nexport {\n\tcreateEditTool,\n\tcreateEditToolDefinition,\n\ttype EditOperations,\n\ttype EditToolDetails,\n\ttype EditToolInput,\n\ttype EditToolOptions,\n\teditTool,\n\teditToolDefinition,\n} from \"./edit.js\";\nexport { withFileMutationQueue } from \"./file-mutation-queue.js\";\nexport {\n\tcreateFindTool,\n\tcreateFindToolDefinition,\n\ttype FindOperations,\n\ttype FindToolDetails,\n\ttype FindToolInput,\n\ttype FindToolOptions,\n\tfindTool,\n\tfindToolDefinition,\n} from \"./find.js\";\nexport {\n\tcreateGrepTool,\n\tcreateGrepToolDefinition,\n\ttype GrepOperations,\n\ttype GrepToolDetails,\n\ttype GrepToolInput,\n\ttype GrepToolOptions,\n\tgrepTool,\n\tgrepToolDefinition,\n} from \"./grep.js\";\nexport {\n\tcreateLsTool,\n\tcreateLsToolDefinition,\n\ttype LsOperations,\n\ttype LsToolDetails,\n\ttype LsToolInput,\n\ttype LsToolOptions,\n\tlsTool,\n\tlsToolDefinition,\n} from \"./ls.js\";\nexport {\n\tcreateReadTool,\n\tcreateReadToolDefinition,\n\ttype ReadOperations,\n\ttype ReadToolDetails,\n\ttype ReadToolInput,\n\ttype ReadToolOptions,\n\treadTool,\n\treadToolDefinition,\n} from \"./read.js\";\nexport {\n\tcreateSearchTool,\n\tcreateSearchToolDefinition,\n\tisSearchAvailable,\n\ttype SearchToolDetails,\n\ttype SearchToolInput,\n\tsearchTool,\n\tsearchToolDefinition,\n} from \"./search.js\";\nexport {\n\tcreateSkillTool,\n\tcreateSkillToolDefinition,\n\ttype SkillToolDetails,\n\ttype SkillToolInput,\n\ttype SkillToolOptions,\n} from \"./skill.js\";\nexport {\n\tabortBackgroundAgents,\n\ttype BackgroundAgentInfo,\n\tcreateSubagentConcurrencyGate,\n\tcreateSubagentTool,\n\tcreateSubagentToolDefinition,\n\tdiscoverAgentTypes,\n\tfilterSubagentTools,\n\tgetBackgroundAgents,\n\tgetRunningBackgroundAgents,\n\tpruneBackgroundAgents,\n\ttype SubagentArbitrationEvent,\n\ttype SubagentConcurrencyGate,\n\ttype SubagentResult,\n\ttype SubagentStepMetadata,\n\ttype SubagentToolDetails,\n\ttype SubagentToolInput,\n\ttype SubagentToolOptions,\n\tsubagentTool,\n\tsubagentToolDefinition,\n} from \"./subagent.js\";\nexport {\n\tcreateSuggestNextToolDefinition,\n\ttype SuggestNextCallback,\n\ttype SuggestNextDetails,\n\ttype SuggestNextInput,\n} from \"./suggest-next.js\";\nexport {\n\tcreateTasksToolDefinition,\n\ttype SessionTask,\n\ttype TaskStatus,\n\ttype TasksToolDetails,\n\ttype TasksToolInput,\n\ttype TasksUpdateCallback,\n} from \"./tasks.js\";\nexport { createTmpReadToolDefinition } from \"./tmp-read.js\";\nexport {\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\tformatSize,\n\ttype TruncationOptions,\n\ttype TruncationResult,\n\ttruncateHead,\n\ttruncateLine,\n\ttruncateTail,\n} from \"./truncate.js\";\nexport {\n\tcreateWaitToolDefinition,\n\tformatWaitCall,\n\tformatWaitResult,\n\ttype WaitAgentInfo,\n\ttype WaitToolDetails,\n\ttype WaitToolInput,\n\ttype WaitToolOptions,\n\twaitToolDefinition,\n} from \"./wait.js\";\nexport {\n\tcreateLocalGithubCiOperations,\n\tcreateWatchGithubCiTool,\n\tcreateWatchGithubCiToolDefinition,\n\ttype GithubCiOperations,\n\ttype WatchGithubCiToolDetails,\n\ttype WatchGithubCiToolInput,\n\ttype WatchGithubCiToolOptions,\n\twatchGithubCiTool,\n\twatchGithubCiToolDefinition,\n} from \"./watch-github-ci.js\";\nexport {\n\tcreateWebFetchTool,\n\tcreateWebFetchToolDefinition,\n\tcreateWebSearchTool,\n\tcreateWebSearchToolDefinition,\n\ttype WebFetchToolDetails,\n\ttype WebFetchToolInput,\n\ttype WebSearchConfig,\n\ttype WebSearchToolDetails,\n\ttype WebSearchToolInput,\n\twebFetchTool,\n\twebFetchToolDefinition,\n\twebSearchTool,\n\twebSearchToolDefinition,\n} from \"./web.js\";\nexport {\n\tcreateWriteTool,\n\tcreateWriteToolDefinition,\n\ttype WriteOperations,\n\ttype WriteToolInput,\n\ttype WriteToolOptions,\n\twriteTool,\n\twriteToolDefinition,\n} from \"./write.js\";\n\nimport type { AgentTool } from \"@dreb/agent-core\";\nimport type { ToolDefinition } from \"../extensions/types.js\";\nimport { createAskUserToolDefinition } from \"./ask-user.js\";\nimport {\n\ttype BashToolOptions,\n\tbashTool,\n\tbashToolDefinition,\n\tcreateBashTool,\n\tcreateBashToolDefinition,\n} from \"./bash.js\";\nimport { createEditTool, createEditToolDefinition, editTool, editToolDefinition } from \"./edit.js\";\nimport { createFindTool, createFindToolDefinition, findTool, findToolDefinition } from \"./find.js\";\nimport { createGrepTool, createGrepToolDefinition, grepTool, grepToolDefinition } from \"./grep.js\";\nimport { createLsTool, createLsToolDefinition, lsTool, lsToolDefinition } from \"./ls.js\";\nimport {\n\tcreateReadTool,\n\tcreateReadToolDefinition,\n\ttype ReadToolOptions,\n\treadTool,\n\treadToolDefinition,\n} from \"./read.js\";\nimport { createSearchTool, createSearchToolDefinition, searchTool, searchToolDefinition } from \"./search.js\";\nimport { createSkillTool, createSkillToolDefinition, type SkillToolOptions } from \"./skill.js\";\nimport {\n\tcreateSubagentTool,\n\tcreateSubagentToolDefinition,\n\tgetRunningBackgroundAgents,\n\ttype SubagentToolOptions,\n\tsubagentTool,\n\tsubagentToolDefinition,\n} from \"./subagent.js\";\nimport { createSuggestNextToolDefinition, type SuggestNextCallback } from \"./suggest-next.js\";\nimport { createTasksToolDefinition, type TasksUpdateCallback } from \"./tasks.js\";\nimport { createTmpReadToolDefinition } from \"./tmp-read.js\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.js\";\nimport { createWaitToolDefinition, waitToolDefinition } from \"./wait.js\";\nimport {\n\tcreateWatchGithubCiTool,\n\tcreateWatchGithubCiToolDefinition,\n\twatchGithubCiTool,\n\twatchGithubCiToolDefinition,\n} from \"./watch-github-ci.js\";\nimport {\n\tcreateWebFetchTool,\n\tcreateWebFetchToolDefinition,\n\tcreateWebSearchTool,\n\tcreateWebSearchToolDefinition,\n\twebFetchTool,\n\twebFetchToolDefinition,\n\twebSearchTool,\n\twebSearchToolDefinition,\n} from \"./web.js\";\nimport { createWriteTool, createWriteToolDefinition, writeTool, writeToolDefinition } from \"./write.js\";\n\nexport type Tool = AgentTool<any>;\nexport type ToolDef = ToolDefinition<any, any>;\n\nexport const codingTools: Tool[] = [readTool, bashTool, editTool, writeTool];\nexport const readOnlyTools: Tool[] = [readTool, grepTool, findTool, lsTool];\n\nconst tmpReadToolDefinition = createTmpReadToolDefinition();\nconst tmpReadTool = wrapToolDefinition(tmpReadToolDefinition);\nconst waitTool = wrapToolDefinition(waitToolDefinition);\nconst askUserToolDefinition = createAskUserToolDefinition();\nconst askUserTool = wrapToolDefinition(askUserToolDefinition);\n\nexport const allTools = {\n\tread: readTool,\n\tbash: bashTool,\n\tedit: editTool,\n\twrite: writeTool,\n\tgrep: grepTool,\n\tfind: findTool,\n\tls: lsTool,\n\tweb_search: webSearchTool,\n\tweb_fetch: webFetchTool,\n\tsubagent: subagentTool,\n\ttmp_read: tmpReadTool,\n\twait: waitTool,\n\twatch_github_ci: watchGithubCiTool,\n\tsearch: searchTool,\n\task_user: askUserTool,\n};\n\nexport const allToolDefinitions = {\n\tread: readToolDefinition,\n\tbash: bashToolDefinition,\n\tedit: editToolDefinition,\n\twrite: writeToolDefinition,\n\tgrep: grepToolDefinition,\n\tfind: findToolDefinition,\n\tls: lsToolDefinition,\n\tweb_search: webSearchToolDefinition,\n\tweb_fetch: webFetchToolDefinition,\n\tsubagent: subagentToolDefinition,\n\ttmp_read: tmpReadToolDefinition,\n\twait: waitToolDefinition,\n\twatch_github_ci: watchGithubCiToolDefinition,\n\tsearch: searchToolDefinition,\n\task_user: askUserToolDefinition,\n};\n\nexport type ToolName = keyof typeof allTools;\n\nexport interface ToolsOptions {\n\tread?: ReadToolOptions;\n\tbash?: BashToolOptions;\n\tsubagent?: SubagentToolOptions;\n\tskill?: SkillToolOptions;\n\ttasks?: { onUpdate: TasksUpdateCallback };\n\tsuggestNext?: { onSuggest: SuggestNextCallback };\n}\n\nexport function createCodingToolDefinitions(cwd: string, options?: ToolsOptions): ToolDef[] {\n\treturn [\n\t\tcreateReadToolDefinition(cwd, options?.read),\n\t\tcreateBashToolDefinition(cwd, options?.bash),\n\t\tcreateEditToolDefinition(cwd),\n\t\tcreateWriteToolDefinition(cwd),\n\t];\n}\n\nexport function createReadOnlyToolDefinitions(cwd: string, options?: ToolsOptions): ToolDef[] {\n\treturn [\n\t\tcreateReadToolDefinition(cwd, options?.read),\n\t\tcreateGrepToolDefinition(cwd),\n\t\tcreateFindToolDefinition(cwd),\n\t\tcreateLsToolDefinition(cwd),\n\t];\n}\n\nexport function createAllToolDefinitions(cwd: string, options?: ToolsOptions): Record<ToolName | \"skill\", ToolDef> {\n\tconst tools: Record<string, ToolDef> = {\n\t\tread: createReadToolDefinition(cwd, options?.read),\n\t\tbash: createBashToolDefinition(cwd, options?.bash),\n\t\tedit: createEditToolDefinition(cwd),\n\t\twrite: createWriteToolDefinition(cwd),\n\t\tgrep: createGrepToolDefinition(cwd),\n\t\tfind: createFindToolDefinition(cwd),\n\t\tls: createLsToolDefinition(cwd),\n\t\tweb_search: createWebSearchToolDefinition(cwd),\n\t\tweb_fetch: createWebFetchToolDefinition(cwd),\n\t\tsubagent: createSubagentToolDefinition(cwd, options?.subagent),\n\t\ttmp_read: createTmpReadToolDefinition(options?.read),\n\t\twait: createWaitToolDefinition({ getRunningAgents: getRunningBackgroundAgents }),\n\t\twatch_github_ci: createWatchGithubCiToolDefinition(cwd),\n\t\tsearch: createSearchToolDefinition(cwd),\n\t\task_user: createAskUserToolDefinition(),\n\t};\n\tif (options?.skill) {\n\t\ttools.skill = createSkillToolDefinition(cwd, options.skill);\n\t}\n\tif (options?.tasks) {\n\t\ttools.tasks_update = createTasksToolDefinition(options.tasks.onUpdate);\n\t}\n\tif (options?.suggestNext) {\n\t\ttools.suggest_next = createSuggestNextToolDefinition(options.suggestNext.onSuggest);\n\t}\n\treturn tools as Record<ToolName | \"skill\", ToolDef>;\n}\n\nexport function createCodingTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [\n\t\tcreateReadTool(cwd, options?.read),\n\t\tcreateBashTool(cwd, options?.bash),\n\t\tcreateEditTool(cwd),\n\t\tcreateWriteTool(cwd),\n\t];\n}\n\nexport function createReadOnlyTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [createReadTool(cwd, options?.read), createGrepTool(cwd), createFindTool(cwd), createLsTool(cwd)];\n}\n\nexport function createAllTools(cwd: string, options?: ToolsOptions): Record<ToolName | \"skill\", Tool> {\n\tconst tools: Record<string, Tool> = {\n\t\tread: createReadTool(cwd, options?.read),\n\t\tbash: createBashTool(cwd, options?.bash),\n\t\tedit: createEditTool(cwd),\n\t\twrite: createWriteTool(cwd),\n\t\tgrep: createGrepTool(cwd),\n\t\tfind: createFindTool(cwd),\n\t\tls: createLsTool(cwd),\n\t\tweb_search: createWebSearchTool(cwd),\n\t\tweb_fetch: createWebFetchTool(cwd),\n\t\tsubagent: createSubagentTool(cwd, options?.subagent),\n\t\ttmp_read: wrapToolDefinition(createTmpReadToolDefinition(options?.read)),\n\t\twait: wrapToolDefinition(createWaitToolDefinition({ getRunningAgents: getRunningBackgroundAgents })),\n\t\twatch_github_ci: createWatchGithubCiTool(cwd),\n\t\tsearch: createSearchTool(cwd),\n\t\task_user: wrapToolDefinition(createAskUserToolDefinition()),\n\t};\n\tif (options?.skill) {\n\t\ttools.skill = createSkillTool(cwd, options.skill);\n\t}\n\tif (options?.tasks) {\n\t\ttools.tasks_update = wrapToolDefinition(createTasksToolDefinition(options.tasks.onUpdate));\n\t}\n\tif (options?.suggestNext) {\n\t\ttools.suggest_next = wrapToolDefinition(createSuggestNextToolDefinition(options.suggestNext.onSuggest));\n\t}\n\treturn tools as Record<ToolName | \"skill\", Tool>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/tools/index.ts"],"names":[],"mappings":"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","sourcesContent":["export {\n\ttype AskUserAnswerDetail,\n\ttype AskUserDetails,\n\ttype AskUserInput,\n\tcreateAskUserToolDefinition,\n} from \"./ask-user.js\";\nexport {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tbashTool,\n\tbashToolDefinition,\n\tcreateBashTool,\n\tcreateBashToolDefinition,\n\tcreateLocalBashOperations,\n} from \"./bash.js\";\nexport {\n\tcreateEditTool,\n\tcreateEditToolDefinition,\n\ttype EditOperations,\n\ttype EditToolDetails,\n\ttype EditToolInput,\n\ttype EditToolOptions,\n\teditTool,\n\teditToolDefinition,\n} from \"./edit.js\";\nexport { withFileMutationQueue } from \"./file-mutation-queue.js\";\nexport {\n\tcreateFindTool,\n\tcreateFindToolDefinition,\n\ttype FindOperations,\n\ttype FindToolDetails,\n\ttype FindToolInput,\n\ttype FindToolOptions,\n\tfindTool,\n\tfindToolDefinition,\n} from \"./find.js\";\nexport {\n\tcreateGrepTool,\n\tcreateGrepToolDefinition,\n\ttype GrepOperations,\n\ttype GrepToolDetails,\n\ttype GrepToolInput,\n\ttype GrepToolOptions,\n\tgrepTool,\n\tgrepToolDefinition,\n} from \"./grep.js\";\nexport {\n\tcreateLsTool,\n\tcreateLsToolDefinition,\n\ttype LsOperations,\n\ttype LsToolDetails,\n\ttype LsToolInput,\n\ttype LsToolOptions,\n\tlsTool,\n\tlsToolDefinition,\n} from \"./ls.js\";\nexport {\n\tcreateReadTool,\n\tcreateReadToolDefinition,\n\ttype ReadOperations,\n\ttype ReadToolDetails,\n\ttype ReadToolInput,\n\ttype ReadToolOptions,\n\treadTool,\n\treadToolDefinition,\n} from \"./read.js\";\nexport {\n\tcreateSearchTool,\n\tcreateSearchToolDefinition,\n\tisSearchAvailable,\n\ttype SearchToolDetails,\n\ttype SearchToolInput,\n\tsearchTool,\n\tsearchToolDefinition,\n} from \"./search.js\";\nexport {\n\tcreateSkillTool,\n\tcreateSkillToolDefinition,\n\ttype SkillToolDetails,\n\ttype SkillToolInput,\n\ttype SkillToolOptions,\n} from \"./skill.js\";\nexport {\n\tabortBackgroundAgents,\n\ttype BackgroundAgentInfo,\n\tcreateSubagentConcurrencyGate,\n\tcreateSubagentTool,\n\tcreateSubagentToolDefinition,\n\tdiscoverAgentTypes,\n\tfilterSubagentTools,\n\tgetBackgroundAgents,\n\tgetRunningBackgroundAgents,\n\tpruneBackgroundAgents,\n\ttype SubagentArbitrationEvent,\n\ttype SubagentConcurrencyGate,\n\ttype SubagentResult,\n\ttype SubagentStepMetadata,\n\ttype SubagentToolDetails,\n\ttype SubagentToolInput,\n\ttype SubagentToolOptions,\n\tsubagentTool,\n\tsubagentToolDefinition,\n} from \"./subagent.js\";\nexport {\n\tcreateSuggestNextToolDefinition,\n\ttype SuggestNextCallback,\n\ttype SuggestNextDetails,\n\ttype SuggestNextInput,\n} from \"./suggest-next.js\";\nexport {\n\tcreateTasksToolDefinition,\n\ttype SessionTask,\n\ttype TaskStatus,\n\ttype TasksToolDetails,\n\ttype TasksToolInput,\n\ttype TasksUpdateCallback,\n} from \"./tasks.js\";\nexport { createTmpReadToolDefinition } from \"./tmp-read.js\";\nexport {\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\tformatSize,\n\ttype TruncationOptions,\n\ttype TruncationResult,\n\ttruncateHead,\n\ttruncateLine,\n\ttruncateTail,\n} from \"./truncate.js\";\nexport {\n\tcreateWaitToolDefinition,\n\tformatWaitCall,\n\tformatWaitResult,\n\ttype WaitAgentInfo,\n\ttype WaitToolDetails,\n\ttype WaitToolInput,\n\ttype WaitToolOptions,\n\twaitToolDefinition,\n} from \"./wait.js\";\nexport {\n\tcreateLocalGithubCiOperations,\n\tcreateWatchGithubCiTool,\n\tcreateWatchGithubCiToolDefinition,\n\ttype GithubCiOperations,\n\ttype WatchGithubCiToolDetails,\n\ttype WatchGithubCiToolInput,\n\ttype WatchGithubCiToolOptions,\n\twatchGithubCiTool,\n\twatchGithubCiToolDefinition,\n} from \"./watch-github-ci.js\";\nexport {\n\tcreateWebFetchTool,\n\tcreateWebFetchToolDefinition,\n\tcreateWebSearchTool,\n\tcreateWebSearchToolDefinition,\n\ttype WebFetchToolDetails,\n\ttype WebFetchToolInput,\n\ttype WebSearchConfig,\n\ttype WebSearchToolDetails,\n\ttype WebSearchToolInput,\n\twebFetchTool,\n\twebFetchToolDefinition,\n\twebSearchTool,\n\twebSearchToolDefinition,\n} from \"./web.js\";\nexport {\n\tcreateWriteTool,\n\tcreateWriteToolDefinition,\n\ttype WriteOperations,\n\ttype WriteToolInput,\n\ttype WriteToolOptions,\n\twriteTool,\n\twriteToolDefinition,\n} from \"./write.js\";\n\nimport type { AgentTool } from \"@dreb/agent-core\";\nimport type { ToolDefinition } from \"../extensions/types.js\";\nimport { createAskUserToolDefinition } from \"./ask-user.js\";\nimport {\n\ttype BashToolOptions,\n\tbashTool,\n\tbashToolDefinition,\n\tcreateBashTool,\n\tcreateBashToolDefinition,\n} from \"./bash.js\";\nimport { createEditTool, createEditToolDefinition, editTool, editToolDefinition } from \"./edit.js\";\nimport { createFindTool, createFindToolDefinition, findTool, findToolDefinition } from \"./find.js\";\nimport { createGrepTool, createGrepToolDefinition, grepTool, grepToolDefinition } from \"./grep.js\";\nimport { createLsTool, createLsToolDefinition, lsTool, lsToolDefinition } from \"./ls.js\";\nimport {\n\tcreateReadTool,\n\tcreateReadToolDefinition,\n\ttype ReadToolOptions,\n\treadTool,\n\treadToolDefinition,\n} from \"./read.js\";\nimport { createSearchTool, createSearchToolDefinition, searchTool, searchToolDefinition } from \"./search.js\";\nimport { createSkillTool, createSkillToolDefinition, type SkillToolOptions } from \"./skill.js\";\nimport {\n\tcreateSubagentTool,\n\tcreateSubagentToolDefinition,\n\tgetRunningBackgroundAgents,\n\ttype SubagentToolOptions,\n\tsubagentTool,\n\tsubagentToolDefinition,\n} from \"./subagent.js\";\nimport { createSuggestNextToolDefinition, type SuggestNextCallback } from \"./suggest-next.js\";\nimport { createTasksToolDefinition, type TasksUpdateCallback } from \"./tasks.js\";\nimport { createTmpReadToolDefinition } from \"./tmp-read.js\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.js\";\nimport { createWaitToolDefinition, waitToolDefinition } from \"./wait.js\";\nimport {\n\tcreateWatchGithubCiTool,\n\tcreateWatchGithubCiToolDefinition,\n\twatchGithubCiTool,\n\twatchGithubCiToolDefinition,\n} from \"./watch-github-ci.js\";\nimport {\n\tcreateWebFetchTool,\n\tcreateWebFetchToolDefinition,\n\tcreateWebSearchTool,\n\tcreateWebSearchToolDefinition,\n\twebFetchTool,\n\twebFetchToolDefinition,\n\twebSearchTool,\n\twebSearchToolDefinition,\n} from \"./web.js\";\nimport { createWriteTool, createWriteToolDefinition, writeTool, writeToolDefinition } from \"./write.js\";\n\nexport type Tool = AgentTool<any>;\nexport type ToolDef = ToolDefinition<any, any>;\n\nexport const codingTools: Tool[] = [readTool, bashTool, editTool, writeTool];\nexport const readOnlyTools: Tool[] = [readTool, grepTool, findTool, lsTool];\n\nconst tmpReadToolDefinition = createTmpReadToolDefinition();\nconst tmpReadTool = wrapToolDefinition(tmpReadToolDefinition);\nconst waitTool = wrapToolDefinition(waitToolDefinition);\nconst askUserToolDefinition = createAskUserToolDefinition();\nconst askUserTool = wrapToolDefinition(askUserToolDefinition);\n\nexport const allTools = {\n\tread: readTool,\n\tbash: bashTool,\n\tedit: editTool,\n\twrite: writeTool,\n\tgrep: grepTool,\n\tfind: findTool,\n\tls: lsTool,\n\tweb_search: webSearchTool,\n\tweb_fetch: webFetchTool,\n\tsubagent: subagentTool,\n\ttmp_read: tmpReadTool,\n\twait: waitTool,\n\twatch_github_ci: watchGithubCiTool,\n\tsearch: searchTool,\n\task_user: askUserTool,\n};\n\nexport const allToolDefinitions = {\n\tread: readToolDefinition,\n\tbash: bashToolDefinition,\n\tedit: editToolDefinition,\n\twrite: writeToolDefinition,\n\tgrep: grepToolDefinition,\n\tfind: findToolDefinition,\n\tls: lsToolDefinition,\n\tweb_search: webSearchToolDefinition,\n\tweb_fetch: webFetchToolDefinition,\n\tsubagent: subagentToolDefinition,\n\ttmp_read: tmpReadToolDefinition,\n\twait: waitToolDefinition,\n\twatch_github_ci: watchGithubCiToolDefinition,\n\tsearch: searchToolDefinition,\n\task_user: askUserToolDefinition,\n};\n\nexport type ToolName = keyof typeof allTools;\n\nexport interface ToolsOptions {\n\tread?: ReadToolOptions;\n\tbash?: BashToolOptions;\n\tsubagent?: SubagentToolOptions;\n\tskill?: SkillToolOptions;\n\ttasks?: { onUpdate: TasksUpdateCallback };\n\tsuggestNext?: { onSuggest: SuggestNextCallback };\n}\n\nexport function createCodingToolDefinitions(cwd: string, options?: ToolsOptions): ToolDef[] {\n\treturn [\n\t\tcreateReadToolDefinition(cwd, options?.read),\n\t\tcreateBashToolDefinition(cwd, options?.bash),\n\t\tcreateEditToolDefinition(cwd),\n\t\tcreateWriteToolDefinition(cwd),\n\t];\n}\n\nexport function createReadOnlyToolDefinitions(cwd: string, options?: ToolsOptions): ToolDef[] {\n\treturn [\n\t\tcreateReadToolDefinition(cwd, options?.read),\n\t\tcreateGrepToolDefinition(cwd),\n\t\tcreateFindToolDefinition(cwd),\n\t\tcreateLsToolDefinition(cwd),\n\t];\n}\n\nexport function createAllToolDefinitions(cwd: string, options?: ToolsOptions): Record<ToolName | \"skill\", ToolDef> {\n\tconst tools: Record<string, ToolDef> = {\n\t\tread: createReadToolDefinition(cwd, options?.read),\n\t\tbash: createBashToolDefinition(cwd, options?.bash),\n\t\tedit: createEditToolDefinition(cwd),\n\t\twrite: createWriteToolDefinition(cwd),\n\t\tgrep: createGrepToolDefinition(cwd),\n\t\tfind: createFindToolDefinition(cwd),\n\t\tls: createLsToolDefinition(cwd),\n\t\tweb_search: createWebSearchToolDefinition(cwd),\n\t\tweb_fetch: createWebFetchToolDefinition(cwd),\n\t\tsubagent: createSubagentToolDefinition(cwd, options?.subagent),\n\t\ttmp_read: createTmpReadToolDefinition(options?.read),\n\t\twait: createWaitToolDefinition({ getRunningAgents: getRunningBackgroundAgents }),\n\t\twatch_github_ci: createWatchGithubCiToolDefinition(cwd),\n\t\tsearch: createSearchToolDefinition(cwd),\n\t\task_user: createAskUserToolDefinition(),\n\t};\n\tif (options?.skill) {\n\t\ttools.skill = createSkillToolDefinition(cwd, options.skill);\n\t}\n\tif (options?.tasks) {\n\t\ttools.tasks_update = createTasksToolDefinition(options.tasks.onUpdate);\n\t}\n\tif (options?.suggestNext) {\n\t\ttools.suggest_next = createSuggestNextToolDefinition(options.suggestNext.onSuggest);\n\t}\n\treturn tools as Record<ToolName | \"skill\", ToolDef>;\n}\n\nexport function createCodingTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [\n\t\tcreateReadTool(cwd, options?.read),\n\t\tcreateBashTool(cwd, options?.bash),\n\t\tcreateEditTool(cwd),\n\t\tcreateWriteTool(cwd),\n\t];\n}\n\nexport function createReadOnlyTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [createReadTool(cwd, options?.read), createGrepTool(cwd), createFindTool(cwd), createLsTool(cwd)];\n}\n\nexport function createAllTools(cwd: string, options?: ToolsOptions): Record<ToolName | \"skill\", Tool> {\n\tconst tools: Record<string, Tool> = {\n\t\tread: createReadTool(cwd, options?.read),\n\t\tbash: createBashTool(cwd, options?.bash),\n\t\tedit: createEditTool(cwd),\n\t\twrite: createWriteTool(cwd),\n\t\tgrep: createGrepTool(cwd),\n\t\tfind: createFindTool(cwd),\n\t\tls: createLsTool(cwd),\n\t\tweb_search: createWebSearchTool(cwd),\n\t\tweb_fetch: createWebFetchTool(cwd),\n\t\tsubagent: createSubagentTool(cwd, options?.subagent),\n\t\ttmp_read: wrapToolDefinition(createTmpReadToolDefinition(options?.read)),\n\t\twait: wrapToolDefinition(createWaitToolDefinition({ getRunningAgents: getRunningBackgroundAgents })),\n\t\twatch_github_ci: createWatchGithubCiTool(cwd),\n\t\tsearch: createSearchTool(cwd),\n\t\task_user: wrapToolDefinition(createAskUserToolDefinition()),\n\t};\n\tif (options?.skill) {\n\t\ttools.skill = createSkillTool(cwd, options.skill);\n\t}\n\tif (options?.tasks) {\n\t\ttools.tasks_update = wrapToolDefinition(createTasksToolDefinition(options.tasks.onUpdate));\n\t}\n\tif (options?.suggestNext) {\n\t\ttools.suggest_next = wrapToolDefinition(createSuggestNextToolDefinition(options.suggestNext.onSuggest));\n\t}\n\treturn tools as Record<ToolName | \"skill\", Tool>;\n}\n"]}
|