gencode-ai 0.1.2 → 0.1.3
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/CLAUDE.md +86 -0
- package/README.md +14 -17
- package/dist/agent/agent.d.ts +8 -0
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +14 -1
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/types.d.ts +14 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/cli/components/App.d.ts.map +1 -1
- package/dist/cli/components/App.js +38 -3
- package/dist/cli/components/App.js.map +1 -1
- package/dist/cli/components/Messages.d.ts.map +1 -1
- package/dist/cli/components/Messages.js +17 -0
- package/dist/cli/components/Messages.js.map +1 -1
- package/dist/cli/components/QuestionPrompt.d.ts +23 -0
- package/dist/cli/components/QuestionPrompt.d.ts.map +1 -0
- package/dist/cli/components/QuestionPrompt.js +231 -0
- package/dist/cli/components/QuestionPrompt.js.map +1 -0
- package/dist/cli/components/index.d.ts +1 -0
- package/dist/cli/components/index.d.ts.map +1 -1
- package/dist/cli/components/index.js +1 -0
- package/dist/cli/components/index.js.map +1 -1
- package/dist/cli/components/theme.d.ts +7 -0
- package/dist/cli/components/theme.d.ts.map +1 -1
- package/dist/cli/components/theme.js +11 -1
- package/dist/cli/components/theme.js.map +1 -1
- package/dist/permissions/types.d.ts.map +1 -1
- package/dist/permissions/types.js +2 -0
- package/dist/permissions/types.js.map +1 -1
- package/dist/tools/builtin/ask-user.d.ts +64 -0
- package/dist/tools/builtin/ask-user.d.ts.map +1 -0
- package/dist/tools/builtin/ask-user.js +148 -0
- package/dist/tools/builtin/ask-user.js.map +1 -0
- package/dist/tools/index.d.ts +12 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/types.d.ts +17 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js.map +1 -1
- package/docs/proposals/0012-ask-user-question.md +66 -1
- package/docs/proposals/README.md +1 -1
- package/examples/test-ask-user.ts +167 -0
- package/package.json +1 -1
- package/src/agent/agent.ts +20 -1
- package/src/agent/index.ts +1 -0
- package/src/agent/types.ts +13 -1
- package/src/cli/components/App.tsx +55 -3
- package/src/cli/components/Messages.tsx +43 -0
- package/src/cli/components/QuestionPrompt.tsx +462 -0
- package/src/cli/components/index.ts +1 -0
- package/src/cli/components/theme.ts +11 -1
- package/src/permissions/types.ts +2 -0
- package/src/prompts/system/base.txt +42 -0
- package/src/prompts/tools/ask-user.txt +110 -0
- package/src/tools/builtin/ask-user.ts +185 -0
- package/src/tools/index.ts +15 -0
- package/src/tools/types.ts +18 -0
|
@@ -61,6 +61,48 @@ When making changes to files, first understand the file's code conventions. Mimi
|
|
|
61
61
|
- Do not add docstrings, type annotations, or comments to code you didn't change
|
|
62
62
|
- Keep solutions simple and focused. Only make changes directly requested or clearly necessary.
|
|
63
63
|
|
|
64
|
+
# Asking Questions
|
|
65
|
+
|
|
66
|
+
You have access to the AskUserQuestion tool to ask the user questions during execution.
|
|
67
|
+
|
|
68
|
+
CRITICAL: You MUST use the AskUserQuestion tool for ALL questions with choices. NEVER write numbered lists, bullet points, or "which do you prefer" questions as plain text.
|
|
69
|
+
|
|
70
|
+
## Wrong - Plain Text Questions (DO NOT DO THIS)
|
|
71
|
+
|
|
72
|
+
<bad-example>
|
|
73
|
+
user: Set up a new database
|
|
74
|
+
assistant: I can set up a database for you. Which one would you prefer?
|
|
75
|
+
1. PostgreSQL - relational database
|
|
76
|
+
2. MongoDB - document database
|
|
77
|
+
3. SQLite - embedded database
|
|
78
|
+
</bad-example>
|
|
79
|
+
|
|
80
|
+
<bad-example>
|
|
81
|
+
user: Create a new project
|
|
82
|
+
assistant: What type of project?
|
|
83
|
+
- Web app
|
|
84
|
+
- CLI tool
|
|
85
|
+
- API server
|
|
86
|
+
</bad-example>
|
|
87
|
+
|
|
88
|
+
## Correct - Use AskUserQuestion Tool
|
|
89
|
+
|
|
90
|
+
<example>
|
|
91
|
+
user: Set up a new database
|
|
92
|
+
assistant: [uses AskUserQuestion tool with questions: [{question: "Which database?", header: "Database", options: [{label: "PostgreSQL", description: "Relational DB"}, {label: "MongoDB", description: "Document DB"}], multiSelect: false}]]
|
|
93
|
+
</example>
|
|
94
|
+
|
|
95
|
+
<example>
|
|
96
|
+
user: Create a new project
|
|
97
|
+
assistant: [uses AskUserQuestion tool to ask about project type, framework preferences, etc.]
|
|
98
|
+
</example>
|
|
99
|
+
|
|
100
|
+
Use AskUserQuestion when you need to:
|
|
101
|
+
- Gather user preferences (database choice, framework, etc.)
|
|
102
|
+
- Clarify ambiguous instructions with specific options
|
|
103
|
+
- Get decisions on implementation approaches
|
|
104
|
+
- Offer choices about direction to take
|
|
105
|
+
|
|
64
106
|
# Task Management
|
|
65
107
|
|
|
66
108
|
You have access to the TodoWrite tool to manage tasks.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Use this tool when you need to ask the user questions during execution.
|
|
2
|
+
|
|
3
|
+
CRITICAL: You MUST use this tool for ANY question with 2+ choices. NEVER present options as plain text, numbered lists, or bullet points.
|
|
4
|
+
|
|
5
|
+
WRONG (never do this):
|
|
6
|
+
- "Which do you prefer? 1. Option A 2. Option B"
|
|
7
|
+
- "What type? - Web - CLI - API"
|
|
8
|
+
- Writing any numbered or bulleted choices in your response
|
|
9
|
+
|
|
10
|
+
CORRECT: Call this tool with structured questions and options.
|
|
11
|
+
|
|
12
|
+
This allows you to:
|
|
13
|
+
1. Gather user preferences or requirements
|
|
14
|
+
2. Clarify ambiguous instructions
|
|
15
|
+
3. Get decisions on implementation choices as you work
|
|
16
|
+
4. Offer choices to the user about what direction to take
|
|
17
|
+
|
|
18
|
+
## When to Use This Tool
|
|
19
|
+
|
|
20
|
+
Use when you encounter:
|
|
21
|
+
- Ambiguous requirements that could be interpreted multiple ways
|
|
22
|
+
- Technology choices where user preference matters (database, framework, etc.)
|
|
23
|
+
- Implementation approaches with different trade-offs
|
|
24
|
+
- Features or options that should be user-selected
|
|
25
|
+
|
|
26
|
+
## When NOT to Use This Tool
|
|
27
|
+
|
|
28
|
+
Don't use for:
|
|
29
|
+
- Asking "Is my plan ready?" or "Should I proceed?" - just proceed or use planning tools
|
|
30
|
+
- Simple yes/no confirmations - just make a reasonable choice
|
|
31
|
+
- Questions you can answer by reading the codebase
|
|
32
|
+
- Trivial implementation details
|
|
33
|
+
|
|
34
|
+
## Usage Guidelines
|
|
35
|
+
|
|
36
|
+
- Keep headers short (max 12 chars): "Database", "Auth", "Features"
|
|
37
|
+
- Provide 2-4 options per question
|
|
38
|
+
- Put recommended option FIRST and add "(Recommended)" to its label
|
|
39
|
+
- Use multiSelect: true for non-mutually-exclusive options
|
|
40
|
+
- "Other" option is automatically added - don't include it manually
|
|
41
|
+
- Keep option labels concise (1-5 words)
|
|
42
|
+
- Descriptions should explain trade-offs or implications
|
|
43
|
+
|
|
44
|
+
## Examples
|
|
45
|
+
|
|
46
|
+
### Single Choice - Technology Selection
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"questions": [{
|
|
50
|
+
"question": "Which database should we use?",
|
|
51
|
+
"header": "Database",
|
|
52
|
+
"options": [
|
|
53
|
+
{ "label": "PostgreSQL (Recommended)", "description": "Robust relational DB" },
|
|
54
|
+
{ "label": "MongoDB", "description": "Document-based NoSQL" },
|
|
55
|
+
{ "label": "SQLite", "description": "Lightweight embedded DB" }
|
|
56
|
+
],
|
|
57
|
+
"multiSelect": false
|
|
58
|
+
}]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Multi-Select - Feature Selection
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"questions": [{
|
|
66
|
+
"question": "Which features should we enable?",
|
|
67
|
+
"header": "Features",
|
|
68
|
+
"options": [
|
|
69
|
+
{ "label": "TypeScript", "description": "Type safety" },
|
|
70
|
+
{ "label": "ESLint", "description": "Code linting" },
|
|
71
|
+
{ "label": "Testing", "description": "Unit tests" },
|
|
72
|
+
{ "label": "Tailwind", "description": "CSS framework" }
|
|
73
|
+
],
|
|
74
|
+
"multiSelect": true
|
|
75
|
+
}]
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Multiple Questions
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"questions": [
|
|
83
|
+
{
|
|
84
|
+
"question": "Which auth method?",
|
|
85
|
+
"header": "Auth",
|
|
86
|
+
"options": [
|
|
87
|
+
{ "label": "OAuth 2.0 (Recommended)", "description": "Industry standard" },
|
|
88
|
+
{ "label": "JWT", "description": "Stateless tokens" }
|
|
89
|
+
],
|
|
90
|
+
"multiSelect": false
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"question": "Which providers to support?",
|
|
94
|
+
"header": "Providers",
|
|
95
|
+
"options": [
|
|
96
|
+
{ "label": "Google", "description": "Most common" },
|
|
97
|
+
{ "label": "GitHub", "description": "Developer-focused" }
|
|
98
|
+
],
|
|
99
|
+
"multiSelect": true
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Constraints
|
|
106
|
+
|
|
107
|
+
- Maximum 4 questions per call
|
|
108
|
+
- Maximum 4 options per question
|
|
109
|
+
- Header: max 12 characters
|
|
110
|
+
- multiSelect must be explicitly set (required, not optional)
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AskUserQuestion Tool - Structured user questioning
|
|
3
|
+
*
|
|
4
|
+
* Allows the agent to pause execution and present structured questions
|
|
5
|
+
* to the user with predefined options. Supports single-select, multi-select,
|
|
6
|
+
* and custom "Other" input.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import type { Tool, ToolResult, ToolContext } from '../types.js';
|
|
11
|
+
import { loadToolDescription } from '../../prompts/index.js';
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Zod Schemas
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
export const QuestionOptionSchema = z.object({
|
|
18
|
+
label: z
|
|
19
|
+
.string()
|
|
20
|
+
.min(1)
|
|
21
|
+
.max(50)
|
|
22
|
+
.describe('Display text for this option (1-5 words, concise)'),
|
|
23
|
+
description: z
|
|
24
|
+
.string()
|
|
25
|
+
.min(1)
|
|
26
|
+
.max(200)
|
|
27
|
+
.describe('Explanation of what this option means or implications'),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export const QuestionSchema = z.object({
|
|
31
|
+
question: z
|
|
32
|
+
.string()
|
|
33
|
+
.min(1)
|
|
34
|
+
.describe('The complete question to ask the user, ending with a question mark'),
|
|
35
|
+
header: z
|
|
36
|
+
.string()
|
|
37
|
+
.min(1)
|
|
38
|
+
.max(12)
|
|
39
|
+
.describe('Very short label displayed as a chip/tag (max 12 chars)'),
|
|
40
|
+
options: z
|
|
41
|
+
.array(QuestionOptionSchema)
|
|
42
|
+
.min(2)
|
|
43
|
+
.max(4)
|
|
44
|
+
.describe('2-4 options for the user to choose from'),
|
|
45
|
+
multiSelect: z
|
|
46
|
+
.boolean()
|
|
47
|
+
.describe('Set to true to allow multiple selections, false for single choice'),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export const AskUserQuestionInputSchema = z.object({
|
|
51
|
+
questions: z
|
|
52
|
+
.array(QuestionSchema)
|
|
53
|
+
.min(1)
|
|
54
|
+
.max(4)
|
|
55
|
+
.describe('1-4 questions to ask the user'),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Types
|
|
60
|
+
// ============================================================================
|
|
61
|
+
|
|
62
|
+
export type QuestionOption = z.infer<typeof QuestionOptionSchema>;
|
|
63
|
+
export type Question = z.infer<typeof QuestionSchema>;
|
|
64
|
+
export type AskUserQuestionInput = z.infer<typeof AskUserQuestionInputSchema>;
|
|
65
|
+
|
|
66
|
+
export interface QuestionAnswer {
|
|
67
|
+
question: string;
|
|
68
|
+
header: string;
|
|
69
|
+
selectedOptions: string[];
|
|
70
|
+
customInput?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface AskUserQuestionResult {
|
|
74
|
+
answers: QuestionAnswer[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// Answer Formatting
|
|
79
|
+
// ============================================================================
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Format answers for display to the agent
|
|
83
|
+
*/
|
|
84
|
+
export function formatAnswersForAgent(answers: QuestionAnswer[]): string {
|
|
85
|
+
const lines: string[] = ['User answered the following questions:', ''];
|
|
86
|
+
|
|
87
|
+
answers.forEach((answer, index) => {
|
|
88
|
+
lines.push(`${index + 1}. ${answer.header} (${answer.question})`);
|
|
89
|
+
|
|
90
|
+
if (answer.selectedOptions.length > 0) {
|
|
91
|
+
lines.push(` Selected: ${answer.selectedOptions.join(', ')}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (answer.customInput) {
|
|
95
|
+
lines.push(` Custom input: ${answer.customInput}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
lines.push('');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
lines.push('Proceeding with user selections.');
|
|
102
|
+
|
|
103
|
+
return lines.join('\n');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Format answers for CLI confirmation display
|
|
108
|
+
*/
|
|
109
|
+
export function formatAnswersForDisplay(answers: QuestionAnswer[]): string {
|
|
110
|
+
return answers
|
|
111
|
+
.map((answer) => {
|
|
112
|
+
const selections = answer.customInput
|
|
113
|
+
? [...answer.selectedOptions, answer.customInput].join(', ')
|
|
114
|
+
: answer.selectedOptions.join(', ');
|
|
115
|
+
return `✔ ${answer.header}: ${selections}`;
|
|
116
|
+
})
|
|
117
|
+
.join('\n');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// Tool Implementation
|
|
122
|
+
// ============================================================================
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* AskUserQuestion tool
|
|
126
|
+
*
|
|
127
|
+
* This tool is special - it doesn't execute immediately but signals
|
|
128
|
+
* the agent loop to pause and wait for user input via the CLI.
|
|
129
|
+
*
|
|
130
|
+
* The actual questioning is handled by the CLI layer (QuestionPrompt component).
|
|
131
|
+
* This tool just validates the input and returns a marker for the agent loop.
|
|
132
|
+
*/
|
|
133
|
+
export const askUserQuestionTool: Tool<AskUserQuestionInput> = {
|
|
134
|
+
name: 'AskUserQuestion',
|
|
135
|
+
description: loadToolDescription('ask-user'),
|
|
136
|
+
parameters: AskUserQuestionInputSchema,
|
|
137
|
+
|
|
138
|
+
async execute(input: AskUserQuestionInput, context: ToolContext): Promise<ToolResult> {
|
|
139
|
+
// Validation is handled by Zod schema
|
|
140
|
+
// Additional validation for recommended options format
|
|
141
|
+
for (const question of input.questions) {
|
|
142
|
+
// Check if first option has (Recommended) - this is just a hint, not enforced
|
|
143
|
+
const firstOption = question.options[0];
|
|
144
|
+
if (firstOption && !firstOption.label.includes('(Recommended)')) {
|
|
145
|
+
// This is fine - recommended suffix is optional
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Check if context has askUser callback
|
|
150
|
+
if (context.askUser) {
|
|
151
|
+
try {
|
|
152
|
+
const answers = await context.askUser(input.questions);
|
|
153
|
+
return {
|
|
154
|
+
success: true,
|
|
155
|
+
output: formatAnswersForAgent(answers),
|
|
156
|
+
metadata: {
|
|
157
|
+
title: 'AskUserQuestion',
|
|
158
|
+
subtitle: `${answers.length} answer(s) received`,
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
} catch (error) {
|
|
162
|
+
return {
|
|
163
|
+
success: false,
|
|
164
|
+
output: '',
|
|
165
|
+
error: `Failed to get user response: ${error instanceof Error ? error.message : String(error)}`,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// If no askUser callback, return a special marker
|
|
171
|
+
// The agent loop should detect this and handle it specially
|
|
172
|
+
return {
|
|
173
|
+
success: true,
|
|
174
|
+
output: JSON.stringify({
|
|
175
|
+
type: 'ask_user_question',
|
|
176
|
+
questions: input.questions,
|
|
177
|
+
requiresUserInput: true,
|
|
178
|
+
}),
|
|
179
|
+
metadata: {
|
|
180
|
+
title: 'AskUserQuestion',
|
|
181
|
+
subtitle: `${input.questions.length} question(s) pending`,
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
},
|
|
185
|
+
};
|
package/src/tools/index.ts
CHANGED
|
@@ -15,6 +15,18 @@ export { grepTool } from './builtin/grep.js';
|
|
|
15
15
|
export { webfetchTool } from './builtin/webfetch.js';
|
|
16
16
|
export { websearchTool } from './builtin/websearch.js';
|
|
17
17
|
export { todowriteTool, getTodos, clearTodos } from './builtin/todowrite.js';
|
|
18
|
+
export {
|
|
19
|
+
askUserQuestionTool,
|
|
20
|
+
formatAnswersForAgent,
|
|
21
|
+
formatAnswersForDisplay,
|
|
22
|
+
} from './builtin/ask-user.js';
|
|
23
|
+
export type {
|
|
24
|
+
Question as AskUserQuestion,
|
|
25
|
+
QuestionOption as AskUserQuestionOption,
|
|
26
|
+
QuestionAnswer as AskUserQuestionAnswer,
|
|
27
|
+
AskUserQuestionInput,
|
|
28
|
+
AskUserQuestionResult,
|
|
29
|
+
} from './builtin/ask-user.js';
|
|
18
30
|
|
|
19
31
|
import { ToolRegistry } from './registry.js';
|
|
20
32
|
import { readTool } from './builtin/read.js';
|
|
@@ -26,6 +38,7 @@ import { grepTool } from './builtin/grep.js';
|
|
|
26
38
|
import { webfetchTool } from './builtin/webfetch.js';
|
|
27
39
|
import { websearchTool } from './builtin/websearch.js';
|
|
28
40
|
import { todowriteTool } from './builtin/todowrite.js';
|
|
41
|
+
import { askUserQuestionTool } from './builtin/ask-user.js';
|
|
29
42
|
|
|
30
43
|
/**
|
|
31
44
|
* Create a registry with all built-in tools
|
|
@@ -42,6 +55,7 @@ export function createDefaultRegistry(): ToolRegistry {
|
|
|
42
55
|
webfetchTool,
|
|
43
56
|
websearchTool,
|
|
44
57
|
todowriteTool,
|
|
58
|
+
askUserQuestionTool,
|
|
45
59
|
]);
|
|
46
60
|
return registry;
|
|
47
61
|
}
|
|
@@ -59,4 +73,5 @@ export const builtinTools = [
|
|
|
59
73
|
webfetchTool,
|
|
60
74
|
websearchTool,
|
|
61
75
|
todowriteTool,
|
|
76
|
+
askUserQuestionTool,
|
|
62
77
|
];
|
package/src/tools/types.ts
CHANGED
|
@@ -9,9 +9,27 @@ import { z } from 'zod';
|
|
|
9
9
|
// Tool Definition Types
|
|
10
10
|
// ============================================================================
|
|
11
11
|
|
|
12
|
+
// Forward declaration for Question type (used by AskUserQuestion tool)
|
|
13
|
+
export interface Question {
|
|
14
|
+
question: string;
|
|
15
|
+
header: string;
|
|
16
|
+
options: Array<{ label: string; description: string }>;
|
|
17
|
+
multiSelect: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Forward declaration for QuestionAnswer type (used by AskUserQuestion tool)
|
|
21
|
+
export interface QuestionAnswer {
|
|
22
|
+
question: string;
|
|
23
|
+
header: string;
|
|
24
|
+
selectedOptions: string[];
|
|
25
|
+
customInput?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
12
28
|
export interface ToolContext {
|
|
13
29
|
cwd: string;
|
|
14
30
|
abortSignal?: AbortSignal;
|
|
31
|
+
/** Callback for AskUserQuestion tool to interact with user */
|
|
32
|
+
askUser?: (questions: Question[]) => Promise<QuestionAnswer[]>;
|
|
15
33
|
}
|
|
16
34
|
|
|
17
35
|
export interface ToolResultMetadata {
|