mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-06 09:53:07 +00:00
feat: update Claude model to Opus 4.6 and enhance adaptive thinking support
- Changed model identifier from `claude-opus-4-5-20251101` to `claude-opus-4-6` across various files, including documentation and code references. - Updated the SDK to support adaptive thinking for Opus 4.6, allowing the model to determine its own reasoning depth. - Enhanced the thinking level options to include 'adaptive' and adjusted related components to reflect this change. - Updated tests to ensure compatibility with the new model and its features. These changes improve the model's capabilities and user experience by leveraging adaptive reasoning.
This commit is contained in:
@@ -161,7 +161,7 @@ Use `resolveModelString()` from `@automaker/model-resolver` to convert model ali
|
|||||||
|
|
||||||
- `haiku` → `claude-haiku-4-5`
|
- `haiku` → `claude-haiku-4-5`
|
||||||
- `sonnet` → `claude-sonnet-4-20250514`
|
- `sonnet` → `claude-sonnet-4-20250514`
|
||||||
- `opus` → `claude-opus-4-5-20251101`
|
- `opus` → `claude-opus-4-6`
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
"test:unit": "vitest run tests/unit"
|
"test:unit": "vitest run tests/unit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anthropic-ai/claude-agent-sdk": "0.1.76",
|
"@anthropic-ai/claude-agent-sdk": "0.2.32",
|
||||||
"@automaker/dependency-resolver": "1.0.0",
|
"@automaker/dependency-resolver": "1.0.0",
|
||||||
"@automaker/git-utils": "1.0.0",
|
"@automaker/git-utils": "1.0.0",
|
||||||
"@automaker/model-resolver": "1.0.0",
|
"@automaker/model-resolver": "1.0.0",
|
||||||
|
|||||||
@@ -253,11 +253,27 @@ function buildMcpOptions(config: CreateSdkOptionsConfig): McpOptions {
|
|||||||
/**
|
/**
|
||||||
* Build thinking options for SDK configuration.
|
* Build thinking options for SDK configuration.
|
||||||
* Converts ThinkingLevel to maxThinkingTokens for the Claude SDK.
|
* Converts ThinkingLevel to maxThinkingTokens for the Claude SDK.
|
||||||
|
* For adaptive thinking (Opus 4.6), omits maxThinkingTokens to let the model
|
||||||
|
* decide its own reasoning depth.
|
||||||
*
|
*
|
||||||
* @param thinkingLevel - The thinking level to convert
|
* @param thinkingLevel - The thinking level to convert
|
||||||
* @returns Object with maxThinkingTokens if thinking is enabled
|
* @returns Object with maxThinkingTokens if thinking is enabled with a budget
|
||||||
*/
|
*/
|
||||||
function buildThinkingOptions(thinkingLevel?: ThinkingLevel): Partial<Options> {
|
function buildThinkingOptions(thinkingLevel?: ThinkingLevel): Partial<Options> {
|
||||||
|
if (!thinkingLevel || thinkingLevel === 'none') {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adaptive thinking (Opus 4.6): don't set maxThinkingTokens
|
||||||
|
// The model will use adaptive thinking by default
|
||||||
|
if (thinkingLevel === 'adaptive') {
|
||||||
|
logger.debug(
|
||||||
|
`buildThinkingOptions: thinkingLevel="adaptive" -> no maxThinkingTokens (model decides)`
|
||||||
|
);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manual budget-based thinking for Haiku/Sonnet
|
||||||
const maxThinkingTokens = getThinkingTokenBudget(thinkingLevel);
|
const maxThinkingTokens = getThinkingTokenBudget(thinkingLevel);
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`buildThinkingOptions: thinkingLevel="${thinkingLevel}" -> maxThinkingTokens=${maxThinkingTokens}`
|
`buildThinkingOptions: thinkingLevel="${thinkingLevel}" -> maxThinkingTokens=${maxThinkingTokens}`
|
||||||
|
|||||||
@@ -219,8 +219,11 @@ export class ClaudeProvider extends BaseProvider {
|
|||||||
// claudeCompatibleProvider takes precedence over claudeApiProfile
|
// claudeCompatibleProvider takes precedence over claudeApiProfile
|
||||||
const providerConfig = claudeCompatibleProvider || claudeApiProfile;
|
const providerConfig = claudeCompatibleProvider || claudeApiProfile;
|
||||||
|
|
||||||
// Convert thinking level to token budget
|
// Build thinking configuration
|
||||||
const maxThinkingTokens = getThinkingTokenBudget(thinkingLevel);
|
// Adaptive thinking (Opus 4.6): don't set maxThinkingTokens, model uses adaptive by default
|
||||||
|
// Manual thinking (Haiku/Sonnet): use budget_tokens
|
||||||
|
const maxThinkingTokens =
|
||||||
|
thinkingLevel === 'adaptive' ? undefined : getThinkingTokenBudget(thinkingLevel);
|
||||||
|
|
||||||
// Build Claude SDK options
|
// Build Claude SDK options
|
||||||
const sdkOptions: Options = {
|
const sdkOptions: Options = {
|
||||||
@@ -349,13 +352,13 @@ export class ClaudeProvider extends BaseProvider {
|
|||||||
getAvailableModels(): ModelDefinition[] {
|
getAvailableModels(): ModelDefinition[] {
|
||||||
const models = [
|
const models = [
|
||||||
{
|
{
|
||||||
id: 'claude-opus-4-5-20251101',
|
id: 'claude-opus-4-6',
|
||||||
name: 'Claude Opus 4.5',
|
name: 'Claude Opus 4.6',
|
||||||
modelString: 'claude-opus-4-5-20251101',
|
modelString: 'claude-opus-4-6',
|
||||||
provider: 'anthropic',
|
provider: 'anthropic',
|
||||||
description: 'Most capable Claude model',
|
description: 'Most capable Claude model with adaptive thinking',
|
||||||
contextWindow: 200000,
|
contextWindow: 200000,
|
||||||
maxOutputTokens: 16000,
|
maxOutputTokens: 128000,
|
||||||
supportsVision: true,
|
supportsVision: true,
|
||||||
supportsTools: true,
|
supportsTools: true,
|
||||||
tier: 'premium' as const,
|
tier: 'premium' as const,
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export class ProviderFactory {
|
|||||||
/**
|
/**
|
||||||
* Get the appropriate provider for a given model ID
|
* Get the appropriate provider for a given model ID
|
||||||
*
|
*
|
||||||
* @param modelId Model identifier (e.g., "claude-opus-4-5-20251101", "cursor-gpt-4o", "cursor-auto")
|
* @param modelId Model identifier (e.g., "claude-opus-4-6", "cursor-gpt-4o", "cursor-auto")
|
||||||
* @param options Optional settings
|
* @param options Optional settings
|
||||||
* @param options.throwOnDisconnected Throw error if provider is disconnected (default: true)
|
* @param options.throwOnDisconnected Throw error if provider is disconnected (default: true)
|
||||||
* @returns Provider instance for the model
|
* @returns Provider instance for the model
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ describe('model-resolver.ts', () => {
|
|||||||
|
|
||||||
it("should resolve 'opus' alias to full model string", () => {
|
it("should resolve 'opus' alias to full model string", () => {
|
||||||
const result = resolveModelString('opus');
|
const result = resolveModelString('opus');
|
||||||
expect(result).toBe('claude-opus-4-5-20251101');
|
expect(result).toBe('claude-opus-4-6');
|
||||||
expect(consoleSpy.log).toHaveBeenCalledWith(
|
expect(consoleSpy.log).toHaveBeenCalledWith(
|
||||||
expect.stringContaining('Migrated legacy ID: "opus" -> "claude-opus"')
|
expect.stringContaining('Migrated legacy ID: "opus" -> "claude-opus"')
|
||||||
);
|
);
|
||||||
@@ -117,7 +117,7 @@ describe('model-resolver.ts', () => {
|
|||||||
describe('getEffectiveModel', () => {
|
describe('getEffectiveModel', () => {
|
||||||
it('should prioritize explicit model over session and default', () => {
|
it('should prioritize explicit model over session and default', () => {
|
||||||
const result = getEffectiveModel('opus', 'haiku', 'gpt-5.2');
|
const result = getEffectiveModel('opus', 'haiku', 'gpt-5.2');
|
||||||
expect(result).toBe('claude-opus-4-5-20251101');
|
expect(result).toBe('claude-opus-4-6');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use session model when explicit is not provided', () => {
|
it('should use session model when explicit is not provided', () => {
|
||||||
|
|||||||
@@ -491,5 +491,29 @@ describe('sdk-options.ts', () => {
|
|||||||
expect(options.maxThinkingTokens).toBeUndefined();
|
expect(options.maxThinkingTokens).toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('adaptive thinking for Opus 4.6', () => {
|
||||||
|
it('should not set maxThinkingTokens for adaptive thinking (model decides)', async () => {
|
||||||
|
const { createAutoModeOptions } = await import('@/lib/sdk-options.js');
|
||||||
|
|
||||||
|
const options = createAutoModeOptions({
|
||||||
|
cwd: '/test/path',
|
||||||
|
thinkingLevel: 'adaptive',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(options.maxThinkingTokens).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not include maxThinkingTokens when thinkingLevel is "none"', async () => {
|
||||||
|
const { createAutoModeOptions } = await import('@/lib/sdk-options.js');
|
||||||
|
|
||||||
|
const options = createAutoModeOptions({
|
||||||
|
cwd: '/test/path',
|
||||||
|
thinkingLevel: 'none',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(options.maxThinkingTokens).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ describe('claude-provider.ts', () => {
|
|||||||
|
|
||||||
const generator = provider.executeQuery({
|
const generator = provider.executeQuery({
|
||||||
prompt: 'Hello',
|
prompt: 'Hello',
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/test',
|
cwd: '/test',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ describe('claude-provider.ts', () => {
|
|||||||
|
|
||||||
const generator = provider.executeQuery({
|
const generator = provider.executeQuery({
|
||||||
prompt: 'Test prompt',
|
prompt: 'Test prompt',
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/test/dir',
|
cwd: '/test/dir',
|
||||||
systemPrompt: 'You are helpful',
|
systemPrompt: 'You are helpful',
|
||||||
maxTurns: 10,
|
maxTurns: 10,
|
||||||
@@ -71,7 +71,7 @@ describe('claude-provider.ts', () => {
|
|||||||
expect(sdk.query).toHaveBeenCalledWith({
|
expect(sdk.query).toHaveBeenCalledWith({
|
||||||
prompt: 'Test prompt',
|
prompt: 'Test prompt',
|
||||||
options: expect.objectContaining({
|
options: expect.objectContaining({
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
systemPrompt: 'You are helpful',
|
systemPrompt: 'You are helpful',
|
||||||
maxTurns: 10,
|
maxTurns: 10,
|
||||||
cwd: '/test/dir',
|
cwd: '/test/dir',
|
||||||
@@ -91,7 +91,7 @@ describe('claude-provider.ts', () => {
|
|||||||
|
|
||||||
const generator = provider.executeQuery({
|
const generator = provider.executeQuery({
|
||||||
prompt: 'Test',
|
prompt: 'Test',
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/test',
|
cwd: '/test',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ describe('claude-provider.ts', () => {
|
|||||||
|
|
||||||
const generator = provider.executeQuery({
|
const generator = provider.executeQuery({
|
||||||
prompt: 'Test',
|
prompt: 'Test',
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/test',
|
cwd: '/test',
|
||||||
abortController,
|
abortController,
|
||||||
});
|
});
|
||||||
@@ -145,7 +145,7 @@ describe('claude-provider.ts', () => {
|
|||||||
|
|
||||||
const generator = provider.executeQuery({
|
const generator = provider.executeQuery({
|
||||||
prompt: 'Current message',
|
prompt: 'Current message',
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/test',
|
cwd: '/test',
|
||||||
conversationHistory,
|
conversationHistory,
|
||||||
sdkSessionId: 'test-session-id',
|
sdkSessionId: 'test-session-id',
|
||||||
@@ -176,7 +176,7 @@ describe('claude-provider.ts', () => {
|
|||||||
|
|
||||||
const generator = provider.executeQuery({
|
const generator = provider.executeQuery({
|
||||||
prompt: arrayPrompt as any,
|
prompt: arrayPrompt as any,
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/test',
|
cwd: '/test',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ describe('claude-provider.ts', () => {
|
|||||||
|
|
||||||
const generator = provider.executeQuery({
|
const generator = provider.executeQuery({
|
||||||
prompt: 'Test',
|
prompt: 'Test',
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/test',
|
cwd: '/test',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ describe('claude-provider.ts', () => {
|
|||||||
|
|
||||||
const generator = provider.executeQuery({
|
const generator = provider.executeQuery({
|
||||||
prompt: 'Test',
|
prompt: 'Test',
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/test',
|
cwd: '/test',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -286,7 +286,7 @@ describe('claude-provider.ts', () => {
|
|||||||
|
|
||||||
const generator = provider.executeQuery({
|
const generator = provider.executeQuery({
|
||||||
prompt: 'Test',
|
prompt: 'Test',
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/test',
|
cwd: '/test',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -313,7 +313,7 @@ describe('claude-provider.ts', () => {
|
|||||||
|
|
||||||
const generator = provider.executeQuery({
|
const generator = provider.executeQuery({
|
||||||
prompt: 'Test',
|
prompt: 'Test',
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/test',
|
cwd: '/test',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -341,7 +341,7 @@ describe('claude-provider.ts', () => {
|
|||||||
|
|
||||||
const generator = provider.executeQuery({
|
const generator = provider.executeQuery({
|
||||||
prompt: 'Test',
|
prompt: 'Test',
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/test',
|
cwd: '/test',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -366,12 +366,12 @@ describe('claude-provider.ts', () => {
|
|||||||
expect(models).toHaveLength(4);
|
expect(models).toHaveLength(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should include Claude Opus 4.5', () => {
|
it('should include Claude Opus 4.6', () => {
|
||||||
const models = provider.getAvailableModels();
|
const models = provider.getAvailableModels();
|
||||||
|
|
||||||
const opus = models.find((m) => m.id === 'claude-opus-4-5-20251101');
|
const opus = models.find((m) => m.id === 'claude-opus-4-6');
|
||||||
expect(opus).toBeDefined();
|
expect(opus).toBeDefined();
|
||||||
expect(opus?.name).toBe('Claude Opus 4.5');
|
expect(opus?.name).toBe('Claude Opus 4.6');
|
||||||
expect(opus?.provider).toBe('anthropic');
|
expect(opus?.provider).toBe('anthropic');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -400,7 +400,7 @@ describe('claude-provider.ts', () => {
|
|||||||
it('should mark Opus as default', () => {
|
it('should mark Opus as default', () => {
|
||||||
const models = provider.getAvailableModels();
|
const models = provider.getAvailableModels();
|
||||||
|
|
||||||
const opus = models.find((m) => m.id === 'claude-opus-4-5-20251101');
|
const opus = models.find((m) => m.id === 'claude-opus-4-6');
|
||||||
expect(opus?.default).toBe(true);
|
expect(opus?.default).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ describe('provider-factory.ts', () => {
|
|||||||
|
|
||||||
describe('getProviderForModel', () => {
|
describe('getProviderForModel', () => {
|
||||||
describe('Claude models (claude-* prefix)', () => {
|
describe('Claude models (claude-* prefix)', () => {
|
||||||
it('should return ClaudeProvider for claude-opus-4-5-20251101', () => {
|
it('should return ClaudeProvider for claude-opus-4-6', () => {
|
||||||
const provider = ProviderFactory.getProviderForModel('claude-opus-4-5-20251101');
|
const provider = ProviderFactory.getProviderForModel('claude-opus-4-6');
|
||||||
expect(provider).toBeInstanceOf(ClaudeProvider);
|
expect(provider).toBeInstanceOf(ClaudeProvider);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ describe('provider-factory.ts', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be case-insensitive for claude models', () => {
|
it('should be case-insensitive for claude models', () => {
|
||||||
const provider = ProviderFactory.getProviderForModel('CLAUDE-OPUS-4-5-20251101');
|
const provider = ProviderFactory.getProviderForModel('CLAUDE-OPUS-4-6');
|
||||||
expect(provider).toBeInstanceOf(ClaudeProvider);
|
expect(provider).toBeInstanceOf(ClaudeProvider);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ The agent is configured with:
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
{
|
{
|
||||||
model: "claude-opus-4-5-20251101",
|
model: "claude-opus-4-6",
|
||||||
maxTurns: 20,
|
maxTurns: 20,
|
||||||
cwd: workingDirectory,
|
cwd: workingDirectory,
|
||||||
allowedTools: [
|
allowedTools: [
|
||||||
|
|||||||
@@ -264,7 +264,21 @@ export function AddFeatureDialog({
|
|||||||
}, [planningMode]);
|
}, [planningMode]);
|
||||||
|
|
||||||
const handleModelChange = (entry: PhaseModelEntry) => {
|
const handleModelChange = (entry: PhaseModelEntry) => {
|
||||||
setModelEntry(entry);
|
// Normalize thinking level when switching between adaptive and non-adaptive models
|
||||||
|
const isNewModelAdaptive =
|
||||||
|
entry.model === 'claude-opus' ||
|
||||||
|
(typeof entry.model === 'string' && entry.model.includes('opus-4-6'));
|
||||||
|
const currentLevel = entry.thinkingLevel || 'none';
|
||||||
|
|
||||||
|
if (isNewModelAdaptive && currentLevel !== 'none' && currentLevel !== 'adaptive') {
|
||||||
|
// Switching TO Opus 4.6 with a manual level -> auto-switch to 'adaptive'
|
||||||
|
setModelEntry({ ...entry, thinkingLevel: 'adaptive' });
|
||||||
|
} else if (!isNewModelAdaptive && currentLevel === 'adaptive') {
|
||||||
|
// Switching FROM Opus 4.6 with adaptive -> auto-switch to 'high'
|
||||||
|
setModelEntry({ ...entry, thinkingLevel: 'high' });
|
||||||
|
} else {
|
||||||
|
setModelEntry(entry);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildFeatureData = (): FeatureData | null => {
|
const buildFeatureData = (): FeatureData | null => {
|
||||||
|
|||||||
@@ -167,7 +167,14 @@ export const ALL_MODELS: ModelOption[] = [
|
|||||||
...COPILOT_MODELS,
|
...COPILOT_MODELS,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const THINKING_LEVELS: ThinkingLevel[] = ['none', 'low', 'medium', 'high', 'ultrathink'];
|
export const THINKING_LEVELS: ThinkingLevel[] = [
|
||||||
|
'none',
|
||||||
|
'low',
|
||||||
|
'medium',
|
||||||
|
'high',
|
||||||
|
'ultrathink',
|
||||||
|
'adaptive',
|
||||||
|
];
|
||||||
|
|
||||||
export const THINKING_LEVEL_LABELS: Record<ThinkingLevel, string> = {
|
export const THINKING_LEVEL_LABELS: Record<ThinkingLevel, string> = {
|
||||||
none: 'None',
|
none: 'None',
|
||||||
@@ -175,6 +182,7 @@ export const THINKING_LEVEL_LABELS: Record<ThinkingLevel, string> = {
|
|||||||
medium: 'Med',
|
medium: 'Med',
|
||||||
high: 'High',
|
high: 'High',
|
||||||
ultrathink: 'Ultra',
|
ultrathink: 'Ultra',
|
||||||
|
adaptive: 'Adaptive',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,19 +2,25 @@ import { Label } from '@/components/ui/label';
|
|||||||
import { Brain } from 'lucide-react';
|
import { Brain } from 'lucide-react';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { ThinkingLevel } from '@/store/app-store';
|
import { ThinkingLevel } from '@/store/app-store';
|
||||||
import { THINKING_LEVELS, THINKING_LEVEL_LABELS } from './model-constants';
|
import { THINKING_LEVEL_LABELS } from './model-constants';
|
||||||
|
import { getThinkingLevelsForModel } from '@automaker/types';
|
||||||
|
|
||||||
interface ThinkingLevelSelectorProps {
|
interface ThinkingLevelSelectorProps {
|
||||||
selectedLevel: ThinkingLevel;
|
selectedLevel: ThinkingLevel;
|
||||||
onLevelSelect: (level: ThinkingLevel) => void;
|
onLevelSelect: (level: ThinkingLevel) => void;
|
||||||
testIdPrefix?: string;
|
testIdPrefix?: string;
|
||||||
|
/** Optional model ID to filter available thinking levels (e.g., Opus 4.6 only shows None/Adaptive) */
|
||||||
|
model?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ThinkingLevelSelector({
|
export function ThinkingLevelSelector({
|
||||||
selectedLevel,
|
selectedLevel,
|
||||||
onLevelSelect,
|
onLevelSelect,
|
||||||
testIdPrefix = 'thinking-level',
|
testIdPrefix = 'thinking-level',
|
||||||
|
model,
|
||||||
}: ThinkingLevelSelectorProps) {
|
}: ThinkingLevelSelectorProps) {
|
||||||
|
const levels = model ? getThinkingLevelsForModel(model) : getThinkingLevelsForModel('');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2 pt-2 border-t border-border">
|
<div className="space-y-2 pt-2 border-t border-border">
|
||||||
<Label className="flex items-center gap-2 text-sm">
|
<Label className="flex items-center gap-2 text-sm">
|
||||||
@@ -22,7 +28,7 @@ export function ThinkingLevelSelector({
|
|||||||
Thinking Level
|
Thinking Level
|
||||||
</Label>
|
</Label>
|
||||||
<div className="flex gap-2 flex-wrap">
|
<div className="flex gap-2 flex-wrap">
|
||||||
{THINKING_LEVELS.map((level) => (
|
{levels.map((level) => (
|
||||||
<button
|
<button
|
||||||
key={level}
|
key={level}
|
||||||
type="button"
|
type="button"
|
||||||
@@ -40,7 +46,9 @@ export function ThinkingLevelSelector({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
Higher levels give more time to reason through complex problems.
|
{model && getThinkingLevelsForModel(model).includes('adaptive')
|
||||||
|
? 'Adaptive thinking lets the model decide how much reasoning to use.'
|
||||||
|
: 'Higher levels give more time to reason through complex problems.'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
isGroupSelected,
|
isGroupSelected,
|
||||||
getSelectedVariant,
|
getSelectedVariant,
|
||||||
codexModelHasThinking,
|
codexModelHasThinking,
|
||||||
|
getThinkingLevelsForModel,
|
||||||
} from '@automaker/types';
|
} from '@automaker/types';
|
||||||
import {
|
import {
|
||||||
CLAUDE_MODELS,
|
CLAUDE_MODELS,
|
||||||
@@ -28,7 +29,6 @@ import {
|
|||||||
OPENCODE_MODELS,
|
OPENCODE_MODELS,
|
||||||
GEMINI_MODELS,
|
GEMINI_MODELS,
|
||||||
COPILOT_MODELS,
|
COPILOT_MODELS,
|
||||||
THINKING_LEVELS,
|
|
||||||
THINKING_LEVEL_LABELS,
|
THINKING_LEVEL_LABELS,
|
||||||
REASONING_EFFORT_LEVELS,
|
REASONING_EFFORT_LEVELS,
|
||||||
REASONING_EFFORT_LABELS,
|
REASONING_EFFORT_LABELS,
|
||||||
@@ -1296,7 +1296,9 @@ export function PhaseModelSelector({
|
|||||||
<div className="px-2 py-1 text-xs font-medium text-muted-foreground">
|
<div className="px-2 py-1 text-xs font-medium text-muted-foreground">
|
||||||
Thinking Level
|
Thinking Level
|
||||||
</div>
|
</div>
|
||||||
{THINKING_LEVELS.map((level) => (
|
{getThinkingLevelsForModel(
|
||||||
|
model.mapsToClaudeModel === 'opus' ? 'claude-opus' : ''
|
||||||
|
).map((level) => (
|
||||||
<button
|
<button
|
||||||
key={level}
|
key={level}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -1322,6 +1324,7 @@ export function PhaseModelSelector({
|
|||||||
{level === 'medium' && 'Moderate reasoning (10k tokens)'}
|
{level === 'medium' && 'Moderate reasoning (10k tokens)'}
|
||||||
{level === 'high' && 'Deep reasoning (16k tokens)'}
|
{level === 'high' && 'Deep reasoning (16k tokens)'}
|
||||||
{level === 'ultrathink' && 'Maximum reasoning (32k tokens)'}
|
{level === 'ultrathink' && 'Maximum reasoning (32k tokens)'}
|
||||||
|
{level === 'adaptive' && 'Model decides reasoning depth'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{isSelected && currentThinking === level && (
|
{isSelected && currentThinking === level && (
|
||||||
@@ -1402,7 +1405,9 @@ export function PhaseModelSelector({
|
|||||||
<div className="px-2 py-1.5 text-xs font-medium text-muted-foreground border-b border-border/50 mb-1">
|
<div className="px-2 py-1.5 text-xs font-medium text-muted-foreground border-b border-border/50 mb-1">
|
||||||
Thinking Level
|
Thinking Level
|
||||||
</div>
|
</div>
|
||||||
{THINKING_LEVELS.map((level) => (
|
{getThinkingLevelsForModel(
|
||||||
|
model.mapsToClaudeModel === 'opus' ? 'claude-opus' : ''
|
||||||
|
).map((level) => (
|
||||||
<button
|
<button
|
||||||
key={level}
|
key={level}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -1428,6 +1433,7 @@ export function PhaseModelSelector({
|
|||||||
{level === 'medium' && 'Moderate reasoning (10k tokens)'}
|
{level === 'medium' && 'Moderate reasoning (10k tokens)'}
|
||||||
{level === 'high' && 'Deep reasoning (16k tokens)'}
|
{level === 'high' && 'Deep reasoning (16k tokens)'}
|
||||||
{level === 'ultrathink' && 'Maximum reasoning (32k tokens)'}
|
{level === 'ultrathink' && 'Maximum reasoning (32k tokens)'}
|
||||||
|
{level === 'adaptive' && 'Model decides reasoning depth'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{isSelected && currentThinking === level && (
|
{isSelected && currentThinking === level && (
|
||||||
@@ -1564,7 +1570,7 @@ export function PhaseModelSelector({
|
|||||||
<div className="px-2 py-1 text-xs font-medium text-muted-foreground">
|
<div className="px-2 py-1 text-xs font-medium text-muted-foreground">
|
||||||
Thinking Level
|
Thinking Level
|
||||||
</div>
|
</div>
|
||||||
{THINKING_LEVELS.map((level) => (
|
{getThinkingLevelsForModel(model.id).map((level) => (
|
||||||
<button
|
<button
|
||||||
key={level}
|
key={level}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -1589,6 +1595,7 @@ export function PhaseModelSelector({
|
|||||||
{level === 'medium' && 'Moderate reasoning (10k tokens)'}
|
{level === 'medium' && 'Moderate reasoning (10k tokens)'}
|
||||||
{level === 'high' && 'Deep reasoning (16k tokens)'}
|
{level === 'high' && 'Deep reasoning (16k tokens)'}
|
||||||
{level === 'ultrathink' && 'Maximum reasoning (32k tokens)'}
|
{level === 'ultrathink' && 'Maximum reasoning (32k tokens)'}
|
||||||
|
{level === 'adaptive' && 'Model decides reasoning depth'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{isSelected && currentThinking === level && (
|
{isSelected && currentThinking === level && (
|
||||||
@@ -1685,7 +1692,7 @@ export function PhaseModelSelector({
|
|||||||
<div className="px-2 py-1.5 text-xs font-medium text-muted-foreground border-b border-border/50 mb-1">
|
<div className="px-2 py-1.5 text-xs font-medium text-muted-foreground border-b border-border/50 mb-1">
|
||||||
Thinking Level
|
Thinking Level
|
||||||
</div>
|
</div>
|
||||||
{THINKING_LEVELS.map((level) => (
|
{getThinkingLevelsForModel(model.id).map((level) => (
|
||||||
<button
|
<button
|
||||||
key={level}
|
key={level}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -1710,6 +1717,7 @@ export function PhaseModelSelector({
|
|||||||
{level === 'medium' && 'Moderate reasoning (10k tokens)'}
|
{level === 'medium' && 'Moderate reasoning (10k tokens)'}
|
||||||
{level === 'high' && 'Deep reasoning (16k tokens)'}
|
{level === 'high' && 'Deep reasoning (16k tokens)'}
|
||||||
{level === 'ultrathink' && 'Maximum reasoning (32k tokens)'}
|
{level === 'ultrathink' && 'Maximum reasoning (32k tokens)'}
|
||||||
|
{level === 'adaptive' && 'Model decides reasoning depth'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{isSelected && currentThinking === level && (
|
{isSelected && currentThinking === level && (
|
||||||
|
|||||||
@@ -27,13 +27,14 @@ export interface AgentTaskInfo {
|
|||||||
/**
|
/**
|
||||||
* Default model used by the feature executor
|
* Default model used by the feature executor
|
||||||
*/
|
*/
|
||||||
export const DEFAULT_MODEL = 'claude-opus-4-5-20251101';
|
export const DEFAULT_MODEL = 'claude-opus-4-6';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a model name for display
|
* Formats a model name for display
|
||||||
*/
|
*/
|
||||||
export function formatModelName(model: string): string {
|
export function formatModelName(model: string): string {
|
||||||
// Claude models
|
// Claude models
|
||||||
|
if (model.includes('opus-4-6')) return 'Opus 4.6';
|
||||||
if (model.includes('opus')) return 'Opus 4.5';
|
if (model.includes('opus')) return 'Opus 4.5';
|
||||||
if (model.includes('sonnet')) return 'Sonnet 4.5';
|
if (model.includes('sonnet')) return 'Sonnet 4.5';
|
||||||
if (model.includes('haiku')) return 'Haiku 4.5';
|
if (model.includes('haiku')) return 'Haiku 4.5';
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ const modelId = resolveModelString('sonnet'); // → 'claude-sonnet-4-20250514'
|
|||||||
|
|
||||||
- `haiku` → `claude-haiku-4-5` (fast, simple tasks)
|
- `haiku` → `claude-haiku-4-5` (fast, simple tasks)
|
||||||
- `sonnet` → `claude-sonnet-4-20250514` (balanced, recommended)
|
- `sonnet` → `claude-sonnet-4-20250514` (balanced, recommended)
|
||||||
- `opus` → `claude-opus-4-5-20251101` (maximum capability)
|
- `opus` → `claude-opus-4-6` (maximum capability)
|
||||||
|
|
||||||
### @automaker/dependency-resolver
|
### @automaker/dependency-resolver
|
||||||
|
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ Uses `@anthropic-ai/claude-agent-sdk` for direct SDK integration.
|
|||||||
|
|
||||||
Routes models that:
|
Routes models that:
|
||||||
|
|
||||||
- Start with `"claude-"` (e.g., `"claude-opus-4-5-20251101"`)
|
- Start with `"claude-"` (e.g., `"claude-opus-4-6"`)
|
||||||
- Are Claude aliases: `"opus"`, `"sonnet"`, `"haiku"`
|
- Are Claude aliases: `"opus"`, `"sonnet"`, `"haiku"`
|
||||||
|
|
||||||
#### Authentication
|
#### Authentication
|
||||||
@@ -191,7 +191,7 @@ const provider = new ClaudeProvider();
|
|||||||
|
|
||||||
const stream = provider.executeQuery({
|
const stream = provider.executeQuery({
|
||||||
prompt: 'What is 2+2?',
|
prompt: 'What is 2+2?',
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
cwd: '/project/path',
|
cwd: '/project/path',
|
||||||
systemPrompt: 'You are a helpful assistant.',
|
systemPrompt: 'You are a helpful assistant.',
|
||||||
maxTurns: 20,
|
maxTurns: 20,
|
||||||
@@ -701,7 +701,7 @@ Test provider interaction with services:
|
|||||||
```typescript
|
```typescript
|
||||||
describe('Provider Integration', () => {
|
describe('Provider Integration', () => {
|
||||||
it('should work with AgentService', async () => {
|
it('should work with AgentService', async () => {
|
||||||
const provider = ProviderFactory.getProviderForModel('claude-opus-4-5-20251101');
|
const provider = ProviderFactory.getProviderForModel('claude-opus-4-6');
|
||||||
|
|
||||||
// Test full workflow
|
// Test full workflow
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ Model alias mapping for Claude models.
|
|||||||
export const CLAUDE_MODEL_MAP: Record<string, string> = {
|
export const CLAUDE_MODEL_MAP: Record<string, string> = {
|
||||||
haiku: 'claude-haiku-4-5',
|
haiku: 'claude-haiku-4-5',
|
||||||
sonnet: 'claude-sonnet-4-20250514',
|
sonnet: 'claude-sonnet-4-20250514',
|
||||||
opus: 'claude-opus-4-5-20251101',
|
opus: 'claude-opus-4-6',
|
||||||
} as const;
|
} as const;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ Default models per provider.
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
export const DEFAULT_MODELS = {
|
export const DEFAULT_MODELS = {
|
||||||
claude: 'claude-opus-4-5-20251101',
|
claude: 'claude-opus-4-6',
|
||||||
openai: 'gpt-5.2',
|
openai: 'gpt-5.2',
|
||||||
} as const;
|
} as const;
|
||||||
```
|
```
|
||||||
@@ -248,8 +248,8 @@ Resolve a model key/alias to a full model string.
|
|||||||
import { resolveModelString, DEFAULT_MODELS } from '../lib/model-resolver.js';
|
import { resolveModelString, DEFAULT_MODELS } from '../lib/model-resolver.js';
|
||||||
|
|
||||||
resolveModelString('opus');
|
resolveModelString('opus');
|
||||||
// Returns: "claude-opus-4-5-20251101"
|
// Returns: "claude-opus-4-6"
|
||||||
// Logs: "[ModelResolver] Resolved model alias: "opus" -> "claude-opus-4-5-20251101""
|
// Logs: "[ModelResolver] Resolved model alias: "opus" -> "claude-opus-4-6""
|
||||||
|
|
||||||
resolveModelString('gpt-5.2');
|
resolveModelString('gpt-5.2');
|
||||||
// Returns: "gpt-5.2"
|
// Returns: "gpt-5.2"
|
||||||
@@ -260,8 +260,8 @@ resolveModelString('claude-sonnet-4-20250514');
|
|||||||
// Logs: "[ModelResolver] Using full Claude model string: claude-sonnet-4-20250514"
|
// Logs: "[ModelResolver] Using full Claude model string: claude-sonnet-4-20250514"
|
||||||
|
|
||||||
resolveModelString('invalid-model');
|
resolveModelString('invalid-model');
|
||||||
// Returns: "claude-opus-4-5-20251101"
|
// Returns: "claude-opus-4-6"
|
||||||
// Logs: "[ModelResolver] Unknown model key "invalid-model", using default: "claude-opus-4-5-20251101""
|
// Logs: "[ModelResolver] Unknown model key "invalid-model", using default: "claude-opus-4-6""
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -30,15 +30,15 @@ const model2 = resolveModelString('haiku');
|
|||||||
// Returns: 'claude-haiku-4-5'
|
// Returns: 'claude-haiku-4-5'
|
||||||
|
|
||||||
const model3 = resolveModelString('opus');
|
const model3 = resolveModelString('opus');
|
||||||
// Returns: 'claude-opus-4-5-20251101'
|
// Returns: 'claude-opus-4-6'
|
||||||
|
|
||||||
// Use with custom default
|
// Use with custom default
|
||||||
const model4 = resolveModelString(undefined, 'claude-sonnet-4-20250514');
|
const model4 = resolveModelString(undefined, 'claude-sonnet-4-20250514');
|
||||||
// Returns: 'claude-sonnet-4-20250514' (default)
|
// Returns: 'claude-sonnet-4-20250514' (default)
|
||||||
|
|
||||||
// Direct model ID passthrough
|
// Direct model ID passthrough
|
||||||
const model5 = resolveModelString('claude-opus-4-5-20251101');
|
const model5 = resolveModelString('claude-opus-4-6');
|
||||||
// Returns: 'claude-opus-4-5-20251101' (unchanged)
|
// Returns: 'claude-opus-4-6' (unchanged)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Get Effective Model
|
### Get Effective Model
|
||||||
@@ -72,7 +72,7 @@ console.log(DEFAULT_MODELS.chat); // 'claude-sonnet-4-20250514'
|
|||||||
// Model alias mappings
|
// Model alias mappings
|
||||||
console.log(CLAUDE_MODEL_MAP.haiku); // 'claude-haiku-4-5'
|
console.log(CLAUDE_MODEL_MAP.haiku); // 'claude-haiku-4-5'
|
||||||
console.log(CLAUDE_MODEL_MAP.sonnet); // 'claude-sonnet-4-20250514'
|
console.log(CLAUDE_MODEL_MAP.sonnet); // 'claude-sonnet-4-20250514'
|
||||||
console.log(CLAUDE_MODEL_MAP.opus); // 'claude-opus-4-5-20251101'
|
console.log(CLAUDE_MODEL_MAP.opus); // 'claude-opus-4-6'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage Example
|
## Usage Example
|
||||||
@@ -103,7 +103,7 @@ const feature: Feature = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
prepareFeatureExecution(feature);
|
prepareFeatureExecution(feature);
|
||||||
// Output: Executing feature with model: claude-opus-4-5-20251101
|
// Output: Executing feature with model: claude-opus-4-6
|
||||||
```
|
```
|
||||||
|
|
||||||
## Supported Models
|
## Supported Models
|
||||||
@@ -112,7 +112,7 @@ prepareFeatureExecution(feature);
|
|||||||
|
|
||||||
- `haiku` → `claude-haiku-4-5`
|
- `haiku` → `claude-haiku-4-5`
|
||||||
- `sonnet` → `claude-sonnet-4-20250514`
|
- `sonnet` → `claude-sonnet-4-20250514`
|
||||||
- `opus` → `claude-opus-4-5-20251101`
|
- `opus` → `claude-opus-4-6`
|
||||||
|
|
||||||
### Model Selection Guide
|
### Model Selection Guide
|
||||||
|
|
||||||
|
|||||||
@@ -484,12 +484,12 @@ describe('model-resolver', () => {
|
|||||||
|
|
||||||
it('should handle full Claude model string in entry', () => {
|
it('should handle full Claude model string in entry', () => {
|
||||||
const entry: PhaseModelEntry = {
|
const entry: PhaseModelEntry = {
|
||||||
model: 'claude-opus-4-5-20251101',
|
model: 'claude-opus-4-6',
|
||||||
thinkingLevel: 'high',
|
thinkingLevel: 'high',
|
||||||
};
|
};
|
||||||
const result = resolvePhaseModel(entry);
|
const result = resolvePhaseModel(entry);
|
||||||
|
|
||||||
expect(result.model).toBe('claude-opus-4-5-20251101');
|
expect(result.model).toBe('claude-opus-4-6');
|
||||||
expect(result.thinkingLevel).toBe('high');
|
expect(result.thinkingLevel).toBe('high');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -196,6 +196,8 @@ export {
|
|||||||
PROJECT_SETTINGS_VERSION,
|
PROJECT_SETTINGS_VERSION,
|
||||||
THINKING_TOKEN_BUDGET,
|
THINKING_TOKEN_BUDGET,
|
||||||
getThinkingTokenBudget,
|
getThinkingTokenBudget,
|
||||||
|
isAdaptiveThinkingModel,
|
||||||
|
getThinkingLevelsForModel,
|
||||||
// Event hook constants
|
// Event hook constants
|
||||||
EVENT_HOOK_TRIGGER_LABELS,
|
EVENT_HOOK_TRIGGER_LABELS,
|
||||||
// Claude-compatible provider templates (new)
|
// Claude-compatible provider templates (new)
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ export const THINKING_LEVELS: ThinkingLevelOption[] = [
|
|||||||
{ id: 'medium', label: 'Medium' },
|
{ id: 'medium', label: 'Medium' },
|
||||||
{ id: 'high', label: 'High' },
|
{ id: 'high', label: 'High' },
|
||||||
{ id: 'ultrathink', label: 'Ultrathink' },
|
{ id: 'ultrathink', label: 'Ultrathink' },
|
||||||
|
{ id: 'adaptive', label: 'Adaptive' },
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -162,6 +163,7 @@ export const THINKING_LEVEL_LABELS: Record<ThinkingLevel, string> = {
|
|||||||
medium: 'Med',
|
medium: 'Med',
|
||||||
high: 'High',
|
high: 'High',
|
||||||
ultrathink: 'Ultra',
|
ultrathink: 'Ultra',
|
||||||
|
adaptive: 'Adaptive',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export type ClaudeCanonicalId = 'claude-haiku' | 'claude-sonnet' | 'claude-opus'
|
|||||||
export const CLAUDE_CANONICAL_MAP: Record<ClaudeCanonicalId, string> = {
|
export const CLAUDE_CANONICAL_MAP: Record<ClaudeCanonicalId, string> = {
|
||||||
'claude-haiku': 'claude-haiku-4-5-20251001',
|
'claude-haiku': 'claude-haiku-4-5-20251001',
|
||||||
'claude-sonnet': 'claude-sonnet-4-5-20250929',
|
'claude-sonnet': 'claude-sonnet-4-5-20250929',
|
||||||
'claude-opus': 'claude-opus-4-5-20251101',
|
'claude-opus': 'claude-opus-4-6',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,7 +29,7 @@ export const CLAUDE_CANONICAL_MAP: Record<ClaudeCanonicalId, string> = {
|
|||||||
export const CLAUDE_MODEL_MAP: Record<string, string> = {
|
export const CLAUDE_MODEL_MAP: Record<string, string> = {
|
||||||
haiku: 'claude-haiku-4-5-20251001',
|
haiku: 'claude-haiku-4-5-20251001',
|
||||||
sonnet: 'claude-sonnet-4-5-20250929',
|
sonnet: 'claude-sonnet-4-5-20250929',
|
||||||
opus: 'claude-opus-4-5-20251101',
|
opus: 'claude-opus-4-6',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,7 +99,7 @@ export function getAllCodexModelIds(): CodexModelId[] {
|
|||||||
* Uses canonical prefixed IDs for consistent routing.
|
* Uses canonical prefixed IDs for consistent routing.
|
||||||
*/
|
*/
|
||||||
export const DEFAULT_MODELS = {
|
export const DEFAULT_MODELS = {
|
||||||
claude: 'claude-opus-4-5-20251101',
|
claude: 'claude-opus-4-6',
|
||||||
cursor: 'cursor-auto', // Cursor's recommended default (with prefix)
|
cursor: 'cursor-auto', // Cursor's recommended default (with prefix)
|
||||||
codex: CODEX_MODEL_MAP.gpt52Codex, // GPT-5.2-Codex is the most advanced agentic coding model
|
codex: CODEX_MODEL_MAP.gpt52Codex, // GPT-5.2-Codex is the most advanced agentic coding model
|
||||||
} as const;
|
} as const;
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ export type PlanningMode = 'skip' | 'lite' | 'spec' | 'full';
|
|||||||
export type ServerLogLevel = 'error' | 'warn' | 'info' | 'debug';
|
export type ServerLogLevel = 'error' | 'warn' | 'info' | 'debug';
|
||||||
|
|
||||||
/** ThinkingLevel - Extended thinking levels for Claude models (reasoning intensity) */
|
/** ThinkingLevel - Extended thinking levels for Claude models (reasoning intensity) */
|
||||||
export type ThinkingLevel = 'none' | 'low' | 'medium' | 'high' | 'ultrathink';
|
export type ThinkingLevel = 'none' | 'low' | 'medium' | 'high' | 'ultrathink' | 'adaptive';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SidebarStyle - Sidebar layout style options
|
* SidebarStyle - Sidebar layout style options
|
||||||
@@ -237,6 +237,7 @@ export const THINKING_TOKEN_BUDGET: Record<ThinkingLevel, number | undefined> =
|
|||||||
medium: 10000, // Light reasoning
|
medium: 10000, // Light reasoning
|
||||||
high: 16000, // Complex tasks (recommended starting point)
|
high: 16000, // Complex tasks (recommended starting point)
|
||||||
ultrathink: 32000, // Maximum safe (above this risks timeouts)
|
ultrathink: 32000, // Maximum safe (above this risks timeouts)
|
||||||
|
adaptive: undefined, // Adaptive thinking (Opus 4.6) - SDK handles token allocation
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -247,6 +248,26 @@ export function getThinkingTokenBudget(level: ThinkingLevel | undefined): number
|
|||||||
return THINKING_TOKEN_BUDGET[level];
|
return THINKING_TOKEN_BUDGET[level];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a model uses adaptive thinking (Opus 4.6+)
|
||||||
|
* Adaptive thinking models let the SDK decide token allocation automatically.
|
||||||
|
*/
|
||||||
|
export function isAdaptiveThinkingModel(model: string): boolean {
|
||||||
|
return model.includes('opus-4-6') || model === 'claude-opus';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the available thinking levels for a given model.
|
||||||
|
* - Opus 4.6: Only 'none' and 'adaptive' (SDK handles token allocation)
|
||||||
|
* - Others: Full range of manual thinking levels
|
||||||
|
*/
|
||||||
|
export function getThinkingLevelsForModel(model: string): ThinkingLevel[] {
|
||||||
|
if (isAdaptiveThinkingModel(model)) {
|
||||||
|
return ['none', 'adaptive'];
|
||||||
|
}
|
||||||
|
return ['none', 'low', 'medium', 'high', 'ultrathink'];
|
||||||
|
}
|
||||||
|
|
||||||
/** ModelProvider - AI model provider for credentials and API key management */
|
/** ModelProvider - AI model provider for credentials and API key management */
|
||||||
export type ModelProvider = 'claude' | 'cursor' | 'codex' | 'opencode' | 'gemini' | 'copilot';
|
export type ModelProvider = 'claude' | 'cursor' | 'codex' | 'opencode' | 'gemini' | 'copilot';
|
||||||
|
|
||||||
|
|||||||
10
package-lock.json
generated
10
package-lock.json
generated
@@ -35,7 +35,7 @@
|
|||||||
"version": "0.13.0",
|
"version": "0.13.0",
|
||||||
"license": "SEE LICENSE IN LICENSE",
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anthropic-ai/claude-agent-sdk": "0.1.76",
|
"@anthropic-ai/claude-agent-sdk": "0.2.32",
|
||||||
"@automaker/dependency-resolver": "1.0.0",
|
"@automaker/dependency-resolver": "1.0.0",
|
||||||
"@automaker/git-utils": "1.0.0",
|
"@automaker/git-utils": "1.0.0",
|
||||||
"@automaker/model-resolver": "1.0.0",
|
"@automaker/model-resolver": "1.0.0",
|
||||||
@@ -657,9 +657,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@anthropic-ai/claude-agent-sdk": {
|
"node_modules/@anthropic-ai/claude-agent-sdk": {
|
||||||
"version": "0.1.76",
|
"version": "0.2.32",
|
||||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.1.76.tgz",
|
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.2.32.tgz",
|
||||||
"integrity": "sha512-s7RvpXoFaLXLG7A1cJBAPD8ilwOhhc/12fb5mJXRuD561o4FmPtQ+WRfuy9akMmrFRfLsKv8Ornw3ClGAPL2fw==",
|
"integrity": "sha512-8AtsSx/M9jxd0ihS08eqa7VireTEuwQy0i1+6ZJX93LECT6Svlf47dPJiAm7JB+BhVMmwTfQeS6x1akIcCfvbQ==",
|
||||||
"license": "SEE LICENSE IN README.md",
|
"license": "SEE LICENSE IN README.md",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0"
|
"node": ">=18.0.0"
|
||||||
@@ -675,7 +675,7 @@
|
|||||||
"@img/sharp-win32-x64": "^0.33.5"
|
"@img/sharp-win32-x64": "^0.33.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"zod": "^3.24.1 || ^4.0.0"
|
"zod": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@automaker/dependency-resolver": {
|
"node_modules/@automaker/dependency-resolver": {
|
||||||
|
|||||||
Reference in New Issue
Block a user