mirror of
https://github.com/KeygraphHQ/shannon.git
synced 2026-07-07 21:58:10 +02:00
feat(ai): upgrade to Opus 4.7 with adaptive thinking (#325)
This commit is contained in:
@@ -32,7 +32,10 @@ export async function setup(): Promise<void> {
|
||||
|
||||
const config = await setupProvider(provider as Provider);
|
||||
|
||||
// 2. Save config
|
||||
// 2. Adaptive thinking
|
||||
await maybePromptAdaptiveThinking(config);
|
||||
|
||||
// 3. Save config
|
||||
saveConfig(config);
|
||||
|
||||
const configPath = path.join(SHANNON_HOME, 'config.toml');
|
||||
@@ -80,7 +83,7 @@ async function setupAnthropic(): Promise<ShannonConfig> {
|
||||
'Do you want to change the default models?\n' +
|
||||
' Small - claude-haiku-4-5-20251001\n' +
|
||||
' Medium - claude-sonnet-4-6\n' +
|
||||
' Large - claude-opus-4-6',
|
||||
' Large - claude-opus-4-7',
|
||||
initialValue: false,
|
||||
});
|
||||
if (p.isCancel(customizeModels)) return cancelAndExit();
|
||||
@@ -102,7 +105,7 @@ async function setupAnthropic(): Promise<ShannonConfig> {
|
||||
|
||||
const large = await p.text({
|
||||
message: 'Large model ID',
|
||||
initialValue: 'claude-opus-4-6',
|
||||
initialValue: 'claude-opus-4-7',
|
||||
validate: required('Large model ID is required'),
|
||||
});
|
||||
if (p.isCancel(large)) return cancelAndExit();
|
||||
@@ -140,7 +143,7 @@ async function setupCustomBaseUrl(): Promise<ShannonConfig> {
|
||||
'Do you want to change the default models?\n' +
|
||||
' Small - claude-haiku-4-5-20251001\n' +
|
||||
' Medium - claude-sonnet-4-6\n' +
|
||||
' Large - claude-opus-4-6',
|
||||
' Large - claude-opus-4-7',
|
||||
initialValue: false,
|
||||
});
|
||||
if (p.isCancel(customizeModels)) return cancelAndExit();
|
||||
@@ -162,7 +165,7 @@ async function setupCustomBaseUrl(): Promise<ShannonConfig> {
|
||||
|
||||
const large = await p.text({
|
||||
message: 'Large model ID',
|
||||
initialValue: 'claude-opus-4-6',
|
||||
initialValue: 'claude-opus-4-7',
|
||||
validate: required('Large model ID is required'),
|
||||
});
|
||||
if (p.isCancel(large)) return cancelAndExit();
|
||||
@@ -199,7 +202,7 @@ async function setupBedrock(): Promise<ShannonConfig> {
|
||||
|
||||
const large = await p.text({
|
||||
message: 'Large model ID',
|
||||
placeholder: 'us.anthropic.claude-opus-4-6',
|
||||
placeholder: 'us.anthropic.claude-opus-4-7',
|
||||
validate: required('Large model ID is required'),
|
||||
});
|
||||
if (p.isCancel(large)) return cancelAndExit();
|
||||
@@ -262,7 +265,7 @@ async function setupVertex(): Promise<ShannonConfig> {
|
||||
large: () =>
|
||||
p.text({
|
||||
message: 'Large model ID',
|
||||
placeholder: 'claude-opus-4-6',
|
||||
placeholder: 'claude-opus-4-7',
|
||||
validate: required('Large model ID is required'),
|
||||
}),
|
||||
});
|
||||
@@ -281,6 +284,20 @@ async function setupVertex(): Promise<ShannonConfig> {
|
||||
|
||||
// === Helpers ===
|
||||
|
||||
async function maybePromptAdaptiveThinking(config: ShannonConfig): Promise<void> {
|
||||
const m = config.models;
|
||||
const hasOpus47 = !m || [m.small, m.medium, m.large].some((v) => v && /opus-4-[67]/.test(v));
|
||||
if (!hasOpus47) return;
|
||||
|
||||
const enable = await p.confirm({
|
||||
message: 'Enable adaptive thinking on Opus 4.6/4.7? Claude decides when and how deeply to reason.',
|
||||
initialValue: true,
|
||||
});
|
||||
if (p.isCancel(enable)) return cancelAndExit();
|
||||
|
||||
config.core = { ...config.core, adaptive_thinking: enable };
|
||||
}
|
||||
|
||||
async function promptSecret(message: string): Promise<string> {
|
||||
const value = await p.password({
|
||||
message,
|
||||
|
||||
@@ -18,12 +18,14 @@ interface ConfigMapping {
|
||||
readonly env: string;
|
||||
readonly toml: string;
|
||||
readonly type: TOMLType;
|
||||
readonly boolFormat?: 'numeric' | 'literal';
|
||||
}
|
||||
|
||||
/** Maps every supported env var to its TOML path (section.key) and expected type. */
|
||||
const CONFIG_MAP: readonly ConfigMapping[] = [
|
||||
// Core
|
||||
{ env: 'CLAUDE_CODE_MAX_OUTPUT_TOKENS', toml: 'core.max_tokens', type: 'number' },
|
||||
{ env: 'CLAUDE_ADAPTIVE_THINKING', toml: 'core.adaptive_thinking', type: 'boolean', boolFormat: 'literal' },
|
||||
|
||||
// Anthropic
|
||||
{ env: 'ANTHROPIC_API_KEY', toml: 'anthropic.api_key', type: 'string' },
|
||||
@@ -56,9 +58,9 @@ type TOMLValue = string | number | boolean;
|
||||
type TOMLSection = Record<string, TOMLValue>;
|
||||
type TOMLConfig = Record<string, TOMLSection>;
|
||||
|
||||
/** Read a nested TOML value by dotted path (e.g. "anthropic.api_key"). */
|
||||
function getTomlValue(config: TOMLConfig, path: string): string | undefined {
|
||||
const [section, key] = path.split('.');
|
||||
/** Read a nested TOML value for a given mapping. */
|
||||
function getTomlValue(config: TOMLConfig, mapping: ConfigMapping): string | undefined {
|
||||
const [section, key] = mapping.toml.split('.');
|
||||
if (!section || !key) return undefined;
|
||||
|
||||
const sectionObj = config[section];
|
||||
@@ -67,8 +69,10 @@ function getTomlValue(config: TOMLConfig, path: string): string | undefined {
|
||||
const value = sectionObj[key];
|
||||
if (value === undefined || value === null) return undefined;
|
||||
|
||||
// NOTE: env.ts checks bedrock/vertex via `=== '1'`, so booleans must map to "1"/"0"
|
||||
if (typeof value === 'boolean') return value ? '1' : '0';
|
||||
if (typeof value === 'boolean') {
|
||||
if (mapping.boolFormat === 'literal') return value ? 'true' : 'false';
|
||||
return value ? '1' : '0';
|
||||
}
|
||||
|
||||
return String(value);
|
||||
}
|
||||
@@ -273,7 +277,7 @@ export function resolveConfig(): void {
|
||||
for (const mapping of CONFIG_MAP) {
|
||||
if (process.env[mapping.env]) continue;
|
||||
|
||||
const value = getTomlValue(toml, mapping.toml);
|
||||
const value = getTomlValue(toml, mapping);
|
||||
if (value) {
|
||||
process.env[mapping.env] = value;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { getConfigFile } from '../home.js';
|
||||
// === Types ===
|
||||
|
||||
export interface ShannonConfig {
|
||||
core?: { max_tokens?: number };
|
||||
core?: { max_tokens?: number; adaptive_thinking?: boolean };
|
||||
anthropic?: { api_key?: string; oauth_token?: string };
|
||||
custom_base_url?: { base_url?: string; auth_token?: string };
|
||||
bedrock?: { use?: boolean; region?: string; token?: string };
|
||||
|
||||
@@ -26,6 +26,7 @@ const FORWARD_VARS = [
|
||||
'ANTHROPIC_MEDIUM_MODEL',
|
||||
'ANTHROPIC_LARGE_MODEL',
|
||||
'CLAUDE_CODE_MAX_OUTPUT_TOKENS',
|
||||
'CLAUDE_ADAPTIVE_THINKING',
|
||||
] as const;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user