@braingrid/cli 0.0.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.
Files changed (155) hide show
  1. package/README.md +164 -0
  2. package/dist/.build-info.json +9 -0
  3. package/dist/build-config.d.ts +25 -0
  4. package/dist/build-config.d.ts.map +1 -0
  5. package/dist/build-config.js +27 -0
  6. package/dist/build-config.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +246 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/handlers/auth.handlers.d.ts +13 -0
  12. package/dist/handlers/auth.handlers.d.ts.map +1 -0
  13. package/dist/handlers/auth.handlers.js +99 -0
  14. package/dist/handlers/auth.handlers.js.map +1 -0
  15. package/dist/handlers/index.d.ts +11 -0
  16. package/dist/handlers/index.d.ts.map +1 -0
  17. package/dist/handlers/index.js +11 -0
  18. package/dist/handlers/index.js.map +1 -0
  19. package/dist/handlers/project.handlers.d.ts +29 -0
  20. package/dist/handlers/project.handlers.d.ts.map +1 -0
  21. package/dist/handlers/project.handlers.js +200 -0
  22. package/dist/handlers/project.handlers.js.map +1 -0
  23. package/dist/handlers/requirement.handlers.d.ts +32 -0
  24. package/dist/handlers/requirement.handlers.d.ts.map +1 -0
  25. package/dist/handlers/requirement.handlers.js +234 -0
  26. package/dist/handlers/requirement.handlers.js.map +1 -0
  27. package/dist/handlers/status.handlers.d.ts +12 -0
  28. package/dist/handlers/status.handlers.d.ts.map +1 -0
  29. package/dist/handlers/status.handlers.js +209 -0
  30. package/dist/handlers/status.handlers.js.map +1 -0
  31. package/dist/handlers/task.handlers.d.ts +29 -0
  32. package/dist/handlers/task.handlers.d.ts.map +1 -0
  33. package/dist/handlers/task.handlers.js +272 -0
  34. package/dist/handlers/task.handlers.js.map +1 -0
  35. package/dist/handlers/types.d.ts +10 -0
  36. package/dist/handlers/types.d.ts.map +1 -0
  37. package/dist/handlers/types.js +5 -0
  38. package/dist/handlers/types.js.map +1 -0
  39. package/dist/services/auth.d.ts +41 -0
  40. package/dist/services/auth.d.ts.map +1 -0
  41. package/dist/services/auth.js +498 -0
  42. package/dist/services/auth.js.map +1 -0
  43. package/dist/services/claude.d.ts +18 -0
  44. package/dist/services/claude.d.ts.map +1 -0
  45. package/dist/services/claude.js +164 -0
  46. package/dist/services/claude.js.map +1 -0
  47. package/dist/services/context-manager.d.ts +170 -0
  48. package/dist/services/context-manager.d.ts.map +1 -0
  49. package/dist/services/context-manager.js +261 -0
  50. package/dist/services/context-manager.js.map +1 -0
  51. package/dist/services/credential-store.d.ts +47 -0
  52. package/dist/services/credential-store.d.ts.map +1 -0
  53. package/dist/services/credential-store.js +88 -0
  54. package/dist/services/credential-store.js.map +1 -0
  55. package/dist/services/oauth2-auth.d.ts +60 -0
  56. package/dist/services/oauth2-auth.d.ts.map +1 -0
  57. package/dist/services/oauth2-auth.js +377 -0
  58. package/dist/services/oauth2-auth.js.map +1 -0
  59. package/dist/services/project-service.d.ts +22 -0
  60. package/dist/services/project-service.d.ts.map +1 -0
  61. package/dist/services/project-service.js +52 -0
  62. package/dist/services/project-service.js.map +1 -0
  63. package/dist/services/requirement-service.d.ts +32 -0
  64. package/dist/services/requirement-service.d.ts.map +1 -0
  65. package/dist/services/requirement-service.js +91 -0
  66. package/dist/services/requirement-service.js.map +1 -0
  67. package/dist/services/task-service.d.ts +22 -0
  68. package/dist/services/task-service.d.ts.map +1 -0
  69. package/dist/services/task-service.js +52 -0
  70. package/dist/services/task-service.js.map +1 -0
  71. package/dist/test/setup.d.ts +2 -0
  72. package/dist/test/setup.d.ts.map +1 -0
  73. package/dist/test/setup.js +40 -0
  74. package/dist/test/setup.js.map +1 -0
  75. package/dist/types/api.d.ts +16 -0
  76. package/dist/types/api.d.ts.map +1 -0
  77. package/dist/types/api.js +5 -0
  78. package/dist/types/api.js.map +1 -0
  79. package/dist/types/auth.d.ts +68 -0
  80. package/dist/types/auth.d.ts.map +1 -0
  81. package/dist/types/auth.js +2 -0
  82. package/dist/types/auth.js.map +1 -0
  83. package/dist/types/claude.d.ts +22 -0
  84. package/dist/types/claude.d.ts.map +1 -0
  85. package/dist/types/claude.js +2 -0
  86. package/dist/types/claude.js.map +1 -0
  87. package/dist/types/project.d.ts +32 -0
  88. package/dist/types/project.d.ts.map +1 -0
  89. package/dist/types/project.js +5 -0
  90. package/dist/types/project.js.map +1 -0
  91. package/dist/types/requirement.d.ts +69 -0
  92. package/dist/types/requirement.d.ts.map +1 -0
  93. package/dist/types/requirement.js +5 -0
  94. package/dist/types/requirement.js.map +1 -0
  95. package/dist/types/task.d.ts +44 -0
  96. package/dist/types/task.d.ts.map +1 -0
  97. package/dist/types/task.js +5 -0
  98. package/dist/types/task.js.map +1 -0
  99. package/dist/utils/axios-retry.d.ts +25 -0
  100. package/dist/utils/axios-retry.d.ts.map +1 -0
  101. package/dist/utils/axios-retry.js +174 -0
  102. package/dist/utils/axios-retry.js.map +1 -0
  103. package/dist/utils/axios-with-auth.d.ts +10 -0
  104. package/dist/utils/axios-with-auth.d.ts.map +1 -0
  105. package/dist/utils/axios-with-auth.js +118 -0
  106. package/dist/utils/axios-with-auth.js.map +1 -0
  107. package/dist/utils/cli-tools.d.ts +30 -0
  108. package/dist/utils/cli-tools.d.ts.map +1 -0
  109. package/dist/utils/cli-tools.js +131 -0
  110. package/dist/utils/cli-tools.js.map +1 -0
  111. package/dist/utils/command-execution.d.ts +30 -0
  112. package/dist/utils/command-execution.d.ts.map +1 -0
  113. package/dist/utils/command-execution.js +264 -0
  114. package/dist/utils/command-execution.js.map +1 -0
  115. package/dist/utils/command-parser.d.ts +85 -0
  116. package/dist/utils/command-parser.d.ts.map +1 -0
  117. package/dist/utils/command-parser.js +287 -0
  118. package/dist/utils/command-parser.js.map +1 -0
  119. package/dist/utils/config.d.ts +9 -0
  120. package/dist/utils/config.d.ts.map +1 -0
  121. package/dist/utils/config.js +59 -0
  122. package/dist/utils/config.js.map +1 -0
  123. package/dist/utils/error-formatter.d.ts +17 -0
  124. package/dist/utils/error-formatter.d.ts.map +1 -0
  125. package/dist/utils/error-formatter.js +115 -0
  126. package/dist/utils/error-formatter.js.map +1 -0
  127. package/dist/utils/formatting.d.ts +10 -0
  128. package/dist/utils/formatting.d.ts.map +1 -0
  129. package/dist/utils/formatting.js +122 -0
  130. package/dist/utils/formatting.js.map +1 -0
  131. package/dist/utils/git.d.ts +55 -0
  132. package/dist/utils/git.d.ts.map +1 -0
  133. package/dist/utils/git.js +131 -0
  134. package/dist/utils/git.js.map +1 -0
  135. package/dist/utils/jwt.d.ts +45 -0
  136. package/dist/utils/jwt.d.ts.map +1 -0
  137. package/dist/utils/jwt.js +64 -0
  138. package/dist/utils/jwt.js.map +1 -0
  139. package/dist/utils/logger.d.ts +36 -0
  140. package/dist/utils/logger.d.ts.map +1 -0
  141. package/dist/utils/logger.js +176 -0
  142. package/dist/utils/logger.js.map +1 -0
  143. package/dist/utils/requirements.d.ts +28 -0
  144. package/dist/utils/requirements.d.ts.map +1 -0
  145. package/dist/utils/requirements.js +54 -0
  146. package/dist/utils/requirements.js.map +1 -0
  147. package/dist/utils/status-parser.d.ts +95 -0
  148. package/dist/utils/status-parser.d.ts.map +1 -0
  149. package/dist/utils/status-parser.js +189 -0
  150. package/dist/utils/status-parser.js.map +1 -0
  151. package/dist/utils/tasks.d.ts +9 -0
  152. package/dist/utils/tasks.d.ts.map +1 -0
  153. package/dist/utils/tasks.js +38 -0
  154. package/dist/utils/tasks.js.map +1 -0
  155. package/package.json +101 -0
