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 the agent name "test-dummy"
139
- expect(agentLinePlain, 'expected agent name "test-dummy" in delegation line')
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
- // Verify sub-agent's internal tool calls show sub-agent name (not orchestrator)
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, not orchestrator')
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
- return `${ts()}🤖 ${colored}${desc && agentType ? ` ${TC.dim}${desc}${TC.reset}` : ''}`;
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
- _agentTag = `${colorizeAgent(name)} `;
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 and sub-agent type', () => {
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
- // 2. Sub-agent's internal tool call — should show ui-engineer
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',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claude-workspace",
3
- "version": "1.1.82",
3
+ "version": "1.1.83",
4
4
  "description": "Scaffold a project with Claude Code agents for autonomous AI-driven development",
5
5
  "type": "module",
6
6
  "bin": {