gencode-ai 0.1.0
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/.env.example +11 -0
- package/CLAUDE.md +70 -0
- package/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/agent/agent.d.ts +84 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +233 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/index.d.ts +6 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +6 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/types.d.ts +47 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli/components/App.d.ts +14 -0
- package/dist/cli/components/App.d.ts.map +1 -0
- package/dist/cli/components/App.js +395 -0
- package/dist/cli/components/App.js.map +1 -0
- package/dist/cli/components/CommandSuggestions.d.ts +13 -0
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
- package/dist/cli/components/CommandSuggestions.js +32 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -0
- package/dist/cli/components/Header.d.ts +9 -0
- package/dist/cli/components/Header.d.ts.map +1 -0
- package/dist/cli/components/Header.js +13 -0
- package/dist/cli/components/Header.js.map +1 -0
- package/dist/cli/components/Input.d.ts +13 -0
- package/dist/cli/components/Input.d.ts.map +1 -0
- package/dist/cli/components/Input.js +27 -0
- package/dist/cli/components/Input.js.map +1 -0
- package/dist/cli/components/Logo.d.ts +2 -0
- package/dist/cli/components/Logo.d.ts.map +1 -0
- package/dist/cli/components/Logo.js +8 -0
- package/dist/cli/components/Logo.js.map +1 -0
- package/dist/cli/components/Messages.d.ts +37 -0
- package/dist/cli/components/Messages.d.ts.map +1 -0
- package/dist/cli/components/Messages.js +106 -0
- package/dist/cli/components/Messages.js.map +1 -0
- package/dist/cli/components/ModelSelector.d.ts +13 -0
- package/dist/cli/components/ModelSelector.d.ts.map +1 -0
- package/dist/cli/components/ModelSelector.js +72 -0
- package/dist/cli/components/ModelSelector.js.map +1 -0
- package/dist/cli/components/Spinner.d.ts +12 -0
- package/dist/cli/components/Spinner.d.ts.map +1 -0
- package/dist/cli/components/Spinner.js +45 -0
- package/dist/cli/components/Spinner.js.map +1 -0
- package/dist/cli/components/index.d.ts +12 -0
- package/dist/cli/components/index.d.ts.map +1 -0
- package/dist/cli/components/index.js +12 -0
- package/dist/cli/components/index.js.map +1 -0
- package/dist/cli/components/theme.d.ts +31 -0
- package/dist/cli/components/theme.d.ts.map +1 -0
- package/dist/cli/components/theme.js +36 -0
- package/dist/cli/components/theme.js.map +1 -0
- package/dist/cli/index-legacy.d.ts +7 -0
- package/dist/cli/index-legacy.d.ts.map +1 -0
- package/dist/cli/index-legacy.js +431 -0
- package/dist/cli/index-legacy.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +116 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ink-cli.d.ts +7 -0
- package/dist/cli/ink-cli.d.ts.map +1 -0
- package/dist/cli/ink-cli.js +105 -0
- package/dist/cli/ink-cli.js.map +1 -0
- package/dist/cli/session-picker.d.ts +16 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +280 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli/ui.d.ts +61 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +364 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/manager.d.ts +31 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +65 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/types.d.ts +22 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +6 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/index.d.ts +10 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/init.d.ts +20 -0
- package/dist/memory/init.d.ts.map +1 -0
- package/dist/memory/init.js +332 -0
- package/dist/memory/init.js.map +1 -0
- package/dist/memory/manager.d.ts +85 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +234 -0
- package/dist/memory/manager.js.map +1 -0
- package/dist/memory/types.d.ts +74 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +6 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/permissions/index.d.ts +7 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +6 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/manager.d.ts +32 -0
- package/dist/permissions/manager.d.ts.map +1 -0
- package/dist/permissions/manager.js +79 -0
- package/dist/permissions/manager.js.map +1 -0
- package/dist/permissions/types.d.ts +14 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/providers/anthropic.d.ts +20 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +185 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/gemini.d.ts +21 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +241 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +34 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +72 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai.d.ts +19 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +221 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/types.d.ts +125 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +6 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/session/index.d.ts +6 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +6 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +101 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +295 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/types.d.ts +39 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +10 -0
- package/dist/session/types.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +7 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +80 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/edit.d.ts +7 -0
- package/dist/tools/builtin/edit.d.ts.map +1 -0
- package/dist/tools/builtin/edit.js +32 -0
- package/dist/tools/builtin/edit.js.map +1 -0
- package/dist/tools/builtin/glob.d.ts +7 -0
- package/dist/tools/builtin/glob.d.ts.map +1 -0
- package/dist/tools/builtin/glob.js +36 -0
- package/dist/tools/builtin/glob.js.map +1 -0
- package/dist/tools/builtin/grep.d.ts +7 -0
- package/dist/tools/builtin/grep.d.ts.map +1 -0
- package/dist/tools/builtin/grep.js +59 -0
- package/dist/tools/builtin/grep.js.map +1 -0
- package/dist/tools/builtin/read.d.ts +7 -0
- package/dist/tools/builtin/read.d.ts.map +1 -0
- package/dist/tools/builtin/read.js +29 -0
- package/dist/tools/builtin/read.js.map +1 -0
- package/dist/tools/builtin/write.d.ts +7 -0
- package/dist/tools/builtin/write.d.ts.map +1 -0
- package/dist/tools/builtin/write.js +24 -0
- package/dist/tools/builtin/write.js.map +1 -0
- package/dist/tools/index.d.ts +38 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +32 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +22 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +71 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +62 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +126 -0
- package/dist/tools/types.js.map +1 -0
- package/docs/README.md +16 -0
- package/docs/proposals/0001-web-fetch-tool.md +293 -0
- package/docs/proposals/0002-web-search-tool.md +306 -0
- package/docs/proposals/0003-task-subagents.md +333 -0
- package/docs/proposals/0004-plan-mode.md +338 -0
- package/docs/proposals/0005-todo-system.md +299 -0
- package/docs/proposals/0006-memory-system.md +539 -0
- package/docs/proposals/0007-context-management.md +429 -0
- package/docs/proposals/0008-checkpointing.md +327 -0
- package/docs/proposals/0009-hooks-system.md +343 -0
- package/docs/proposals/0010-mcp-integration.md +382 -0
- package/docs/proposals/0011-custom-commands.md +374 -0
- package/docs/proposals/0012-ask-user-question.md +317 -0
- package/docs/proposals/0013-multi-edit-tool.md +345 -0
- package/docs/proposals/0014-lsp-tool.md +478 -0
- package/docs/proposals/0015-ls-tool.md +407 -0
- package/docs/proposals/0016-kill-shell-tool.md +455 -0
- package/docs/proposals/0017-background-tasks.md +489 -0
- package/docs/proposals/0018-parallel-tool-execution.md +415 -0
- package/docs/proposals/0019-session-enhancements.md +462 -0
- package/docs/proposals/0020-session-summarization.md +447 -0
- package/docs/proposals/0021-skills-system.md +409 -0
- package/docs/proposals/0022-plugin-system.md +467 -0
- package/docs/proposals/0023-permission-enhancements.md +470 -0
- package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
- package/docs/proposals/0025-cost-tracking.md +447 -0
- package/docs/proposals/0026-git-integration.md +475 -0
- package/docs/proposals/0027-enhanced-read-tool.md +514 -0
- package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
- package/docs/proposals/0029-notebook-edit-tool.md +413 -0
- package/docs/proposals/0030-plugin-marketplace.md +360 -0
- package/docs/proposals/0031-command-suggestions.md +295 -0
- package/docs/proposals/0032-ide-integrations.md +328 -0
- package/docs/proposals/0033-enterprise-deployment.md +221 -0
- package/docs/proposals/0034-sandboxing.md +273 -0
- package/docs/proposals/0035-auto-updater.md +311 -0
- package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
- package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
- package/docs/proposals/0038-interactive-cli-ui.md +373 -0
- package/docs/proposals/0039-streaming-enhancements.md +359 -0
- package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
- package/docs/proposals/README.md +84 -0
- package/docs/proposals/TEMPLATE.md +57 -0
- package/docs/proposals/research/claude-code-research.md +307 -0
- package/examples/agent-demo.ts +115 -0
- package/examples/basic.ts +166 -0
- package/package.json +50 -0
- package/src/agent/agent.ts +276 -0
- package/src/agent/index.ts +6 -0
- package/src/agent/types.ts +62 -0
- package/src/cli/components/App.tsx +565 -0
- package/src/cli/components/CommandSuggestions.tsx +58 -0
- package/src/cli/components/Header.tsx +36 -0
- package/src/cli/components/Input.tsx +60 -0
- package/src/cli/components/Logo.tsx +16 -0
- package/src/cli/components/Messages.tsx +210 -0
- package/src/cli/components/ModelSelector.tsx +135 -0
- package/src/cli/components/Spinner.tsx +72 -0
- package/src/cli/components/index.ts +21 -0
- package/src/cli/components/theme.ts +36 -0
- package/src/cli/index.tsx +136 -0
- package/src/config/index.ts +7 -0
- package/src/config/manager.ts +77 -0
- package/src/config/types.ts +25 -0
- package/src/index.ts +86 -0
- package/src/permissions/index.ts +7 -0
- package/src/permissions/manager.ts +97 -0
- package/src/permissions/types.ts +29 -0
- package/src/providers/anthropic.ts +224 -0
- package/src/providers/gemini.ts +295 -0
- package/src/providers/index.ts +97 -0
- package/src/providers/openai.ts +261 -0
- package/src/providers/types.ts +181 -0
- package/src/session/index.ts +6 -0
- package/src/session/manager.ts +354 -0
- package/src/session/types.ts +49 -0
- package/src/tools/builtin/bash.ts +92 -0
- package/src/tools/builtin/edit.ts +37 -0
- package/src/tools/builtin/glob.ts +42 -0
- package/src/tools/builtin/grep.ts +67 -0
- package/src/tools/builtin/read.ts +34 -0
- package/src/tools/builtin/write.ts +27 -0
- package/src/tools/index.ts +36 -0
- package/src/tools/registry.ts +83 -0
- package/src/tools/types.ts +172 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
# Proposal: Custom Commands (Slash Commands)
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0011
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Implement a custom commands system that allows users to define reusable prompt templates as slash commands. Commands are stored as markdown files in `.mycode/commands/` and can accept arguments, making common workflows easily accessible.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
Currently, users must re-type common prompts. This leads to:
|
|
16
|
+
|
|
17
|
+
1. **Repetition**: Same prompts typed repeatedly
|
|
18
|
+
2. **Inconsistency**: Variations in how tasks are requested
|
|
19
|
+
3. **No sharing**: Can't share workflows with team
|
|
20
|
+
4. **No organization**: Common tasks not documented
|
|
21
|
+
5. **Slow workflows**: Complex prompts take time to compose
|
|
22
|
+
|
|
23
|
+
Custom commands enable one-command access to common workflows.
|
|
24
|
+
|
|
25
|
+
## Claude Code Reference
|
|
26
|
+
|
|
27
|
+
Claude Code provides a powerful slash command system:
|
|
28
|
+
|
|
29
|
+
### Command Definition
|
|
30
|
+
```markdown
|
|
31
|
+
<!-- .claude/commands/fix-issue.md -->
|
|
32
|
+
---
|
|
33
|
+
description: Fix a GitHub issue
|
|
34
|
+
argument-hint: <issue-number>
|
|
35
|
+
allowed-tools: Bash(gh:*), Read, Edit, Write
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
# Fix GitHub Issue
|
|
39
|
+
|
|
40
|
+
Fetch issue $ARGUMENTS from GitHub and implement a fix:
|
|
41
|
+
|
|
42
|
+
1. Read the issue details using `gh issue view $ARGUMENTS`
|
|
43
|
+
2. Understand the problem and find relevant code
|
|
44
|
+
3. Implement the fix
|
|
45
|
+
4. Create a commit with descriptive message
|
|
46
|
+
5. Push the changes
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Usage
|
|
50
|
+
```
|
|
51
|
+
> /fix-issue 123
|
|
52
|
+
|
|
53
|
+
Agent: [Reads issue #123, implements fix, commits, pushes]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Features
|
|
57
|
+
- Markdown files with YAML frontmatter
|
|
58
|
+
- `$ARGUMENTS` for user input
|
|
59
|
+
- `$1`, `$2` for positional arguments
|
|
60
|
+
- `@file` syntax for file inclusion
|
|
61
|
+
- `allowed-tools` for pre-authorized tools
|
|
62
|
+
- Project and user-level commands
|
|
63
|
+
|
|
64
|
+
### Command Locations
|
|
65
|
+
- `~/.mycode/commands/` - User commands (all projects)
|
|
66
|
+
- `.mycode/commands/` - Project commands
|
|
67
|
+
|
|
68
|
+
### Built-in Variables
|
|
69
|
+
- `$ARGUMENTS` - All arguments as string
|
|
70
|
+
- `$1`, `$2`, etc. - Positional arguments
|
|
71
|
+
- `@path/to/file` - Include file content
|
|
72
|
+
|
|
73
|
+
## Detailed Design
|
|
74
|
+
|
|
75
|
+
### API Design
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
// src/commands/types.ts
|
|
79
|
+
interface CommandDefinition {
|
|
80
|
+
name: string; // Command name (from filename)
|
|
81
|
+
description?: string; // Short description
|
|
82
|
+
argumentHint?: string; // Usage hint for arguments
|
|
83
|
+
allowedTools?: string[]; // Pre-authorized tools
|
|
84
|
+
content: string; // Prompt template
|
|
85
|
+
filePath: string; // Source file path
|
|
86
|
+
scope: 'user' | 'project'; // Command scope
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface CommandInput {
|
|
90
|
+
command: string; // Command name
|
|
91
|
+
arguments: string; // Raw argument string
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface ParsedCommand {
|
|
95
|
+
definition: CommandDefinition;
|
|
96
|
+
expandedPrompt: string; // Template with variables filled
|
|
97
|
+
preAuthorizedTools: string[];
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// src/commands/command-manager.ts
|
|
103
|
+
class CommandManager {
|
|
104
|
+
private commands: Map<string, CommandDefinition>;
|
|
105
|
+
private userDir: string;
|
|
106
|
+
private projectDir: string;
|
|
107
|
+
|
|
108
|
+
constructor(projectDir: string);
|
|
109
|
+
|
|
110
|
+
// Load commands from directories
|
|
111
|
+
async loadCommands(): Promise<void>;
|
|
112
|
+
|
|
113
|
+
// Get all available commands
|
|
114
|
+
listCommands(): CommandDefinition[];
|
|
115
|
+
|
|
116
|
+
// Check if command exists
|
|
117
|
+
hasCommand(name: string): boolean;
|
|
118
|
+
|
|
119
|
+
// Parse and expand a command
|
|
120
|
+
parseCommand(input: CommandInput): ParsedCommand;
|
|
121
|
+
|
|
122
|
+
// Get command by name
|
|
123
|
+
getCommand(name: string): CommandDefinition | undefined;
|
|
124
|
+
|
|
125
|
+
// Reload commands
|
|
126
|
+
async refresh(): Promise<void>;
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Command Parsing
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// src/commands/parser.ts
|
|
134
|
+
interface CommandFrontmatter {
|
|
135
|
+
description?: string;
|
|
136
|
+
'argument-hint'?: string;
|
|
137
|
+
'allowed-tools'?: string | string[];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function parseCommandFile(filePath: string, content: string): CommandDefinition {
|
|
141
|
+
// Parse YAML frontmatter
|
|
142
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
143
|
+
|
|
144
|
+
// Extract name from filename
|
|
145
|
+
const name = path.basename(filePath, '.md');
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
name,
|
|
149
|
+
description: frontmatter.description,
|
|
150
|
+
argumentHint: frontmatter['argument-hint'],
|
|
151
|
+
allowedTools: normalizeAllowedTools(frontmatter['allowed-tools']),
|
|
152
|
+
content: body,
|
|
153
|
+
filePath,
|
|
154
|
+
scope: filePath.includes('~/.mycode') ? 'user' : 'project'
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function expandTemplate(template: string, args: string): string {
|
|
159
|
+
// Split arguments
|
|
160
|
+
const argList = parseArguments(args);
|
|
161
|
+
|
|
162
|
+
let result = template;
|
|
163
|
+
|
|
164
|
+
// Replace $ARGUMENTS with full string
|
|
165
|
+
result = result.replace(/\$ARGUMENTS/g, args);
|
|
166
|
+
|
|
167
|
+
// Replace positional $1, $2, etc.
|
|
168
|
+
for (let i = 0; i < argList.length; i++) {
|
|
169
|
+
result = result.replace(new RegExp(`\\$${i + 1}`, 'g'), argList[i]);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Handle @file includes
|
|
173
|
+
result = expandFileIncludes(result);
|
|
174
|
+
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Tool Pre-Authorization
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// Parse allowed-tools patterns
|
|
183
|
+
function normalizeAllowedTools(tools: string | string[] | undefined): string[] {
|
|
184
|
+
if (!tools) return [];
|
|
185
|
+
if (typeof tools === 'string') {
|
|
186
|
+
return tools.split(',').map(t => t.trim());
|
|
187
|
+
}
|
|
188
|
+
return tools;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Examples:
|
|
192
|
+
// "Bash(npm:*)" - Allow npm commands
|
|
193
|
+
// "Bash(gh:*)" - Allow GitHub CLI
|
|
194
|
+
// "Read, Write" - Allow Read and Write tools
|
|
195
|
+
// "Bash(mkdir:*), Bash(tee:*)" - Multiple Bash patterns
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### File Changes
|
|
199
|
+
|
|
200
|
+
| File | Action | Description |
|
|
201
|
+
|------|--------|-------------|
|
|
202
|
+
| `src/commands/types.ts` | Create | Command type definitions |
|
|
203
|
+
| `src/commands/command-manager.ts` | Create | Command loading and management |
|
|
204
|
+
| `src/commands/parser.ts` | Create | Markdown/frontmatter parsing |
|
|
205
|
+
| `src/commands/expander.ts` | Create | Template expansion |
|
|
206
|
+
| `src/commands/index.ts` | Create | Module exports |
|
|
207
|
+
| `src/cli/input-handler.ts` | Modify | Handle slash command input |
|
|
208
|
+
| `src/permissions/permission-manager.ts` | Modify | Pre-authorize tools |
|
|
209
|
+
|
|
210
|
+
## User Experience
|
|
211
|
+
|
|
212
|
+
### Creating a Command
|
|
213
|
+
Create `.mycode/commands/review-pr.md`:
|
|
214
|
+
|
|
215
|
+
```markdown
|
|
216
|
+
---
|
|
217
|
+
description: Review a GitHub pull request
|
|
218
|
+
argument-hint: <pr-number>
|
|
219
|
+
allowed-tools: Bash(gh:*), Read, Grep
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
# Review Pull Request
|
|
223
|
+
|
|
224
|
+
Review PR #$ARGUMENTS:
|
|
225
|
+
|
|
226
|
+
1. Fetch PR details: `gh pr view $ARGUMENTS`
|
|
227
|
+
2. Get the diff: `gh pr diff $ARGUMENTS`
|
|
228
|
+
3. Review code changes for:
|
|
229
|
+
- Code quality issues
|
|
230
|
+
- Potential bugs
|
|
231
|
+
- Style violations
|
|
232
|
+
4. Provide a summary with actionable feedback
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Using Commands
|
|
236
|
+
```
|
|
237
|
+
> /review-pr 42
|
|
238
|
+
|
|
239
|
+
Agent: I'll review PR #42 for you.
|
|
240
|
+
[Fetches PR, analyzes diff, provides feedback]
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Listing Commands
|
|
244
|
+
```
|
|
245
|
+
> /help
|
|
246
|
+
|
|
247
|
+
Available Commands:
|
|
248
|
+
┌───────────────┬────────────────────────────────────────┐
|
|
249
|
+
│ Command │ Description │
|
|
250
|
+
├───────────────┼────────────────────────────────────────┤
|
|
251
|
+
│ /fix-issue │ Fix a GitHub issue │
|
|
252
|
+
│ /review-pr │ Review a GitHub pull request │
|
|
253
|
+
│ /create-test │ Create unit tests for a file │
|
|
254
|
+
│ /summarize │ Summarize a file or directory │
|
|
255
|
+
└───────────────┴────────────────────────────────────────┘
|
|
256
|
+
|
|
257
|
+
Project commands: .mycode/commands/
|
|
258
|
+
User commands: ~/.mycode/commands/
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Command with Multiple Arguments
|
|
262
|
+
```markdown
|
|
263
|
+
---
|
|
264
|
+
description: Create a component
|
|
265
|
+
argument-hint: <name> <type>
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
Create a $2 component named $1:
|
|
269
|
+
- File: src/components/$1.$2
|
|
270
|
+
- Include tests
|
|
271
|
+
- Follow project conventions
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
> /create-component Button tsx
|
|
276
|
+
|
|
277
|
+
Agent: Creating a tsx component named Button...
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### File Inclusion
|
|
281
|
+
```markdown
|
|
282
|
+
---
|
|
283
|
+
description: Apply coding standards
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
Apply these coding standards to the codebase:
|
|
287
|
+
|
|
288
|
+
@.mycode/standards.md
|
|
289
|
+
|
|
290
|
+
Focus on the most critical violations first.
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Alternatives Considered
|
|
294
|
+
|
|
295
|
+
### Alternative 1: JSON Command Format
|
|
296
|
+
Define commands in JSON files.
|
|
297
|
+
|
|
298
|
+
**Pros**: Structured, easier to parse
|
|
299
|
+
**Cons**: Less readable, harder to write prompts
|
|
300
|
+
**Decision**: Rejected - Markdown is more natural
|
|
301
|
+
|
|
302
|
+
### Alternative 2: Inline Command Definition
|
|
303
|
+
Define commands within settings.json.
|
|
304
|
+
|
|
305
|
+
**Pros**: Single config file
|
|
306
|
+
**Cons**: Hard to manage many commands, no syntax highlighting
|
|
307
|
+
**Decision**: Rejected - Separate files are more manageable
|
|
308
|
+
|
|
309
|
+
### Alternative 3: JavaScript Commands
|
|
310
|
+
Write commands as JS/TS modules.
|
|
311
|
+
|
|
312
|
+
**Pros**: Full programmability
|
|
313
|
+
**Cons**: Security concerns, higher barrier to entry
|
|
314
|
+
**Decision**: Deferred - Start with templates, add later
|
|
315
|
+
|
|
316
|
+
## Security Considerations
|
|
317
|
+
|
|
318
|
+
1. **Tool Restrictions**: Pre-authorized tools respect permission system
|
|
319
|
+
2. **File Inclusion**: Only allow including files within project
|
|
320
|
+
3. **Argument Sanitization**: Sanitize arguments before expansion
|
|
321
|
+
4. **Path Traversal**: Prevent `@../../../etc/passwd`
|
|
322
|
+
5. **Execution Scope**: Commands run with normal permissions
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
// Safe file inclusion
|
|
326
|
+
function expandFileIncludes(content: string, projectRoot: string): string {
|
|
327
|
+
return content.replace(/@([^\s]+)/g, (match, filePath) => {
|
|
328
|
+
const absolutePath = path.resolve(projectRoot, filePath);
|
|
329
|
+
|
|
330
|
+
// Prevent path traversal
|
|
331
|
+
if (!absolutePath.startsWith(projectRoot)) {
|
|
332
|
+
return `[Error: Cannot include files outside project]`;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (fs.existsSync(absolutePath)) {
|
|
336
|
+
return fs.readFileSync(absolutePath, 'utf-8');
|
|
337
|
+
}
|
|
338
|
+
return `[File not found: ${filePath}]`;
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Testing Strategy
|
|
344
|
+
|
|
345
|
+
1. **Unit Tests**:
|
|
346
|
+
- Frontmatter parsing
|
|
347
|
+
- Argument expansion
|
|
348
|
+
- File inclusion
|
|
349
|
+
|
|
350
|
+
2. **Integration Tests**:
|
|
351
|
+
- Command loading
|
|
352
|
+
- Command execution
|
|
353
|
+
- Pre-authorization
|
|
354
|
+
|
|
355
|
+
3. **Manual Testing**:
|
|
356
|
+
- Various command formats
|
|
357
|
+
- Argument edge cases
|
|
358
|
+
- File inclusion
|
|
359
|
+
|
|
360
|
+
## Migration Path
|
|
361
|
+
|
|
362
|
+
1. **Phase 1**: Basic command loading and execution
|
|
363
|
+
2. **Phase 2**: Argument expansion ($ARGUMENTS, $1, $2)
|
|
364
|
+
3. **Phase 3**: File inclusion (@file)
|
|
365
|
+
4. **Phase 4**: Tool pre-authorization
|
|
366
|
+
5. **Phase 5**: /help command and discoverability
|
|
367
|
+
|
|
368
|
+
No breaking changes to existing functionality.
|
|
369
|
+
|
|
370
|
+
## References
|
|
371
|
+
|
|
372
|
+
- [Claude Code Commands Documentation](https://code.claude.com/docs/en/commands)
|
|
373
|
+
- [Claude Code Plugins Reference](https://code.claude.com/docs/en/plugins-reference)
|
|
374
|
+
- [YAML Frontmatter Specification](https://jekyllrb.com/docs/front-matter/)
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# Proposal: AskUserQuestion Tool
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0012
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Implement an AskUserQuestion tool that allows the agent to pause execution and present structured questions to the user with predefined options. This enables gathering user preferences, clarifying ambiguous instructions, and making decisions during task execution.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
Currently, mycode has no structured way for the agent to ask clarifying questions. This leads to:
|
|
16
|
+
|
|
17
|
+
1. **Assumptions**: Agent guesses when requirements are unclear
|
|
18
|
+
2. **Wasted work**: Wrong assumptions lead to redoing work
|
|
19
|
+
3. **Poor UX**: Unstructured questions mixed with output
|
|
20
|
+
4. **No multi-select**: Can't gather multiple preferences at once
|
|
21
|
+
5. **No defaults**: Can't recommend options to users
|
|
22
|
+
|
|
23
|
+
A structured question tool enables clear, efficient user interaction.
|
|
24
|
+
|
|
25
|
+
## Claude Code Reference
|
|
26
|
+
|
|
27
|
+
Claude Code's AskUserQuestion tool provides rich interactive questioning:
|
|
28
|
+
|
|
29
|
+
### Tool Definition
|
|
30
|
+
```typescript
|
|
31
|
+
AskUserQuestion({
|
|
32
|
+
questions: [
|
|
33
|
+
{
|
|
34
|
+
question: "Which database should we use?",
|
|
35
|
+
header: "Database", // Short label (max 12 chars)
|
|
36
|
+
options: [
|
|
37
|
+
{ label: "PostgreSQL (Recommended)", description: "Relational DB with rich features" },
|
|
38
|
+
{ label: "MongoDB", description: "Document-based NoSQL database" },
|
|
39
|
+
{ label: "SQLite", description: "Lightweight embedded database" }
|
|
40
|
+
],
|
|
41
|
+
multiSelect: false
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
})
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Key Features
|
|
48
|
+
- 1-4 questions per invocation
|
|
49
|
+
- 2-4 options per question
|
|
50
|
+
- Automatic "Other" option for custom input
|
|
51
|
+
- Multi-select support
|
|
52
|
+
- Short headers for chips/tags
|
|
53
|
+
- Descriptions for each option
|
|
54
|
+
- Recommended options (first position + label suffix)
|
|
55
|
+
|
|
56
|
+
### Example Usage
|
|
57
|
+
```
|
|
58
|
+
Agent: Before implementing authentication, I need to clarify some details.
|
|
59
|
+
|
|
60
|
+
[AskUserQuestion:
|
|
61
|
+
Q1: "Which authentication method should we use?"
|
|
62
|
+
- OAuth 2.0 (Recommended) - Industry standard, supports social login
|
|
63
|
+
- JWT - Stateless tokens, good for APIs
|
|
64
|
+
- Session-based - Traditional cookie sessions
|
|
65
|
+
|
|
66
|
+
Q2: "Which user storage should we use?"
|
|
67
|
+
- PostgreSQL (Recommended) - Your existing database
|
|
68
|
+
- Firebase Auth - Managed auth service
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
User selects: OAuth 2.0, PostgreSQL
|
|
72
|
+
|
|
73
|
+
Agent: Great! I'll implement OAuth 2.0 authentication with PostgreSQL storage.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Detailed Design
|
|
77
|
+
|
|
78
|
+
### API Design
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
// src/tools/ask-user/types.ts
|
|
82
|
+
interface QuestionOption {
|
|
83
|
+
label: string; // Display text (1-5 words)
|
|
84
|
+
description: string; // Explanation of the option
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface Question {
|
|
88
|
+
question: string; // The question to ask
|
|
89
|
+
header: string; // Short label (max 12 chars)
|
|
90
|
+
options: QuestionOption[]; // 2-4 options
|
|
91
|
+
multiSelect: boolean; // Allow multiple selections
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface AskUserQuestionInput {
|
|
95
|
+
questions: Question[]; // 1-4 questions
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface QuestionAnswer {
|
|
99
|
+
question: string;
|
|
100
|
+
selectedOptions: string[]; // Labels of selected options
|
|
101
|
+
customInput?: string; // If "Other" was selected
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
interface AskUserQuestionOutput {
|
|
105
|
+
answers: QuestionAnswer[];
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// src/tools/ask-user/ask-user-tool.ts
|
|
111
|
+
const askUserQuestionTool: Tool<AskUserQuestionInput> = {
|
|
112
|
+
name: 'AskUserQuestion',
|
|
113
|
+
description: `Ask the user structured questions during execution.
|
|
114
|
+
|
|
115
|
+
Use this tool when you need to:
|
|
116
|
+
1. Gather user preferences or requirements
|
|
117
|
+
2. Clarify ambiguous instructions
|
|
118
|
+
3. Get decisions on implementation choices
|
|
119
|
+
4. Offer choices about direction
|
|
120
|
+
|
|
121
|
+
Guidelines:
|
|
122
|
+
- Use multiSelect: true for non-mutually-exclusive options
|
|
123
|
+
- Put recommended option first with "(Recommended)" suffix
|
|
124
|
+
- Keep headers short (max 12 chars)
|
|
125
|
+
- Users can always select "Other" for custom input
|
|
126
|
+
`,
|
|
127
|
+
parameters: z.object({
|
|
128
|
+
questions: z.array(z.object({
|
|
129
|
+
question: z.string(),
|
|
130
|
+
header: z.string().max(12),
|
|
131
|
+
options: z.array(z.object({
|
|
132
|
+
label: z.string(),
|
|
133
|
+
description: z.string()
|
|
134
|
+
})).min(2).max(4),
|
|
135
|
+
multiSelect: z.boolean()
|
|
136
|
+
})).min(1).max(4)
|
|
137
|
+
}),
|
|
138
|
+
execute: async (input, context) => { ... }
|
|
139
|
+
};
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Implementation Approach
|
|
143
|
+
|
|
144
|
+
1. **Tool Registration**: Add AskUserQuestion to tool registry
|
|
145
|
+
2. **UI Integration**: Create interactive question display
|
|
146
|
+
3. **Blocking Execution**: Tool blocks until user responds
|
|
147
|
+
4. **Answer Processing**: Return structured answers to agent
|
|
148
|
+
5. **Other Handling**: Support custom text input
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// Question display and collection
|
|
152
|
+
async function execute(input: AskUserQuestionInput, context: ToolContext): Promise<ToolResult> {
|
|
153
|
+
const { promptUser } = context;
|
|
154
|
+
|
|
155
|
+
const answers: QuestionAnswer[] = [];
|
|
156
|
+
|
|
157
|
+
for (const question of input.questions) {
|
|
158
|
+
// Display question with options
|
|
159
|
+
const response = await promptUser({
|
|
160
|
+
type: question.multiSelect ? 'multiselect' : 'select',
|
|
161
|
+
message: question.question,
|
|
162
|
+
choices: [
|
|
163
|
+
...question.options.map(opt => ({
|
|
164
|
+
name: opt.label,
|
|
165
|
+
message: opt.label,
|
|
166
|
+
hint: opt.description
|
|
167
|
+
})),
|
|
168
|
+
{ name: 'Other', message: 'Other (custom input)' }
|
|
169
|
+
]
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
let customInput: string | undefined;
|
|
173
|
+
if (response.includes('Other')) {
|
|
174
|
+
customInput = await promptUser({
|
|
175
|
+
type: 'input',
|
|
176
|
+
message: 'Please specify:'
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
answers.push({
|
|
181
|
+
question: question.question,
|
|
182
|
+
selectedOptions: response,
|
|
183
|
+
customInput
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
success: true,
|
|
189
|
+
output: JSON.stringify({ answers })
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### File Changes
|
|
195
|
+
|
|
196
|
+
| File | Action | Description |
|
|
197
|
+
|------|--------|-------------|
|
|
198
|
+
| `src/tools/ask-user/types.ts` | Create | Question/answer type definitions |
|
|
199
|
+
| `src/tools/ask-user/ask-user-tool.ts` | Create | AskUserQuestion tool implementation |
|
|
200
|
+
| `src/tools/ask-user/index.ts` | Create | Module exports |
|
|
201
|
+
| `src/tools/index.ts` | Modify | Register tool |
|
|
202
|
+
| `src/cli/components/QuestionPrompt.tsx` | Create | Question UI component |
|
|
203
|
+
|
|
204
|
+
## User Experience
|
|
205
|
+
|
|
206
|
+
### Single Select Display
|
|
207
|
+
```
|
|
208
|
+
┌─ Database ─────────────────────────────────┐
|
|
209
|
+
│ Which database should we use? │
|
|
210
|
+
│ │
|
|
211
|
+
│ ○ PostgreSQL (Recommended) │
|
|
212
|
+
│ Relational DB with rich features │
|
|
213
|
+
│ │
|
|
214
|
+
│ ○ MongoDB │
|
|
215
|
+
│ Document-based NoSQL database │
|
|
216
|
+
│ │
|
|
217
|
+
│ ○ SQLite │
|
|
218
|
+
│ Lightweight embedded database │
|
|
219
|
+
│ │
|
|
220
|
+
│ ○ Other │
|
|
221
|
+
│ Provide custom input │
|
|
222
|
+
└────────────────────────────────────────────┘
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Multi Select Display
|
|
226
|
+
```
|
|
227
|
+
┌─ Features ─────────────────────────────────┐
|
|
228
|
+
│ Which features should we enable? │
|
|
229
|
+
│ (Select multiple with space) │
|
|
230
|
+
│ │
|
|
231
|
+
│ ☑ Dark mode │
|
|
232
|
+
│ Enable dark theme support │
|
|
233
|
+
│ │
|
|
234
|
+
│ ☐ Notifications │
|
|
235
|
+
│ Push notification support │
|
|
236
|
+
│ │
|
|
237
|
+
│ ☑ Offline mode │
|
|
238
|
+
│ Work without internet connection │
|
|
239
|
+
└────────────────────────────────────────────┘
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Keyboard Navigation
|
|
243
|
+
- `↑/↓` - Navigate options
|
|
244
|
+
- `Space` - Toggle selection (multi-select)
|
|
245
|
+
- `Enter` - Confirm selection
|
|
246
|
+
- `Esc` - Cancel (if allowed)
|
|
247
|
+
|
|
248
|
+
### Answer Display
|
|
249
|
+
After user answers:
|
|
250
|
+
```
|
|
251
|
+
✓ Database: PostgreSQL
|
|
252
|
+
✓ Features: Dark mode, Offline mode
|
|
253
|
+
|
|
254
|
+
Continuing with implementation...
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Alternatives Considered
|
|
258
|
+
|
|
259
|
+
### Alternative 1: Plain Text Questions
|
|
260
|
+
Agent asks questions in regular output.
|
|
261
|
+
|
|
262
|
+
**Pros**: Simpler, no special UI
|
|
263
|
+
**Cons**: No structure, easy to miss, no validation
|
|
264
|
+
**Decision**: Rejected - Structured questions are clearer
|
|
265
|
+
|
|
266
|
+
### Alternative 2: Form-Based Input
|
|
267
|
+
Complex form with multiple field types.
|
|
268
|
+
|
|
269
|
+
**Pros**: More input flexibility
|
|
270
|
+
**Cons**: Overcomplicated for most use cases
|
|
271
|
+
**Decision**: Rejected - Options are sufficient for most needs
|
|
272
|
+
|
|
273
|
+
### Alternative 3: Always Allow Custom Input
|
|
274
|
+
Every option is editable text.
|
|
275
|
+
|
|
276
|
+
**Pros**: Maximum flexibility
|
|
277
|
+
**Cons**: Slower, more error-prone
|
|
278
|
+
**Decision**: Rejected - "Other" option provides this when needed
|
|
279
|
+
|
|
280
|
+
## Security Considerations
|
|
281
|
+
|
|
282
|
+
1. **Input Sanitization**: Validate user custom input
|
|
283
|
+
2. **Option Limits**: Enforce max questions and options
|
|
284
|
+
3. **Timeout**: Consider timeout for unresponsive users
|
|
285
|
+
4. **No Code Execution**: Custom input is text only
|
|
286
|
+
|
|
287
|
+
## Testing Strategy
|
|
288
|
+
|
|
289
|
+
1. **Unit Tests**:
|
|
290
|
+
- Input validation
|
|
291
|
+
- Option parsing
|
|
292
|
+
- Answer formatting
|
|
293
|
+
|
|
294
|
+
2. **Integration Tests**:
|
|
295
|
+
- Tool registration
|
|
296
|
+
- Agent flow with questions
|
|
297
|
+
- Answer processing
|
|
298
|
+
|
|
299
|
+
3. **Manual Testing**:
|
|
300
|
+
- UI rendering
|
|
301
|
+
- Keyboard navigation
|
|
302
|
+
- Multi-select behavior
|
|
303
|
+
- Custom input flow
|
|
304
|
+
|
|
305
|
+
## Migration Path
|
|
306
|
+
|
|
307
|
+
1. **Phase 1**: Core tool and basic select UI
|
|
308
|
+
2. **Phase 2**: Multi-select support
|
|
309
|
+
3. **Phase 3**: Enhanced UI with descriptions
|
|
310
|
+
4. **Phase 4**: Keyboard shortcuts and accessibility
|
|
311
|
+
|
|
312
|
+
No breaking changes to existing functionality.
|
|
313
|
+
|
|
314
|
+
## References
|
|
315
|
+
|
|
316
|
+
- [Claude Code AskUserQuestion Tool](https://code.claude.com/docs/en/tools)
|
|
317
|
+
- [Inquirer.js](https://github.com/SBoudrias/Inquirer.js) (inspiration for UI)
|