tlc-claude-code 1.6.0 → 1.6.2

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.
@@ -5,11 +5,11 @@
5
5
 
6
6
  const { BaseAdapter } = require('./base-adapter.js');
7
7
 
8
- // Latest model: claude-opus-4-5-20251101 (Claude Opus 4.5)
9
- const CLAUDE_MODEL = 'claude-opus-4-5-20251101';
8
+ // Latest model: claude-opus-4-6-20260205 (Claude Opus 4.6)
9
+ const CLAUDE_MODEL = 'claude-opus-4-6-20260205';
10
10
 
11
11
  const CLAUDE_PRICING = {
12
- // Pricing per 1M tokens (Claude Opus 4.5)
12
+ // Pricing per 1M tokens (Claude Opus 4.6)
13
13
  inputPerMillion: 15.00,
14
14
  outputPerMillion: 75.00,
15
15
  };
@@ -166,7 +166,7 @@ describe('ClaudeAdapter', () => {
166
166
  });
167
167
 
168
168
  describe('CLAUDE_PRICING', () => {
169
- it('exports default pricing for Opus 4.5', () => {
169
+ it('exports default pricing for Opus 4.6', () => {
170
170
  expect(CLAUDE_PRICING.inputPerMillion).toBe(15.00);
171
171
  expect(CLAUDE_PRICING.outputPerMillion).toBe(75.00);
172
172
  });
@@ -174,7 +174,7 @@ describe('ClaudeAdapter', () => {
174
174
 
175
175
  describe('CLAUDE_MODEL', () => {
176
176
  it('exports latest model identifier', () => {
177
- expect(CLAUDE_MODEL).toBe('claude-opus-4-5-20251101');
177
+ expect(CLAUDE_MODEL).toBe('claude-opus-4-6-20260205');
178
178
  });
179
179
  });
180
180
  });
@@ -4,11 +4,11 @@
4
4
 
5
5
  const { BaseAdapter } = require('./base-adapter.js');
6
6
 
7
- // Latest model: o3 (January 2025)
8
- const OPENAI_MODEL = 'o3';
7
+ // Latest model: gpt-5.3-codex (February 2026)
8
+ const OPENAI_MODEL = 'gpt-5.3-codex';
9
9
 
10
10
  const OPENAI_PRICING = {
11
- // Pricing per 1M tokens (o3)
11
+ // Pricing per 1M tokens (gpt-5.3-codex)
12
12
  inputPerMillion: 10.00,
13
13
  outputPerMillion: 40.00,
14
14
  };
@@ -214,13 +214,13 @@ describe('OpenAIAdapter', () => {
214
214
  });
215
215
 
216
216
  describe('exports', () => {
217
- it('exports OPENAI_PRICING for o3', () => {
217
+ it('exports OPENAI_PRICING for gpt-5.3-codex', () => {
218
218
  expect(OPENAI_PRICING.inputPerMillion).toBe(10.00);
219
219
  expect(OPENAI_PRICING.outputPerMillion).toBe(40.00);
220
220
  });
221
221
 
222
222
  it('exports OPENAI_MODEL', () => {
223
- expect(OPENAI_MODEL).toBe('o3');
223
+ expect(OPENAI_MODEL).toBe('gpt-5.3-codex');
224
224
  });
225
225
 
226
226
  it('exports DEFAULT_RATE_LIMITS', () => {
@@ -19,6 +19,7 @@ const DEFAULT_PRICING = {
19
19
  'claude-4-opus': { inputPer1kTokens: 0.015, outputPer1kTokens: 0.075 },
20
20
  'claude-4-sonnet': { inputPer1kTokens: 0.003, outputPer1kTokens: 0.015 },
21
21
  'claude-opus-4-5-20251101': { inputPer1kTokens: 0.015, outputPer1kTokens: 0.075 },
22
+ 'claude-opus-4-6-20260205': { inputPer1kTokens: 0.015, outputPer1kTokens: 0.075 },
22
23
 
23
24
  // OpenAI models
24
25
  'gpt-4': { inputPer1kTokens: 0.03, outputPer1kTokens: 0.06 },
@@ -33,6 +34,7 @@ const DEFAULT_PRICING = {
33
34
  'o1-pro': { inputPer1kTokens: 0.15, outputPer1kTokens: 0.6 },
34
35
  'o3': { inputPer1kTokens: 0.015, outputPer1kTokens: 0.06 },
35
36
  'o3-mini': { inputPer1kTokens: 0.0011, outputPer1kTokens: 0.0044 },
37
+ 'gpt-5.3-codex': { inputPer1kTokens: 0.01, outputPer1kTokens: 0.04 },
36
38
 
37
39
  // DeepSeek models
38
40
  'deepseek-r1': { inputPer1kTokens: 0.00055, outputPer1kTokens: 0.00219 },
@@ -5,14 +5,99 @@
5
5
  * This is NOT a command - it's integrated into /tlc:build
6
6
  * When a plan has independent tasks, they run in parallel automatically.
7
7
  *
8
- * Default behavior: Auto-parallelize up to 10 agents based on task dependencies
8
+ * Default behavior: Auto-parallelize with one agent per independent task
9
9
  * Use --sequential to force one-at-a-time execution
10
10
  * Use --agents N to limit parallelism to specific number
11
+ *
12
+ * Opus 4.6 Multi-Agent Features:
13
+ * - Model selection per agent (opus/sonnet/haiku) based on task complexity
14
+ * - Agent resumption via `resume` parameter for retry/continuation
15
+ * - TaskOutput for non-blocking progress checks on background agents
16
+ * - TaskStop for cancelling stuck agents
17
+ * - Specialized agent types: general-purpose, Bash, Explore, Plan
18
+ * - max_turns to limit agent execution length
11
19
  */
12
20
 
13
21
  const fs = require('fs');
14
22
  const path = require('path');
15
23
 
24
+ /**
25
+ * Valid subagent types for the Task tool (Opus 4.6)
26
+ */
27
+ const AGENT_TYPES = {
28
+ BUILD: 'general-purpose',
29
+ SHELL: 'Bash',
30
+ EXPLORE: 'Explore',
31
+ PLAN: 'Plan',
32
+ };
33
+
34
+ /**
35
+ * Model tiers for cost/capability optimization (Opus 4.6)
36
+ * Agents are assigned models based on task complexity.
37
+ */
38
+ const MODEL_TIERS = {
39
+ HEAVY: 'opus', // Complex multi-file features, architectural work
40
+ STANDARD: 'sonnet', // Normal implementation tasks (default)
41
+ LIGHT: 'haiku', // Simple tasks: config, boilerplate, single-file changes
42
+ };
43
+
44
+ /**
45
+ * Default max turns per agent to prevent runaway execution
46
+ */
47
+ const DEFAULT_MAX_TURNS = 50;
48
+
49
+ /**
50
+ * Estimate task complexity from its description/title
51
+ * @param {Object} task - Task with id and title
52
+ * @returns {'heavy'|'standard'|'light'} Complexity tier
53
+ */
54
+ function estimateTaskComplexity(task) {
55
+ const title = (task.title || '').toLowerCase();
56
+
57
+ const heavyPatterns = [
58
+ /architect/i, /refactor/i, /migration/i, /redesign/i,
59
+ /integration/i, /multi.?file/i, /cross.?cutting/i,
60
+ /security/i, /auth/i, /database/i, /schema/i,
61
+ ];
62
+
63
+ const lightPatterns = [
64
+ /config/i, /boilerplate/i, /rename/i, /update.*readme/i,
65
+ /add.*comment/i, /fix.*typo/i, /seed/i, /constant/i,
66
+ /enum/i, /dto/i, /interface/i,
67
+ ];
68
+
69
+ if (heavyPatterns.some(p => p.test(title))) {
70
+ return 'heavy';
71
+ }
72
+ if (lightPatterns.some(p => p.test(title))) {
73
+ return 'light';
74
+ }
75
+ return 'standard';
76
+ }
77
+
78
+ /**
79
+ * Get model for a task based on its complexity
80
+ * @param {Object} task - Task object
81
+ * @param {string} [modelOverride] - Force a specific model
82
+ * @returns {string} Model name (opus, sonnet, haiku)
83
+ */
84
+ function getModelForTask(task, modelOverride) {
85
+ if (modelOverride) {
86
+ return modelOverride;
87
+ }
88
+
89
+ const complexity = estimateTaskComplexity(task);
90
+
91
+ switch (complexity) {
92
+ case 'heavy':
93
+ return MODEL_TIERS.HEAVY;
94
+ case 'light':
95
+ return MODEL_TIERS.LIGHT;
96
+ default:
97
+ return MODEL_TIERS.STANDARD;
98
+ }
99
+ }
100
+
16
101
  /**
17
102
  * Parse overdrive command arguments
18
103
  * @param {string} args - Command arguments
@@ -21,10 +106,12 @@ const path = require('path');
21
106
  function parseOverdriveArgs(args = '') {
22
107
  const options = {
23
108
  phase: null,
24
- agents: 'auto', // Auto-detect based on independent tasks (up to 10)
109
+ agents: 'auto', // One agent per independent task
25
110
  mode: 'build', // build, test, fix
26
111
  dryRun: false,
27
112
  sequential: false,
113
+ model: null, // null = auto-select per task complexity
114
+ maxTurns: DEFAULT_MAX_TURNS,
28
115
  };
29
116
 
30
117
  const parts = args.trim().split(/\s+/).filter(Boolean);
@@ -35,9 +122,16 @@ function parseOverdriveArgs(args = '') {
35
122
  if (/^\d+$/.test(part)) {
36
123
  options.phase = parseInt(part, 10);
37
124
  } else if (part === '--agents' && parts[i + 1]) {
38
- options.agents = Math.min(parseInt(parts[++i], 10), 10); // Max 10 agents
125
+ options.agents = parseInt(parts[++i], 10);
39
126
  } else if (part === '--mode' && parts[i + 1]) {
40
127
  options.mode = parts[++i];
128
+ } else if (part === '--model' && parts[i + 1]) {
129
+ const model = parts[++i].toLowerCase();
130
+ if (['opus', 'sonnet', 'haiku'].includes(model)) {
131
+ options.model = model;
132
+ }
133
+ } else if (part === '--max-turns' && parts[i + 1]) {
134
+ options.maxTurns = parseInt(parts[++i], 10);
41
135
  } else if (part === '--dry-run') {
42
136
  options.dryRun = true;
43
137
  } else if (part === '--sequential' || part === '-s') {
@@ -104,6 +198,18 @@ function loadPhaseTasks(projectDir, phase) {
104
198
  };
105
199
  }
106
200
 
201
+ /**
202
+ * Determine the best agent type for a task
203
+ * @param {Object} task - Task object
204
+ * @param {string} mode - Execution mode (build, test, fix)
205
+ * @returns {string} Agent type for Task tool subagent_type
206
+ */
207
+ function selectAgentType(task, mode) {
208
+ // Build/test/fix all require full general-purpose agent
209
+ // (reads files, writes code, runs tests, commits)
210
+ return AGENT_TYPES.BUILD;
211
+ }
212
+
107
213
  /**
108
214
  * Generate agent prompts for parallel execution
109
215
  * @param {Array} tasks - Tasks to distribute
@@ -111,7 +217,7 @@ function loadPhaseTasks(projectDir, phase) {
111
217
  * @returns {Array} Agent prompts
112
218
  */
113
219
  function generateAgentPrompts(tasks, options = {}) {
114
- const { mode = 'build', projectDir, phase } = options;
220
+ const { mode = 'build', projectDir, phase, model, maxTurns } = options;
115
221
 
116
222
  return tasks.map((task, index) => {
117
223
  const basePrompt = `You are Agent ${index + 1} working on Phase ${phase}.
@@ -142,7 +248,10 @@ GO. Execute now. No questions.`;
142
248
  taskId: task.id,
143
249
  taskTitle: task.title,
144
250
  prompt: basePrompt,
145
- agentType: 'tlc-executor',
251
+ agentType: selectAgentType(task, mode),
252
+ model: getModelForTask(task, model),
253
+ maxTurns: maxTurns || DEFAULT_MAX_TURNS,
254
+ complexity: estimateTaskComplexity(task),
146
255
  };
147
256
  });
148
257
  }
@@ -171,7 +280,7 @@ function distributeTasks(tasks, agentCount) {
171
280
  function formatOverdrivePlan(plan) {
172
281
  const lines = [];
173
282
 
174
- lines.push('# Overdrive Mode');
283
+ lines.push('# Overdrive Mode (Opus 4.6)');
175
284
  lines.push('');
176
285
  lines.push(`**Phase:** ${plan.phase}`);
177
286
  lines.push(`**Mode:** ${plan.mode}`);
@@ -184,16 +293,24 @@ function formatOverdrivePlan(plan) {
184
293
  plan.agentAssignments.forEach((assignment, idx) => {
185
294
  lines.push(`### Agent ${idx + 1}`);
186
295
  assignment.tasks.forEach(task => {
187
- lines.push(`- Task ${task.id}: ${task.title}`);
296
+ const complexity = estimateTaskComplexity(task);
297
+ const model = getModelForTask(task, plan.modelOverride);
298
+ lines.push(`- Task ${task.id}: ${task.title} [${model}] (${complexity})`);
188
299
  });
189
300
  lines.push('');
190
301
  });
191
302
 
192
303
  lines.push('## Execution');
193
304
  lines.push('');
194
- lines.push('All agents will be spawned simultaneously using Task tool.');
305
+ lines.push('All agents spawned simultaneously via Task tool (Opus 4.6 multi-agent).');
195
306
  lines.push('Each agent works independently until completion.');
196
307
  lines.push('');
308
+ lines.push('**Capabilities:**');
309
+ lines.push('- Model selection per task complexity (opus/sonnet/haiku)');
310
+ lines.push('- Agent resumption for failed tasks (resume parameter)');
311
+ lines.push('- Non-blocking progress checks (TaskOutput block=false)');
312
+ lines.push('- Agent cancellation (TaskStop) for stuck agents');
313
+ lines.push('');
197
314
  lines.push('**Rules enforced:**');
198
315
  lines.push('- No confirmation prompts');
199
316
  lines.push('- No "shall I continue" questions');
@@ -204,7 +321,8 @@ function formatOverdrivePlan(plan) {
204
321
  }
205
322
 
206
323
  /**
207
- * Generate Task tool calls for parallel execution
324
+ * Generate Task tool calls for parallel execution (Opus 4.6)
325
+ * Includes model selection, max_turns, and correct subagent_type.
208
326
  * @param {Array} prompts - Agent prompts
209
327
  * @returns {Array} Task tool call specifications
210
328
  */
@@ -216,6 +334,8 @@ function generateTaskCalls(prompts) {
216
334
  prompt: p.prompt,
217
335
  subagent_type: p.agentType,
218
336
  run_in_background: true,
337
+ model: p.model,
338
+ max_turns: p.maxTurns,
219
339
  },
220
340
  }));
221
341
  }
@@ -270,12 +390,12 @@ async function executeOverdriveCommand(args = '', context = {}) {
270
390
  };
271
391
  }
272
392
 
273
- // Determine agent count: auto = max parallelism based on independent tasks
393
+ // Determine agent count: auto = one agent per independent task (no cap)
274
394
  let agentCount;
275
395
  if (options.sequential) {
276
396
  agentCount = 1;
277
397
  } else if (options.agents === 'auto') {
278
- // Auto-detect: use as many agents as there are independent tasks (up to 10)
398
+ // Auto-detect: one agent per independent task, no arbitrary cap
279
399
  let planContent = '';
280
400
  try {
281
401
  planContent = fs.readFileSync(phaseInfo.planPath, 'utf-8');
@@ -285,7 +405,7 @@ async function executeOverdriveCommand(args = '', context = {}) {
285
405
  const depAnalysis = analyzeDependencies(planContent);
286
406
  const parallelAnalysis = canParallelize(availableTasks, depAnalysis);
287
407
  agentCount = parallelAnalysis.canParallelize
288
- ? Math.min(parallelAnalysis.independentTasks.length, 10)
408
+ ? parallelAnalysis.independentTasks.length
289
409
  : 1;
290
410
  } else {
291
411
  agentCount = Math.min(options.agents, availableTasks.length);
@@ -293,7 +413,7 @@ async function executeOverdriveCommand(args = '', context = {}) {
293
413
 
294
414
  const taskGroups = distributeTasks(availableTasks, agentCount);
295
415
 
296
- // Generate prompts
416
+ // Generate prompts with model selection and max turns
297
417
  const agentAssignments = taskGroups.map((tasks, idx) => ({
298
418
  agentId: idx + 1,
299
419
  tasks,
@@ -301,6 +421,8 @@ async function executeOverdriveCommand(args = '', context = {}) {
301
421
  mode: options.mode,
302
422
  projectDir,
303
423
  phase: options.phase,
424
+ model: options.model,
425
+ maxTurns: options.maxTurns,
304
426
  }),
305
427
  }));
306
428
 
@@ -310,6 +432,7 @@ async function executeOverdriveCommand(args = '', context = {}) {
310
432
  agentCount,
311
433
  totalTasks: availableTasks.length,
312
434
  agentAssignments,
435
+ modelOverride: options.model,
313
436
  };
314
437
 
315
438
  if (options.dryRun) {
@@ -331,7 +454,7 @@ async function executeOverdriveCommand(args = '', context = {}) {
331
454
  taskCalls,
332
455
  output: formatOverdrivePlan(plan),
333
456
  instructions: `
334
- EXECUTE NOW: Spawn ${agentCount} agents in parallel using the Task tool.
457
+ EXECUTE NOW: Spawn ${agentCount} agents in parallel using the Task tool (Opus 4.6).
335
458
 
336
459
  ${taskCalls.map((tc, i) => `
337
460
  Agent ${i + 1}:
@@ -339,12 +462,18 @@ Task(
339
462
  description="${tc.params.description}",
340
463
  prompt="${tc.params.prompt.slice(0, 100)}...",
341
464
  subagent_type="${tc.params.subagent_type}",
465
+ model="${tc.params.model}",
466
+ max_turns=${tc.params.max_turns},
342
467
  run_in_background=true
343
468
  )
344
469
  `).join('\n')}
345
470
 
346
471
  CRITICAL: Call ALL Task tools in a SINGLE message to run them in parallel.
347
472
  Do NOT wait between spawns. Fire them all at once.
473
+
474
+ MONITORING: Use TaskOutput(task_id, block=false) to check progress.
475
+ STUCK AGENT: Use TaskStop(task_id) to cancel, then resume with Task(resume=agent_id).
476
+ FAILED AGENT: Use Task(resume=agent_id) to continue from where it left off.
348
477
  `,
349
478
  };
350
479
  }
@@ -458,7 +587,7 @@ function canParallelize(tasks, depAnalysis) {
458
587
  canParallelize: true,
459
588
  independentTasks,
460
589
  dependentTasks: tasks.filter(t => dependentTasks.has(t.id)),
461
- recommendedAgents: Math.min(independentTasks.length, 10), // Max 10 parallel agents
590
+ recommendedAgents: independentTasks.length, // One agent per independent task
462
591
  };
463
592
  }
464
593
 
@@ -543,4 +672,11 @@ module.exports = {
543
672
  canParallelize,
544
673
  shouldUseOverdrive,
545
674
  autoParallelize,
675
+ // Opus 4.6 multi-agent functions
676
+ estimateTaskComplexity,
677
+ getModelForTask,
678
+ selectAgentType,
679
+ AGENT_TYPES,
680
+ MODEL_TIERS,
681
+ DEFAULT_MAX_TURNS,
546
682
  };