prjct-cli 0.4.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/CHANGELOG.md +312 -0
- package/CLAUDE.md +300 -0
- package/LICENSE +21 -0
- package/README.md +424 -0
- package/bin/prjct +214 -0
- package/core/agent-detector.js +249 -0
- package/core/agents/claude-agent.js +250 -0
- package/core/agents/codex-agent.js +256 -0
- package/core/agents/terminal-agent.js +465 -0
- package/core/analyzer.js +596 -0
- package/core/animations-simple.js +240 -0
- package/core/animations.js +277 -0
- package/core/author-detector.js +218 -0
- package/core/capability-installer.js +190 -0
- package/core/command-installer.js +775 -0
- package/core/commands.js +2050 -0
- package/core/config-manager.js +335 -0
- package/core/migrator.js +784 -0
- package/core/path-manager.js +324 -0
- package/core/project-capabilities.js +144 -0
- package/core/session-manager.js +439 -0
- package/core/version.js +107 -0
- package/core/workflow-engine.js +213 -0
- package/core/workflow-prompts.js +192 -0
- package/core/workflow-rules.js +147 -0
- package/package.json +80 -0
- package/scripts/install.sh +433 -0
- package/scripts/verify-installation.sh +158 -0
- package/templates/agents/AGENTS.md +164 -0
- package/templates/commands/analyze.md +125 -0
- package/templates/commands/cleanup.md +102 -0
- package/templates/commands/context.md +105 -0
- package/templates/commands/design.md +113 -0
- package/templates/commands/done.md +44 -0
- package/templates/commands/fix.md +87 -0
- package/templates/commands/git.md +79 -0
- package/templates/commands/help.md +72 -0
- package/templates/commands/idea.md +50 -0
- package/templates/commands/init.md +237 -0
- package/templates/commands/next.md +74 -0
- package/templates/commands/now.md +35 -0
- package/templates/commands/progress.md +92 -0
- package/templates/commands/recap.md +86 -0
- package/templates/commands/roadmap.md +107 -0
- package/templates/commands/ship.md +41 -0
- package/templates/commands/stuck.md +48 -0
- package/templates/commands/task.md +97 -0
- package/templates/commands/test.md +94 -0
- package/templates/commands/workflow.md +224 -0
- package/templates/examples/natural-language-examples.md +320 -0
- package/templates/mcp-config.json +8 -0
- package/templates/workflows/analyze.md +159 -0
- package/templates/workflows/cleanup.md +73 -0
- package/templates/workflows/context.md +72 -0
- package/templates/workflows/design.md +88 -0
- package/templates/workflows/done.md +20 -0
- package/templates/workflows/fix.md +201 -0
- package/templates/workflows/git.md +192 -0
- package/templates/workflows/help.md +13 -0
- package/templates/workflows/idea.md +22 -0
- package/templates/workflows/init.md +80 -0
- package/templates/workflows/natural-language-handler.md +183 -0
- package/templates/workflows/next.md +44 -0
- package/templates/workflows/now.md +19 -0
- package/templates/workflows/progress.md +113 -0
- package/templates/workflows/recap.md +66 -0
- package/templates/workflows/roadmap.md +95 -0
- package/templates/workflows/ship.md +18 -0
- package/templates/workflows/stuck.md +25 -0
- package/templates/workflows/task.md +109 -0
- package/templates/workflows/test.md +243 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Detection Module for prjct-cli
|
|
3
|
+
* Automatically detects which AI agent is executing commands
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs')
|
|
7
|
+
const path = require('path')
|
|
8
|
+
|
|
9
|
+
class AgentDetector {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.detectedAgent = null
|
|
12
|
+
this.detectionMethods = [
|
|
13
|
+
this.detectByEnvironmentVariables.bind(this),
|
|
14
|
+
this.detectByConfigFiles.bind(this),
|
|
15
|
+
this.detectByRuntimeCapabilities.bind(this),
|
|
16
|
+
this.detectByFileSystem.bind(this),
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Main detection method - tries multiple strategies
|
|
22
|
+
* @returns {Object} Agent information
|
|
23
|
+
*/
|
|
24
|
+
async detect() {
|
|
25
|
+
if (this.detectedAgent) {
|
|
26
|
+
return this.detectedAgent
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
for (const method of this.detectionMethods) {
|
|
30
|
+
const result = await method()
|
|
31
|
+
if (result) {
|
|
32
|
+
this.detectedAgent = result
|
|
33
|
+
return result
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this.detectedAgent = this.getTerminalAgent()
|
|
38
|
+
return this.detectedAgent
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Detect agent by environment variables
|
|
43
|
+
*/
|
|
44
|
+
async detectByEnvironmentVariables() {
|
|
45
|
+
if (process.env.CODEX_AGENT || process.env.OPENAI_CODEX) {
|
|
46
|
+
return this.getCodexAgent()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (process.env.CLAUDE_AGENT || process.env.ANTHROPIC_CLAUDE) {
|
|
50
|
+
return this.getClaudeAgent()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (process.env.CODESPACES) {
|
|
54
|
+
return this.getCodexAgent()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Detect agent by configuration files
|
|
62
|
+
*/
|
|
63
|
+
async detectByConfigFiles() {
|
|
64
|
+
const projectRoot = process.cwd()
|
|
65
|
+
|
|
66
|
+
if (fs.existsSync(path.join(projectRoot, 'AGENTS.md'))) {
|
|
67
|
+
if (!fs.existsSync(path.join(projectRoot, '.claude'))) {
|
|
68
|
+
return this.getCodexAgent()
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (fs.existsSync(path.join(projectRoot, 'CLAUDE.md'))) {
|
|
73
|
+
return this.getClaudeAgent()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (fs.existsSync(path.join(process.env.HOME || '', '.claude'))) {
|
|
77
|
+
return this.getClaudeAgent()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return null
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Detect agent by runtime capabilities
|
|
85
|
+
*/
|
|
86
|
+
async detectByRuntimeCapabilities() {
|
|
87
|
+
try {
|
|
88
|
+
if (global.mcp || process.env.MCP_AVAILABLE) {
|
|
89
|
+
return this.getClaudeAgent()
|
|
90
|
+
}
|
|
91
|
+
} catch (e) {
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (this.isRunningInContainer()) {
|
|
95
|
+
return this.getCodexAgent()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Detect agent by filesystem characteristics
|
|
103
|
+
*/
|
|
104
|
+
async detectByFileSystem() {
|
|
105
|
+
if (process.cwd().includes('/sandbox/') || process.cwd().includes('/tmp/codex/')) {
|
|
106
|
+
return this.getCodexAgent()
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (process.cwd().includes('/.claude/') || process.cwd().includes('/claude-workspace/')) {
|
|
110
|
+
return this.getClaudeAgent()
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return null
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Check if running in a container
|
|
118
|
+
*/
|
|
119
|
+
isRunningInContainer() {
|
|
120
|
+
if (fs.existsSync('/.dockerenv')) {
|
|
121
|
+
return true
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
const cgroup = fs.readFileSync('/proc/self/cgroup', 'utf8')
|
|
126
|
+
if (cgroup.includes('docker') || cgroup.includes('containerd')) {
|
|
127
|
+
return true
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return false
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get Claude agent configuration
|
|
137
|
+
*/
|
|
138
|
+
getClaudeAgent() {
|
|
139
|
+
return {
|
|
140
|
+
type: 'claude',
|
|
141
|
+
name: 'Claude Code',
|
|
142
|
+
capabilities: {
|
|
143
|
+
mcp: true,
|
|
144
|
+
filesystem: 'mcp',
|
|
145
|
+
markdown: true,
|
|
146
|
+
emojis: true,
|
|
147
|
+
colors: true,
|
|
148
|
+
interactive: true,
|
|
149
|
+
},
|
|
150
|
+
config: {
|
|
151
|
+
configFile: 'CLAUDE.md',
|
|
152
|
+
commandPrefix: '/p:',
|
|
153
|
+
responseStyle: 'rich',
|
|
154
|
+
dataDir: '.prjct',
|
|
155
|
+
},
|
|
156
|
+
environment: {
|
|
157
|
+
hasMCP: true,
|
|
158
|
+
sandboxed: false,
|
|
159
|
+
persistent: true,
|
|
160
|
+
},
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get Codex agent configuration
|
|
166
|
+
*/
|
|
167
|
+
getCodexAgent() {
|
|
168
|
+
return {
|
|
169
|
+
type: 'codex',
|
|
170
|
+
name: 'OpenAI Codex',
|
|
171
|
+
capabilities: {
|
|
172
|
+
mcp: false,
|
|
173
|
+
filesystem: 'native',
|
|
174
|
+
markdown: true,
|
|
175
|
+
emojis: true,
|
|
176
|
+
colors: false,
|
|
177
|
+
interactive: false,
|
|
178
|
+
},
|
|
179
|
+
config: {
|
|
180
|
+
configFile: 'AGENTS.md',
|
|
181
|
+
commandPrefix: '/p:',
|
|
182
|
+
responseStyle: 'structured',
|
|
183
|
+
dataDir: '.prjct',
|
|
184
|
+
},
|
|
185
|
+
environment: {
|
|
186
|
+
hasMCP: false,
|
|
187
|
+
sandboxed: true,
|
|
188
|
+
persistent: false,
|
|
189
|
+
},
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Get terminal agent configuration (fallback)
|
|
195
|
+
*/
|
|
196
|
+
getTerminalAgent() {
|
|
197
|
+
return {
|
|
198
|
+
type: 'terminal',
|
|
199
|
+
name: 'Terminal/CLI',
|
|
200
|
+
capabilities: {
|
|
201
|
+
mcp: false,
|
|
202
|
+
filesystem: 'native',
|
|
203
|
+
markdown: false,
|
|
204
|
+
emojis: true,
|
|
205
|
+
colors: true,
|
|
206
|
+
interactive: true,
|
|
207
|
+
},
|
|
208
|
+
config: {
|
|
209
|
+
configFile: null,
|
|
210
|
+
commandPrefix: 'prjct',
|
|
211
|
+
responseStyle: 'cli',
|
|
212
|
+
dataDir: '.prjct',
|
|
213
|
+
},
|
|
214
|
+
environment: {
|
|
215
|
+
hasMCP: false,
|
|
216
|
+
sandboxed: false,
|
|
217
|
+
persistent: true,
|
|
218
|
+
},
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Force set agent type (for testing)
|
|
224
|
+
*/
|
|
225
|
+
setAgent(type) {
|
|
226
|
+
switch (type) {
|
|
227
|
+
case 'claude':
|
|
228
|
+
this.detectedAgent = this.getClaudeAgent()
|
|
229
|
+
break
|
|
230
|
+
case 'codex':
|
|
231
|
+
this.detectedAgent = this.getCodexAgent()
|
|
232
|
+
break
|
|
233
|
+
case 'terminal':
|
|
234
|
+
default:
|
|
235
|
+
this.detectedAgent = this.getTerminalAgent()
|
|
236
|
+
break
|
|
237
|
+
}
|
|
238
|
+
return this.detectedAgent
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Reset detection (clear cache)
|
|
243
|
+
*/
|
|
244
|
+
reset() {
|
|
245
|
+
this.detectedAgent = null
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
module.exports = new AgentDetector()
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Agent Adapter
|
|
3
|
+
* Implements prjct commands for Claude Code environment
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs').promises
|
|
7
|
+
|
|
8
|
+
class ClaudeAgent {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.name = 'Claude Code'
|
|
11
|
+
this.type = 'claude'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Format response - minimal, actionable
|
|
16
|
+
*/
|
|
17
|
+
formatResponse(message, type = 'info') {
|
|
18
|
+
const emojis = {
|
|
19
|
+
success: '✅',
|
|
20
|
+
error: '❌',
|
|
21
|
+
warning: '⚠️',
|
|
22
|
+
info: 'ℹ️',
|
|
23
|
+
celebrate: '🎉',
|
|
24
|
+
ship: '🚀',
|
|
25
|
+
focus: '🎯',
|
|
26
|
+
idea: '💡',
|
|
27
|
+
progress: '📊',
|
|
28
|
+
task: '📝',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return `${emojis[type] || emojis.info} ${message}`
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Read file using MCP if available, fallback to fs
|
|
36
|
+
*/
|
|
37
|
+
async readFile(filePath) {
|
|
38
|
+
try {
|
|
39
|
+
if (global.mcp && global.mcp.filesystem) {
|
|
40
|
+
return await global.mcp.filesystem.read(filePath)
|
|
41
|
+
}
|
|
42
|
+
} catch (e) {
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return await fs.readFile(filePath, 'utf8')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Write file using MCP if available, fallback to fs
|
|
51
|
+
*/
|
|
52
|
+
async writeFile(filePath, content) {
|
|
53
|
+
try {
|
|
54
|
+
if (global.mcp && global.mcp.filesystem) {
|
|
55
|
+
return await global.mcp.filesystem.write(filePath, content)
|
|
56
|
+
}
|
|
57
|
+
} catch (e) {
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
await fs.writeFile(filePath, content, 'utf8')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* List directory contents
|
|
66
|
+
*/
|
|
67
|
+
async listDirectory(dirPath) {
|
|
68
|
+
try {
|
|
69
|
+
if (global.mcp && global.mcp.filesystem) {
|
|
70
|
+
return await global.mcp.filesystem.list(dirPath)
|
|
71
|
+
}
|
|
72
|
+
} catch (e) {
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return await fs.readdir(dirPath)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Check if file exists
|
|
81
|
+
*/
|
|
82
|
+
async fileExists(filePath) {
|
|
83
|
+
try {
|
|
84
|
+
await fs.access(filePath)
|
|
85
|
+
return true
|
|
86
|
+
} catch {
|
|
87
|
+
return false
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Create directory
|
|
93
|
+
*/
|
|
94
|
+
async createDirectory(dirPath) {
|
|
95
|
+
await fs.mkdir(dirPath, { recursive: true })
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get current timestamp in ISO format
|
|
100
|
+
*/
|
|
101
|
+
getTimestamp() {
|
|
102
|
+
return new Date().toISOString()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Format task list - data only
|
|
107
|
+
*/
|
|
108
|
+
formatTaskList(tasks) {
|
|
109
|
+
if (!tasks || tasks.length === 0) {
|
|
110
|
+
return '📋 No tasks queued'
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return '📋 Queue:\n' + tasks.map((t, i) => `${i + 1}. ${t}`).join('\n')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Format recap - metrics only
|
|
118
|
+
*/
|
|
119
|
+
formatRecap(data) {
|
|
120
|
+
return `📊 Recap
|
|
121
|
+
|
|
122
|
+
🎯 Current: ${data.currentTask || 'None'}
|
|
123
|
+
🚀 Shipped: ${data.shippedCount}
|
|
124
|
+
📝 Queue: ${data.queuedCount}
|
|
125
|
+
💡 Ideas: ${data.ideasCount}
|
|
126
|
+
${data.recentActivity ? '\n' + data.recentActivity : ''}`
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Format progress - data only
|
|
131
|
+
*/
|
|
132
|
+
formatProgress(data) {
|
|
133
|
+
const trend =
|
|
134
|
+
data.velocity > data.previousVelocity ? '📈' : data.velocity < data.previousVelocity ? '📉' : '➡️'
|
|
135
|
+
|
|
136
|
+
return `📊 ${data.period}
|
|
137
|
+
|
|
138
|
+
Shipped: ${data.count}
|
|
139
|
+
Velocity: ${data.velocity.toFixed(1)}/day ${trend}
|
|
140
|
+
${data.recentFeatures || ''}`
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get help - actionable steps only
|
|
145
|
+
*/
|
|
146
|
+
getHelpContent(issue) {
|
|
147
|
+
const helps = {
|
|
148
|
+
debugging: '🔍 1. Isolate code causing error\n2. Add logs at key points\n3. Search exact error message',
|
|
149
|
+
design: '🎨 1. Define problem clearly\n2. Start with simplest solution\n3. Ship MVP, iterate',
|
|
150
|
+
performance:
|
|
151
|
+
'⚡ 1. Profile/measure first\n2. Optimize slowest parts\n3. Cache expensive operations',
|
|
152
|
+
default: '💡 1. Break into smaller tasks\n2. Start with simplest part\n3. Ship it',
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const helpType = Object.keys(helps).find((key) => issue.toLowerCase().includes(key)) || 'default'
|
|
156
|
+
return helps[helpType]
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Suggest next action - conversational prompts
|
|
161
|
+
*/
|
|
162
|
+
suggestNextAction(context) {
|
|
163
|
+
const suggestions = {
|
|
164
|
+
taskCompleted: `What's next?
|
|
165
|
+
• "start [task]" → Begin working
|
|
166
|
+
• "ship feature" → Track & celebrate
|
|
167
|
+
• "add idea" → Brainstorm
|
|
168
|
+
|
|
169
|
+
Or: /p:now | /p:ship | /p:idea`,
|
|
170
|
+
|
|
171
|
+
featureShipped: `Keep the momentum!
|
|
172
|
+
• "start next task" → Keep building
|
|
173
|
+
• "see progress" → View stats
|
|
174
|
+
• "plan ahead" → Strategic thinking
|
|
175
|
+
|
|
176
|
+
Or: /p:now | /p:recap | /p:roadmap`,
|
|
177
|
+
|
|
178
|
+
ideaCaptured: `Ready to start?
|
|
179
|
+
• "start this" → Begin now
|
|
180
|
+
• "plan more" → Keep brainstorming
|
|
181
|
+
• "see ideas" → View backlog
|
|
182
|
+
|
|
183
|
+
Or: /p:now | /p:idea | /p:recap`,
|
|
184
|
+
|
|
185
|
+
initialized: `Ready to start? Tell me what you want to build!
|
|
186
|
+
|
|
187
|
+
Or type /p:help to see all options`,
|
|
188
|
+
|
|
189
|
+
stuck: `Let's break it down:
|
|
190
|
+
• "start the first part"
|
|
191
|
+
• "add as tasks"
|
|
192
|
+
• "think more"
|
|
193
|
+
|
|
194
|
+
Or: /p:now | /p:task | /p:idea`,
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return suggestions[context] || `What would you like to do?
|
|
198
|
+
|
|
199
|
+
Type /p:help to see all options`
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Detect user intent from natural language
|
|
204
|
+
*/
|
|
205
|
+
detectIntent(message) {
|
|
206
|
+
const msg = message.toLowerCase()
|
|
207
|
+
|
|
208
|
+
// Start/begin task
|
|
209
|
+
if (/^(start|empez|begin|quiero|want|let'?s|voy)/i.test(msg)) {
|
|
210
|
+
return { intent: 'start', command: 'now' }
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Complete task
|
|
214
|
+
if (/^(done|termin|finish|acab|complete|listo|ya)/i.test(msg)) {
|
|
215
|
+
return { intent: 'complete', command: 'done' }
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Ship feature
|
|
219
|
+
if (/^(ship|deploy|launch|public)/i.test(msg)) {
|
|
220
|
+
return { intent: 'ship', command: 'ship' }
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Capture idea
|
|
224
|
+
if (/^(idea|think|thought|ocurr|tengo)/i.test(msg)) {
|
|
225
|
+
return { intent: 'idea', command: 'idea' }
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// View status/progress
|
|
229
|
+
if (
|
|
230
|
+
/(show|see|view|muestra|ver).*(progress|status|recap|avance)/i.test(msg) ||
|
|
231
|
+
/^(progress|status|recap|avance)/i.test(msg)
|
|
232
|
+
) {
|
|
233
|
+
return { intent: 'status', command: 'recap' }
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Stuck/help
|
|
237
|
+
if (/^(stuck|help|ayud|atascado|perdido)/i.test(msg)) {
|
|
238
|
+
return { intent: 'stuck', command: 'stuck' }
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// View queue/next
|
|
242
|
+
if (/(what|que).*(next|sigue|after|despues)/i.test(msg) || /^(next|sigue)/i.test(msg)) {
|
|
243
|
+
return { intent: 'next', command: 'next' }
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return { intent: 'unknown', command: null }
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
module.exports = ClaudeAgent
|