mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
feat(claude): add effort setting parity with model across stack (#353)
Co-authored-by: Xiaoyi <xiaoyizhang@microsoft.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { ApiClient, ApiSessionClient } from '@/lib';
|
||||
import { MessageQueue2 } from '@/utils/MessageQueue2';
|
||||
import type { Metadata, SessionCollaborationMode, SessionModel, SessionPermissionMode } from '@/api/types';
|
||||
import type { Metadata, SessionCollaborationMode, SessionEffort, SessionModel, SessionPermissionMode } from '@/api/types';
|
||||
import { logger } from '@/ui/logger';
|
||||
|
||||
export type AgentSessionBaseOptions<Mode> = {
|
||||
@@ -17,6 +17,7 @@ export type AgentSessionBaseOptions<Mode> = {
|
||||
applySessionIdToMetadata: (metadata: Metadata, sessionId: string) => Metadata;
|
||||
permissionMode?: SessionPermissionMode;
|
||||
model?: SessionModel;
|
||||
effort?: SessionEffort;
|
||||
collaborationMode?: SessionCollaborationMode;
|
||||
};
|
||||
|
||||
@@ -39,6 +40,7 @@ export class AgentSessionBase<Mode> {
|
||||
private keepAliveInterval: NodeJS.Timeout | null = null;
|
||||
protected permissionMode?: SessionPermissionMode;
|
||||
protected model?: SessionModel;
|
||||
protected effort?: SessionEffort;
|
||||
protected collaborationMode?: SessionCollaborationMode;
|
||||
|
||||
constructor(opts: AgentSessionBaseOptions<Mode>) {
|
||||
@@ -55,6 +57,7 @@ export class AgentSessionBase<Mode> {
|
||||
this.mode = opts.mode ?? 'local';
|
||||
this.permissionMode = opts.permissionMode;
|
||||
this.model = opts.model;
|
||||
this.effort = opts.effort;
|
||||
this.collaborationMode = opts.collaborationMode;
|
||||
|
||||
this.client.keepAlive(this.thinking, this.mode, this.getKeepAliveRuntime());
|
||||
@@ -74,10 +77,11 @@ export class AgentSessionBase<Mode> {
|
||||
this.client.keepAlive(this.thinking, mode, this.getKeepAliveRuntime());
|
||||
const permissionLabel = this.permissionMode ?? 'unset';
|
||||
const modelLabel = this.model === undefined ? 'unset' : (this.model ?? 'auto');
|
||||
const effortLabel = this.effort === undefined ? 'unset' : (this.effort ?? 'auto');
|
||||
const collaborationLabel = this.collaborationMode ?? 'unset';
|
||||
logger.debug(
|
||||
`[${this.sessionLabel}] Mode switched to ${mode} ` +
|
||||
`(permissionMode=${permissionLabel}, model=${modelLabel}, collaborationMode=${collaborationLabel})`
|
||||
`(permissionMode=${permissionLabel}, model=${modelLabel}, effort=${effortLabel}, collaborationMode=${collaborationLabel})`
|
||||
);
|
||||
this._onModeChange(mode);
|
||||
};
|
||||
@@ -111,13 +115,19 @@ export class AgentSessionBase<Mode> {
|
||||
};
|
||||
|
||||
protected getKeepAliveRuntime():
|
||||
{ permissionMode?: SessionPermissionMode; model?: SessionModel; collaborationMode?: SessionCollaborationMode } | undefined {
|
||||
if (this.permissionMode === undefined && this.model === undefined && this.collaborationMode === undefined) {
|
||||
{
|
||||
permissionMode?: SessionPermissionMode
|
||||
model?: SessionModel
|
||||
effort?: SessionEffort
|
||||
collaborationMode?: SessionCollaborationMode
|
||||
} | undefined {
|
||||
if (this.permissionMode === undefined && this.model === undefined && this.effort === undefined && this.collaborationMode === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
permissionMode: this.permissionMode,
|
||||
model: this.model,
|
||||
effort: this.effort,
|
||||
collaborationMode: this.collaborationMode
|
||||
};
|
||||
}
|
||||
@@ -130,6 +140,10 @@ export class AgentSessionBase<Mode> {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
getEffort(): SessionEffort | undefined {
|
||||
return this.effort;
|
||||
}
|
||||
|
||||
getCollaborationMode(): SessionCollaborationMode | undefined {
|
||||
return this.collaborationMode;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ export type SessionBootstrapOptions = {
|
||||
tag?: string
|
||||
agentState?: AgentState | null
|
||||
model?: string
|
||||
effort?: string
|
||||
metadataOverrides?: Partial<Metadata>
|
||||
}
|
||||
|
||||
@@ -131,7 +132,8 @@ export async function bootstrapSession(options: SessionBootstrapOptions): Promis
|
||||
tag: sessionTag,
|
||||
metadata,
|
||||
state: agentState,
|
||||
model: options.model
|
||||
model: options.model,
|
||||
effort: options.effort
|
||||
})
|
||||
|
||||
const session = api.sessionSyncClient(sessionInfo)
|
||||
|
||||
+6
-2
@@ -19,6 +19,7 @@ export class ApiClient {
|
||||
metadata: Metadata
|
||||
state: AgentState | null
|
||||
model?: string
|
||||
effort?: string
|
||||
}): Promise<Session> {
|
||||
const response = await axios.post<CreateSessionResponse>(
|
||||
`${configuration.apiUrl}/cli/sessions`,
|
||||
@@ -26,7 +27,8 @@ export class ApiClient {
|
||||
tag: opts.tag,
|
||||
metadata: opts.metadata,
|
||||
agentState: opts.state,
|
||||
model: opts.model
|
||||
model: opts.model,
|
||||
effort: opts.effort
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
@@ -72,7 +74,9 @@ export class ApiClient {
|
||||
thinkingAt: raw.thinkingAt,
|
||||
todos: raw.todos,
|
||||
model: raw.model,
|
||||
permissionMode: raw.permissionMode
|
||||
effort: raw.effort,
|
||||
permissionMode: raw.permissionMode,
|
||||
collaborationMode: raw.collaborationMode
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ export class ApiMachineClient {
|
||||
|
||||
setRPCHandlers({ spawnSession, stopSession, requestShutdown }: MachineRpcHandlers): void {
|
||||
this.rpcHandlerManager.registerHandler('spawn-happy-session', async (params: any) => {
|
||||
const { directory, sessionId, resumeSessionId, machineId, approvedNewDirectoryCreation, agent, model, modelReasoningEffort, yolo, token, sessionType, worktreeName } = params || {}
|
||||
const { directory, sessionId, resumeSessionId, machineId, approvedNewDirectoryCreation, agent, model, effort, modelReasoningEffort, yolo, token, sessionType, worktreeName } = params || {}
|
||||
|
||||
if (!directory) {
|
||||
throw new Error('Directory is required')
|
||||
@@ -116,6 +116,7 @@ export class ApiMachineClient {
|
||||
approvedNewDirectoryCreation,
|
||||
agent,
|
||||
model,
|
||||
effort,
|
||||
modelReasoningEffort,
|
||||
yolo,
|
||||
token,
|
||||
|
||||
@@ -443,6 +443,7 @@ export class ApiSessionClient extends EventEmitter {
|
||||
runtime?: {
|
||||
permissionMode?: SessionPermissionMode
|
||||
model?: SessionModel
|
||||
effort?: string | null
|
||||
collaborationMode?: SessionCollaborationMode
|
||||
}
|
||||
): void {
|
||||
|
||||
@@ -24,6 +24,7 @@ export type {
|
||||
export type SessionPermissionMode = PermissionMode
|
||||
export type SessionCollaborationMode = CodexCollaborationMode
|
||||
export type SessionModel = string | null
|
||||
export type SessionEffort = string | null
|
||||
|
||||
export { AgentStateSchema, AttachmentMetadataSchema, MetadataSchema }
|
||||
|
||||
@@ -99,6 +100,7 @@ export const CreateSessionResponseSchema = z.object({
|
||||
thinkingAt: z.number(),
|
||||
todos: TodosSchema.optional(),
|
||||
model: z.string().nullable(),
|
||||
effort: z.string().nullable(),
|
||||
permissionMode: PermissionModeSchema.optional(),
|
||||
collaborationMode: CodexCollaborationModeSchema.optional()
|
||||
})
|
||||
|
||||
@@ -125,6 +125,7 @@ export async function claudeRemote(opts: {
|
||||
mcpServers: opts.mcpServers,
|
||||
permissionMode: initial.mode.permissionMode,
|
||||
model: initial.mode.model,
|
||||
effort: initial.mode.effort,
|
||||
fallbackModel: initial.mode.fallbackModel,
|
||||
customSystemPrompt: initial.mode.customSystemPrompt ? initial.mode.customSystemPrompt + '\n\n' + systemPrompt : undefined,
|
||||
appendSystemPrompt: initial.mode.appendSystemPrompt ? initial.mode.appendSystemPrompt + '\n\n' + systemPrompt : systemPrompt,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { normalizeClaudeSessionEffort } from './effort'
|
||||
|
||||
describe('normalizeClaudeSessionEffort', () => {
|
||||
it('returns null when effort is missing', () => {
|
||||
expect(normalizeClaudeSessionEffort()).toBeNull()
|
||||
})
|
||||
|
||||
it('returns null for auto-like values', () => {
|
||||
expect(normalizeClaudeSessionEffort('')).toBeNull()
|
||||
expect(normalizeClaudeSessionEffort('auto')).toBeNull()
|
||||
expect(normalizeClaudeSessionEffort('default')).toBeNull()
|
||||
expect(normalizeClaudeSessionEffort(' AUTO ')).toBeNull()
|
||||
})
|
||||
|
||||
it('normalizes supported effort values', () => {
|
||||
expect(normalizeClaudeSessionEffort('medium')).toBe('medium')
|
||||
expect(normalizeClaudeSessionEffort('high')).toBe('high')
|
||||
expect(normalizeClaudeSessionEffort('max')).toBe('max')
|
||||
expect(normalizeClaudeSessionEffort(' High ')).toBe('high')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,10 @@
|
||||
import type { SessionEffort } from '@/api/types'
|
||||
|
||||
export function normalizeClaudeSessionEffort(effort?: string | null): SessionEffort {
|
||||
const trimmedEffort = effort?.trim().toLowerCase()
|
||||
if (!trimmedEffort || trimmedEffort === 'auto' || trimmedEffort === 'default') {
|
||||
return null
|
||||
}
|
||||
|
||||
return trimmedEffort
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import { Session } from "./session"
|
||||
import { claudeLocalLauncher } from "./claudeLocalLauncher"
|
||||
import { claudeRemoteLauncher } from "./claudeRemoteLauncher"
|
||||
import { ApiClient } from "@/lib"
|
||||
import type { SessionModel } from "@/api/types"
|
||||
import type { SessionEffort, SessionModel } from "@/api/types"
|
||||
import type { ClaudePermissionMode } from "@hapi/protocol/types"
|
||||
|
||||
export type PermissionMode = ClaudePermissionMode;
|
||||
@@ -14,6 +14,7 @@ export type PermissionMode = ClaudePermissionMode;
|
||||
export interface EnhancedMode {
|
||||
permissionMode: PermissionMode;
|
||||
model?: string;
|
||||
effort?: string;
|
||||
fallbackModel?: string;
|
||||
customSystemPrompt?: string;
|
||||
appendSystemPrompt?: string;
|
||||
@@ -24,6 +25,7 @@ export interface EnhancedMode {
|
||||
interface LoopOptions {
|
||||
path: string
|
||||
model?: SessionModel
|
||||
effort?: SessionEffort
|
||||
permissionMode?: PermissionMode
|
||||
startingMode?: 'local' | 'remote'
|
||||
startedBy?: 'runner' | 'terminal'
|
||||
@@ -62,7 +64,8 @@ export async function loop(opts: LoopOptions) {
|
||||
startingMode,
|
||||
hookSettingsPath: opts.hookSettingsPath,
|
||||
permissionMode: opts.permissionMode ?? 'default',
|
||||
model: opts.model
|
||||
model: opts.model,
|
||||
effort: opts.effort
|
||||
});
|
||||
|
||||
await runLocalRemoteSession({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { logger } from '@/ui/logger';
|
||||
import { loop } from '@/claude/loop';
|
||||
import { AgentState, SessionModel } from '@/api/types';
|
||||
import { AgentState, SessionEffort, SessionModel } from '@/api/types';
|
||||
import { EnhancedMode, PermissionMode } from './loop';
|
||||
import { MessageQueue2 } from '@/utils/MessageQueue2';
|
||||
import { hashObject } from '@/utils/deterministicJson';
|
||||
@@ -18,10 +18,12 @@ import { isPermissionModeAllowedForFlavor } from '@hapi/protocol';
|
||||
import { PermissionModeSchema } from '@hapi/protocol/schemas';
|
||||
import { formatMessageWithAttachments } from '@/utils/attachmentFormatter';
|
||||
import { normalizeClaudeSessionModel } from './model';
|
||||
import { normalizeClaudeSessionEffort } from './effort';
|
||||
import { getInvokedCwd } from '@/utils/invokedCwd';
|
||||
|
||||
export interface StartOptions {
|
||||
model?: string
|
||||
effort?: string
|
||||
permissionMode?: PermissionMode
|
||||
startingMode?: 'local' | 'remote'
|
||||
shouldStartRunner?: boolean
|
||||
@@ -48,12 +50,14 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
|
||||
|
||||
const initialState: AgentState = {};
|
||||
const initialModel = normalizeClaudeSessionModel(options.model);
|
||||
const initialEffort = normalizeClaudeSessionEffort(options.effort);
|
||||
const { api, session, sessionInfo } = await bootstrapSession({
|
||||
flavor: 'claude',
|
||||
startedBy,
|
||||
workingDirectory,
|
||||
agentState: initialState,
|
||||
model: initialModel ?? undefined
|
||||
model: initialModel ?? undefined,
|
||||
effort: initialEffort ?? undefined
|
||||
});
|
||||
logger.debug(`Session created: ${sessionInfo.id}`);
|
||||
|
||||
@@ -138,6 +142,7 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
|
||||
const messageQueue = new MessageQueue2<EnhancedMode>(mode => hashObject({
|
||||
isPlan: mode.permissionMode === 'plan',
|
||||
model: mode.model,
|
||||
effort: mode.effort,
|
||||
fallbackModel: mode.fallbackModel,
|
||||
customSystemPrompt: mode.customSystemPrompt,
|
||||
appendSystemPrompt: mode.appendSystemPrompt,
|
||||
@@ -148,6 +153,7 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
|
||||
// Forward messages to the queue
|
||||
let currentPermissionMode: PermissionMode = options.permissionMode ?? 'default';
|
||||
let currentModel: SessionModel = initialModel;
|
||||
let currentEffort: SessionEffort = initialEffort;
|
||||
let currentFallbackModel: string | undefined = undefined; // Track current fallback model
|
||||
let currentCustomSystemPrompt: string | undefined = undefined; // Track current custom system prompt
|
||||
let currentAppendSystemPrompt: string | undefined = undefined; // Track current append system prompt
|
||||
@@ -161,7 +167,8 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
|
||||
}
|
||||
sessionInstance.setPermissionMode(currentPermissionMode);
|
||||
sessionInstance.setModel(currentModel);
|
||||
logger.debug(`[loop] Synced session config for keepalive: permissionMode=${currentPermissionMode}, model=${currentModel ?? 'auto'}`);
|
||||
sessionInstance.setEffort(currentEffort);
|
||||
logger.debug(`[loop] Synced session config for keepalive: permissionMode=${currentPermissionMode}, model=${currentModel ?? 'auto'}, effort=${currentEffort ?? 'auto'}`);
|
||||
};
|
||||
session.onUserMessage((message) => {
|
||||
const sessionPermissionMode = currentSessionRef.current?.getPermissionMode();
|
||||
@@ -172,9 +179,14 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
|
||||
if (sessionModel !== undefined) {
|
||||
currentModel = sessionModel;
|
||||
}
|
||||
const sessionEffort = currentSessionRef.current?.getEffort();
|
||||
if (sessionEffort !== undefined) {
|
||||
currentEffort = sessionEffort;
|
||||
}
|
||||
const messagePermissionMode = currentPermissionMode;
|
||||
const messageModel = currentModel ?? undefined;
|
||||
logger.debug(`[loop] User message received with permission mode: ${currentPermissionMode}, model: ${currentModel ?? 'auto'}`);
|
||||
const messageEffort = currentEffort ?? undefined;
|
||||
logger.debug(`[loop] User message received with permission mode: ${currentPermissionMode}, model: ${currentModel ?? 'auto'}, effort: ${currentEffort ?? 'auto'}`);
|
||||
|
||||
// Resolve custom system prompt - use message.meta.customSystemPrompt if provided, otherwise use current
|
||||
let messageCustomSystemPrompt = currentCustomSystemPrompt;
|
||||
@@ -237,6 +249,7 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
|
||||
const enhancedMode: EnhancedMode = {
|
||||
permissionMode: messagePermissionMode ?? 'default',
|
||||
model: messageModel,
|
||||
effort: messageEffort,
|
||||
fallbackModel: messageFallbackModel,
|
||||
customSystemPrompt: messageCustomSystemPrompt,
|
||||
appendSystemPrompt: messageAppendSystemPrompt,
|
||||
@@ -255,6 +268,7 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
|
||||
const enhancedMode: EnhancedMode = {
|
||||
permissionMode: messagePermissionMode ?? 'default',
|
||||
model: messageModel,
|
||||
effort: messageEffort,
|
||||
fallbackModel: messageFallbackModel,
|
||||
customSystemPrompt: messageCustomSystemPrompt,
|
||||
appendSystemPrompt: messageAppendSystemPrompt,
|
||||
@@ -272,6 +286,7 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
|
||||
const enhancedMode: EnhancedMode = {
|
||||
permissionMode: messagePermissionMode ?? 'default',
|
||||
model: messageModel,
|
||||
effort: messageEffort,
|
||||
fallbackModel: messageFallbackModel,
|
||||
customSystemPrompt: messageCustomSystemPrompt,
|
||||
appendSystemPrompt: messageAppendSystemPrompt,
|
||||
@@ -302,11 +317,23 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
|
||||
return normalizeClaudeSessionModel(value);
|
||||
};
|
||||
|
||||
const resolveEffort = (value: unknown): SessionEffort => {
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof value !== 'string') {
|
||||
throw new Error('Invalid effort');
|
||||
}
|
||||
|
||||
return normalizeClaudeSessionEffort(value);
|
||||
};
|
||||
|
||||
session.rpcHandlerManager.registerHandler('set-session-config', async (payload: unknown) => {
|
||||
if (!payload || typeof payload !== 'object') {
|
||||
throw new Error('Invalid session config payload');
|
||||
}
|
||||
const config = payload as { permissionMode?: unknown; model?: unknown };
|
||||
const config = payload as { permissionMode?: unknown; model?: unknown; effort?: unknown };
|
||||
|
||||
if (config.permissionMode !== undefined) {
|
||||
currentPermissionMode = resolvePermissionMode(config.permissionMode);
|
||||
@@ -316,8 +343,12 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
|
||||
currentModel = resolveModel(config.model);
|
||||
}
|
||||
|
||||
if (config.effort !== undefined) {
|
||||
currentEffort = resolveEffort(config.effort);
|
||||
}
|
||||
|
||||
syncSessionModes();
|
||||
return { applied: { permissionMode: currentPermissionMode, model: currentModel } };
|
||||
return { applied: { permissionMode: currentPermissionMode, model: currentModel, effort: currentEffort } };
|
||||
});
|
||||
|
||||
let loopError: unknown = null;
|
||||
@@ -326,6 +357,7 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
|
||||
await loop({
|
||||
path: workingDirectory,
|
||||
model: currentModel,
|
||||
effort: currentEffort,
|
||||
permissionMode: options.permissionMode,
|
||||
startingMode,
|
||||
messageQueue,
|
||||
|
||||
@@ -280,6 +280,7 @@ export function query(config: {
|
||||
continue: continueConversation,
|
||||
resume,
|
||||
model,
|
||||
effort,
|
||||
fallbackModel,
|
||||
settingsPath,
|
||||
strictMcpConfig,
|
||||
@@ -300,6 +301,7 @@ export function query(config: {
|
||||
if (appendSystemPrompt) args.push('--append-system-prompt', stripNewlinesForWindowsShellArg(appendSystemPrompt))
|
||||
if (maxTurns) args.push('--max-turns', maxTurns.toString())
|
||||
if (model) args.push('--model', model)
|
||||
if (effort) args.push('--effort', effort)
|
||||
if (canCallTool) {
|
||||
if (typeof prompt === 'string') {
|
||||
throw new Error('canCallTool callback requires --input-format stream-json. Please set prompt as an AsyncIterable.')
|
||||
|
||||
@@ -170,6 +170,7 @@ export interface QueryOptions {
|
||||
continue?: boolean
|
||||
resume?: string
|
||||
model?: string
|
||||
effort?: string
|
||||
fallbackModel?: string
|
||||
settingsPath?: string
|
||||
strictMcpConfig?: boolean
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ApiClient, ApiSessionClient } from '@/lib';
|
||||
import { MessageQueue2 } from '@/utils/MessageQueue2';
|
||||
import { logger } from '@/ui/logger';
|
||||
import { AgentSessionBase } from '@/agent/sessionBase';
|
||||
import type { SessionModel } from '@/api/types';
|
||||
import type { SessionEffort, SessionModel } from '@/api/types';
|
||||
import type { EnhancedMode } from './loop';
|
||||
import type { PermissionMode } from './loop';
|
||||
import type { LocalLaunchExitReason } from '@/agent/localLaunchPolicy';
|
||||
@@ -40,6 +40,7 @@ export class Session extends AgentSessionBase<EnhancedMode> {
|
||||
hookSettingsPath: string;
|
||||
permissionMode?: PermissionMode;
|
||||
model?: SessionModel;
|
||||
effort?: SessionEffort;
|
||||
}) {
|
||||
super({
|
||||
api: opts.api,
|
||||
@@ -57,7 +58,8 @@ export class Session extends AgentSessionBase<EnhancedMode> {
|
||||
claudeSessionId: sessionId
|
||||
}),
|
||||
permissionMode: opts.permissionMode,
|
||||
model: opts.model
|
||||
model: opts.model,
|
||||
effort: opts.effort
|
||||
});
|
||||
|
||||
this.claudeEnvVars = opts.claudeEnvVars;
|
||||
@@ -69,6 +71,7 @@ export class Session extends AgentSessionBase<EnhancedMode> {
|
||||
this.startingMode = opts.startingMode;
|
||||
this.permissionMode = opts.permissionMode;
|
||||
this.model = opts.model;
|
||||
this.effort = opts.effort;
|
||||
}
|
||||
|
||||
setPermissionMode = (mode: PermissionMode): void => {
|
||||
@@ -79,6 +82,10 @@ export class Session extends AgentSessionBase<EnhancedMode> {
|
||||
this.model = model;
|
||||
};
|
||||
|
||||
setEffort = (effort: SessionEffort): void => {
|
||||
this.effort = effort;
|
||||
};
|
||||
|
||||
recordLocalLaunchFailure = (message: string, exitReason: LocalLaunchExitReason): void => {
|
||||
this.localLaunchFailure = { message, exitReason };
|
||||
};
|
||||
|
||||
@@ -49,6 +49,13 @@ export const claudeCommand: CommandDefinition = {
|
||||
}
|
||||
options.model = model
|
||||
unknownArgs.push('--model', model)
|
||||
} else if (arg === '--effort') {
|
||||
const effort = args[++i]
|
||||
if (!effort) {
|
||||
throw new Error('Missing --effort value')
|
||||
}
|
||||
options.effort = effort
|
||||
unknownArgs.push('--effort', effort)
|
||||
} else if (arg === '--started-by') {
|
||||
options.startedBy = args[++i] as 'runner' | 'terminal'
|
||||
} else {
|
||||
|
||||
@@ -6,6 +6,7 @@ export interface SpawnSessionOptions {
|
||||
approvedNewDirectoryCreation?: boolean
|
||||
agent?: 'claude' | 'codex' | 'cursor' | 'gemini' | 'opencode'
|
||||
model?: string
|
||||
effort?: string
|
||||
modelReasoningEffort?: string
|
||||
yolo?: boolean
|
||||
token?: string
|
||||
|
||||
@@ -363,6 +363,9 @@ export async function startRunner(): Promise<void> {
|
||||
if (options.model && agent !== 'opencode') {
|
||||
args.push('--model', options.model);
|
||||
}
|
||||
if (options.effort && agent === 'claude') {
|
||||
args.push('--effort', options.effort);
|
||||
}
|
||||
if (options.modelReasoningEffort && agent === 'codex') {
|
||||
args.push('--model-reasoning-effort', options.modelReasoningEffort);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user