@@ -0,0 +1,264 @@
1
+ import { exec, spawn } from 'child_process';
2
+ import { promisify } from 'util';
3
+ const execAsyncReal = promisify(exec);
4
+ /**
5
+ * Execute a command asynchronously with proper buffer limits and timeout handling
6
+ */
7
+ export async function execAsync(command, options, isTestMode = false, mockExecHandler) {
8
+ if (isTestMode && mockExecHandler) {
9
+ return mockExecHandler(command);
10
+ }
11
+ // Set appropriate buffer limits based on command type
12
+ const defaultOptions = {
13
+ maxBuffer: 1024 * 1024 * 10, // 10MB default
14
+ timeout: 300000, // 5 minutes
15
+ ...options,
16
+ };
17
+ // Increase buffer for Claude commands that may produce large outputs
18
+ if (command.includes('claude')) {
19
+ defaultOptions.maxBuffer = 1024 * 1024 * 50; // 50MB for Claude commands
20
+ defaultOptions.timeout = 600000; // 10 minutes for Claude
21
+ }
22
+ return execAsyncReal(command, defaultOptions);
23
+ }
24
+ /**
25
+ * Execute a command with streaming output support
26
+ */
27
+ export async function execStreamAsync(command, onOutput, isTestMode = false, mockExecHandler, options) {
28
+ if (isTestMode && mockExecHandler) {
29
+ // For test mode, simulate streaming
30
+ const result = await mockExecHandler(command);
31
+ if (onOutput) {
32
+ // Simulate streaming by sending output in chunks
33
+ const lines = result.stdout.split('\n');
34
+ for (const line of lines) {
35
+ if (line.trim()) {
36
+ onOutput(line + '\n');
37
+ await new Promise(resolve => setTimeout(resolve, 200));
38
+ }
39
+ }
40
+ }
41
+ return result;
42
+ }
43
+ return new Promise((resolve, reject) => {
44
+ // Parse command to handle quotes properly
45
+ let cmd;
46
+ let args;
47
+ if (command.startsWith('claude -p --dangerously-skip-permissions "')) {
48
+ cmd = 'claude';
49
+ // Extract the quoted content for non-interactive mode with skip permissions
50
+ const promptMatch = command.match(/^claude -p --dangerously-skip-permissions "(.*)"/s);
51
+ args = promptMatch ? ['-p', '--dangerously-skip-permissions', promptMatch[1]] : [];
52
+ }
53
+ else if (command.startsWith('claude -p "')) {
54
+ cmd = 'claude';
55
+ // Extract the quoted content for non-interactive mode
56
+ const promptMatch = command.match(/^claude -p "(.*)"/s);
57
+ args = promptMatch ? ['-p', promptMatch[1]] : [];
58
+ }
59
+ else if (command.startsWith('claude "')) {
60
+ cmd = 'claude';
61
+ // Extract the quoted content for interactive mode
62
+ const promptMatch = command.match(/^claude "(.*)"/s);
63
+ args = promptMatch ? [promptMatch[1]] : [];
64
+ }
65
+ else if (command.startsWith('git commit')) {
66
+ // Special handling for git commit to properly parse the message
67
+ const parts = command.match(/^git\s+commit\s+(.*)$/);
68
+ if (parts && parts[1]) {
69
+ cmd = 'git';
70
+ args = ['commit'];
71
+ // Parse the rest of the arguments, handling -m "message" properly
72
+ const argString = parts[1];
73
+ const messageMatch = argString.match(/-m\s+"([^"]+)"/);
74
+ if (messageMatch) {
75
+ args.push('-m', messageMatch[1]);
76
+ // Add any other arguments that might be before or after -m
77
+ const beforeMessage = argString.substring(0, argString.indexOf('-m')).trim();
78
+ const afterMessage = argString
79
+ .substring(argString.indexOf(messageMatch[0]) + messageMatch[0].length)
80
+ .trim();
81
+ if (beforeMessage)
82
+ args.unshift(...beforeMessage.split(' '));
83
+ if (afterMessage)
84
+ args.push(...afterMessage.split(' '));
85
+ }
86
+ else {
87
+ args.push(...argString.split(' '));
88
+ }
89
+ }
90
+ else {
91
+ [cmd, ...args] = command.split(' ');
92
+ }
93
+ }
94
+ else {
95
+ // Simple command splitting for other commands
96
+ [cmd, ...args] = command.split(' ');
97
+ }
98
+ const child = spawn(cmd, args, {
99
+ shell: false,
100
+ stdio: ['inherit', 'pipe', 'pipe'],
101
+ });
102
+ let stdout = '';
103
+ let stderr = '';
104
+ // Smart timeout handling
105
+ const isGitCommit = cmd === 'git' && args[0] === 'commit';
106
+ const maxTimeout = options?.timeout || (isGitCommit ? 900000 : 300000); // 15 min for git commit, 5 min default
107
+ const inactivityTimeout = options?.inactivityTimeout || (isGitCommit ? 60000 : 30000); // 60s for git commit, 30s default
108
+ let globalTimeoutId = null;
109
+ let inactivityTimeoutId = null;
110
+ const clearTimeouts = () => {
111
+ if (globalTimeoutId)
112
+ clearTimeout(globalTimeoutId);
113
+ if (inactivityTimeoutId)
114
+ clearTimeout(inactivityTimeoutId);
115
+ };
116
+ const resetInactivityTimeout = () => {
117
+ if (inactivityTimeoutId)
118
+ clearTimeout(inactivityTimeoutId);
119
+ inactivityTimeoutId = setTimeout(() => {
120
+ clearTimeouts();
121
+ child.kill('SIGTERM');
122
+ reject(new Error(`Command timed out due to ${inactivityTimeout / 1000}s of inactivity`));
123
+ }, inactivityTimeout);
124
+ };
125
+ // Set global timeout
126
+ globalTimeoutId = setTimeout(() => {
127
+ clearTimeouts();
128
+ child.kill('SIGTERM');
129
+ reject(new Error(`Command exceeded maximum timeout of ${maxTimeout / 1000}s`));
130
+ }, maxTimeout);
131
+ // Start inactivity timeout
132
+ resetInactivityTimeout();
133
+ child.stdout?.on('data', data => {
134
+ const chunk = data.toString();
135
+ stdout += chunk;
136
+ if (onOutput) {
137
+ onOutput(chunk);
138
+ }
139
+ // Reset inactivity timeout on any output
140
+ resetInactivityTimeout();
141
+ });
142
+ child.stderr?.on('data', data => {
143
+ const chunk = data.toString();
144
+ stderr += chunk;
145
+ if (onOutput) {
146
+ onOutput(chunk);
147
+ }
148
+ // Reset inactivity timeout on any output (pre-commit hooks often write to stderr)
149
+ resetInactivityTimeout();
150
+ });
151
+ child.on('close', code => {
152
+ clearTimeouts();
153
+ if (code === 0) {
154
+ resolve({ stdout, stderr });
155
+ }
156
+ else {
157
+ reject(new Error(`Command failed with exit code ${code}: ${stderr}`));
158
+ }
159
+ });
160
+ child.on('error', error => {
161
+ clearTimeouts();
162
+ reject(error);
163
+ });
164
+ });
165
+ }
166
+ /**
167
+ * Execute git commit with smart timeout handling for pre-commit hooks
168
+ */
169
+ export async function execGitCommitAsync(commitMessage, onOutput, isTestMode = false, mockExecHandler) {
170
+ const command = `git commit -m "${commitMessage}"`;
171
+ return execStreamAsync(command, onOutput, isTestMode, mockExecHandler);
172
+ }
173
+ /**
174
+ * Mock execution handler for testing
175
+ */
176
+ export async function createMockExecHandler(addMessage) {
177
+ return async (command) => {
178
+ if (addMessage) {
179
+ addMessage('info', `🧪 TEST MODE: Simulating command: ${command}`);
180
+ }
181
+ // Simulate delays
182
+ await new Promise(resolve => setTimeout(resolve, 500));
183
+ // Git commands
184
+ if (command.includes('git branch --show-current')) {
185
+ return { stdout: 'feature/test-branch', stderr: '' };
186
+ }
187
+ if (command.includes('gh repo view')) {
188
+ return { stdout: 'main', stderr: '' };
189
+ }
190
+ if (command.includes('git checkout -b')) {
191
+ const branchName = command.split(' ').pop();
192
+ return { stdout: `Switched to a new branch '${branchName}'`, stderr: '' };
193
+ }
194
+ if (command.includes('git checkout main')) {
195
+ return { stdout: 'Switched to branch main', stderr: '' };
196
+ }
197
+ if (command.includes('git pull')) {
198
+ return { stdout: 'Already up to date.', stderr: '' };
199
+ }
200
+ if (command.includes('git add .')) {
201
+ return { stdout: '', stderr: '' };
202
+ }
203
+ if (command.includes('git diff --cached --quiet')) {
204
+ throw new Error('Changes to commit'); // Simulate changes exist
205
+ }
206
+ if (command.includes('git commit')) {
207
+ return { stdout: '[feature/test abc123] feat: mock commit', stderr: '' };
208
+ }
209
+ if (command.includes('git push')) {
210
+ const branchName = command.includes('feature/') ? 'feature/test-branch' : 'current-branch';
211
+ return {
212
+ stdout: `To github.com:test/repo.git\n * [new branch] ${branchName} -> ${branchName}\nBranch '${branchName}' set up to track remote branch '${branchName}' from 'origin'.`,
213
+ stderr: '',
214
+ };
215
+ }
216
+ // CLI version checks
217
+ if (command.includes('claude --version')) {
218
+ return { stdout: 'claude version 2.1.3', stderr: '' };
219
+ }
220
+ if (command.includes('gh --version')) {
221
+ return { stdout: 'gh version 2.40.1', stderr: '' };
222
+ }
223
+ // GitHub commands
224
+ if (command.includes('gh pr create')) {
225
+ return { stdout: 'https://github.com/test/repo/pull/123', stderr: '' };
226
+ }
227
+ // Claude commands
228
+ if (command.includes('Generate a conventional commit')) {
229
+ const taskTitle = command.includes('login')
230
+ ? 'login component'
231
+ : command.includes('JWT')
232
+ ? 'JWT authentication'
233
+ : command.includes('logout')
234
+ ? 'logout functionality'
235
+ : 'test feature';
236
+ return { stdout: `feat(auth): add ${taskTitle}`, stderr: '' };
237
+ }
238
+ if (command.includes('Generate a comprehensive GitHub Pull Request')) {
239
+ return {
240
+ stdout: `## Summary\nImplemented mock authentication system with all required functionality.\n\n## Tasks Completed\n- [x] Mock login component\n- [x] Mock JWT authentication\n- [x] Mock logout functionality\n\n## Testing\nTest the mock implementation thoroughly.\n\n## Notes\nThis is a test implementation.`,
241
+ stderr: '',
242
+ };
243
+ }
244
+ if (command.startsWith('claude -p --dangerously-skip-permissions "') ||
245
+ command.startsWith('claude -p "') ||
246
+ command.startsWith('claude "')) {
247
+ // Handle task content and other prompts
248
+ const taskTitle = command.includes('login')
249
+ ? 'Login Component'
250
+ : command.includes('JWT')
251
+ ? 'JWT Authentication'
252
+ : command.includes('logout')
253
+ ? 'Logout Functionality'
254
+ : 'Test Feature';
255
+ return {
256
+ stdout: `# ${taskTitle} Implementation\n\n## Files Created/Modified\n- src/components/auth/${taskTitle.replace(' ', '')}.tsx\n- src/hooks/useAuth.ts\n- src/utils/auth.ts\n\n## Implementation Details\nCreated comprehensive ${taskTitle.toLowerCase()} with modern React patterns, TypeScript support, and proper error handling.\n\n## Testing\nAdded unit tests and integration tests for the ${taskTitle.toLowerCase()}.`,
257
+ stderr: '',
258
+ };
259
+ }
260
+ // Default response
261
+ return { stdout: 'Mock command executed successfully', stderr: '' };
262
+ };
263
+ }
264
+ //# sourceMappingURL=command-execution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-execution.js","sourceRoot":"","sources":["../../src/utils/command-execution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import { type Status } from './status-parser.js';
2
+ /**
3
+ * Types of commands in the CLI
4
+ */
5
+ export type CommandType = 'contextual' | 'direct' | 'global';
6
+ /**
7
+ * Represents a parsed command with its components
8
+ */
9
+ export interface ParsedCommand {
10
+ /**
11
+ * The type of command (contextual, direct, or global)
12
+ */
13
+ type: CommandType;
14
+ /**
15
+ * The base command (e.g., 'show', 'task', 'build')
16
+ */
17
+ command: string;
18
+ /**
19
+ * The subcommand if any (e.g., 'list' in 'task list')
20
+ */
21
+ subcommand?: string;
22
+ /**
23
+ * Requirement ID if specified (normalized to internal format)
24
+ */
25
+ requirementId?: string;
26
+ /**
27
+ * Additional arguments after command/subcommand/requirementId
28
+ */
29
+ args: string[];
30
+ /**
31
+ * Parsed status filters if any
32
+ */
33
+ statusFilters?: Status[];
34
+ /**
35
+ * Raw input for reference
36
+ */
37
+ rawInput: string;
38
+ /**
39
+ * Any parsing errors or warnings
40
+ */
41
+ errors?: string[];
42
+ }
43
+ /**
44
+ * Validates and normalizes a requirement ID
45
+ * Accepts formats: REQ-123, req-123, 123, or UUID format
46
+ *
47
+ * @param id - The requirement ID to validate
48
+ * @returns Normalized requirement ID or null if invalid
49
+ */
50
+ export declare function validateRequirementId(id: string): string | null;
51
+ /**
52
+ * Extracts status filters from command arguments
53
+ *
54
+ * @param args - Command arguments
55
+ * @returns Object with filtered args and extracted status filters
56
+ */
57
+ export declare function extractStatusFilters(args: string[]): {
58
+ filteredArgs: string[];
59
+ statusFilters?: Status[];
60
+ statusError?: string;
61
+ };
62
+ /**
63
+ * Parses a command string into its components
64
+ *
65
+ * @param input - The raw command input
66
+ * @param hasContext - Whether there's an active requirement context
67
+ * @returns ParsedCommand object
68
+ */
69
+ export declare function parseCommand(input: string, hasContext?: boolean): ParsedCommand;
70
+ /**
71
+ * Formats a requirement ID for display (e.g., req_123 -> REQ-123)
72
+ *
73
+ * @param requirementId - Internal requirement ID
74
+ * @returns Formatted ID for display
75
+ */
76
+ export declare function formatRequirementIdForDisplay(requirementId: string): string;
77
+ /**
78
+ * Suggests commands based on partial input
79
+ *
80
+ * @param partial - Partial command input
81
+ * @param hasContext - Whether there's an active context
82
+ * @returns Array of suggested commands
83
+ */
84
+ export declare function suggestCommands(partial: string, hasContext?: boolean): string[];
85
+ //# sourceMappingURL=command-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-parser.d.ts","sourceRoot":"","sources":["../../src/utils/command-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B;;OAEG;IACH,IAAI,EAAE,WAAW,CAAC;IAElB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AA4CD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgC/D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IACrD,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB,CAgDA;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,OAAe,GAAG,aAAa,CAsItF;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAM3E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,GAAE,OAAe,GAAG,MAAM,EAAE,CAyBtF"}
@@ -0,0 +1,287 @@
1
+ import { parseAndValidateStatus } from './status-parser.js';
2
+ /**
3
+ * Commands that can work with context (no requirement ID needed when context is active)
4
+ */
5
+ const CONTEXTUAL_COMMANDS = new Set([
6
+ 'show',
7
+ 'task',
8
+ 'tasks',
9
+ 'build',
10
+ 'assign',
11
+ 'unassign',
12
+ 'close',
13
+ 'reopen',
14
+ ]);
15
+ /**
16
+ * Commands that are always global (never use context)
17
+ */
18
+ const GLOBAL_COMMANDS = new Set([
19
+ 'help',
20
+ 'version',
21
+ 'login',
22
+ 'logout',
23
+ 'whoami',
24
+ 'status',
25
+ 'clear',
26
+ 'exit',
27
+ 'quit',
28
+ 'use',
29
+ 'context',
30
+ 'list',
31
+ 'my',
32
+ 'mine',
33
+ 'assigned',
34
+ 'req',
35
+ 'requirements',
36
+ 'github',
37
+ 'claude',
38
+ 'logs',
39
+ 'log',
40
+ 'debug:assigned',
41
+ ]);
42
+ /**
43
+ * Validates and normalizes a requirement ID
44
+ * Accepts formats: REQ-123, req-123, 123, or UUID format
45
+ *
46
+ * @param id - The requirement ID to validate
47
+ * @returns Normalized requirement ID or null if invalid
48
+ */
49
+ export function validateRequirementId(id) {
50
+ if (!id || typeof id !== 'string') {
51
+ return null;
52
+ }
53
+ const trimmedId = id.trim();
54
+ // Handle REQ-XXX format
55
+ const reqMatch = trimmedId.match(/^req[-_]?(\d+)$/i);
56
+ if (reqMatch) {
57
+ return `req_${reqMatch[1]}`;
58
+ }
59
+ // Handle numeric ID only
60
+ const numMatch = trimmedId.match(/^(\d+)$/);
61
+ if (numMatch) {
62
+ return `req_${numMatch[1]}`;
63
+ }
64
+ // Handle UUID format (req_abc123 style)
65
+ const uuidMatch = trimmedId.match(/^req_[a-zA-Z0-9]+$/);
66
+ if (uuidMatch) {
67
+ return trimmedId;
68
+ }
69
+ // Handle UUID without req_ prefix (must contain numbers to be valid)
70
+ const bareUuidMatch = trimmedId.match(/^[a-zA-Z]*[0-9]+[a-zA-Z0-9]*$/);
71
+ if (bareUuidMatch && trimmedId.length >= 6) {
72
+ return `req_${trimmedId}`;
73
+ }
74
+ return null;
75
+ }
76
+ /**
77
+ * Extracts status filters from command arguments
78
+ *
79
+ * @param args - Command arguments
80
+ * @returns Object with filtered args and extracted status filters
81
+ */
82
+ export function extractStatusFilters(args) {
83
+ const filteredArgs = [];
84
+ let statusArg = null;
85
+ let skipNext = false;
86
+ for (let i = 0; i < args.length; i++) {
87
+ if (skipNext) {
88
+ skipNext = false;
89
+ continue;
90
+ }
91
+ const arg = args[i];
92
+ // Check for --status flag
93
+ if (arg === '--status' || arg === '-s') {
94
+ if (i + 1 < args.length) {
95
+ statusArg = args[i + 1];
96
+ skipNext = true;
97
+ }
98
+ else {
99
+ return {
100
+ filteredArgs: args,
101
+ statusError: 'Status flag requires a value (e.g., --status todo,doing)',
102
+ };
103
+ }
104
+ }
105
+ else if (arg.startsWith('--status=')) {
106
+ statusArg = arg.substring('--status='.length);
107
+ }
108
+ else {
109
+ filteredArgs.push(arg);
110
+ }
111
+ }
112
+ // Parse status if found
113
+ if (statusArg) {
114
+ const statusResult = parseAndValidateStatus(statusArg);
115
+ if (statusResult.hasErrors) {
116
+ return {
117
+ filteredArgs: args,
118
+ statusError: statusResult.errorMessage,
119
+ };
120
+ }
121
+ return {
122
+ filteredArgs,
123
+ statusFilters: statusResult.statuses,
124
+ };
125
+ }
126
+ return { filteredArgs };
127
+ }
128
+ /**
129
+ * Parses a command string into its components
130
+ *
131
+ * @param input - The raw command input
132
+ * @param hasContext - Whether there's an active requirement context
133
+ * @returns ParsedCommand object
134
+ */
135
+ export function parseCommand(input, hasContext = false) {
136
+ const trimmedInput = input.trim();
137
+ const parts = trimmedInput.split(/\s+/).filter(p => p.length > 0);
138
+ if (parts.length === 0) {
139
+ return {
140
+ type: 'global',
141
+ command: '',
142
+ args: [],
143
+ rawInput: input,
144
+ };
145
+ }
146
+ const [firstPart, ...restParts] = parts;
147
+ const command = firstPart.toLowerCase();
148
+ // Check if it's a global command
149
+ if (GLOBAL_COMMANDS.has(command)) {
150
+ // Special handling for 'use' command
151
+ if (command === 'use' && restParts.length > 0) {
152
+ const reqId = validateRequirementId(restParts[0]);
153
+ if (!reqId) {
154
+ return {
155
+ type: 'global',
156
+ command,
157
+ args: restParts,
158
+ rawInput: input,
159
+ errors: [`Invalid requirement ID: ${restParts[0]}`],
160
+ };
161
+ }
162
+ return {
163
+ type: 'global',
164
+ command,
165
+ requirementId: reqId,
166
+ args: restParts.slice(1),
167
+ rawInput: input,
168
+ };
169
+ }
170
+ // Extract status filters for list commands
171
+ const { filteredArgs, statusFilters, statusError } = extractStatusFilters(restParts);
172
+ const result = {
173
+ type: 'global',
174
+ command,
175
+ args: filteredArgs,
176
+ rawInput: input,
177
+ };
178
+ if (statusFilters) {
179
+ result.statusFilters = statusFilters;
180
+ }
181
+ if (statusError) {
182
+ result.errors = [statusError];
183
+ }
184
+ return result;
185
+ }
186
+ // Check if it's a contextual command
187
+ if (CONTEXTUAL_COMMANDS.has(command)) {
188
+ // Determine if this is contextual or direct based on arguments
189
+ let requirementId = null;
190
+ let subcommand;
191
+ let remainingArgs = restParts;
192
+ // Check if first argument could be a subcommand
193
+ if (restParts.length > 0) {
194
+ const possibleSubcommand = restParts[0].toLowerCase();
195
+ // For task/tasks command, check for subcommands
196
+ if ((command === 'task' || command === 'tasks') &&
197
+ ['list', 'show', 'update', 'complete', 'search', 'for', 'assigned'].includes(possibleSubcommand)) {
198
+ subcommand = possibleSubcommand;
199
+ remainingArgs = restParts.slice(1);
200
+ }
201
+ // Check if next argument is a requirement ID
202
+ if (remainingArgs.length > 0) {
203
+ const possibleReqId = validateRequirementId(remainingArgs[0]);
204
+ if (possibleReqId) {
205
+ requirementId = possibleReqId;
206
+ remainingArgs = remainingArgs.slice(1);
207
+ }
208
+ }
209
+ }
210
+ // Determine command type
211
+ const isContextual = hasContext && !requirementId;
212
+ const isDirect = !hasContext || requirementId !== null;
213
+ // Extract status filters
214
+ const { filteredArgs, statusFilters, statusError } = extractStatusFilters(remainingArgs);
215
+ const result = {
216
+ type: isContextual ? 'contextual' : 'direct',
217
+ command,
218
+ subcommand,
219
+ requirementId: requirementId || undefined,
220
+ args: filteredArgs,
221
+ rawInput: input,
222
+ };
223
+ if (statusFilters) {
224
+ result.statusFilters = statusFilters;
225
+ }
226
+ if (statusError) {
227
+ result.errors = result.errors || [];
228
+ result.errors.push(statusError);
229
+ }
230
+ // Add error if direct command without requirement ID and no context
231
+ if (isDirect && !requirementId && !hasContext) {
232
+ result.errors = result.errors || [];
233
+ result.errors.push(`Command '${command}' requires a requirement ID or active context`);
234
+ }
235
+ return result;
236
+ }
237
+ // Unknown command - treat as global
238
+ return {
239
+ type: 'global',
240
+ command,
241
+ args: restParts,
242
+ rawInput: input,
243
+ errors: [`Unknown command: ${command}`],
244
+ };
245
+ }
246
+ /**
247
+ * Formats a requirement ID for display (e.g., req_123 -> REQ-123)
248
+ *
249
+ * @param requirementId - Internal requirement ID
250
+ * @returns Formatted ID for display
251
+ */
252
+ export function formatRequirementIdForDisplay(requirementId) {
253
+ const match = requirementId.match(/^req_(\d+)$/);
254
+ if (match) {
255
+ return `REQ-${match[1]}`;
256
+ }
257
+ return requirementId;
258
+ }
259
+ /**
260
+ * Suggests commands based on partial input
261
+ *
262
+ * @param partial - Partial command input
263
+ * @param hasContext - Whether there's an active context
264
+ * @returns Array of suggested commands
265
+ */
266
+ export function suggestCommands(partial, hasContext = false) {
267
+ const allCommands = new Set([...GLOBAL_COMMANDS, ...CONTEXTUAL_COMMANDS]);
268
+ const normalizedPartial = partial.toLowerCase();
269
+ if (!normalizedPartial) {
270
+ return Array.from(allCommands).sort();
271
+ }
272
+ const suggestions = Array.from(allCommands)
273
+ .filter(cmd => cmd.startsWith(normalizedPartial))
274
+ .sort();
275
+ // Add context-specific suggestions
276
+ if (hasContext && suggestions.length === 0) {
277
+ // Suggest contextual commands if user might be trying to use them
278
+ const contextualSuggestions = Array.from(CONTEXTUAL_COMMANDS)
279
+ .filter(cmd => cmd.includes(normalizedPartial))
280
+ .sort();
281
+ if (contextualSuggestions.length > 0) {
282
+ return contextualSuggestions;
283
+ }
284
+ }
285
+ return suggestions;
286
+ }
287
+ //# sourceMappingURL=command-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-parser.js","sourceRoot":"","sources":["../../src/utils/command-parser.ts"],"names":[],"mappings":"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"}