From: Jérôme Benoit Date: Fri, 8 May 2026 14:09:44 +0000 (+0200) Subject: fix(sandcastle): wire reasoning effort through to agent providers X-Git-Tag: cli@v4.7.1~5 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=bd65c6c368bf359f53a923425fbbd22d57bf3262;p=e-mobility-charging-stations-simulator.git fix(sandcastle): wire reasoning effort through to agent providers Pass AGENT_*_EFFORT constants through agentProvider() to the opencode provider's variant flag. LoopStrategy gains actorEffort/criticEffort optional overrides following the same pattern as actorModel/criticModel. - opencode: effort mapped to --variant CLI flag - pi: no effort support (provider limitation, param silently ignored) --- diff --git a/.sandcastle/refinement-loop.ts b/.sandcastle/refinement-loop.ts index b29e63d7..ad546ab5 100644 --- a/.sandcastle/refinement-loop.ts +++ b/.sandcastle/refinement-loop.ts @@ -14,7 +14,9 @@ import type { } from './types.js' import { + AGENT_ACTOR_EFFORT, AGENT_ACTOR_MODEL, + AGENT_CRITIC_EFFORT, AGENT_CRITIC_MODEL, AGENT_IDLE_TIMEOUT_S, AGENT_ITERATION_BUDGET, @@ -460,7 +462,10 @@ async function executeRound ( let actorResult: Awaited> try { actorResult = await sandbox.run({ - agent: agentProvider(strategy.actorModel ?? AGENT_ACTOR_MODEL), + agent: agentProvider( + strategy.actorModel ?? AGENT_ACTOR_MODEL, + strategy.actorEffort ?? AGENT_ACTOR_EFFORT + ), completionSignal: COMPLETION_SIGNAL, idleTimeoutSeconds: AGENT_IDLE_TIMEOUT_S, maxIterations: budget, @@ -622,7 +627,10 @@ async function runCritic ( const { baseBranch, sandbox, signal, spec, strategy } = ctx let critic = await sandbox.run({ - agent: agentProvider(strategy.criticModel ?? AGENT_CRITIC_MODEL), + agent: agentProvider( + strategy.criticModel ?? AGENT_CRITIC_MODEL, + strategy.criticEffort ?? AGENT_CRITIC_EFFORT + ), completionSignal: COMPLETION_SIGNAL, idleTimeoutSeconds: AGENT_IDLE_TIMEOUT_S, maxIterations: 1, @@ -637,7 +645,10 @@ async function runCritic ( if (findings === null) { console.warn(` #${spec.id}: Critic parse failed. Retrying.`) critic = await sandbox.run({ - agent: agentProvider(strategy.criticModel ?? AGENT_CRITIC_MODEL), + agent: agentProvider( + strategy.criticModel ?? AGENT_CRITIC_MODEL, + strategy.criticEffort ?? AGENT_CRITIC_EFFORT + ), completionSignal: COMPLETION_SIGNAL, idleTimeoutSeconds: AGENT_IDLE_TIMEOUT_S, maxIterations: 1, diff --git a/.sandcastle/task-source.ts b/.sandcastle/task-source.ts index a17dbb43..5452e8b9 100644 --- a/.sandcastle/task-source.ts +++ b/.sandcastle/task-source.ts @@ -6,6 +6,7 @@ import type { TaskSpec } from './types.js' import { AGENT_IDLE_TIMEOUT_S, + AGENT_PLANNER_EFFORT, AGENT_PLANNER_MODEL, AGENT_TASK_TIMEOUT_MS, COMPLETION_SIGNAL, @@ -97,7 +98,7 @@ export class GithubIssueSource implements TaskSource { let plan: Awaited> try { plan = await sandcastle.run({ - agent: agentProvider(AGENT_PLANNER_MODEL), + agent: agentProvider(AGENT_PLANNER_MODEL, AGENT_PLANNER_EFFORT), completionSignal: COMPLETION_SIGNAL, hooks: SANDBOX_AUTH_HOOKS, idleTimeoutSeconds: AGENT_IDLE_TIMEOUT_S, diff --git a/.sandcastle/types.ts b/.sandcastle/types.ts index ce0c002b..6688a97f 100644 --- a/.sandcastle/types.ts +++ b/.sandcastle/types.ts @@ -66,6 +66,8 @@ export type LoopStatus = 'converged' | 'exhausted' | 'failed' | 'skipped' */ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions export type LoopStrategy = { + /** Reasoning effort for the actor agent. Defaults to AGENT_ACTOR_EFFORT constant. */ + actorEffort?: string /** Model for the actor agent. Defaults to AGENT_ACTOR_MODEL constant. */ actorModel?: string /** Path to the actor prompt file. */ @@ -74,6 +76,8 @@ export type LoopStrategy = { buildActorArgs: (spec: TaskSpec, findings: Finding[]) => Record /** Builds promptArgs for the critic run from task spec and base branch. */ buildCriticArgs: (spec: TaskSpec, baseBranch: string) => Record + /** Reasoning effort for the critic agent. Defaults to AGENT_CRITIC_EFFORT constant. */ + criticEffort?: string /** Model for the critic agent. Defaults to AGENT_CRITIC_MODEL constant. */ criticModel?: string /** Path to the critic prompt file. */ diff --git a/.sandcastle/utils.ts b/.sandcastle/utils.ts index eefa48d9..ec05d7c8 100644 --- a/.sandcastle/utils.ts +++ b/.sandcastle/utils.ts @@ -12,12 +12,13 @@ export const execFileAsync = util.promisify(execFile) /** * Returns a sandcastle agent provider for the given model, selected by AGENT_PROVIDER constant. * @param model - The model identifier (e.g., 'github-copilot/claude-sonnet-4.6'). + * @param effort - Reasoning effort level passed as `variant` to opencode. * @returns The configured agent provider. */ -export function agentProvider (model: string): AgentProvider { +export function agentProvider (model: string, effort?: string): AgentProvider { switch (AGENT_PROVIDER) { case 'opencode': - return sandcastle.opencode(model) + return sandcastle.opencode(model, effort ? { variant: effort } : undefined) case 'pi': return sandcastle.pi(model) }