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.
Files changed (60) hide show
  1. package/CLAUDE.md +86 -0
  2. package/README.md +14 -17
  3. package/dist/agent/agent.d.ts +8 -0
  4. package/dist/agent/agent.d.ts.map +1 -1
  5. package/dist/agent/agent.js +14 -1
  6. package/dist/agent/agent.js.map +1 -1
  7. package/dist/agent/index.d.ts +1 -0
  8. package/dist/agent/index.d.ts.map +1 -1
  9. package/dist/agent/types.d.ts +14 -1
  10. package/dist/agent/types.d.ts.map +1 -1
  11. package/dist/cli/components/App.d.ts.map +1 -1
  12. package/dist/cli/components/App.js +38 -3
  13. package/dist/cli/components/App.js.map +1 -1
  14. package/dist/cli/components/Messages.d.ts.map +1 -1
  15. package/dist/cli/components/Messages.js +17 -0
  16. package/dist/cli/components/Messages.js.map +1 -1
  17. package/dist/cli/components/QuestionPrompt.d.ts +23 -0
  18. package/dist/cli/components/QuestionPrompt.d.ts.map +1 -0
  19. package/dist/cli/components/QuestionPrompt.js +231 -0
  20. package/dist/cli/components/QuestionPrompt.js.map +1 -0
  21. package/dist/cli/components/index.d.ts +1 -0
  22. package/dist/cli/components/index.d.ts.map +1 -1
  23. package/dist/cli/components/index.js +1 -0
  24. package/dist/cli/components/index.js.map +1 -1
  25. package/dist/cli/components/theme.d.ts +7 -0
  26. package/dist/cli/components/theme.d.ts.map +1 -1
  27. package/dist/cli/components/theme.js +11 -1
  28. package/dist/cli/components/theme.js.map +1 -1
  29. package/dist/permissions/types.d.ts.map +1 -1
  30. package/dist/permissions/types.js +2 -0
  31. package/dist/permissions/types.js.map +1 -1
  32. package/dist/tools/builtin/ask-user.d.ts +64 -0
  33. package/dist/tools/builtin/ask-user.d.ts.map +1 -0
  34. package/dist/tools/builtin/ask-user.js +148 -0
  35. package/dist/tools/builtin/ask-user.js.map +1 -0
  36. package/dist/tools/index.d.ts +12 -0
  37. package/dist/tools/index.d.ts.map +1 -1
  38. package/dist/tools/index.js +4 -0
  39. package/dist/tools/index.js.map +1 -1
  40. package/dist/tools/types.d.ts +17 -0
  41. package/dist/tools/types.d.ts.map +1 -1
  42. package/dist/tools/types.js.map +1 -1
  43. package/docs/proposals/0012-ask-user-question.md +66 -1
  44. package/docs/proposals/README.md +1 -1
  45. package/examples/test-ask-user.ts +167 -0
  46. package/package.json +1 -1
  47. package/src/agent/agent.ts +20 -1
  48. package/src/agent/index.ts +1 -0
  49. package/src/agent/types.ts +13 -1
  50. package/src/cli/components/App.tsx +55 -3
  51. package/src/cli/components/Messages.tsx +43 -0
  52. package/src/cli/components/QuestionPrompt.tsx +462 -0
  53. package/src/cli/components/index.ts +1 -0
  54. package/src/cli/components/theme.ts +11 -1
  55. package/src/permissions/types.ts +2 -0
  56. package/src/prompts/system/base.txt +42 -0
  57. package/src/prompts/tools/ask-user.txt +110 -0
  58. package/src/tools/builtin/ask-user.ts +185 -0
  59. package/src/tools/index.ts +15 -0
  60. 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
+ };
@@ -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
  ];
@@ -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 {