@braingrid/cli 0.2.24 โ†’ 0.2.25

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/CHANGELOG.md CHANGED
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.25] - 2025-12-22
11
+
12
+ ### Added
13
+
14
+ - **New CLI commands for AI workflow integration**
15
+ - `task specify` - Create new tasks from natural language prompts using AI
16
+ - `requirement create-branch` - Create git branches for requirements via GitHub API
17
+ - `requirement review` - Stream AI-powered acceptance review for pull requests
18
+
19
+ - **Branch name generation enhancements**
20
+ - Auto-generates branch names: `{username}/REQ-123-slugified-name`
21
+ - Slugifies username from email prefix to handle special characters (e.g., `john+test@` โ†’ `john-test`)
22
+
23
+ - **PR auto-detection for review command**
24
+ - Automatically detects PR number from current branch using `gh pr view`
25
+ - Falls back to interactive prompt if no PR is found
26
+
27
+ ### Fixed
28
+
29
+ - **Empty PR number handling**
30
+ - Fixed edge case where `gh pr view` returns empty string (branch has no associated PR)
31
+ - Now properly triggers fallback to interactive PR number input
32
+
10
33
  ## [0.2.24] - 2025-12-18
11
34
 
12
35
  ### Added
@@ -0,0 +1,230 @@
1
+ // src/utils/command-execution.ts
2
+ import { exec, spawn } from "child_process";
3
+ import { promisify } from "util";
4
+ var execAsyncReal = promisify(exec);
5
+ async function execAsync(command, options, isTestMode = false, mockExecHandler) {
6
+ if (isTestMode && mockExecHandler) {
7
+ return mockExecHandler(command);
8
+ }
9
+ const defaultOptions = {
10
+ maxBuffer: 1024 * 1024 * 10,
11
+ // 10MB default
12
+ timeout: 3e5,
13
+ // 5 minutes
14
+ ...options
15
+ };
16
+ if (command.includes("claude")) {
17
+ defaultOptions.maxBuffer = 1024 * 1024 * 50;
18
+ defaultOptions.timeout = 6e5;
19
+ }
20
+ return execAsyncReal(command, defaultOptions);
21
+ }
22
+ async function execStreamAsync(command, onOutput, isTestMode = false, mockExecHandler, options) {
23
+ if (isTestMode && mockExecHandler) {
24
+ const result = await mockExecHandler(command);
25
+ if (onOutput) {
26
+ const lines = result.stdout.split("\n");
27
+ for (const line of lines) {
28
+ if (line.trim()) {
29
+ onOutput(line + "\n");
30
+ await new Promise((resolve) => setTimeout(resolve, 200));
31
+ }
32
+ }
33
+ }
34
+ return result;
35
+ }
36
+ return new Promise((resolve, reject) => {
37
+ let cmd;
38
+ let args;
39
+ if (command.startsWith('claude -p --dangerously-skip-permissions "')) {
40
+ cmd = "claude";
41
+ const promptMatch = command.match(/^claude -p --dangerously-skip-permissions "(.*)"/s);
42
+ args = promptMatch ? ["-p", "--dangerously-skip-permissions", promptMatch[1]] : [];
43
+ } else if (command.startsWith('claude -p "')) {
44
+ cmd = "claude";
45
+ const promptMatch = command.match(/^claude -p "(.*)"/s);
46
+ args = promptMatch ? ["-p", promptMatch[1]] : [];
47
+ } else if (command.startsWith('claude "')) {
48
+ cmd = "claude";
49
+ const promptMatch = command.match(/^claude "(.*)"/s);
50
+ args = promptMatch ? [promptMatch[1]] : [];
51
+ } else if (command.startsWith("git commit")) {
52
+ const parts = command.match(/^git\s+commit\s+(.*)$/);
53
+ if (parts && parts[1]) {
54
+ cmd = "git";
55
+ args = ["commit"];
56
+ const argString = parts[1];
57
+ const messageMatch = argString.match(/-m\s+"([^"]+)"/);
58
+ if (messageMatch) {
59
+ args.push("-m", messageMatch[1]);
60
+ const beforeMessage = argString.substring(0, argString.indexOf("-m")).trim();
61
+ const afterMessage = argString.substring(argString.indexOf(messageMatch[0]) + messageMatch[0].length).trim();
62
+ if (beforeMessage) args.unshift(...beforeMessage.split(" "));
63
+ if (afterMessage) args.push(...afterMessage.split(" "));
64
+ } else {
65
+ args.push(...argString.split(" "));
66
+ }
67
+ } else {
68
+ [cmd, ...args] = command.split(" ");
69
+ }
70
+ } else {
71
+ [cmd, ...args] = command.split(" ");
72
+ }
73
+ const child = spawn(cmd, args, {
74
+ shell: false,
75
+ stdio: ["inherit", "pipe", "pipe"]
76
+ });
77
+ let stdout = "";
78
+ let stderr = "";
79
+ const isGitCommit = cmd === "git" && args[0] === "commit";
80
+ const maxTimeout = options?.timeout || (isGitCommit ? 9e5 : 3e5);
81
+ const inactivityTimeout = options?.inactivityTimeout || (isGitCommit ? 6e4 : 3e4);
82
+ let globalTimeoutId = null;
83
+ let inactivityTimeoutId = null;
84
+ const clearTimeouts = () => {
85
+ if (globalTimeoutId) clearTimeout(globalTimeoutId);
86
+ if (inactivityTimeoutId) clearTimeout(inactivityTimeoutId);
87
+ };
88
+ const resetInactivityTimeout = () => {
89
+ if (inactivityTimeoutId) clearTimeout(inactivityTimeoutId);
90
+ inactivityTimeoutId = setTimeout(() => {
91
+ clearTimeouts();
92
+ child.kill("SIGTERM");
93
+ reject(new Error(`Command timed out due to ${inactivityTimeout / 1e3}s of inactivity`));
94
+ }, inactivityTimeout);
95
+ };
96
+ globalTimeoutId = setTimeout(() => {
97
+ clearTimeouts();
98
+ child.kill("SIGTERM");
99
+ reject(new Error(`Command exceeded maximum timeout of ${maxTimeout / 1e3}s`));
100
+ }, maxTimeout);
101
+ resetInactivityTimeout();
102
+ child.stdout?.on("data", (data) => {
103
+ const chunk = data.toString();
104
+ stdout += chunk;
105
+ if (onOutput) {
106
+ onOutput(chunk);
107
+ }
108
+ resetInactivityTimeout();
109
+ });
110
+ child.stderr?.on("data", (data) => {
111
+ const chunk = data.toString();
112
+ stderr += chunk;
113
+ if (onOutput) {
114
+ onOutput(chunk);
115
+ }
116
+ resetInactivityTimeout();
117
+ });
118
+ child.on("close", (code) => {
119
+ clearTimeouts();
120
+ if (code === 0) {
121
+ resolve({ stdout, stderr });
122
+ } else {
123
+ reject(new Error(`Command failed with exit code ${code}: ${stderr}`));
124
+ }
125
+ });
126
+ child.on("error", (error) => {
127
+ clearTimeouts();
128
+ reject(error);
129
+ });
130
+ });
131
+ }
132
+ async function createMockExecHandler(addMessage) {
133
+ return async (command) => {
134
+ if (addMessage) {
135
+ addMessage("info", `\u{1F9EA} TEST MODE: Simulating command: ${command}`);
136
+ }
137
+ await new Promise((resolve) => setTimeout(resolve, 500));
138
+ if (command.includes("git branch --show-current")) {
139
+ return { stdout: "feature/test-branch", stderr: "" };
140
+ }
141
+ if (command.includes("gh repo view")) {
142
+ return { stdout: "main", stderr: "" };
143
+ }
144
+ if (command.includes("git checkout -b")) {
145
+ const branchName = command.split(" ").pop();
146
+ return { stdout: `Switched to a new branch '${branchName}'`, stderr: "" };
147
+ }
148
+ if (command.includes("git checkout main")) {
149
+ return { stdout: "Switched to branch main", stderr: "" };
150
+ }
151
+ if (command.includes("git pull")) {
152
+ return { stdout: "Already up to date.", stderr: "" };
153
+ }
154
+ if (command.includes("git add .")) {
155
+ return { stdout: "", stderr: "" };
156
+ }
157
+ if (command.includes("git diff --cached --quiet")) {
158
+ throw new Error("Changes to commit");
159
+ }
160
+ if (command.includes("git commit")) {
161
+ return { stdout: "[feature/test abc123] feat: mock commit", stderr: "" };
162
+ }
163
+ if (command.includes("git push")) {
164
+ const branchName = command.includes("feature/") ? "feature/test-branch" : "current-branch";
165
+ return {
166
+ stdout: `To github.com:test/repo.git
167
+ * [new branch] ${branchName} -> ${branchName}
168
+ Branch '${branchName}' set up to track remote branch '${branchName}' from 'origin'.`,
169
+ stderr: ""
170
+ };
171
+ }
172
+ if (command.includes("claude --version")) {
173
+ return { stdout: "claude version 2.1.3", stderr: "" };
174
+ }
175
+ if (command.includes("gh --version")) {
176
+ return { stdout: "gh version 2.40.1", stderr: "" };
177
+ }
178
+ if (command.includes("gh pr create")) {
179
+ return { stdout: "https://github.com/test/repo/pull/123", stderr: "" };
180
+ }
181
+ if (command.includes("Generate a conventional commit")) {
182
+ const taskTitle = command.includes("login") ? "login component" : command.includes("JWT") ? "JWT authentication" : command.includes("logout") ? "logout functionality" : "test feature";
183
+ return { stdout: `feat(auth): add ${taskTitle}`, stderr: "" };
184
+ }
185
+ if (command.includes("Generate a comprehensive GitHub Pull Request")) {
186
+ return {
187
+ stdout: `## Summary
188
+ Implemented mock authentication system with all required functionality.
189
+
190
+ ## Tasks Completed
191
+ - [x] Mock login component
192
+ - [x] Mock JWT authentication
193
+ - [x] Mock logout functionality
194
+
195
+ ## Testing
196
+ Test the mock implementation thoroughly.
197
+
198
+ ## Notes
199
+ This is a test implementation.`,
200
+ stderr: ""
201
+ };
202
+ }
203
+ if (command.startsWith('claude -p --dangerously-skip-permissions "') || command.startsWith('claude -p "') || command.startsWith('claude "')) {
204
+ const taskTitle = command.includes("login") ? "Login Component" : command.includes("JWT") ? "JWT Authentication" : command.includes("logout") ? "Logout Functionality" : "Test Feature";
205
+ return {
206
+ stdout: `# ${taskTitle} Implementation
207
+
208
+ ## Files Created/Modified
209
+ - src/components/auth/${taskTitle.replace(" ", "")}.tsx
210
+ - src/hooks/useAuth.ts
211
+ - src/utils/auth.ts
212
+
213
+ ## Implementation Details
214
+ Created comprehensive ${taskTitle.toLowerCase()} with modern React patterns, TypeScript support, and proper error handling.
215
+
216
+ ## Testing
217
+ Added unit tests and integration tests for the ${taskTitle.toLowerCase()}.`,
218
+ stderr: ""
219
+ };
220
+ }
221
+ return { stdout: "Mock command executed successfully", stderr: "" };
222
+ };
223
+ }
224
+
225
+ export {
226
+ execAsync,
227
+ execStreamAsync,
228
+ createMockExecHandler
229
+ };
230
+ //# sourceMappingURL=chunk-6GC3UJCM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/command-execution.ts"],"sourcesContent":["import { exec, spawn } from 'child_process';\nimport { promisify } from 'util';\n\nexport interface ExecResult {\n\tstdout: string;\n\tstderr: string;\n}\n\nexport interface ExecOptions {\n\tmaxBuffer?: number;\n\ttimeout?: number;\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n}\n\nconst execAsyncReal = promisify(exec);\n\n/**\n * Execute a command asynchronously with proper buffer limits and timeout handling\n */\nexport async function execAsync(\n\tcommand: string,\n\toptions?: ExecOptions,\n\tisTestMode: boolean = false,\n\tmockExecHandler?: (command: string) => Promise<ExecResult>\n): Promise<ExecResult> {\n\tif (isTestMode && mockExecHandler) {\n\t\treturn mockExecHandler(command);\n\t}\n\n\t// Set appropriate buffer limits based on command type\n\tconst defaultOptions: ExecOptions = {\n\t\tmaxBuffer: 1024 * 1024 * 10, // 10MB default\n\t\ttimeout: 300000, // 5 minutes\n\t\t...options,\n\t};\n\n\t// Increase buffer for Claude commands that may produce large outputs\n\tif (command.includes('claude')) {\n\t\tdefaultOptions.maxBuffer = 1024 * 1024 * 50; // 50MB for Claude commands\n\t\tdefaultOptions.timeout = 600000; // 10 minutes for Claude\n\t}\n\n\treturn execAsyncReal(command, defaultOptions);\n}\n\n/**\n * Execute a command with streaming output support\n */\nexport async function execStreamAsync(\n\tcommand: string,\n\tonOutput?: (chunk: string) => void,\n\tisTestMode: boolean = false,\n\tmockExecHandler?: (command: string) => Promise<ExecResult>,\n\toptions?: {\n\t\ttimeout?: number;\n\t\tinactivityTimeout?: number;\n\t}\n): Promise<ExecResult> {\n\tif (isTestMode && mockExecHandler) {\n\t\t// For test mode, simulate streaming\n\t\tconst result = await mockExecHandler(command);\n\t\tif (onOutput) {\n\t\t\t// Simulate streaming by sending output in chunks\n\t\t\tconst lines = result.stdout.split('\\n');\n\t\t\tfor (const line of lines) {\n\t\t\t\tif (line.trim()) {\n\t\t\t\t\tonOutput(line + '\\n');\n\t\t\t\t\tawait new Promise(resolve => setTimeout(resolve, 200));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\treturn new Promise((resolve, reject) => {\n\t\t// Parse command to handle quotes properly\n\t\tlet cmd: string;\n\t\tlet args: string[];\n\n\t\tif (command.startsWith('claude -p --dangerously-skip-permissions \"')) {\n\t\t\tcmd = 'claude';\n\t\t\t// Extract the quoted content for non-interactive mode with skip permissions\n\t\t\tconst promptMatch = command.match(/^claude -p --dangerously-skip-permissions \"(.*)\"/s);\n\t\t\targs = promptMatch ? ['-p', '--dangerously-skip-permissions', promptMatch[1]] : [];\n\t\t} else if (command.startsWith('claude -p \"')) {\n\t\t\tcmd = 'claude';\n\t\t\t// Extract the quoted content for non-interactive mode\n\t\t\tconst promptMatch = command.match(/^claude -p \"(.*)\"/s);\n\t\t\targs = promptMatch ? ['-p', promptMatch[1]] : [];\n\t\t} else if (command.startsWith('claude \"')) {\n\t\t\tcmd = 'claude';\n\t\t\t// Extract the quoted content for interactive mode\n\t\t\tconst promptMatch = command.match(/^claude \"(.*)\"/s);\n\t\t\targs = promptMatch ? [promptMatch[1]] : [];\n\t\t} else if (command.startsWith('git commit')) {\n\t\t\t// Special handling for git commit to properly parse the message\n\t\t\tconst parts = command.match(/^git\\s+commit\\s+(.*)$/);\n\t\t\tif (parts && parts[1]) {\n\t\t\t\tcmd = 'git';\n\t\t\t\targs = ['commit'];\n\t\t\t\t// Parse the rest of the arguments, handling -m \"message\" properly\n\t\t\t\tconst argString = parts[1];\n\t\t\t\tconst messageMatch = argString.match(/-m\\s+\"([^\"]+)\"/);\n\t\t\t\tif (messageMatch) {\n\t\t\t\t\targs.push('-m', messageMatch[1]);\n\t\t\t\t\t// Add any other arguments that might be before or after -m\n\t\t\t\t\tconst beforeMessage = argString.substring(0, argString.indexOf('-m')).trim();\n\t\t\t\t\tconst afterMessage = argString\n\t\t\t\t\t\t.substring(argString.indexOf(messageMatch[0]) + messageMatch[0].length)\n\t\t\t\t\t\t.trim();\n\t\t\t\t\tif (beforeMessage) args.unshift(...beforeMessage.split(' '));\n\t\t\t\t\tif (afterMessage) args.push(...afterMessage.split(' '));\n\t\t\t\t} else {\n\t\t\t\t\targs.push(...argString.split(' '));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t[cmd, ...args] = command.split(' ');\n\t\t\t}\n\t\t} else {\n\t\t\t// Simple command splitting for other commands\n\t\t\t[cmd, ...args] = command.split(' ');\n\t\t}\n\n\t\tconst child = spawn(cmd, args, {\n\t\t\tshell: false,\n\t\t\tstdio: ['inherit', 'pipe', 'pipe'],\n\t\t});\n\n\t\tlet stdout = '';\n\t\tlet stderr = '';\n\n\t\t// Smart timeout handling\n\t\tconst isGitCommit = cmd === 'git' && args[0] === 'commit';\n\t\tconst maxTimeout = options?.timeout || (isGitCommit ? 900000 : 300000); // 15 min for git commit, 5 min default\n\t\tconst inactivityTimeout = options?.inactivityTimeout || (isGitCommit ? 60000 : 30000); // 60s for git commit, 30s default\n\n\t\tlet globalTimeoutId: NodeJS.Timeout | null = null;\n\t\tlet inactivityTimeoutId: NodeJS.Timeout | null = null;\n\n\t\tconst clearTimeouts = () => {\n\t\t\tif (globalTimeoutId) clearTimeout(globalTimeoutId);\n\t\t\tif (inactivityTimeoutId) clearTimeout(inactivityTimeoutId);\n\t\t};\n\n\t\tconst resetInactivityTimeout = () => {\n\t\t\tif (inactivityTimeoutId) clearTimeout(inactivityTimeoutId);\n\n\t\t\tinactivityTimeoutId = setTimeout(() => {\n\t\t\t\tclearTimeouts();\n\t\t\t\tchild.kill('SIGTERM');\n\t\t\t\treject(new Error(`Command timed out due to ${inactivityTimeout / 1000}s of inactivity`));\n\t\t\t}, inactivityTimeout);\n\t\t};\n\n\t\t// Set global timeout\n\t\tglobalTimeoutId = setTimeout(() => {\n\t\t\tclearTimeouts();\n\t\t\tchild.kill('SIGTERM');\n\t\t\treject(new Error(`Command exceeded maximum timeout of ${maxTimeout / 1000}s`));\n\t\t}, maxTimeout);\n\n\t\t// Start inactivity timeout\n\t\tresetInactivityTimeout();\n\n\t\tchild.stdout?.on('data', data => {\n\t\t\tconst chunk = data.toString();\n\t\t\tstdout += chunk;\n\t\t\tif (onOutput) {\n\t\t\t\tonOutput(chunk);\n\t\t\t}\n\t\t\t// Reset inactivity timeout on any output\n\t\t\tresetInactivityTimeout();\n\t\t});\n\n\t\tchild.stderr?.on('data', data => {\n\t\t\tconst chunk = data.toString();\n\t\t\tstderr += chunk;\n\t\t\tif (onOutput) {\n\t\t\t\tonOutput(chunk);\n\t\t\t}\n\t\t\t// Reset inactivity timeout on any output (pre-commit hooks often write to stderr)\n\t\t\tresetInactivityTimeout();\n\t\t});\n\n\t\tchild.on('close', code => {\n\t\t\tclearTimeouts();\n\t\t\tif (code === 0) {\n\t\t\t\tresolve({ stdout, stderr });\n\t\t\t} else {\n\t\t\t\treject(new Error(`Command failed with exit code ${code}: ${stderr}`));\n\t\t\t}\n\t\t});\n\n\t\tchild.on('error', error => {\n\t\t\tclearTimeouts();\n\t\t\treject(error);\n\t\t});\n\t});\n}\n\n/**\n * Mock execution handler for testing\n */\nexport async function createMockExecHandler(\n\taddMessage?: (type: 'info' | 'error' | 'system', content: string) => void\n): Promise<(command: string) => Promise<ExecResult>> {\n\treturn async (command: string): Promise<ExecResult> => {\n\t\tif (addMessage) {\n\t\t\taddMessage('info', `๐Ÿงช TEST MODE: Simulating command: ${command}`);\n\t\t}\n\n\t\t// Simulate delays\n\t\tawait new Promise(resolve => setTimeout(resolve, 500));\n\n\t\t// Git commands\n\t\tif (command.includes('git branch --show-current')) {\n\t\t\treturn { stdout: 'feature/test-branch', stderr: '' };\n\t\t}\n\t\tif (command.includes('gh repo view')) {\n\t\t\treturn { stdout: 'main', stderr: '' };\n\t\t}\n\t\tif (command.includes('git checkout -b')) {\n\t\t\tconst branchName = command.split(' ').pop();\n\t\t\treturn { stdout: `Switched to a new branch '${branchName}'`, stderr: '' };\n\t\t}\n\t\tif (command.includes('git checkout main')) {\n\t\t\treturn { stdout: 'Switched to branch main', stderr: '' };\n\t\t}\n\t\tif (command.includes('git pull')) {\n\t\t\treturn { stdout: 'Already up to date.', stderr: '' };\n\t\t}\n\t\tif (command.includes('git add .')) {\n\t\t\treturn { stdout: '', stderr: '' };\n\t\t}\n\t\tif (command.includes('git diff --cached --quiet')) {\n\t\t\tthrow new Error('Changes to commit'); // Simulate changes exist\n\t\t}\n\t\tif (command.includes('git commit')) {\n\t\t\treturn { stdout: '[feature/test abc123] feat: mock commit', stderr: '' };\n\t\t}\n\t\tif (command.includes('git push')) {\n\t\t\tconst branchName = command.includes('feature/') ? 'feature/test-branch' : 'current-branch';\n\t\t\treturn {\n\t\t\t\tstdout: `To github.com:test/repo.git\\n * [new branch] ${branchName} -> ${branchName}\\nBranch '${branchName}' set up to track remote branch '${branchName}' from 'origin'.`,\n\t\t\t\tstderr: '',\n\t\t\t};\n\t\t}\n\n\t\t// CLI version checks\n\t\tif (command.includes('claude --version')) {\n\t\t\treturn { stdout: 'claude version 2.1.3', stderr: '' };\n\t\t}\n\t\tif (command.includes('gh --version')) {\n\t\t\treturn { stdout: 'gh version 2.40.1', stderr: '' };\n\t\t}\n\n\t\t// GitHub commands\n\t\tif (command.includes('gh pr create')) {\n\t\t\treturn { stdout: 'https://github.com/test/repo/pull/123', stderr: '' };\n\t\t}\n\n\t\t// Claude commands\n\t\tif (command.includes('Generate a conventional commit')) {\n\t\t\tconst taskTitle = command.includes('login')\n\t\t\t\t? 'login component'\n\t\t\t\t: command.includes('JWT')\n\t\t\t\t\t? 'JWT authentication'\n\t\t\t\t\t: command.includes('logout')\n\t\t\t\t\t\t? 'logout functionality'\n\t\t\t\t\t\t: 'test feature';\n\t\t\treturn { stdout: `feat(auth): add ${taskTitle}`, stderr: '' };\n\t\t}\n\t\tif (command.includes('Generate a comprehensive GitHub Pull Request')) {\n\t\t\treturn {\n\t\t\t\tstdout: `## 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.`,\n\t\t\t\tstderr: '',\n\t\t\t};\n\t\t}\n\t\tif (\n\t\t\tcommand.startsWith('claude -p --dangerously-skip-permissions \"') ||\n\t\t\tcommand.startsWith('claude -p \"') ||\n\t\t\tcommand.startsWith('claude \"')\n\t\t) {\n\t\t\t// Handle task content and other prompts\n\t\t\tconst taskTitle = command.includes('login')\n\t\t\t\t? 'Login Component'\n\t\t\t\t: command.includes('JWT')\n\t\t\t\t\t? 'JWT Authentication'\n\t\t\t\t\t: command.includes('logout')\n\t\t\t\t\t\t? 'Logout Functionality'\n\t\t\t\t\t\t: 'Test Feature';\n\t\t\treturn {\n\t\t\t\tstdout: `# ${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()}.`,\n\t\t\t\tstderr: '',\n\t\t\t};\n\t\t}\n\n\t\t// Default response\n\t\treturn { stdout: 'Mock command executed successfully', stderr: '' };\n\t};\n}\n"],"mappings":"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","names":[]}