mirror of
https://github.com/qwibitai/nanoclaw.git
synced 2026-06-04 10:14:47 +08:00
feat(container-config): add per-group model + effort overrides
Allow individual agent groups to opt into different models or effort levels
without changing host-wide defaults. Useful when one group is high-stakes
(opus, high effort) but most are routine (sonnet/haiku, low effort).
container.json gains two optional fields:
- model: alias ("sonnet" | "opus" | "haiku") or full model ID
- effort: "low" | "medium" | "high" | "xhigh" | "max"
Both omitted = SDK default (current behavior). The host plumbs them as
NANOCLAW_MODEL / NANOCLAW_EFFORT env vars at container spawn time; the
agent-runner reads them in providers/index.ts and threads through to the
provider via ProviderOptions. The Claude provider passes them straight to
sdkQuery options.
`effort` is currently typed as `any` because the @anthropic-ai/claude-
agent-sdk type doesn't surface it yet — passing it through still works at
runtime via the SDK's loose option handling. Drop the cast once the SDK
adds an `effort` field to its options type.
This commit is contained in:
@@ -16,6 +16,8 @@ export interface RunnerConfig {
|
||||
agentGroupId: string;
|
||||
maxMessagesPerPrompt: number;
|
||||
mcpServers: Record<string, { command: string; args: string[]; env: Record<string, string> }>;
|
||||
model?: string;
|
||||
effort?: string;
|
||||
}
|
||||
|
||||
const DEFAULT_MAX_MESSAGES = 10;
|
||||
@@ -43,6 +45,8 @@ export function loadConfig(): RunnerConfig {
|
||||
agentGroupId: (raw.agentGroupId as string) || '',
|
||||
maxMessagesPerPrompt: (raw.maxMessagesPerPrompt as number) || DEFAULT_MAX_MESSAGES,
|
||||
mcpServers: (raw.mcpServers as RunnerConfig['mcpServers']) || {},
|
||||
model: (raw.model as string) || undefined,
|
||||
effort: (raw.effort as string) || undefined,
|
||||
};
|
||||
|
||||
return _config;
|
||||
|
||||
@@ -91,6 +91,8 @@ async function main(): Promise<void> {
|
||||
mcpServers,
|
||||
env: { ...process.env },
|
||||
additionalDirectories: additionalDirectories.length > 0 ? additionalDirectories : undefined,
|
||||
model: config.model,
|
||||
effort: config.effort,
|
||||
});
|
||||
|
||||
await runPollLoop({
|
||||
|
||||
@@ -257,11 +257,15 @@ export class ClaudeProvider implements AgentProvider {
|
||||
private mcpServers: Record<string, McpServerConfig>;
|
||||
private env: Record<string, string | undefined>;
|
||||
private additionalDirectories?: string[];
|
||||
private model?: string;
|
||||
private effort?: string;
|
||||
|
||||
constructor(options: ProviderOptions = {}) {
|
||||
this.assistantName = options.assistantName;
|
||||
this.mcpServers = options.mcpServers ?? {};
|
||||
this.additionalDirectories = options.additionalDirectories;
|
||||
this.model = options.model;
|
||||
this.effort = options.effort;
|
||||
this.env = {
|
||||
...(options.env ?? {}),
|
||||
CLAUDE_CODE_AUTO_COMPACT_WINDOW,
|
||||
@@ -293,6 +297,9 @@ export class ClaudeProvider implements AgentProvider {
|
||||
],
|
||||
disallowedTools: SDK_DISALLOWED_TOOLS,
|
||||
env: this.env,
|
||||
model: this.model,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
effort: this.effort as any,
|
||||
permissionMode: 'bypassPermissions',
|
||||
allowDangerouslySkipPermissions: true,
|
||||
settingSources: ['project', 'user'],
|
||||
|
||||
@@ -25,6 +25,16 @@ export interface ProviderOptions {
|
||||
mcpServers?: Record<string, McpServerConfig>;
|
||||
env?: Record<string, string | undefined>;
|
||||
additionalDirectories?: string[];
|
||||
/**
|
||||
* Model alias (`sonnet`, `opus`, `haiku`) or full model ID. Passed through
|
||||
* to the underlying SDK. If omitted, the SDK default is used.
|
||||
*/
|
||||
model?: string;
|
||||
/**
|
||||
* Reasoning effort (`'low' | 'medium' | 'high' | 'xhigh' | 'max'`). Passed
|
||||
* through to the underlying SDK. If omitted, the SDK default is used.
|
||||
*/
|
||||
effort?: string;
|
||||
}
|
||||
|
||||
export interface QueryInput {
|
||||
|
||||
Reference in New Issue
Block a user