create-claude-workspace 1.1.82 → 1.1.83
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.
|
@@ -102,11 +102,11 @@ describe('agent tag integration: real Claude CLI', () => {
|
|
|
102
102
|
console.log(`Event types: ${[...new Set(result.rawEvents.map(e => e.type))].join(', ')}`);
|
|
103
103
|
}, 60_000);
|
|
104
104
|
it.skipIf(!hasClaude)('shows sub-agent name when Agent tool is used', async () => {
|
|
105
|
-
// Use a custom agent defined in .claude/agents/test-dummy.md
|
|
106
|
-
// This mirrors how orchestrator delegates: subagent_type="test-dummy"
|
|
105
|
+
// Use a custom agent defined in .claude/agents/test-dummy.md (model: haiku)
|
|
106
|
+
// This mirrors how orchestrator delegates: subagent_type="test-dummy", model="haiku"
|
|
107
107
|
const prompt = [
|
|
108
108
|
'You MUST use the Agent tool exactly once.',
|
|
109
|
-
'Call it with: subagent_type "test-dummy", description "find ts files",',
|
|
109
|
+
'Call it with: subagent_type "test-dummy", model "haiku", description "find ts files",',
|
|
110
110
|
'prompt "Use Glob with pattern **/*.mts to find TypeScript files. Return the list."',
|
|
111
111
|
'After the Agent tool returns, respond with: done',
|
|
112
112
|
].join(' ');
|
|
@@ -135,10 +135,12 @@ describe('agent tag integration: real Claude CLI', () => {
|
|
|
135
135
|
console.log(`Delegation line: ${agentLinePlain.trim()}`);
|
|
136
136
|
// Delegation line should show orchestrator as the caller
|
|
137
137
|
expect(agentLinePlain).toContain(`orchestrator/${result.detectedModel}`);
|
|
138
|
-
// Should contain
|
|
139
|
-
expect(agentLinePlain, 'expected
|
|
138
|
+
// Should contain agent name "test-dummy" with model "haiku"
|
|
139
|
+
expect(agentLinePlain, 'expected "test-dummy" in delegation line')
|
|
140
140
|
.toContain('test-dummy');
|
|
141
|
-
|
|
141
|
+
expect(agentLinePlain, 'expected "haiku" model in delegation line')
|
|
142
|
+
.toContain('haiku');
|
|
143
|
+
// Verify sub-agent's internal tool calls show sub-agent name + model (not orchestrator)
|
|
142
144
|
const plainLines = result.formattedLines.map(stripAnsi);
|
|
143
145
|
const delegationIdx = plainLines.findIndex(l => l.includes('🤖'));
|
|
144
146
|
const subAgentLines = plainLines.slice(delegationIdx + 1).filter(l => l.includes('▶') || l.includes('💭'));
|
|
@@ -146,9 +148,11 @@ describe('agent tag integration: real Claude CLI', () => {
|
|
|
146
148
|
console.log(`Sub-agent internal tool calls (${subAgentLines.length}):`);
|
|
147
149
|
for (const line of subAgentLines) {
|
|
148
150
|
console.log(` ${line.trim()}`);
|
|
149
|
-
// Internal tool calls should show "test-dummy", NOT "orchestrator"
|
|
150
|
-
expect(line, 'sub-agent tool call should show test-dummy
|
|
151
|
+
// Internal tool calls should show "test-dummy/haiku", NOT "orchestrator"
|
|
152
|
+
expect(line, 'sub-agent tool call should show test-dummy')
|
|
151
153
|
.toContain('test-dummy');
|
|
154
|
+
expect(line, 'sub-agent tool call should show haiku model')
|
|
155
|
+
.toContain('haiku');
|
|
152
156
|
expect(line, 'sub-agent tool call should NOT show orchestrator')
|
|
153
157
|
.not.toContain(`orchestrator/${result.detectedModel}`);
|
|
154
158
|
}
|
|
@@ -104,13 +104,15 @@ function getContentBlocks(event) {
|
|
|
104
104
|
}
|
|
105
105
|
function formatToolUse(block) {
|
|
106
106
|
const input = block.input ?? {};
|
|
107
|
-
// Special formatting for Agent tool — show sub-agent with color
|
|
107
|
+
// Special formatting for Agent tool — show sub-agent with color + model
|
|
108
108
|
if (block.name === 'Agent') {
|
|
109
109
|
const agentType = input.subagent_type ?? '';
|
|
110
110
|
const desc = input.description ?? '';
|
|
111
|
+
const model = input.model ?? '';
|
|
111
112
|
const label = agentType || desc || 'sub-agent';
|
|
112
113
|
const colored = colorizeAgent(label);
|
|
113
|
-
|
|
114
|
+
const modelSuffix = model ? `${TC.dim}/${model}${TC.reset}` : '';
|
|
115
|
+
return `${ts()}🤖 → ${colored}${modelSuffix}${desc && agentType ? ` ${TC.dim}${desc}${TC.reset}` : ''}`;
|
|
114
116
|
}
|
|
115
117
|
const detail = input.command ?? input.file_path ?? input.pattern ?? input.query ?? '';
|
|
116
118
|
const short = detail.slice(0, 120);
|
|
@@ -214,7 +216,10 @@ export function formatStreamEventTracked(event) {
|
|
|
214
216
|
_agentReturnDepths.push(_formatToolDepth);
|
|
215
217
|
const input = block.input ?? {};
|
|
216
218
|
const name = input.subagent_type || input.description || 'sub-agent';
|
|
217
|
-
|
|
219
|
+
const model = input.model ?? '';
|
|
220
|
+
_agentTag = model
|
|
221
|
+
? `${colorizeAgent(name)}${TC.dim}/${model}${TC.reset} `
|
|
222
|
+
: `${colorizeAgent(name)} `;
|
|
218
223
|
}
|
|
219
224
|
}
|
|
220
225
|
}
|
|
@@ -317,19 +317,37 @@ describe('formatStreamEvent with Agent tool', () => {
|
|
|
317
317
|
beforeEach(() => {
|
|
318
318
|
resetStreamState();
|
|
319
319
|
});
|
|
320
|
-
it('formats Agent tool_use with robot icon
|
|
320
|
+
it('formats Agent tool_use with robot icon, sub-agent type, and model', () => {
|
|
321
321
|
const result = formatStreamEvent({
|
|
322
322
|
type: 'assistant',
|
|
323
323
|
message: {
|
|
324
324
|
content: [{
|
|
325
325
|
type: 'tool_use',
|
|
326
326
|
name: 'Agent',
|
|
327
|
-
input: { subagent_type: 'ui-engineer', description: 'plan frontend' },
|
|
327
|
+
input: { subagent_type: 'ui-engineer', description: 'plan frontend', model: 'opus' },
|
|
328
328
|
}],
|
|
329
329
|
},
|
|
330
330
|
});
|
|
331
331
|
expect(result).toContain('🤖');
|
|
332
332
|
expect(result).toContain('ui-engineer');
|
|
333
|
+
expect(result).toContain('opus');
|
|
334
|
+
});
|
|
335
|
+
it('formats Agent tool_use without model when not specified', () => {
|
|
336
|
+
const result = formatStreamEvent({
|
|
337
|
+
type: 'assistant',
|
|
338
|
+
message: {
|
|
339
|
+
content: [{
|
|
340
|
+
type: 'tool_use',
|
|
341
|
+
name: 'Agent',
|
|
342
|
+
input: { subagent_type: 'Explore', description: 'find files' },
|
|
343
|
+
}],
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
expect(result).toContain('🤖');
|
|
347
|
+
expect(result).toContain('Explore');
|
|
348
|
+
// No /model suffix when model not specified
|
|
349
|
+
const stripped = result.replace(/\x1b\[\d+m/g, '');
|
|
350
|
+
expect(stripped).not.toMatch(/Explore\//);
|
|
333
351
|
});
|
|
334
352
|
it('falls back to description when no subagent_type', () => {
|
|
335
353
|
const result = formatStreamEvent({
|
|
@@ -370,26 +388,27 @@ describe('formatStreamEventTracked', () => {
|
|
|
370
388
|
setAgentTag('orchestrator', 'opus-4.6');
|
|
371
389
|
});
|
|
372
390
|
it('switches tag to sub-agent after Agent tool_use, restores on tool_result', () => {
|
|
373
|
-
// 1. Agent tool_use — should show orchestrator (parent delegates)
|
|
391
|
+
// 1. Agent tool_use — should show orchestrator (parent delegates) + sub-agent with model
|
|
374
392
|
const delegation = formatStreamEventTracked({
|
|
375
393
|
type: 'assistant',
|
|
376
|
-
message: { content: [{ type: 'tool_use', name: 'Agent', input: { subagent_type: 'ui-engineer', description: 'plan' } }] },
|
|
394
|
+
message: { content: [{ type: 'tool_use', name: 'Agent', input: { subagent_type: 'ui-engineer', description: 'plan', model: 'opus' } }] },
|
|
377
395
|
});
|
|
378
396
|
expect(stripAnsi(delegation)).toContain('orchestrator/opus-4.6');
|
|
379
397
|
expect(stripAnsi(delegation)).toContain('🤖');
|
|
380
|
-
|
|
398
|
+
expect(stripAnsi(delegation)).toContain('ui-engineer/opus');
|
|
399
|
+
// 2. Sub-agent's internal tool call — should show ui-engineer/opus
|
|
381
400
|
const subTool = formatStreamEventTracked({
|
|
382
401
|
type: 'assistant',
|
|
383
402
|
message: { content: [{ type: 'tool_use', name: 'Read', input: { file_path: 'src/main.ts' } }] },
|
|
384
403
|
});
|
|
385
|
-
expect(stripAnsi(subTool)).toContain('ui-engineer');
|
|
404
|
+
expect(stripAnsi(subTool)).toContain('ui-engineer/opus');
|
|
386
405
|
expect(stripAnsi(subTool)).not.toContain('orchestrator');
|
|
387
406
|
// 3. Sub-agent's tool result — still sub-agent context
|
|
388
407
|
const subResult = formatStreamEventTracked({
|
|
389
408
|
type: 'user',
|
|
390
409
|
message: { content: [{ type: 'tool_result', content: 'file contents' }] },
|
|
391
410
|
});
|
|
392
|
-
expect(stripAnsi(subResult)).toContain('ui-engineer');
|
|
411
|
+
expect(stripAnsi(subResult)).toContain('ui-engineer/opus');
|
|
393
412
|
// 4. Agent tool result — restores orchestrator
|
|
394
413
|
const agentResult = formatStreamEventTracked({
|
|
395
414
|
type: 'user',
|
|
@@ -404,33 +423,33 @@ describe('formatStreamEventTracked', () => {
|
|
|
404
423
|
expect(stripAnsi(nextTool)).toContain('orchestrator/opus-4.6');
|
|
405
424
|
});
|
|
406
425
|
it('handles nested Agent calls (agent within agent)', () => {
|
|
407
|
-
// orchestrator → backend-ts-architect → (inner tool)
|
|
426
|
+
// orchestrator → backend-ts-architect/opus → (inner tool)
|
|
408
427
|
formatStreamEventTracked({
|
|
409
428
|
type: 'assistant',
|
|
410
|
-
message: { content: [{ type: 'tool_use', name: 'Agent', input: { subagent_type: 'backend-ts-architect' } }] },
|
|
429
|
+
message: { content: [{ type: 'tool_use', name: 'Agent', input: { subagent_type: 'backend-ts-architect', model: 'opus' } }] },
|
|
411
430
|
});
|
|
412
431
|
// backend-ts-architect calls Agent (hypothetical nested delegation)
|
|
413
432
|
formatStreamEventTracked({
|
|
414
433
|
type: 'assistant',
|
|
415
|
-
message: { content: [{ type: 'tool_use', name: 'Agent', input: { subagent_type: 'Explore' } }] },
|
|
434
|
+
message: { content: [{ type: 'tool_use', name: 'Agent', input: { subagent_type: 'Explore', model: 'haiku' } }] },
|
|
416
435
|
});
|
|
417
|
-
// Inner agent's tool
|
|
436
|
+
// Inner agent's tool — should show Explore/haiku
|
|
418
437
|
const innerTool = formatStreamEventTracked({
|
|
419
438
|
type: 'assistant',
|
|
420
439
|
message: { content: [{ type: 'tool_use', name: 'Grep', input: { pattern: 'TODO' } }] },
|
|
421
440
|
});
|
|
422
|
-
expect(stripAnsi(innerTool)).toContain('Explore');
|
|
441
|
+
expect(stripAnsi(innerTool)).toContain('Explore/haiku');
|
|
423
442
|
// Inner agent's tool result
|
|
424
443
|
formatStreamEventTracked({
|
|
425
444
|
type: 'user',
|
|
426
445
|
message: { content: [{ type: 'tool_result', content: 'found' }] },
|
|
427
446
|
});
|
|
428
|
-
// Inner Agent result → back to backend-ts-architect
|
|
447
|
+
// Inner Agent result → back to backend-ts-architect/opus
|
|
429
448
|
const innerAgentResult = formatStreamEventTracked({
|
|
430
449
|
type: 'user',
|
|
431
450
|
message: { content: [{ type: 'tool_result', content: 'explore done' }] },
|
|
432
451
|
});
|
|
433
|
-
expect(stripAnsi(innerAgentResult)).toContain('backend-ts-architect');
|
|
452
|
+
expect(stripAnsi(innerAgentResult)).toContain('backend-ts-architect/opus');
|
|
434
453
|
// Outer Agent result → back to orchestrator
|
|
435
454
|
const outerAgentResult = formatStreamEventTracked({
|
|
436
455
|
type: 'user',
|