chati-dev 2.0.3 → 2.0.5
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/assets/logo.svg +2 -2
- package/framework/agents/build/dev.md +13 -0
- package/framework/agents/clarity/architect.md +1 -1
- package/framework/agents/clarity/brief.md +4 -4
- package/framework/agents/clarity/brownfield-wu.md +1 -1
- package/framework/agents/clarity/detail.md +1 -1
- package/framework/agents/clarity/greenfield-wu.md +1 -1
- package/framework/agents/clarity/ux.md +1 -1
- package/framework/hooks/model-governance.js +38 -18
- package/framework/orchestrator/chati.md +141 -39
- package/package.json +4 -4
- package/src/terminal/handoff-parser.js +127 -0
- package/src/terminal/index.js +9 -0
- package/src/terminal/prompt-builder.js +313 -0
- package/src/terminal/run-agent.js +248 -0
- package/src/terminal/run-parallel.js +238 -0
- package/src/terminal/spawner.js +29 -18
package/assets/logo.svg
CHANGED
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
<ellipse cx="77" cy="100" rx="3.5" ry="2.5" fill="rgba(255,255,255,0.3)"/>
|
|
36
36
|
<ellipse cx="133" cy="100" rx="3.5" ry="2.5" fill="rgba(255,255,255,0.3)"/>
|
|
37
37
|
|
|
38
|
-
<!-- "
|
|
38
|
+
<!-- "Chati.dev" text inline -->
|
|
39
39
|
<text x="210" y="122" font-family="ui-monospace,'SF Mono','Menlo','Consolas','Liberation Mono',monospace" font-weight="700" font-size="68" letter-spacing="-1">
|
|
40
|
-
<tspan fill="#e6edf3">
|
|
40
|
+
<tspan fill="#e6edf3">Chati</tspan><tspan fill="#4A90D9">.</tspan><tspan fill="#e6edf3">dev</tspan>
|
|
41
41
|
</text>
|
|
42
42
|
</svg>
|
|
@@ -338,6 +338,19 @@ Rules:
|
|
|
338
338
|
|
|
339
339
|
---
|
|
340
340
|
|
|
341
|
+
## Parallelization
|
|
342
|
+
|
|
343
|
+
```
|
|
344
|
+
This agent supports TASK-LEVEL parallelization (all modes):
|
|
345
|
+
- Independent tasks (no shared file dependencies) MUST run in parallel terminals
|
|
346
|
+
- Tasks with dependencies run sequentially within their dependency chain
|
|
347
|
+
- Each parallel terminal gets isolated write scope per task
|
|
348
|
+
- Orchestrator monitors all terminals and merges results after each batch
|
|
349
|
+
- See Transition Logic step 4.5, Group 2 for details
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
341
354
|
## Input
|
|
342
355
|
|
|
343
356
|
$ARGUMENTS
|
|
@@ -362,7 +362,7 @@ Beyond self-validation (Protocol 5.1), the Architect agent enforces:
|
|
|
362
362
|
|
|
363
363
|
---
|
|
364
364
|
|
|
365
|
-
## Parallelization
|
|
365
|
+
## Parallelization
|
|
366
366
|
|
|
367
367
|
- **Can run in parallel with**: Detail agent and UX agent (all three activate post-Brief in parallel-eligible pipelines)
|
|
368
368
|
- **Cannot run in parallel with**: Brief agent (upstream dependency), Phases agent (downstream dependency — requires architecture as input)
|
|
@@ -215,7 +215,7 @@ agents:
|
|
|
215
215
|
score: {calculated}
|
|
216
216
|
criteria_count: 9
|
|
217
217
|
completed_at: "{timestamp}"
|
|
218
|
-
|
|
218
|
+
next_parallel_group: [detail, architect, ux] # PARALLEL GROUP — see Transition Logic 4.5
|
|
219
219
|
last_handoff: chati.dev/artifacts/handoffs/brief-handoff.md
|
|
220
220
|
```
|
|
221
221
|
|
|
@@ -226,7 +226,7 @@ last_handoff: chati.dev/artifacts/handoffs/brief-handoff.md
|
|
|
226
226
|
**Greenfield:**
|
|
227
227
|
```
|
|
228
228
|
Next steps:
|
|
229
|
-
1. Continue to Detail
|
|
229
|
+
1. Continue to Detail + Architect + UX in parallel (Recommended) — 3 agents run simultaneously
|
|
230
230
|
2. Review the Brief report
|
|
231
231
|
3. Adjust Brief content
|
|
232
232
|
```
|
|
@@ -234,7 +234,7 @@ Next steps:
|
|
|
234
234
|
**Brownfield:**
|
|
235
235
|
```
|
|
236
236
|
Next steps:
|
|
237
|
-
1. Continue to Architect
|
|
237
|
+
1. Continue to Detail + Architect + UX in parallel (Recommended) — 3 agents run simultaneously
|
|
238
238
|
2. Review the Brief report
|
|
239
239
|
3. Adjust Brief content
|
|
240
240
|
```
|
|
@@ -444,7 +444,7 @@ On failure:
|
|
|
444
444
|
|
|
445
445
|
---
|
|
446
446
|
|
|
447
|
-
## Parallelization
|
|
447
|
+
## Parallelization
|
|
448
448
|
|
|
449
449
|
```
|
|
450
450
|
This agent is NOT parallelizable.
|
|
@@ -371,7 +371,7 @@ Beyond self-validation (Protocol 5.1), the Detail agent enforces:
|
|
|
371
371
|
|
|
372
372
|
---
|
|
373
373
|
|
|
374
|
-
## Parallelization
|
|
374
|
+
## Parallelization
|
|
375
375
|
|
|
376
376
|
- **Can run in parallel with**: Architect agent and UX agent (all three activate post-Brief in parallel-eligible pipelines)
|
|
377
377
|
- **Cannot run in parallel with**: Brief agent (upstream dependency), Phases agent (downstream dependency — requires PRD as input)
|
|
@@ -392,7 +392,7 @@ Beyond self-validation (Protocol 5.1), the UX agent enforces:
|
|
|
392
392
|
|
|
393
393
|
---
|
|
394
394
|
|
|
395
|
-
## Parallelization
|
|
395
|
+
## Parallelization
|
|
396
396
|
|
|
397
397
|
- **Can run in parallel with**: Detail agent and Architect agent (all three activate post-Brief in parallel-eligible pipelines)
|
|
398
398
|
- **Cannot run in parallel with**: Brief agent (upstream dependency), Phases agent (downstream dependency — requires UX specification as input)
|
|
@@ -5,37 +5,57 @@
|
|
|
5
5
|
* Validates that the model being used matches the agent's assignment.
|
|
6
6
|
* Constitution Article XVI enforcement.
|
|
7
7
|
*
|
|
8
|
-
* Model assignments (from
|
|
9
|
-
* - orchestrator: opus
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
15
|
-
* -
|
|
8
|
+
* Model assignments (from orchestrator spec — Model Map):
|
|
9
|
+
* - orchestrator: sonnet | upgrade: opus if complex routing
|
|
10
|
+
* - greenfield-wu: haiku | upgrade: sonnet if multi-stack
|
|
11
|
+
* - brownfield-wu: opus | no downgrade
|
|
12
|
+
* - brief: sonnet | upgrade: opus if 10+ integrations
|
|
13
|
+
* - detail: opus | no downgrade
|
|
14
|
+
* - architect: opus | no downgrade
|
|
15
|
+
* - ux: sonnet | upgrade: opus if design system from scratch
|
|
16
|
+
* - phases: sonnet | upgrade: opus if 20+ requirements
|
|
17
|
+
* - tasks: sonnet | upgrade: opus if 50+ tasks
|
|
18
|
+
* - qa-planning: opus | no downgrade
|
|
19
|
+
* - qa-implementation: opus | no downgrade
|
|
20
|
+
* - dev: opus | no downgrade
|
|
21
|
+
* - devops: sonnet | upgrade: opus if multi-env
|
|
16
22
|
*
|
|
17
|
-
* This hook is advisory — it warns but does not block.
|
|
23
|
+
* This hook is advisory in IDE mode — it warns but does not block.
|
|
18
24
|
*/
|
|
19
25
|
|
|
20
26
|
import { existsSync, readFileSync } from 'fs';
|
|
21
27
|
import { join } from 'path';
|
|
22
28
|
|
|
23
29
|
const AGENT_MODELS = {
|
|
24
|
-
orchestrator: '
|
|
25
|
-
'greenfield-wu': '
|
|
26
|
-
'brownfield-wu': '
|
|
30
|
+
orchestrator: 'sonnet',
|
|
31
|
+
'greenfield-wu': 'haiku',
|
|
32
|
+
'brownfield-wu': 'opus',
|
|
27
33
|
brief: 'sonnet',
|
|
28
|
-
detail: '
|
|
29
|
-
architect: '
|
|
34
|
+
detail: 'opus',
|
|
35
|
+
architect: 'opus',
|
|
30
36
|
ux: 'sonnet',
|
|
31
37
|
phases: 'sonnet',
|
|
32
38
|
tasks: 'sonnet',
|
|
33
|
-
'qa-planning': '
|
|
34
|
-
'qa-implementation': '
|
|
35
|
-
dev: '
|
|
39
|
+
'qa-planning': 'opus',
|
|
40
|
+
'qa-implementation': 'opus',
|
|
41
|
+
dev: 'opus',
|
|
36
42
|
devops: 'sonnet',
|
|
37
43
|
};
|
|
38
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Upgrade conditions per agent. When context matches, the model
|
|
47
|
+
* should be upgraded to the specified target.
|
|
48
|
+
*/
|
|
49
|
+
const UPGRADE_CONDITIONS = {
|
|
50
|
+
orchestrator: { to: 'opus', condition: 'complex routing or deviation handling' },
|
|
51
|
+
'greenfield-wu': { to: 'sonnet', condition: 'multi-stack or enterprise' },
|
|
52
|
+
brief: { to: 'opus', condition: '10+ integrations' },
|
|
53
|
+
ux: { to: 'opus', condition: 'design system from scratch' },
|
|
54
|
+
phases: { to: 'opus', condition: '20+ requirements' },
|
|
55
|
+
tasks: { to: 'opus', condition: '50+ tasks' },
|
|
56
|
+
devops: { to: 'opus', condition: 'multi-environment or IaC' },
|
|
57
|
+
};
|
|
58
|
+
|
|
39
59
|
function getCurrentAgent(projectDir) {
|
|
40
60
|
const sessionPath = join(projectDir, '.chati', 'session.yaml');
|
|
41
61
|
if (!existsSync(sessionPath)) return null;
|
|
@@ -71,6 +91,6 @@ async function main() {
|
|
|
71
91
|
}
|
|
72
92
|
}
|
|
73
93
|
|
|
74
|
-
export { AGENT_MODELS, getCurrentAgent };
|
|
94
|
+
export { AGENT_MODELS, UPGRADE_CONDITIONS, getCurrentAgent };
|
|
75
95
|
|
|
76
96
|
main();
|
|
@@ -158,6 +158,7 @@ brownfield-wu -> Brief -> Architect -> Detail -> UX -> Phases -> Tasks -> QA-Pla
|
|
|
158
158
|
| devops | chati.dev/agents/deploy/devops.md |
|
|
159
159
|
|
|
160
160
|
### Transition Logic
|
|
161
|
+
|
|
161
162
|
```
|
|
162
163
|
When an agent completes (score >= 95%):
|
|
163
164
|
1. Agent generates handoff at chati.dev/artifacts/handoffs/{agent-name}-handoff.md
|
|
@@ -170,17 +171,124 @@ When an agent completes (score >= 95%):
|
|
|
170
171
|
- Dev + QA-Implementation = build
|
|
171
172
|
- Final validation = validate
|
|
172
173
|
- DevOps = deploy
|
|
173
|
-
7.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
7. Activate agent using Hybrid Activation Protocol (see below)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Hybrid Activation Protocol
|
|
180
|
+
|
|
181
|
+
The orchestrator uses TWO activation modes depending on the agent type:
|
|
182
|
+
|
|
183
|
+
### Interactive Agents (run IN-CONVERSATION)
|
|
184
|
+
|
|
185
|
+
These agents require human interaction and run in the same terminal as the orchestrator:
|
|
186
|
+
- **greenfield-wu** — needs user description of the project
|
|
187
|
+
- **brownfield-wu** — needs user guidance on codebase
|
|
188
|
+
- **brief** — needs iterative requirement extraction with user
|
|
189
|
+
|
|
190
|
+
For interactive agents:
|
|
191
|
+
```
|
|
192
|
+
1. Read the agent's .md file from the Agent Location Map
|
|
193
|
+
2. Display model recommendation (see Model Map below)
|
|
194
|
+
3. Load agent context into the conversation
|
|
195
|
+
4. User interacts with the agent directly
|
|
196
|
+
5. Agent completes, generates handoff, orchestrator continues
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Autonomous Agents (run in SEPARATE TERMINALS)
|
|
200
|
+
|
|
201
|
+
All other agents run in separate Claude Code processes with the correct model:
|
|
202
|
+
- **detail**, **architect**, **ux**, **phases**, **tasks**
|
|
203
|
+
- **qa-planning**, **dev**, **qa-implementation**, **devops**
|
|
204
|
+
|
|
205
|
+
For autonomous agents:
|
|
206
|
+
```
|
|
207
|
+
1. Use the Bash tool to spawn the agent in a separate terminal:
|
|
208
|
+
|
|
209
|
+
node packages/chati-dev/src/terminal/run-agent.js \
|
|
210
|
+
--agent {agent_name} \
|
|
211
|
+
--task-id {primary_task_id} \
|
|
212
|
+
--project-dir {absolute_project_path} \
|
|
213
|
+
--previous-agent {previous_agent_name} \
|
|
214
|
+
--timeout 600000
|
|
215
|
+
|
|
216
|
+
2. Wait for the JSON output
|
|
217
|
+
|
|
218
|
+
3. Parse the result:
|
|
219
|
+
- If "status": "complete" → Save handoff, continue to next agent
|
|
220
|
+
- If "status": "needs_input" → Read "needs_input_question", ask the user,
|
|
221
|
+
then re-run with --additional-context "{user_response}"
|
|
222
|
+
- If "status": "error" → Apply Recovery Protocol (retry up to 2 times)
|
|
223
|
+
- If retries exhausted → Fall back to in-conversation activation
|
|
224
|
+
|
|
225
|
+
4. Update session.yaml with completion data
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Parallel Group Execution
|
|
229
|
+
|
|
230
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
231
|
+
║ PARALLELIZATION CHECK (MANDATORY — DO NOT SKIP) ║
|
|
232
|
+
║ ║
|
|
233
|
+
║ GROUP 1 — Clarity Phase (after Brief completes): ║
|
|
234
|
+
║ Agents: [detail, architect, ux] ║
|
|
235
|
+
║ ALL run in parallel via separate terminals ║
|
|
236
|
+
║ ║
|
|
237
|
+
║ GROUP 2 — Build Phase (Dev agent tasks): ║
|
|
238
|
+
║ Independent tasks ALWAYS run in parallel ║
|
|
239
|
+
║ Tasks with dependencies = sequential within chain ║
|
|
240
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
241
|
+
|
|
242
|
+
When the next agent is part of a parallel group, use:
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
node packages/chati-dev/src/terminal/run-parallel.js \
|
|
246
|
+
--agents detail,architect,ux \
|
|
247
|
+
--task-ids {task_id_detail},{task_id_architect},{task_id_ux} \
|
|
248
|
+
--project-dir {absolute_project_path} \
|
|
249
|
+
--previous-agent brief \
|
|
250
|
+
--timeout 900000
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Parse the consolidated JSON output:
|
|
254
|
+
- If all agents completed → merged handoff ready, continue to next sequential agent
|
|
255
|
+
- If partial failure → present failed agents to user with options:
|
|
256
|
+
1. Retry failed agents only
|
|
257
|
+
2. Continue with partial results
|
|
258
|
+
3. Fall back to sequential execution for failed agents
|
|
259
|
+
|
|
260
|
+
### Sequential Fallback
|
|
261
|
+
|
|
262
|
+
If terminal spawning fails (claude CLI not found, system error, etc.):
|
|
263
|
+
```
|
|
264
|
+
1. Log the failure
|
|
265
|
+
2. Fall back to in-conversation activation (read agent .md file, become agent)
|
|
266
|
+
3. Record in session.yaml:
|
|
267
|
+
terminal_fallback:
|
|
268
|
+
agent: {name}
|
|
269
|
+
reason: "{error_message}"
|
|
270
|
+
timestamp: "{now}"
|
|
271
|
+
4. Continue pipeline normally
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Needs-Input Relay Pattern
|
|
275
|
+
|
|
276
|
+
When a spawned agent needs user input:
|
|
277
|
+
```
|
|
278
|
+
1. Agent returns status: "needs_input" in JSON output
|
|
279
|
+
2. Agent includes question in "needs_input_question" field
|
|
280
|
+
3. Orchestrator reads the question
|
|
281
|
+
4. Orchestrator presents question to user (in their language)
|
|
282
|
+
5. User responds
|
|
283
|
+
6. Orchestrator re-spawns agent with --additional-context "{user_response}"
|
|
284
|
+
7. Repeat until agent completes or max 3 relay cycles
|
|
177
285
|
```
|
|
178
286
|
|
|
179
287
|
---
|
|
180
288
|
|
|
181
289
|
## Model Selection Protocol
|
|
182
290
|
|
|
183
|
-
|
|
291
|
+
Model selection is **enforced by construction**: the orchestrator passes `--model` to the spawned terminal. For interactive agents, the model is recommended to the user.
|
|
184
292
|
|
|
185
293
|
### Model Map (Quick Reference)
|
|
186
294
|
|
|
@@ -199,30 +307,19 @@ Before activating any agent, the orchestrator reads the agent's `Model` field an
|
|
|
199
307
|
| qa-implementation | opus | no downgrade |
|
|
200
308
|
| devops | sonnet | opus if multi-environment or IaC |
|
|
201
309
|
|
|
202
|
-
###
|
|
203
|
-
|
|
204
|
-
```
|
|
205
|
-
1. Read agent's Model field from its .md file
|
|
206
|
-
2. Extract default model and upgrade condition
|
|
207
|
-
3. If upgrade condition exists:
|
|
208
|
-
a. Check session context (project.type, codebase_size, integrations_count, requirements_count)
|
|
209
|
-
b. Check previous agent signals (handoff complexity, discovered tech debt)
|
|
210
|
-
c. If condition matches -> recommend upgraded model
|
|
211
|
-
d. If condition does not match -> use default model
|
|
212
|
-
4. If "no downgrade" -> always use the specified model
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Recommendation Message (IDE Mode)
|
|
216
|
-
|
|
217
|
-
When the recommended model differs from the current model, display:
|
|
310
|
+
### Enforcement
|
|
218
311
|
|
|
219
312
|
```
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
313
|
+
For autonomous agents (spawned terminals):
|
|
314
|
+
→ Model is AUTOMATICALLY selected and passed via --model flag
|
|
315
|
+
→ No user intervention needed
|
|
316
|
+
→ Correct model guaranteed by the prompt builder
|
|
223
317
|
|
|
224
|
-
|
|
225
|
-
|
|
318
|
+
For interactive agents (in-conversation):
|
|
319
|
+
→ Display model recommendation to user:
|
|
320
|
+
💡 Model recommendation for {agent_name}: {recommended_model}
|
|
321
|
+
To switch: /model {recommended_model}
|
|
322
|
+
→ Model governance hook provides defense-in-depth validation
|
|
226
323
|
```
|
|
227
324
|
|
|
228
325
|
### Session Logging
|
|
@@ -230,10 +327,11 @@ When the recommended model differs from the current model, display:
|
|
|
230
327
|
```yaml
|
|
231
328
|
# Appended to session.yaml on each agent activation
|
|
232
329
|
model_selections:
|
|
233
|
-
- agent:
|
|
234
|
-
recommended:
|
|
235
|
-
actual: opus
|
|
236
|
-
|
|
330
|
+
- agent: detail
|
|
331
|
+
recommended: opus
|
|
332
|
+
actual: opus
|
|
333
|
+
mode: terminal # terminal | in-conversation
|
|
334
|
+
reason: "no downgrade"
|
|
237
335
|
timestamp: "2026-..."
|
|
238
336
|
```
|
|
239
337
|
|
|
@@ -862,6 +960,7 @@ Level 4 - Graceful Degradation:
|
|
|
862
960
|
### Autonomous Mode
|
|
863
961
|
```
|
|
864
962
|
- Execute pipeline transitions silently when gates pass (score >= 95%)
|
|
963
|
+
- Spawn parallel agent groups automatically (Detail + Architect + UX after Brief; independent Dev tasks in parallel)
|
|
865
964
|
- Auto-resolve simple deviations (redirect to correct agent)
|
|
866
965
|
- Pause only on:
|
|
867
966
|
- Quality gate failure (score < 95%)
|
|
@@ -886,25 +985,28 @@ Present suggestion with reasoning. User always has final say.
|
|
|
886
985
|
|
|
887
986
|
---
|
|
888
987
|
|
|
889
|
-
## Parallelization
|
|
988
|
+
## Parallelization Rules
|
|
890
989
|
|
|
891
990
|
### Parallelizable Agent Groups
|
|
892
991
|
```
|
|
893
|
-
Group 1 (post-Brief):
|
|
992
|
+
Group 1 (post-Brief) — MANDATORY PARALLEL:
|
|
894
993
|
- Detail + Architect + UX
|
|
895
|
-
-
|
|
994
|
+
- MUST run in 3 parallel terminals (autonomous mode)
|
|
995
|
+
- SHOULD offer parallel option (human-in-the-loop mode)
|
|
896
996
|
- Each writes to isolated artifact directories
|
|
897
|
-
- Orchestrator
|
|
997
|
+
- Orchestrator MUST collect and merge ALL handoffs before proceeding to Phases
|
|
898
998
|
|
|
899
|
-
Group 2 (Dev tasks):
|
|
900
|
-
- Independent dev tasks
|
|
901
|
-
- Each terminal has isolated write scope
|
|
999
|
+
Group 2 (Dev tasks) — MANDATORY PARALLEL:
|
|
1000
|
+
- Independent dev tasks MUST run in N parallel terminals (all modes)
|
|
1001
|
+
- Each terminal has isolated write scope per task
|
|
902
1002
|
- Orchestrator monitors and collects results
|
|
1003
|
+
- Tasks with no shared file dependencies run simultaneously
|
|
1004
|
+
- Tasks with dependencies run sequentially within their chain
|
|
903
1005
|
|
|
904
|
-
NOT parallelizable:
|
|
1006
|
+
NOT parallelizable (always sequential):
|
|
905
1007
|
- WU (needs user interaction)
|
|
906
1008
|
- Brief (needs user interaction)
|
|
907
|
-
- Phases (depends on Detail + Architect + UX)
|
|
1009
|
+
- Phases (depends on Detail + Architect + UX results)
|
|
908
1010
|
- Tasks (depends on Phases)
|
|
909
1011
|
- QA-Planning (validates everything)
|
|
910
1012
|
- QA-Implementation (validates everything)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chati-dev",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"description": "AI-Powered Multi-Agent Orchestration System — 13 agents, 6 IDEs, 4 languages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
"license": "MIT",
|
|
46
46
|
"repository": {
|
|
47
47
|
"type": "git",
|
|
48
|
-
"url": "https://github.com/ogabrielalonso/
|
|
48
|
+
"url": "https://github.com/ogabrielalonso/Chati.dev.git",
|
|
49
49
|
"directory": "packages/chati-dev"
|
|
50
50
|
},
|
|
51
|
-
"homepage": "https://github.com/ogabrielalonso/
|
|
51
|
+
"homepage": "https://github.com/ogabrielalonso/Chati.dev#readme",
|
|
52
52
|
"bugs": {
|
|
53
|
-
"url": "https://github.com/ogabrielalonso/
|
|
53
|
+
"url": "https://github.com/ogabrielalonso/Chati.dev/issues"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@clack/prompts": "^0.7.0",
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Parse structured handoff data from spawned agent output.
|
|
3
|
+
*
|
|
4
|
+
* Agents running in separate `claude -p` terminals include a
|
|
5
|
+
* <chati-handoff> block in their output. This module extracts
|
|
6
|
+
* and parses that block so the orchestrator can read the results.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Parse the <chati-handoff> block from agent stdout.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} output - Full stdout from the agent process
|
|
13
|
+
* @returns {{ found: boolean, handoff: object|null, rawOutput: string }}
|
|
14
|
+
*/
|
|
15
|
+
export function parseAgentOutput(output) {
|
|
16
|
+
if (!output || typeof output !== 'string') {
|
|
17
|
+
return { found: false, handoff: null, rawOutput: '' };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const match = output.match(/<chati-handoff>([\s\S]*?)<\/chati-handoff>/);
|
|
21
|
+
if (!match) {
|
|
22
|
+
return { found: false, handoff: null, rawOutput: output };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const content = match[1].trim();
|
|
26
|
+
const handoff = parseHandoffFields(content);
|
|
27
|
+
|
|
28
|
+
return { found: true, handoff, rawOutput: output };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Parse YAML-like key-value fields from the handoff block content.
|
|
33
|
+
*
|
|
34
|
+
* Supports:
|
|
35
|
+
* scalar: value
|
|
36
|
+
* list:
|
|
37
|
+
* - item1
|
|
38
|
+
* - item2
|
|
39
|
+
* map:
|
|
40
|
+
* key1: value1
|
|
41
|
+
* key2: value2
|
|
42
|
+
*
|
|
43
|
+
* @param {string} content - Content inside <chati-handoff> tags
|
|
44
|
+
* @returns {object} Parsed handoff data
|
|
45
|
+
*/
|
|
46
|
+
function parseHandoffFields(content) {
|
|
47
|
+
const result = {
|
|
48
|
+
status: 'unknown',
|
|
49
|
+
score: null,
|
|
50
|
+
summary: '',
|
|
51
|
+
outputs: [],
|
|
52
|
+
decisions: {},
|
|
53
|
+
blockers: [],
|
|
54
|
+
needs_input_question: null,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const lines = content.split('\n');
|
|
58
|
+
let currentKey = null;
|
|
59
|
+
let currentType = null; // 'list' | 'map'
|
|
60
|
+
|
|
61
|
+
for (const line of lines) {
|
|
62
|
+
const trimmed = line.trim();
|
|
63
|
+
if (!trimmed) continue;
|
|
64
|
+
|
|
65
|
+
// Check if this is a list item ( - value)
|
|
66
|
+
const listMatch = trimmed.match(/^-\s+(.+)/);
|
|
67
|
+
if (listMatch && currentKey && currentType === 'list') {
|
|
68
|
+
if (Array.isArray(result[currentKey])) {
|
|
69
|
+
result[currentKey].push(listMatch[1].trim());
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Check if this is a map item ( key: value) under a map key
|
|
75
|
+
const mapMatch = trimmed.match(/^(\w[\w_-]*):\s+(.+)/);
|
|
76
|
+
if (mapMatch && currentKey && currentType === 'map') {
|
|
77
|
+
if (typeof result[currentKey] === 'object' && !Array.isArray(result[currentKey])) {
|
|
78
|
+
result[currentKey][mapMatch[1]] = mapMatch[2].trim();
|
|
79
|
+
}
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Top-level key: value
|
|
84
|
+
const kvMatch = trimmed.match(/^(\w[\w_-]*):\s*(.*)/);
|
|
85
|
+
if (kvMatch) {
|
|
86
|
+
const key = kvMatch[1];
|
|
87
|
+
const value = kvMatch[2].trim();
|
|
88
|
+
|
|
89
|
+
// Known list keys
|
|
90
|
+
if (['outputs', 'blockers'].includes(key)) {
|
|
91
|
+
currentKey = key;
|
|
92
|
+
currentType = 'list';
|
|
93
|
+
// If value is inline (not empty), treat as single item
|
|
94
|
+
if (value && value !== '') {
|
|
95
|
+
result[key] = [value];
|
|
96
|
+
currentKey = null;
|
|
97
|
+
currentType = null;
|
|
98
|
+
}
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Known map keys
|
|
103
|
+
if (['decisions'].includes(key)) {
|
|
104
|
+
currentKey = key;
|
|
105
|
+
currentType = 'map';
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Scalar keys
|
|
110
|
+
currentKey = null;
|
|
111
|
+
currentType = null;
|
|
112
|
+
|
|
113
|
+
if (key === 'status') {
|
|
114
|
+
result.status = value || 'unknown';
|
|
115
|
+
} else if (key === 'score') {
|
|
116
|
+
const num = parseInt(value, 10);
|
|
117
|
+
result.score = isNaN(num) ? null : num;
|
|
118
|
+
} else if (key === 'summary') {
|
|
119
|
+
result.summary = value || '';
|
|
120
|
+
} else if (key === 'needs_input_question') {
|
|
121
|
+
result.needs_input_question = value === 'null' || value === '' ? null : value;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return result;
|
|
127
|
+
}
|
package/src/terminal/index.js
CHANGED