Skip to content

Commit 7666650

Browse files
authored
Treat expression-backed engine.model as omitted when empty (#46777)
1 parent afe047b commit 7666650

20 files changed

Lines changed: 279 additions & 39 deletions

.github/workflows/daily-cache-strategy-analyzer.lock.yml

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/daily-caveman-optimizer.lock.yml

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/daily-doc-healer.lock.yml

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/test-quality-sentinel.lock.yml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

actions/setup/js/claude_harness.cjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const { emitMissingToolPermissionIssue, hasExpectedSafeOutputs, hasNoopInSafeOut
5353
const { countPermissionDeniedIssues, hasNumerousPermissionDeniedIssues, extractDeniedCommands, buildMissingToolPermissionIssuePayload } = require("./permission_denied_helpers.cjs");
5454
const { detectNonRetryableHarnessGuard, buildSoftTimeoutGuard, emitSoftTimeoutSignal, isAuthenticationFailedError } = require("./harness_retry_guard.cjs");
5555
const { MODEL_NOT_SUPPORTED_PATTERN: INVALID_MODEL_ERROR_PATTERN } = require("./detect_agent_errors.cjs");
56+
const { applyModelFallback } = require("./model_fallback.cjs");
5657

5758
// Pattern to detect Anthropic API overload errors (HTTP 529).
5859
// Matches "overloaded_error" from the Anthropic error type field, and the
@@ -318,6 +319,7 @@ function stripContinueArgs(args) {
318319
*/
319320
async function buildClaudeChildEnv() {
320321
const childEnv = { ...process.env };
322+
applyModelFallback(childEnv, "ANTHROPIC_MODEL", log);
321323
const provider = normalizeReflectProviderName(process.env.GH_AW_LLM_PROVIDER, "anthropic");
322324
try {
323325
const raw = fs.readFileSync(AWF_REFLECT_OUTPUT_PATH, "utf8");
@@ -611,6 +613,7 @@ if (typeof module !== "undefined" && module.exports) {
611613
hasExpectedSafeOutputs,
612614
resolveRetryConfig,
613615
resolveStartupRetryLimit,
616+
applyModelFallback,
614617
};
615618
}
616619

actions/setup/js/codex_harness.cjs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const { countPermissionDeniedIssues, hasNumerousPermissionDeniedIssues, extractD
5454
const { detectNonRetryableHarnessGuard, buildSoftTimeoutGuard, emitSoftTimeoutSignal, isAuthenticationFailedError } = require("./harness_retry_guard.cjs");
5555
const { MODEL_NOT_SUPPORTED_PATTERN: INVALID_MODEL_ERROR_PATTERN } = require("./detect_agent_errors.cjs");
5656
const { resolveRetryConfig } = require("./harness_retry_config.cjs");
57+
const { applyModelFallback, injectModelFlagAfterExec } = require("./model_fallback.cjs");
5758

5859
// Pattern to detect OpenAI rate-limit errors.
5960
// Matches the JSON error type field ("rate_limit_exceeded"), the HTTP status code
@@ -221,6 +222,16 @@ function injectJsonFlag(args) {
221222
return ["exec", "--json", ...args.slice(1)];
222223
}
223224

225+
function getCodexModelEnvVar(env = process.env) {
226+
if ("GH_AW_MODEL_DETECTION_CODEX" in env) {
227+
return "GH_AW_MODEL_DETECTION_CODEX";
228+
}
229+
if ("GH_AW_MODEL_AGENT_CODEX" in env) {
230+
return "GH_AW_MODEL_AGENT_CODEX";
231+
}
232+
return "";
233+
}
234+
224235
/**
225236
* Build child process environment for Codex execution.
226237
* Preserve API keys captured at harness startup, even if the parent environment
@@ -425,6 +436,10 @@ async function main() {
425436
process.exit(1);
426437
}
427438

439+
const codexModelEnvVar = getCodexModelEnvVar(process.env);
440+
const resolvedModel = codexModelEnvVar ? applyModelFallback(process.env, codexModelEnvVar, log) : "";
441+
resolvedArgs = injectModelFlagAfterExec(resolvedArgs, resolvedModel);
442+
428443
// Safe arg list for logging: when --prompt-file was present, the last element of
429444
// resolvedArgs is the resolved prompt content. Replace it with a placeholder so that
430445
// task instructions are never written to stderr or captured in agent logs.
@@ -641,6 +656,9 @@ if (typeof module !== "undefined" && module.exports) {
641656
hasNoopInSafeOutputs,
642657
hasExpectedSafeOutputs,
643658
resolveRetryConfig,
659+
applyModelFallback,
660+
injectModelFlagAfterExec,
661+
getCodexModelEnvVar,
644662
};
645663
}
646664

actions/setup/js/copilot_harness.cjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ const { runSafeOutputsCLI, buildMissingToolAlternatives, emitMissingToolPermissi
6565
const { countPermissionDeniedIssues, hasNumerousPermissionDeniedIssues, extractDeniedCommands, buildMissingToolPermissionIssuePayload } = require("./permission_denied_helpers.cjs");
6666
const { detectNonRetryableHarnessGuard, buildSoftTimeoutGuard, emitSoftTimeoutSignal, isAuthenticationFailedError: isCommonAuthenticationFailedError } = require("./harness_retry_guard.cjs");
6767
const { isCAPIQuotaExceededError } = require("./detect_agent_errors.cjs");
68+
const { applyModelFallback } = require("./model_fallback.cjs");
6869
const { loadModelsJson } = require("./model_costs.cjs");
6970
const { resolveConfiguredCopilotModel } = require("./resolve_model_alias.cjs");
7071

@@ -950,6 +951,7 @@ async function main() {
950951
}
951952
}
952953

954+
applyModelFallback(process.env, "COPILOT_MODEL", log);
953955
applyCopilotModelAliasResolution({ awfReflectData, logger: log });
954956
applyCopilotWireAPI({ modelsJson: loadModelsJson(), logger: log });
955957

@@ -1456,6 +1458,7 @@ if (typeof module !== "undefined" && module.exports) {
14561458
parseCopilotSDKServerArgsFromEnv,
14571459
isCAPIQuotaExceededError,
14581460
hasTerminalSafeOutput,
1461+
applyModelFallback,
14591462
applyCopilotModelAliasResolution,
14601463
applyCopilotWireAPI,
14611464
loadAwfConfigData,

actions/setup/js/copilot_sdk_driver.cjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const fs = require("fs");
3030
const { runWithCopilotSDK, extractPromptFromArgs } = require("./copilot_sdk_session.cjs");
3131
const { parsePermissionConfigFromServerArgs } = require("./copilot_sdk_permissions.cjs");
3232
const { parseMultiProviderJson } = require("./copilot_sdk_multi_provider.cjs");
33+
const { applyModelFallback } = require("./model_fallback.cjs");
3334

3435
// Re-export the session and permission helpers so that existing callers that
3536
// require("./copilot_sdk_driver.cjs") (e.g. copilot_harness.cjs) continue to work.
@@ -103,7 +104,7 @@ async function main() {
103104
const providers = multiProviderConfig.providers;
104105
/** @type {import("@github/copilot-sdk").ProviderModelConfig[]} */
105106
const sdkModels = multiProviderConfig.models;
106-
let model = process.env.COPILOT_MODEL || multiProviderConfig.model || undefined;
107+
let model = applyModelFallback(process.env, "COPILOT_MODEL", log) || multiProviderConfig.model || undefined;
107108
log(`multi-provider mode: ${providers.length} providers, ${sdkModels.length} models, model=${model ?? "(env)"}`);
108109
for (const p of providers) {
109110
log(` provider: name=${p.name} type=${p.type} baseUrl=${p.baseUrl}${p.wireApi ? ` wireApi=${p.wireApi}` : ""}`);

actions/setup/js/copilot_sdk_session.cjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const fs = require("fs");
3636
const path = require("path");
3737
const os = require("os");
3838
const { buildCopilotSDKPermissionHandler, getEnvPositiveIntOrDefault, parseMaxToolDenialsLimit, MAX_TOOL_DENIALS_DEFAULT } = require("./copilot_sdk_permissions.cjs");
39+
const { resolveModelWithFallback } = require("./model_fallback.cjs");
3940
const { extractShellCommandFromToolData } = require("./tool_call_details.cjs");
4041

4142
// Default timeout for a single sendAndWait call: 10 minutes.
@@ -254,7 +255,7 @@ async function runWithCopilotSDK({ sdkUri, prompt, logger, attempt = 0, model, c
254255
// Build session config using the multi-provider surface.
255256
/** @type {import("@github/copilot-sdk").SessionConfig} */
256257
const sessionConfig = {
257-
model: model || process.env.COPILOT_MODEL || undefined,
258+
model: model || resolveModelWithFallback(process.env, "COPILOT_MODEL") || undefined,
258259
providers,
259260
models: providerModels,
260261
onPermissionRequest,
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"use strict";
2+
3+
const MODEL_FALLBACK_ENV_VAR = "GH_AW_MODEL_FALLBACK";
4+
5+
function readTrimmedEnv(env, name) {
6+
return typeof env?.[name] === "string" ? env[name].trim() : "";
7+
}
8+
9+
function resolveModelWithFallback(env, primaryEnvVar) {
10+
return readTrimmedEnv(env, primaryEnvVar) || readTrimmedEnv(env, MODEL_FALLBACK_ENV_VAR);
11+
}
12+
13+
/**
14+
* @param {NodeJS.ProcessEnv} env
15+
* @param {string} primaryEnvVar
16+
* @param {(message: string) => void} [logger]
17+
* @returns {string}
18+
*/
19+
function applyModelFallback(env, primaryEnvVar, logger = () => {}) {
20+
const primary = readTrimmedEnv(env, primaryEnvVar);
21+
if (primary) {
22+
return primary;
23+
}
24+
const fallback = readTrimmedEnv(env, MODEL_FALLBACK_ENV_VAR);
25+
if (fallback) {
26+
env[primaryEnvVar] = fallback;
27+
logger(`applied ${MODEL_FALLBACK_ENV_VAR} to ${primaryEnvVar}`);
28+
}
29+
return fallback;
30+
}
31+
32+
function injectModelFlagAfterExec(args, model) {
33+
if (!model || args.includes("--model")) {
34+
return args;
35+
}
36+
const execIndex = args.indexOf("exec");
37+
if (execIndex === -1) {
38+
return [...args, "--model", model];
39+
}
40+
return [...args.slice(0, execIndex + 1), "--model", model, ...args.slice(execIndex + 1)];
41+
}
42+
43+
module.exports = {
44+
MODEL_FALLBACK_ENV_VAR,
45+
resolveModelWithFallback,
46+
applyModelFallback,
47+
injectModelFlagAfterExec,
48+
};

0 commit comments

Comments
 (0)