@kata-sh/cli 0.1.0 → 0.1.2
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/LICENSE +21 -0
- package/README.md +156 -0
- package/dist/app-paths.d.ts +4 -0
- package/dist/app-paths.js +6 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +56 -0
- package/dist/loader.d.ts +2 -0
- package/dist/loader.js +95 -0
- package/dist/resource-loader.d.ts +18 -0
- package/dist/resource-loader.js +50 -0
- package/dist/wizard.d.ts +15 -0
- package/dist/wizard.js +159 -0
- package/package.json +50 -21
- package/pkg/dist/modes/interactive/theme/dark.json +85 -0
- package/pkg/dist/modes/interactive/theme/light.json +84 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/pkg/dist/modes/interactive/theme/theme.d.ts +78 -0
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/pkg/dist/modes/interactive/theme/theme.js +949 -0
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -0
- package/pkg/package.json +8 -0
- package/scripts/postinstall.js +45 -0
- package/src/resources/AGENTS.md +108 -0
- package/src/resources/KATA-WORKFLOW.md +661 -0
- package/src/resources/agents/researcher.md +29 -0
- package/src/resources/agents/scout.md +56 -0
- package/src/resources/agents/worker.md +31 -0
- package/src/resources/extensions/ask-user-questions.ts +200 -0
- package/src/resources/extensions/bg-shell/index.ts +2758 -0
- package/src/resources/extensions/browser-tools/BROWSER-TOOLS-V2-PROPOSAL.md +1277 -0
- package/src/resources/extensions/browser-tools/core.js +1057 -0
- package/src/resources/extensions/browser-tools/index.ts +4916 -0
- package/src/resources/extensions/browser-tools/package.json +20 -0
- package/src/resources/extensions/context7/index.ts +428 -0
- package/src/resources/extensions/context7/package.json +11 -0
- package/src/resources/extensions/get-secrets-from-user.ts +352 -0
- package/src/resources/extensions/github/formatters.ts +207 -0
- package/src/resources/extensions/github/gh-api.ts +537 -0
- package/src/resources/extensions/github/index.ts +778 -0
- package/src/resources/extensions/kata/activity-log.ts +88 -0
- package/src/resources/extensions/kata/auto.ts +2786 -0
- package/src/resources/extensions/kata/commands.ts +355 -0
- package/src/resources/extensions/kata/crash-recovery.ts +85 -0
- package/src/resources/extensions/kata/dashboard-overlay.ts +516 -0
- package/src/resources/extensions/kata/docs/preferences-reference.md +103 -0
- package/src/resources/extensions/kata/doctor.ts +683 -0
- package/src/resources/extensions/kata/files.ts +730 -0
- package/src/resources/extensions/kata/gitignore.ts +165 -0
- package/src/resources/extensions/kata/guided-flow.ts +976 -0
- package/src/resources/extensions/kata/index.ts +556 -0
- package/src/resources/extensions/kata/metrics.ts +397 -0
- package/src/resources/extensions/kata/observability-validator.ts +408 -0
- package/src/resources/extensions/kata/package.json +11 -0
- package/src/resources/extensions/kata/paths.ts +346 -0
- package/src/resources/extensions/kata/preferences.ts +695 -0
- package/src/resources/extensions/kata/prompt-loader.ts +50 -0
- package/src/resources/extensions/kata/prompts/complete-milestone.md +25 -0
- package/src/resources/extensions/kata/prompts/complete-slice.md +27 -0
- package/src/resources/extensions/kata/prompts/discuss.md +151 -0
- package/src/resources/extensions/kata/prompts/doctor-heal.md +29 -0
- package/src/resources/extensions/kata/prompts/execute-task.md +64 -0
- package/src/resources/extensions/kata/prompts/guided-complete-slice.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-discuss-milestone.md +3 -0
- package/src/resources/extensions/kata/prompts/guided-discuss-slice.md +59 -0
- package/src/resources/extensions/kata/prompts/guided-execute-task.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-plan-milestone.md +23 -0
- package/src/resources/extensions/kata/prompts/guided-plan-slice.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-research-slice.md +11 -0
- package/src/resources/extensions/kata/prompts/guided-resume-task.md +1 -0
- package/src/resources/extensions/kata/prompts/plan-milestone.md +47 -0
- package/src/resources/extensions/kata/prompts/plan-slice.md +63 -0
- package/src/resources/extensions/kata/prompts/queue.md +85 -0
- package/src/resources/extensions/kata/prompts/reassess-roadmap.md +48 -0
- package/src/resources/extensions/kata/prompts/replan-slice.md +39 -0
- package/src/resources/extensions/kata/prompts/research-milestone.md +37 -0
- package/src/resources/extensions/kata/prompts/research-slice.md +28 -0
- package/src/resources/extensions/kata/prompts/run-uat.md +109 -0
- package/src/resources/extensions/kata/prompts/system.md +341 -0
- package/src/resources/extensions/kata/session-forensics.ts +550 -0
- package/src/resources/extensions/kata/skill-discovery.ts +137 -0
- package/src/resources/extensions/kata/state.ts +509 -0
- package/src/resources/extensions/kata/templates/context.md +76 -0
- package/src/resources/extensions/kata/templates/decisions.md +8 -0
- package/src/resources/extensions/kata/templates/milestone-summary.md +73 -0
- package/src/resources/extensions/kata/templates/plan.md +133 -0
- package/src/resources/extensions/kata/templates/preferences.md +15 -0
- package/src/resources/extensions/kata/templates/project.md +31 -0
- package/src/resources/extensions/kata/templates/reassessment.md +28 -0
- package/src/resources/extensions/kata/templates/requirements.md +81 -0
- package/src/resources/extensions/kata/templates/research.md +46 -0
- package/src/resources/extensions/kata/templates/roadmap.md +118 -0
- package/src/resources/extensions/kata/templates/slice-context.md +58 -0
- package/src/resources/extensions/kata/templates/slice-summary.md +99 -0
- package/src/resources/extensions/kata/templates/state.md +19 -0
- package/src/resources/extensions/kata/templates/task-plan.md +52 -0
- package/src/resources/extensions/kata/templates/task-summary.md +57 -0
- package/src/resources/extensions/kata/templates/uat.md +54 -0
- package/src/resources/extensions/kata/tests/activity-log-prune.test.ts +327 -0
- package/src/resources/extensions/kata/tests/auto-preflight.test.ts +97 -0
- package/src/resources/extensions/kata/tests/auto-supervisor.test.mjs +53 -0
- package/src/resources/extensions/kata/tests/complete-milestone.test.ts +317 -0
- package/src/resources/extensions/kata/tests/cost-projection.test.ts +160 -0
- package/src/resources/extensions/kata/tests/derive-state-deps.test.ts +477 -0
- package/src/resources/extensions/kata/tests/derive-state.test.ts +1013 -0
- package/src/resources/extensions/kata/tests/doctor.test.ts +718 -0
- package/src/resources/extensions/kata/tests/idle-recovery.test.ts +490 -0
- package/src/resources/extensions/kata/tests/metrics-io.test.ts +254 -0
- package/src/resources/extensions/kata/tests/metrics.test.ts +217 -0
- package/src/resources/extensions/kata/tests/must-have-parser.test.ts +309 -0
- package/src/resources/extensions/kata/tests/parsers.test.ts +1257 -0
- package/src/resources/extensions/kata/tests/plan-milestone.test.ts +185 -0
- package/src/resources/extensions/kata/tests/plan-quality-validator.test.ts +386 -0
- package/src/resources/extensions/kata/tests/reassess-prompt.test.ts +208 -0
- package/src/resources/extensions/kata/tests/replan-slice.test.ts +686 -0
- package/src/resources/extensions/kata/tests/requirements.test.ts +151 -0
- package/src/resources/extensions/kata/tests/resolve-ts-hooks.mjs +17 -0
- package/src/resources/extensions/kata/tests/resolve-ts.mjs +11 -0
- package/src/resources/extensions/kata/tests/run-uat.test.ts +383 -0
- package/src/resources/extensions/kata/tests/unit-runtime.test.ts +388 -0
- package/src/resources/extensions/kata/tests/workspace-index.test.ts +118 -0
- package/src/resources/extensions/kata/tests/worktree.test.ts +222 -0
- package/src/resources/extensions/kata/types.ts +159 -0
- package/src/resources/extensions/kata/unit-runtime.ts +163 -0
- package/src/resources/extensions/kata/workspace-index.ts +203 -0
- package/src/resources/extensions/kata/worktree.ts +182 -0
- package/src/resources/extensions/mac-tools/index.ts +852 -0
- package/src/resources/extensions/mac-tools/swift-cli/Package.swift +22 -0
- package/src/resources/extensions/mac-tools/swift-cli/Sources/main.swift +1318 -0
- package/src/resources/extensions/search-the-web/cache.ts +78 -0
- package/src/resources/extensions/search-the-web/format.ts +258 -0
- package/src/resources/extensions/search-the-web/http.ts +238 -0
- package/src/resources/extensions/search-the-web/index.ts +68 -0
- package/src/resources/extensions/search-the-web/tool-fetch-page.ts +519 -0
- package/src/resources/extensions/search-the-web/tool-llm-context.ts +404 -0
- package/src/resources/extensions/search-the-web/tool-search.ts +503 -0
- package/src/resources/extensions/search-the-web/url-utils.ts +91 -0
- package/src/resources/extensions/shared/confirm-ui.ts +126 -0
- package/src/resources/extensions/shared/interview-ui.ts +822 -0
- package/src/resources/extensions/shared/next-action-ui.ts +235 -0
- package/src/resources/extensions/shared/progress-widget.ts +282 -0
- package/src/resources/extensions/shared/thinking-widget.ts +107 -0
- package/src/resources/extensions/shared/ui.ts +400 -0
- package/src/resources/extensions/shared/wizard-ui.ts +551 -0
- package/src/resources/extensions/slash-commands/audit.ts +92 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +375 -0
- package/src/resources/extensions/slash-commands/create-slash-command.ts +280 -0
- package/src/resources/extensions/slash-commands/index.ts +12 -0
- package/src/resources/extensions/slash-commands/kata-run.ts +34 -0
- package/src/resources/extensions/subagent/agents.ts +126 -0
- package/src/resources/extensions/subagent/index.ts +1293 -0
- package/src/resources/skills/debug-like-expert/SKILL.md +231 -0
- package/src/resources/skills/debug-like-expert/references/debugging-mindset.md +253 -0
- package/src/resources/skills/debug-like-expert/references/hypothesis-testing.md +373 -0
- package/src/resources/skills/debug-like-expert/references/investigation-techniques.md +337 -0
- package/src/resources/skills/debug-like-expert/references/verification-patterns.md +425 -0
- package/src/resources/skills/debug-like-expert/references/when-to-research.md +361 -0
- package/src/resources/skills/frontend-design/SKILL.md +45 -0
- package/src/resources/skills/swiftui/SKILL.md +208 -0
- package/src/resources/skills/swiftui/references/animations.md +921 -0
- package/src/resources/skills/swiftui/references/architecture.md +1561 -0
- package/src/resources/skills/swiftui/references/layout-system.md +1186 -0
- package/src/resources/skills/swiftui/references/navigation.md +1492 -0
- package/src/resources/skills/swiftui/references/networking-async.md +214 -0
- package/src/resources/skills/swiftui/references/performance.md +1706 -0
- package/src/resources/skills/swiftui/references/platform-integration.md +204 -0
- package/src/resources/skills/swiftui/references/state-management.md +1443 -0
- package/src/resources/skills/swiftui/references/swiftdata.md +297 -0
- package/src/resources/skills/swiftui/references/testing-debugging.md +247 -0
- package/src/resources/skills/swiftui/references/uikit-appkit-interop.md +218 -0
- package/src/resources/skills/swiftui/workflows/add-feature.md +191 -0
- package/src/resources/skills/swiftui/workflows/build-new-app.md +311 -0
- package/src/resources/skills/swiftui/workflows/debug-swiftui.md +192 -0
- package/src/resources/skills/swiftui/workflows/optimize-performance.md +197 -0
- package/src/resources/skills/swiftui/workflows/ship-app.md +203 -0
- package/src/resources/skills/swiftui/workflows/write-tests.md +235 -0
- package/dist/commands/task.d.ts +0 -9
- package/dist/commands/task.d.ts.map +0 -1
- package/dist/commands/task.js +0 -129
- package/dist/commands/task.js.map +0 -1
- package/dist/commands/task.test.d.ts +0 -2
- package/dist/commands/task.test.d.ts.map +0 -1
- package/dist/commands/task.test.js +0 -169
- package/dist/commands/task.test.js.map +0 -1
- package/dist/e2e/task-e2e.test.d.ts +0 -2
- package/dist/e2e/task-e2e.test.d.ts.map +0 -1
- package/dist/e2e/task-e2e.test.js +0 -173
- package/dist/e2e/task-e2e.test.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -93
- package/dist/index.js.map +0 -1
- package/dist/slug.d.ts +0 -2
- package/dist/slug.d.ts.map +0 -1
- package/dist/slug.js +0 -12
- package/dist/slug.js.map +0 -1
- package/dist/slug.test.d.ts +0 -2
- package/dist/slug.test.d.ts.map +0 -1
- package/dist/slug.test.js +0 -32
- package/dist/slug.test.js.map +0 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scout
|
|
3
|
+
description: Fast codebase recon that returns compressed context for handoff to other agents
|
|
4
|
+
tools: read, grep, find, ls, bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are a scout. Quickly investigate a codebase and return structured findings that another agent can use without re-reading everything.
|
|
8
|
+
|
|
9
|
+
Your output will be passed to an agent who has NOT seen the files you explored.
|
|
10
|
+
|
|
11
|
+
Thoroughness (infer from task, default medium):
|
|
12
|
+
|
|
13
|
+
- Quick: Targeted lookups, key files only
|
|
14
|
+
- Medium: Follow imports, read critical sections
|
|
15
|
+
- Thorough: Trace all dependencies, check tests/types
|
|
16
|
+
|
|
17
|
+
Strategy:
|
|
18
|
+
|
|
19
|
+
1. grep/find to locate relevant code
|
|
20
|
+
2. Read key sections (not entire files)
|
|
21
|
+
3. Identify types, interfaces, key functions
|
|
22
|
+
4. Note dependencies between files
|
|
23
|
+
|
|
24
|
+
Output format:
|
|
25
|
+
|
|
26
|
+
## Files Retrieved
|
|
27
|
+
|
|
28
|
+
List with exact line ranges:
|
|
29
|
+
|
|
30
|
+
1. `path/to/file.ts` (lines 10-50) - Description of what's here
|
|
31
|
+
2. `path/to/other.ts` (lines 100-150) - Description
|
|
32
|
+
3. ...
|
|
33
|
+
|
|
34
|
+
## Key Code
|
|
35
|
+
|
|
36
|
+
Critical types, interfaces, or functions:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
interface Example {
|
|
40
|
+
// actual code from the files
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
function keyFunction() {
|
|
46
|
+
// actual implementation
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Architecture
|
|
51
|
+
|
|
52
|
+
Brief explanation of how the pieces connect.
|
|
53
|
+
|
|
54
|
+
## Start Here
|
|
55
|
+
|
|
56
|
+
Which file to look at first and why.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: worker
|
|
3
|
+
description: General-purpose subagent with full capabilities, isolated context
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are a worker agent with full capabilities. You operate in an isolated context window to handle delegated tasks without polluting the main conversation.
|
|
7
|
+
|
|
8
|
+
Work autonomously to complete the assigned task. Use all available tools as needed, with one important restriction:
|
|
9
|
+
|
|
10
|
+
- Do **not** spawn subagents or act as an orchestrator unless the parent task explicitly instructs you to do so.
|
|
11
|
+
- If the task looks like Kata orchestration, planning, scouting, parallel dispatch, or review routing, stop and report that the caller should use the appropriate specialist agent instead (for example: `kata-worker`, `kata-scout`, `kata-reviewer`, or the top-level orchestrator).
|
|
12
|
+
- In particular, do **not** call `kata_scout`, `subagent`, `launch_parallel_view`, or `kata_execute_parallel` on your own initiative.
|
|
13
|
+
|
|
14
|
+
Output format when finished:
|
|
15
|
+
|
|
16
|
+
## Completed
|
|
17
|
+
|
|
18
|
+
What was done.
|
|
19
|
+
|
|
20
|
+
## Files Changed
|
|
21
|
+
|
|
22
|
+
- `path/to/file.ts` - what changed
|
|
23
|
+
|
|
24
|
+
## Notes (if any)
|
|
25
|
+
|
|
26
|
+
Anything the main agent should know.
|
|
27
|
+
|
|
28
|
+
If handing off to another agent (e.g. reviewer), include:
|
|
29
|
+
|
|
30
|
+
- Exact file paths changed
|
|
31
|
+
- Key functions/types touched (short list)
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request User Input — LLM tool for asking the user questions
|
|
3
|
+
*
|
|
4
|
+
* Thin wrapper around the shared interview-ui. The LLM presents 1-3
|
|
5
|
+
* questions with 2-3 options each. Each question can be single-select (default)
|
|
6
|
+
* or multi-select (allowMultiple: true). A free-form "None of the above" option
|
|
7
|
+
* is added automatically to single-select questions.
|
|
8
|
+
*
|
|
9
|
+
* Based on: https://github.com/openai/codex (codex-rs/core/src/tools/handlers/ask_user_questions.rs)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
13
|
+
import { Text } from "@mariozechner/pi-tui";
|
|
14
|
+
import { Type } from "@sinclair/typebox";
|
|
15
|
+
import {
|
|
16
|
+
showInterviewRound,
|
|
17
|
+
type Question,
|
|
18
|
+
type QuestionOption,
|
|
19
|
+
type RoundResult,
|
|
20
|
+
} from "./shared/interview-ui.js";
|
|
21
|
+
|
|
22
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
interface AskUserQuestionsDetails {
|
|
25
|
+
questions: Question[];
|
|
26
|
+
response: RoundResult | null;
|
|
27
|
+
cancelled: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ─── Schema ───────────────────────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
const OptionSchema = Type.Object({
|
|
33
|
+
label: Type.String({ description: "User-facing label (1-5 words)" }),
|
|
34
|
+
description: Type.String({ description: "One short sentence explaining impact/tradeoff if selected" }),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const QuestionSchema = Type.Object({
|
|
38
|
+
id: Type.String({ description: "Stable identifier for mapping answers (snake_case)" }),
|
|
39
|
+
header: Type.String({ description: "Short header label shown in the UI (12 or fewer chars)" }),
|
|
40
|
+
question: Type.String({ description: "Single-sentence prompt shown to the user" }),
|
|
41
|
+
options: Type.Array(OptionSchema, {
|
|
42
|
+
description:
|
|
43
|
+
'Provide 2-3 mutually exclusive choices for single-select, or any number for multi-select. Put the recommended option first and suffix its label with "(Recommended)". Do not include an "Other" option for single-select; the client adds a free-form "None of the above" option automatically.',
|
|
44
|
+
}),
|
|
45
|
+
allowMultiple: Type.Optional(
|
|
46
|
+
Type.Boolean({
|
|
47
|
+
description:
|
|
48
|
+
"If true, the user can select multiple options using SPACE to toggle and ENTER to confirm. No 'None of the above' option is added. Default: false.",
|
|
49
|
+
}),
|
|
50
|
+
),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const AskUserQuestionsParams = Type.Object({
|
|
54
|
+
questions: Type.Array(QuestionSchema, {
|
|
55
|
+
description: "Questions to show the user. Prefer 1 and do not exceed 3.",
|
|
56
|
+
}),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
const OTHER_OPTION_LABEL = "None of the above";
|
|
62
|
+
|
|
63
|
+
function errorResult(
|
|
64
|
+
message: string,
|
|
65
|
+
questions: Question[] = [],
|
|
66
|
+
): { content: { type: "text"; text: string }[]; details: AskUserQuestionsDetails } {
|
|
67
|
+
return {
|
|
68
|
+
content: [{ type: "text", text: message }],
|
|
69
|
+
details: { questions, response: null, cancelled: true },
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Convert the shared RoundResult into the JSON the LLM expects. */
|
|
74
|
+
function formatForLLM(result: RoundResult): string {
|
|
75
|
+
const answers: Record<string, { answers: string[] }> = {};
|
|
76
|
+
for (const [id, answer] of Object.entries(result.answers)) {
|
|
77
|
+
const list: string[] = [];
|
|
78
|
+
if (Array.isArray(answer.selected)) {
|
|
79
|
+
list.push(...answer.selected);
|
|
80
|
+
} else {
|
|
81
|
+
list.push(answer.selected);
|
|
82
|
+
}
|
|
83
|
+
if (answer.notes) {
|
|
84
|
+
list.push(`user_note: ${answer.notes}`);
|
|
85
|
+
}
|
|
86
|
+
answers[id] = { answers: list };
|
|
87
|
+
}
|
|
88
|
+
return JSON.stringify({ answers });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ─── Extension ────────────────────────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
export default function AskUserQuestions(pi: ExtensionAPI) {
|
|
94
|
+
pi.registerTool({
|
|
95
|
+
name: "ask_user_questions",
|
|
96
|
+
label: "Request User Input",
|
|
97
|
+
description:
|
|
98
|
+
"Request user input for one to three short questions and wait for the response. Single-select questions have 2-3 mutually exclusive options with a free-form 'None of the above' added automatically. Multi-select questions (allowMultiple: true) let the user toggle multiple options with SPACE and confirm with ENTER.",
|
|
99
|
+
promptGuidelines: [
|
|
100
|
+
"Use ask_user_questions when you need the user to choose between concrete alternatives before proceeding.",
|
|
101
|
+
"Keep questions to 1 when possible; never exceed 3.",
|
|
102
|
+
"For single-select: each question must have 2-3 options. Put the recommended option first with '(Recommended)' suffix. Do not include an 'Other' or 'None of the above' option - the client adds one automatically.",
|
|
103
|
+
"For multi-select: set allowMultiple: true. The user can pick any number of options. No 'None of the above' is added.",
|
|
104
|
+
],
|
|
105
|
+
parameters: AskUserQuestionsParams,
|
|
106
|
+
|
|
107
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
108
|
+
// Validation
|
|
109
|
+
if (params.questions.length === 0 || params.questions.length > 3) {
|
|
110
|
+
return errorResult("Error: questions must contain 1-3 items", params.questions);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for (const q of params.questions) {
|
|
114
|
+
if (!q.options || q.options.length === 0) {
|
|
115
|
+
return errorResult(
|
|
116
|
+
`Error: ask_user_questions requires non-empty options for every question (question "${q.id}" has none)`,
|
|
117
|
+
params.questions,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!ctx.hasUI) {
|
|
123
|
+
return errorResult("Error: UI not available (non-interactive mode)", params.questions);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Delegate to shared interview UI
|
|
127
|
+
const result = await showInterviewRound(params.questions, {}, ctx);
|
|
128
|
+
|
|
129
|
+
// Check if cancelled (empty answers = user exited)
|
|
130
|
+
const hasAnswers = Object.keys(result.answers).length > 0;
|
|
131
|
+
if (!hasAnswers) {
|
|
132
|
+
return {
|
|
133
|
+
content: [{ type: "text", text: "ask_user_questions was cancelled before receiving a response" }],
|
|
134
|
+
details: { questions: params.questions, response: null, cancelled: true } as AskUserQuestionsDetails,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
content: [{ type: "text", text: formatForLLM(result) }],
|
|
140
|
+
details: { questions: params.questions, response: result, cancelled: false } as AskUserQuestionsDetails,
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
// ─── Rendering ────────────────────────────────────────────────────────
|
|
145
|
+
|
|
146
|
+
renderCall(args, theme) {
|
|
147
|
+
const qs = (args.questions as Question[]) || [];
|
|
148
|
+
let text = theme.fg("toolTitle", theme.bold("ask_user_questions "));
|
|
149
|
+
text += theme.fg("muted", `${qs.length} question${qs.length !== 1 ? "s" : ""}`);
|
|
150
|
+
if (qs.length > 0) {
|
|
151
|
+
const headers = qs.map((q) => q.header).join(", ");
|
|
152
|
+
text += theme.fg("dim", ` (${headers})`);
|
|
153
|
+
}
|
|
154
|
+
for (const q of qs) {
|
|
155
|
+
const multiSel = !!q.allowMultiple;
|
|
156
|
+
text += `\n ${theme.fg("text", q.question)}`;
|
|
157
|
+
const optLabels = multiSel
|
|
158
|
+
? (q.options || []).map((o: QuestionOption) => o.label)
|
|
159
|
+
: [...(q.options || []).map((o: QuestionOption) => o.label), OTHER_OPTION_LABEL];
|
|
160
|
+
const prefix = multiSel ? "☐" : "";
|
|
161
|
+
const numbered = optLabels.map((l, i) => `${prefix}${i + 1}. ${l}`).join(", ");
|
|
162
|
+
text += `\n ${theme.fg("dim", numbered)}`;
|
|
163
|
+
}
|
|
164
|
+
return new Text(text, 0, 0);
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
renderResult(result, _options, theme) {
|
|
168
|
+
const details = result.details as AskUserQuestionsDetails | undefined;
|
|
169
|
+
if (!details) {
|
|
170
|
+
const text = result.content[0];
|
|
171
|
+
return new Text(text?.type === "text" ? text.text : "", 0, 0);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (details.cancelled || !details.response) {
|
|
175
|
+
return new Text(theme.fg("warning", "Cancelled"), 0, 0);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const lines: string[] = [];
|
|
179
|
+
for (const q of details.questions) {
|
|
180
|
+
const answer = details.response.answers[q.id];
|
|
181
|
+
if (!answer) {
|
|
182
|
+
lines.push(`${theme.fg("accent", q.header)}: ${theme.fg("dim", "(no answer)")}`);
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
const selected = answer.selected;
|
|
186
|
+
const notes = answer.notes;
|
|
187
|
+
const multiSel = !!q.allowMultiple;
|
|
188
|
+
const answerText = multiSel && Array.isArray(selected)
|
|
189
|
+
? selected.join(", ")
|
|
190
|
+
: (Array.isArray(selected) ? selected[0] : selected) ?? "(no answer)";
|
|
191
|
+
let line = `${theme.fg("success", "✓ ")}${theme.fg("accent", q.header)}: ${answerText}`;
|
|
192
|
+
if (notes) {
|
|
193
|
+
line += ` ${theme.fg("muted", `[note: ${notes}]`)}`;
|
|
194
|
+
}
|
|
195
|
+
lines.push(line);
|
|
196
|
+
}
|
|
197
|
+
return new Text(lines.join("\n"), 0, 0);
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
}
|