* fix(#2832): gsd-sdk auto detects Codex runtime correctly Two-part fix for #2832 (gsd-sdk auto silently routing non-Claude runtime projects through the Claude Agent SDK): 1. Runtime gate at the `auto` entry point. New `runtime-gate.ts` exports `assertRuntimeSupportsAutoMode(config)` which throws an actionable error when `GSD_RUNTIME` / `config.runtime` resolves to a non-Claude runtime (codex, gemini, opencode, etc.). The autonomous orchestrator only knows how to drive `@anthropic-ai/claude-agent-sdk` today; failing fast with a clear pointer at the in-session slash commands beats the previous instant `[FAILED] $0.00 0.1s` flake. Wired into `cli.ts` before the GSD/InitRunner construction. 2. Runtime-aware `resolveModel()` in `session-runner.ts`. The profile -> id map (`balanced -> claude-sonnet-4-6`, etc.) was applied unconditionally, so even with `runtime: codex` and `resolve_model_ids: omit` the SDK forced a Claude id into `query()`. Now the profile map only fires when the runtime is Claude and the explicit `resolve_model_ids: "omit"` knob short-circuits to undefined, mirroring `query/config-query.ts`. Tests (vitest, sdk/src): - runtime-gate.test.ts (8 cases): claude / unset / unknown pass; codex, gemini, opencode throw; GSD_RUNTIME wins over config.runtime; error message references #2832 and the slash-command workaround. - session-runner.test.ts (4 new cases under "resolveModel runtime awareness (#2832)"): codex runtime + balanced profile -> no model injected; resolve_model_ids: omit -> no model; claude runtime still resolves to claude-sonnet-4-6 (no regression); explicit options.model wins on any runtime. * fix(#2832): address CR — env-precedence in resolveModel + accurate source attribution Two CodeRabbit findings on PR #2844: 1. session-runner.ts:resolveModel() (Major) — read runtime via detectRuntime() so GSD_RUNTIME env precedence is honored. Without this, a Codex run with a Claude-shaped config still fell into the Claude-only profile-id branch. 2. runtime-gate.ts:assertRuntimeSupportsAutoMode() (Minor) — when GSD_RUNTIME holds an unsupported value, detectRuntime() falls through to config but the source label still reported the discarded env value. Fix: validate env against SUPPORTED_RUNTIMES before attributing the source. Tests added for both: env-precedence in session-runner, source attribution in runtime-gate. 17/17 pass.
This commit is contained in:
@@ -13,6 +13,7 @@ import type { GSDConfig } from './config.js';
|
||||
import { buildExecutorPrompt, parseAgentTools, DEFAULT_ALLOWED_TOOLS } from './prompt-builder.js';
|
||||
import type { GSDEventStream, EventStreamContext } from './event-stream.js';
|
||||
import { getToolsForPhase } from './tool-scoping.js';
|
||||
import { detectRuntime } from './query/helpers.js';
|
||||
|
||||
// ─── Model resolution ────────────────────────────────────────────────────────
|
||||
|
||||
@@ -20,11 +21,34 @@ import { getToolsForPhase } from './tool-scoping.js';
|
||||
* Resolve model identifier from options or config profile.
|
||||
*
|
||||
* Priority: explicit model option > config model_profile > default.
|
||||
*
|
||||
* Runtime-aware (#2832): the profile -> Claude-id map only applies when the
|
||||
* project is targeting the Claude runtime. For Codex, Gemini, OpenCode, etc.,
|
||||
* forcing a Claude model id (e.g. 'claude-sonnet-4-6') silently routes the
|
||||
* autonomous run through the Claude path, which is wrong for those runtimes.
|
||||
* In those cases — and whenever `resolve_model_ids: "omit"` is set — leave
|
||||
* `model` unset so the runtime falls back to its configured default.
|
||||
*/
|
||||
function resolveModel(options?: SessionOptions, config?: GSDConfig): string | undefined {
|
||||
if (options?.model) return options.model;
|
||||
|
||||
// Map model_profile names to model IDs
|
||||
// Honor the explicit "don't resolve model ids" config knob (#2652, #2832).
|
||||
// Mirrors `query/config-query.ts` resolve_model_ids === 'omit' branch.
|
||||
if ((config as Record<string, unknown> | undefined)?.resolve_model_ids === 'omit') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Profile -> Claude id map. Applies only on the Claude runtime.
|
||||
// Use `detectRuntime` so `GSD_RUNTIME` env precedence is honored — a Codex
|
||||
// run with a Claude-shaped config must NOT be silently routed to Claude.
|
||||
const runtime = detectRuntime({
|
||||
runtime: (config as Record<string, unknown> | undefined)?.runtime,
|
||||
});
|
||||
if (runtime !== 'claude') {
|
||||
// Non-Claude runtimes: never inject a Claude id from the profile map.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (config?.model_profile) {
|
||||
const profileMap: Record<string, string> = {
|
||||
balanced: 'claude-sonnet-4-6',
|
||||
|
||||
Reference in New Issue
Block a user