@autohq/cli 0.1.316 → 0.1.317

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23431,7 +23431,7 @@ Object.assign(lookup, {
23431
23431
  // package.json
23432
23432
  var package_default = {
23433
23433
  name: "@autohq/cli",
23434
- version: "0.1.316",
23434
+ version: "0.1.317",
23435
23435
  license: "SEE LICENSE IN README.md",
23436
23436
  publishConfig: {
23437
23437
  access: "public"
@@ -25285,6 +25285,12 @@ var AgentModelSelectionSchema = external_exports.object({
25285
25285
  var ResolvedAgentModelSelectionSchema = AgentModelSelectionSchema.extend({
25286
25286
  provider: ModelApiTokenProviderSchema
25287
25287
  });
25288
+ var InvalidModelSelectionError = class extends Error {
25289
+ constructor(message) {
25290
+ super(message);
25291
+ this.name = "InvalidModelSelectionError";
25292
+ }
25293
+ };
25288
25294
  var HARNESS_MODEL_RULES = {
25289
25295
  "claude-code": {
25290
25296
  defaultProvider: "anthropic",
@@ -25335,7 +25341,7 @@ function validateReasoningEffortForHarness(input) {
25335
25341
  }
25336
25342
  const rules = modelRulesForHarness(input.harness);
25337
25343
  if (!rules.reasoningEfforts.includes(input.reasoningEffort)) {
25338
- throw new Error(
25344
+ throw new InvalidModelSelectionError(
25339
25345
  `${input.harness} does not support reasoning effort "${input.reasoningEffort}"`
25340
25346
  );
25341
25347
  }
@@ -25372,7 +25378,9 @@ function validateAgentModelFieldsForHarness(spec, context) {
25372
25378
  function validateModelProviderForHarness(harness, provider) {
25373
25379
  const rules = modelRulesForHarness(harness);
25374
25380
  if (!rules.providers.includes(provider)) {
25375
- throw new Error(`${harness} does not support ${provider} models`);
25381
+ throw new InvalidModelSelectionError(
25382
+ `${harness} does not support ${provider} models`
25383
+ );
25376
25384
  }
25377
25385
  }
25378
25386
  function validateModelIdForProvider(input) {
@@ -25386,11 +25394,11 @@ function validateModelIdForProvider(input) {
25386
25394
  return;
25387
25395
  }
25388
25396
  if (curated) {
25389
- throw new Error(
25397
+ throw new InvalidModelSelectionError(
25390
25398
  `${input.provider} model "${input.id}" is not available for ${input.harness}`
25391
25399
  );
25392
25400
  }
25393
- throw new Error(
25401
+ throw new InvalidModelSelectionError(
25394
25402
  `${input.provider} model ids are not open for ${input.harness}`
25395
25403
  );
25396
25404
  }
@@ -61678,7 +61686,8 @@ function claudeAgentOptions(config2, input = {}) {
61678
61686
  includePartialMessages: true,
61679
61687
  thinking: { type: "adaptive", display: "summarized" },
61680
61688
  settings: { showThinkingSummaries: true },
61681
- model: CLAUDE_CODE_DEFAULT_MODEL,
61689
+ model: config2.model?.id ?? CLAUDE_CODE_DEFAULT_MODEL,
61690
+ ...config2.reasoningEffort ? { effort: config2.reasoningEffort } : {},
61682
61691
  permissionMode: "bypassPermissions",
61683
61692
  allowDangerouslySkipPermissions: true,
61684
61693
  pathToClaudeCodeExecutable: claudeCodeExecutablePath(),
@@ -62420,7 +62429,10 @@ var ClaudeAgentBridgeSessionImpl = class {
62420
62429
  );
62421
62430
  return { outcome: "timeout" };
62422
62431
  }
62423
- await delay(CLAUDE_MCP_REGISTRATION_POLL_INTERVAL_MS);
62432
+ await delay(
62433
+ CLAUDE_MCP_REGISTRATION_POLL_INTERVAL_MS,
62434
+ this.abortController.signal
62435
+ );
62424
62436
  }
62425
62437
  }
62426
62438
  messageProbeContext() {
@@ -62575,10 +62587,19 @@ function mcpStatusDetailList(statuses) {
62575
62587
  (server) => server.error ? `${server.name}:${server.status}(${server.error})` : `${server.name}:${server.status}`
62576
62588
  ).join(",");
62577
62589
  }
62578
- function delay(ms) {
62590
+ function delay(ms, signal) {
62591
+ if (signal?.aborted) {
62592
+ return Promise.resolve();
62593
+ }
62579
62594
  return new Promise((resolve2) => {
62580
- const timer = setTimeout(resolve2, ms);
62595
+ const finish = () => {
62596
+ clearTimeout(timer);
62597
+ signal?.removeEventListener("abort", finish);
62598
+ resolve2();
62599
+ };
62600
+ const timer = setTimeout(finish, ms);
62581
62601
  timer.unref?.();
62602
+ signal?.addEventListener("abort", finish, { once: true });
62582
62603
  });
62583
62604
  }
62584
62605
  function claudeAgentUserMessage(message) {
@@ -62675,11 +62696,13 @@ function createClaudeCodeCommandHandler(input) {
62675
62696
  var ClaudeCodeCommandHandler = class {
62676
62697
  constructor(input) {
62677
62698
  this.input = input;
62699
+ this.claudeConfig = input.claude;
62678
62700
  this.outputBuffer = new AgentBridgeOutputBuffer(input);
62679
62701
  }
62680
62702
  input;
62681
62703
  context = null;
62682
62704
  agentSession = null;
62705
+ claudeConfig;
62683
62706
  persistedAgentId = null;
62684
62707
  injectedCommands = /* @__PURE__ */ new Set();
62685
62708
  // Message commands whose injection has started but not settled. A fresh SDK
@@ -62879,6 +62902,7 @@ var ClaudeCodeCommandHandler = class {
62879
62902
  );
62880
62903
  const sendStartedAt = Date.now();
62881
62904
  const mode = deliveryMode(delivery);
62905
+ this.applySelectionForMessage(delivery);
62882
62906
  this.input.runtimeLogger?.info(
62883
62907
  "agent_bridge_claude_command_send_message_started",
62884
62908
  commandLogContext(delivery, {
@@ -63112,7 +63136,7 @@ var ClaudeCodeCommandHandler = class {
63112
63136
  return this.agentSession;
63113
63137
  }
63114
63138
  const session = claudeAgentBridgeRuntime.start({
63115
- claude: this.input.claude,
63139
+ claude: this.claudeConfig,
63116
63140
  resumeAgentId: this.storedResumeAgentId(),
63117
63141
  canUseTool: this.canUseTool,
63118
63142
  onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
@@ -63129,6 +63153,27 @@ var ClaudeCodeCommandHandler = class {
63129
63153
  this.agentSession = session;
63130
63154
  return session;
63131
63155
  }
63156
+ applySelectionForMessage(delivery) {
63157
+ const selection = deliverySelection(delivery);
63158
+ if (!selection.model && selection.reasoningEffort === void 0) {
63159
+ return;
63160
+ }
63161
+ const next = {
63162
+ ...this.claudeConfig,
63163
+ ...selection.model ? { model: selection.model } : {},
63164
+ ...selection.reasoningEffort ? { reasoningEffort: selection.reasoningEffort } : {}
63165
+ };
63166
+ if (sameClaudeConfigSelection(this.claudeConfig, next)) {
63167
+ return;
63168
+ }
63169
+ this.claudeConfig = next;
63170
+ this.agentSession?.close();
63171
+ this.agentSession = null;
63172
+ this.settlePendingQuestions("The runtime restarted to change model");
63173
+ this.input.writeOutput?.(
63174
+ `agent_bridge_claude_model_selection_changed provider=${next.model?.provider ?? ""} model=${next.model?.id ?? ""} reasoning_effort=${next.reasoningEffort ?? ""}`
63175
+ );
63176
+ }
63132
63177
  };
63133
63178
  function withConsumedCommandIds(projection, meta3) {
63134
63179
  const consumedCommandIds = meta3?.consumedCommandIds;
@@ -63153,6 +63198,23 @@ function deliveryMessage(delivery) {
63153
63198
  }
63154
63199
  return null;
63155
63200
  }
63201
+ function deliverySelection(delivery) {
63202
+ const payload = delivery.payload;
63203
+ if (!payload || typeof payload !== "object") {
63204
+ return {};
63205
+ }
63206
+ const model = "model" in payload ? AgentBridgeModelSelectionSchema.safeParse(payload.model) : null;
63207
+ const reasoningEffort = "reasoningEffort" in payload ? AgentBridgeClaudeReasoningEffortSchema.safeParse(
63208
+ payload.reasoningEffort
63209
+ ) : null;
63210
+ return {
63211
+ ...model?.success ? { model: model.data } : {},
63212
+ ...reasoningEffort?.success ? { reasoningEffort: reasoningEffort.data } : {}
63213
+ };
63214
+ }
63215
+ function sameClaudeConfigSelection(current, next) {
63216
+ return current.model?.provider === next.model?.provider && current.model?.id === next.model?.id && current.reasoningEffort === next.reasoningEffort;
63217
+ }
63156
63218
  function deliveryMode(delivery) {
63157
63219
  const payload = delivery.payload;
63158
63220
  if (payload && typeof payload === "object" && "deliveryMode" in payload) {
@@ -63536,9 +63598,12 @@ import { join } from "path";
63536
63598
  var CODEX_EXECUTABLE_PATH = "codex";
63537
63599
  var CODEX_DEFAULT_MODEL = "gpt-5.3-codex";
63538
63600
  var CODEX_HTTP_PROVIDER_ID = "openai-responses-http";
63601
+ var CODEX_OPENROUTER_PROVIDER_ID = "openrouter-responses-http";
63539
63602
  var CODEX_OPENAI_BASE_URL = "https://api.openai.com/v1";
63603
+ var CODEX_OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
63540
63604
  var CODEX_API_KEY_ENV = "OPENAI_API_KEY";
63541
63605
  var MODEL_GATEWAY_OPENAI_BASE_URL_ENV = "AUTO_MODEL_GATEWAY_OPENAI_BASE_URL";
63606
+ var MODEL_GATEWAY_OPENROUTER_BASE_URL_ENV = "AUTO_MODEL_GATEWAY_OPENROUTER_BASE_URL";
63542
63607
  var CODEX_RUNTIME_PROCESS_ENV_KEYS = ["PATH", "HOME"];
63543
63608
  function codexLaunchOptions(config2) {
63544
63609
  return {
@@ -63561,8 +63626,14 @@ function codexThreadParams(config2) {
63561
63626
  }
63562
63627
  function renderCodexConfigToml(config2) {
63563
63628
  const lines = [];
63564
- lines.push(`model = ${tomlString(CODEX_DEFAULT_MODEL)}`);
63565
- lines.push(`model_provider = ${tomlString(CODEX_HTTP_PROVIDER_ID)}`);
63629
+ const selectedProvider = codexProviderIdForModel(config2);
63630
+ lines.push(`model = ${tomlString(config2.model?.id ?? CODEX_DEFAULT_MODEL)}`);
63631
+ lines.push(`model_provider = ${tomlString(selectedProvider)}`);
63632
+ if (config2.reasoningEffort) {
63633
+ lines.push(
63634
+ `model_reasoning_effort = ${tomlString(config2.reasoningEffort)}`
63635
+ );
63636
+ }
63566
63637
  lines.push("");
63567
63638
  lines.push(`[model_providers.${CODEX_HTTP_PROVIDER_ID}]`);
63568
63639
  lines.push('name = "OpenAI"');
@@ -63572,6 +63643,15 @@ function renderCodexConfigToml(config2) {
63572
63643
  lines.push('wire_api = "responses"');
63573
63644
  lines.push(`env_key = ${tomlString(CODEX_API_KEY_ENV)}`);
63574
63645
  lines.push("supports_websockets = false");
63646
+ lines.push("");
63647
+ lines.push(`[model_providers.${CODEX_OPENROUTER_PROVIDER_ID}]`);
63648
+ lines.push('name = "OpenRouter"');
63649
+ lines.push(
63650
+ `base_url = ${tomlString(openRouterBaseUrlForCodexConfig(config2.env))}`
63651
+ );
63652
+ lines.push('wire_api = "responses"');
63653
+ lines.push(`env_key = ${tomlString(CODEX_API_KEY_ENV)}`);
63654
+ lines.push("supports_websockets = false");
63575
63655
  for (const [name23, server] of Object.entries(config2.mcpServers ?? {})) {
63576
63656
  lines.push("");
63577
63657
  lines.push(`[mcp_servers.${tomlKey(name23)}]`);
@@ -63599,6 +63679,12 @@ function codexProcessEnv(env) {
63599
63679
  function openaiBaseUrlForCodexConfig(env) {
63600
63680
  return env[MODEL_GATEWAY_OPENAI_BASE_URL_ENV] ?? CODEX_OPENAI_BASE_URL;
63601
63681
  }
63682
+ function openRouterBaseUrlForCodexConfig(env) {
63683
+ return env[MODEL_GATEWAY_OPENROUTER_BASE_URL_ENV] ?? CODEX_OPENROUTER_BASE_URL;
63684
+ }
63685
+ function codexProviderIdForModel(config2) {
63686
+ return config2.model?.provider === "openrouter" ? CODEX_OPENROUTER_PROVIDER_ID : CODEX_HTTP_PROVIDER_ID;
63687
+ }
63602
63688
  function codexHomeDir() {
63603
63689
  const home = process.env.HOME;
63604
63690
  if (!home) {
@@ -63653,6 +63739,7 @@ var CodexAgentBridgeSessionImpl = class {
63653
63739
  // set means an interrupt/steer would race an unsettled item (FRA-3049 analog).
63654
63740
  pendingToolItemIds = /* @__PURE__ */ new Set();
63655
63741
  settlementWaiters = /* @__PURE__ */ new Set();
63742
+ callbackQueue = Promise.resolve();
63656
63743
  // Messages held in "deferred" mode while a turn is in flight; flushed as a
63657
63744
  // fresh turn once the active turn completes.
63658
63745
  deferredMessages = [];
@@ -63924,10 +64011,12 @@ var CodexAgentBridgeSessionImpl = class {
63924
64011
  return;
63925
64012
  case "notification":
63926
64013
  this.trackNotification(message.notification);
63927
- void this.input.onNotification(message.notification);
64014
+ this.enqueueCallback(
64015
+ () => this.input.onNotification(message.notification)
64016
+ );
63928
64017
  return;
63929
64018
  case "serverRequest":
63930
- void this.input.onServerRequest(message.request);
64019
+ this.enqueueCallback(() => this.input.onServerRequest(message.request));
63931
64020
  return;
63932
64021
  case "elicitation":
63933
64022
  this.writeFrame({
@@ -63953,6 +64042,18 @@ var CodexAgentBridgeSessionImpl = class {
63953
64042
  return;
63954
64043
  }
63955
64044
  }
64045
+ enqueueCallback(callback) {
64046
+ this.callbackQueue = this.callbackQueue.then(async () => {
64047
+ try {
64048
+ await callback();
64049
+ } catch (error51) {
64050
+ try {
64051
+ await this.input.onError(error51);
64052
+ } catch {
64053
+ }
64054
+ }
64055
+ });
64056
+ }
63956
64057
  // Track turn/item lifecycle so steer/interrupt target the live turn and gate on
63957
64058
  // tool-item settlement.
63958
64059
  trackNotification(notification) {
@@ -64090,17 +64191,20 @@ function createCodexCommandHandler(input) {
64090
64191
  var CodexCommandHandler = class {
64091
64192
  constructor(input) {
64092
64193
  this.input = input;
64194
+ this.codexConfig = input.codex;
64093
64195
  this.outputBuffer = new AgentBridgeOutputBuffer(input);
64094
64196
  }
64095
64197
  input;
64096
64198
  context = null;
64097
64199
  session = null;
64200
+ codexConfig;
64098
64201
  injectedCommands = /* @__PURE__ */ new Set();
64099
64202
  // itemId -> JSON-RPC request id of the parked approval request, so an `answer`
64100
64203
  // command keyed by toolCallId (= itemId) can resolve the right server request.
64101
64204
  pendingApprovals = /* @__PURE__ */ new Map();
64102
64205
  outputBuffer;
64103
64206
  projector = new CodexProjector();
64207
+ skipResumeForNextSession = false;
64104
64208
  // ---------------------------------------------------------------------------
64105
64209
  // Lifecycle (public API)
64106
64210
  // ---------------------------------------------------------------------------
@@ -64155,6 +64259,7 @@ var CodexCommandHandler = class {
64155
64259
  }
64156
64260
  this.injectedCommands.add(delivery.commandId);
64157
64261
  try {
64262
+ this.applySelectionForMessage(delivery);
64158
64263
  await this.emitUserMessageEntry(
64159
64264
  activeContext,
64160
64265
  delivery.commandId,
@@ -64288,9 +64393,10 @@ var CodexCommandHandler = class {
64288
64393
  if (this.session) {
64289
64394
  return this.session;
64290
64395
  }
64291
- const resumeThreadId = this.storedResumeThreadId();
64396
+ const resumeThreadId = this.skipResumeForNextSession ? void 0 : this.storedResumeThreadId();
64397
+ this.skipResumeForNextSession = false;
64292
64398
  const session = codexAgentBridgeRuntime.start({
64293
- codex: this.input.codex,
64399
+ codex: this.codexConfig,
64294
64400
  ...resumeThreadId ? { resumeThreadId } : {},
64295
64401
  onNotification: (notification) => this.handleNotification(notification),
64296
64402
  onServerRequest: (request) => this.handleServerRequest(request),
@@ -64307,6 +64413,28 @@ var CodexCommandHandler = class {
64307
64413
  this.session = session;
64308
64414
  return session;
64309
64415
  }
64416
+ applySelectionForMessage(delivery) {
64417
+ const selection = deliverySelection2(delivery);
64418
+ if (!selection.model && selection.reasoningEffort === void 0) {
64419
+ return;
64420
+ }
64421
+ const next = {
64422
+ ...this.codexConfig,
64423
+ ...selection.model ? { model: selection.model } : {},
64424
+ ...selection.reasoningEffort ? { reasoningEffort: selection.reasoningEffort } : {}
64425
+ };
64426
+ if (sameCodexConfigSelection(this.codexConfig, next)) {
64427
+ return;
64428
+ }
64429
+ this.codexConfig = next;
64430
+ this.skipResumeForNextSession = true;
64431
+ this.session?.close();
64432
+ this.session = null;
64433
+ this.pendingApprovals.clear();
64434
+ this.input.writeOutput?.(
64435
+ `agent_bridge_codex_model_selection_changed provider=${next.model?.provider ?? ""} model=${next.model?.id ?? ""} reasoning_effort=${next.reasoningEffort ?? ""}`
64436
+ );
64437
+ }
64310
64438
  storedResumeThreadId() {
64311
64439
  const store = this.input.sessionResume;
64312
64440
  const activeContext = this.context;
@@ -64353,6 +64481,21 @@ function deliveryMessage2(delivery) {
64353
64481
  }
64354
64482
  return null;
64355
64483
  }
64484
+ function deliverySelection2(delivery) {
64485
+ const payload = delivery.payload;
64486
+ if (!payload || typeof payload !== "object") {
64487
+ return {};
64488
+ }
64489
+ const model = "model" in payload ? AgentBridgeModelSelectionSchema.safeParse(payload.model) : null;
64490
+ const reasoningEffort = "reasoningEffort" in payload ? AgentBridgeCodexReasoningEffortSchema.safeParse(payload.reasoningEffort) : null;
64491
+ return {
64492
+ ...model?.success ? { model: model.data } : {},
64493
+ ...reasoningEffort?.success ? { reasoningEffort: reasoningEffort.data } : {}
64494
+ };
64495
+ }
64496
+ function sameCodexConfigSelection(current, next) {
64497
+ return current.model?.provider === next.model?.provider && current.model?.id === next.model?.id && current.reasoningEffort === next.reasoningEffort;
64498
+ }
64356
64499
  function deliveryMode2(delivery) {
64357
64500
  const payload = delivery.payload;
64358
64501
  if (payload && typeof payload === "object" && "deliveryMode" in payload) {
package/dist/index.js CHANGED
@@ -16694,7 +16694,7 @@ function validateReasoningEffortForHarness(input) {
16694
16694
  }
16695
16695
  const rules = modelRulesForHarness(input.harness);
16696
16696
  if (!rules.reasoningEfforts.includes(input.reasoningEffort)) {
16697
- throw new Error(
16697
+ throw new InvalidModelSelectionError(
16698
16698
  `${input.harness} does not support reasoning effort "${input.reasoningEffort}"`
16699
16699
  );
16700
16700
  }
@@ -16731,7 +16731,9 @@ function validateAgentModelFieldsForHarness(spec, context) {
16731
16731
  function validateModelProviderForHarness(harness, provider) {
16732
16732
  const rules = modelRulesForHarness(harness);
16733
16733
  if (!rules.providers.includes(provider)) {
16734
- throw new Error(`${harness} does not support ${provider} models`);
16734
+ throw new InvalidModelSelectionError(
16735
+ `${harness} does not support ${provider} models`
16736
+ );
16735
16737
  }
16736
16738
  }
16737
16739
  function validateModelIdForProvider(input) {
@@ -16745,15 +16747,15 @@ function validateModelIdForProvider(input) {
16745
16747
  return;
16746
16748
  }
16747
16749
  if (curated) {
16748
- throw new Error(
16750
+ throw new InvalidModelSelectionError(
16749
16751
  `${input.provider} model "${input.id}" is not available for ${input.harness}`
16750
16752
  );
16751
16753
  }
16752
- throw new Error(
16754
+ throw new InvalidModelSelectionError(
16753
16755
  `${input.provider} model ids are not open for ${input.harness}`
16754
16756
  );
16755
16757
  }
16756
- var MODEL_API_TOKEN_PROVIDERS, ModelApiTokenProviderSchema, CLAUDE_CODE_REASONING_EFFORTS, CODEX_REASONING_EFFORTS, ClaudeCodeReasoningEffortSchema, CodexReasoningEffortSchema, AgentReasoningEffortSchema, OPENROUTER_MODEL_SLUG_PATTERN, AgentModelSelectionSchema, ResolvedAgentModelSelectionSchema, HARNESS_MODEL_RULES;
16758
+ var MODEL_API_TOKEN_PROVIDERS, ModelApiTokenProviderSchema, CLAUDE_CODE_REASONING_EFFORTS, CODEX_REASONING_EFFORTS, ClaudeCodeReasoningEffortSchema, CodexReasoningEffortSchema, AgentReasoningEffortSchema, OPENROUTER_MODEL_SLUG_PATTERN, AgentModelSelectionSchema, ResolvedAgentModelSelectionSchema, InvalidModelSelectionError, HARNESS_MODEL_RULES;
16757
16759
  var init_model_selection = __esm({
16758
16760
  "../../packages/schemas/src/model-selection.ts"() {
16759
16761
  "use strict";
@@ -16797,6 +16799,12 @@ var init_model_selection = __esm({
16797
16799
  ResolvedAgentModelSelectionSchema = AgentModelSelectionSchema.extend({
16798
16800
  provider: ModelApiTokenProviderSchema
16799
16801
  });
16802
+ InvalidModelSelectionError = class extends Error {
16803
+ constructor(message) {
16804
+ super(message);
16805
+ this.name = "InvalidModelSelectionError";
16806
+ }
16807
+ };
16800
16808
  HARNESS_MODEL_RULES = {
16801
16809
  "claude-code": {
16802
16810
  defaultProvider: "anthropic",
@@ -27058,7 +27066,7 @@ var init_package = __esm({
27058
27066
  "package.json"() {
27059
27067
  package_default = {
27060
27068
  name: "@autohq/cli",
27061
- version: "0.1.316",
27069
+ version: "0.1.317",
27062
27070
  license: "SEE LICENSE IN README.md",
27063
27071
  publishConfig: {
27064
27072
  access: "public"
@@ -39219,7 +39227,8 @@ function claudeAgentOptions(config2, input = {}) {
39219
39227
  includePartialMessages: true,
39220
39228
  thinking: { type: "adaptive", display: "summarized" },
39221
39229
  settings: { showThinkingSummaries: true },
39222
- model: CLAUDE_CODE_DEFAULT_MODEL,
39230
+ model: config2.model?.id ?? CLAUDE_CODE_DEFAULT_MODEL,
39231
+ ...config2.reasoningEffort ? { effort: config2.reasoningEffort } : {},
39223
39232
  permissionMode: "bypassPermissions",
39224
39233
  allowDangerouslySkipPermissions: true,
39225
39234
  pathToClaudeCodeExecutable: claudeCodeExecutablePath(),
@@ -39961,7 +39970,10 @@ var ClaudeAgentBridgeSessionImpl = class {
39961
39970
  );
39962
39971
  return { outcome: "timeout" };
39963
39972
  }
39964
- await delay(CLAUDE_MCP_REGISTRATION_POLL_INTERVAL_MS);
39973
+ await delay(
39974
+ CLAUDE_MCP_REGISTRATION_POLL_INTERVAL_MS,
39975
+ this.abortController.signal
39976
+ );
39965
39977
  }
39966
39978
  }
39967
39979
  messageProbeContext() {
@@ -40116,10 +40128,19 @@ function mcpStatusDetailList(statuses) {
40116
40128
  (server) => server.error ? `${server.name}:${server.status}(${server.error})` : `${server.name}:${server.status}`
40117
40129
  ).join(",");
40118
40130
  }
40119
- function delay(ms) {
40131
+ function delay(ms, signal) {
40132
+ if (signal?.aborted) {
40133
+ return Promise.resolve();
40134
+ }
40120
40135
  return new Promise((resolve4) => {
40121
- const timer = setTimeout(resolve4, ms);
40136
+ const finish = () => {
40137
+ clearTimeout(timer);
40138
+ signal?.removeEventListener("abort", finish);
40139
+ resolve4();
40140
+ };
40141
+ const timer = setTimeout(finish, ms);
40122
40142
  timer.unref?.();
40143
+ signal?.addEventListener("abort", finish, { once: true });
40123
40144
  });
40124
40145
  }
40125
40146
  function claudeAgentUserMessage(message) {
@@ -40216,11 +40237,13 @@ function createClaudeCodeCommandHandler(input) {
40216
40237
  var ClaudeCodeCommandHandler = class {
40217
40238
  constructor(input) {
40218
40239
  this.input = input;
40240
+ this.claudeConfig = input.claude;
40219
40241
  this.outputBuffer = new AgentBridgeOutputBuffer(input);
40220
40242
  }
40221
40243
  input;
40222
40244
  context = null;
40223
40245
  agentSession = null;
40246
+ claudeConfig;
40224
40247
  persistedAgentId = null;
40225
40248
  injectedCommands = /* @__PURE__ */ new Set();
40226
40249
  // Message commands whose injection has started but not settled. A fresh SDK
@@ -40420,6 +40443,7 @@ var ClaudeCodeCommandHandler = class {
40420
40443
  );
40421
40444
  const sendStartedAt = Date.now();
40422
40445
  const mode = deliveryMode(delivery);
40446
+ this.applySelectionForMessage(delivery);
40423
40447
  this.input.runtimeLogger?.info(
40424
40448
  "agent_bridge_claude_command_send_message_started",
40425
40449
  commandLogContext(delivery, {
@@ -40653,7 +40677,7 @@ var ClaudeCodeCommandHandler = class {
40653
40677
  return this.agentSession;
40654
40678
  }
40655
40679
  const session = claudeAgentBridgeRuntime.start({
40656
- claude: this.input.claude,
40680
+ claude: this.claudeConfig,
40657
40681
  resumeAgentId: this.storedResumeAgentId(),
40658
40682
  canUseTool: this.canUseTool,
40659
40683
  onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
@@ -40670,6 +40694,27 @@ var ClaudeCodeCommandHandler = class {
40670
40694
  this.agentSession = session;
40671
40695
  return session;
40672
40696
  }
40697
+ applySelectionForMessage(delivery) {
40698
+ const selection = deliverySelection(delivery);
40699
+ if (!selection.model && selection.reasoningEffort === void 0) {
40700
+ return;
40701
+ }
40702
+ const next = {
40703
+ ...this.claudeConfig,
40704
+ ...selection.model ? { model: selection.model } : {},
40705
+ ...selection.reasoningEffort ? { reasoningEffort: selection.reasoningEffort } : {}
40706
+ };
40707
+ if (sameClaudeConfigSelection(this.claudeConfig, next)) {
40708
+ return;
40709
+ }
40710
+ this.claudeConfig = next;
40711
+ this.agentSession?.close();
40712
+ this.agentSession = null;
40713
+ this.settlePendingQuestions("The runtime restarted to change model");
40714
+ this.input.writeOutput?.(
40715
+ `agent_bridge_claude_model_selection_changed provider=${next.model?.provider ?? ""} model=${next.model?.id ?? ""} reasoning_effort=${next.reasoningEffort ?? ""}`
40716
+ );
40717
+ }
40673
40718
  };
40674
40719
  function withConsumedCommandIds(projection, meta3) {
40675
40720
  const consumedCommandIds = meta3?.consumedCommandIds;
@@ -40694,6 +40739,23 @@ function deliveryMessage(delivery) {
40694
40739
  }
40695
40740
  return null;
40696
40741
  }
40742
+ function deliverySelection(delivery) {
40743
+ const payload = delivery.payload;
40744
+ if (!payload || typeof payload !== "object") {
40745
+ return {};
40746
+ }
40747
+ const model = "model" in payload ? AgentBridgeModelSelectionSchema.safeParse(payload.model) : null;
40748
+ const reasoningEffort = "reasoningEffort" in payload ? AgentBridgeClaudeReasoningEffortSchema.safeParse(
40749
+ payload.reasoningEffort
40750
+ ) : null;
40751
+ return {
40752
+ ...model?.success ? { model: model.data } : {},
40753
+ ...reasoningEffort?.success ? { reasoningEffort: reasoningEffort.data } : {}
40754
+ };
40755
+ }
40756
+ function sameClaudeConfigSelection(current, next) {
40757
+ return current.model?.provider === next.model?.provider && current.model?.id === next.model?.id && current.reasoningEffort === next.reasoningEffort;
40758
+ }
40697
40759
  function deliveryMode(delivery) {
40698
40760
  const payload = delivery.payload;
40699
40761
  if (payload && typeof payload === "object" && "deliveryMode" in payload) {
@@ -41082,9 +41144,12 @@ import { join as join3 } from "path";
41082
41144
  var CODEX_EXECUTABLE_PATH = "codex";
41083
41145
  var CODEX_DEFAULT_MODEL = "gpt-5.3-codex";
41084
41146
  var CODEX_HTTP_PROVIDER_ID = "openai-responses-http";
41147
+ var CODEX_OPENROUTER_PROVIDER_ID = "openrouter-responses-http";
41085
41148
  var CODEX_OPENAI_BASE_URL = "https://api.openai.com/v1";
41149
+ var CODEX_OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
41086
41150
  var CODEX_API_KEY_ENV = "OPENAI_API_KEY";
41087
41151
  var MODEL_GATEWAY_OPENAI_BASE_URL_ENV = "AUTO_MODEL_GATEWAY_OPENAI_BASE_URL";
41152
+ var MODEL_GATEWAY_OPENROUTER_BASE_URL_ENV = "AUTO_MODEL_GATEWAY_OPENROUTER_BASE_URL";
41088
41153
  var CODEX_RUNTIME_PROCESS_ENV_KEYS = ["PATH", "HOME"];
41089
41154
  function codexLaunchOptions(config2) {
41090
41155
  return {
@@ -41107,8 +41172,14 @@ function codexThreadParams(config2) {
41107
41172
  }
41108
41173
  function renderCodexConfigToml(config2) {
41109
41174
  const lines = [];
41110
- lines.push(`model = ${tomlString(CODEX_DEFAULT_MODEL)}`);
41111
- lines.push(`model_provider = ${tomlString(CODEX_HTTP_PROVIDER_ID)}`);
41175
+ const selectedProvider = codexProviderIdForModel(config2);
41176
+ lines.push(`model = ${tomlString(config2.model?.id ?? CODEX_DEFAULT_MODEL)}`);
41177
+ lines.push(`model_provider = ${tomlString(selectedProvider)}`);
41178
+ if (config2.reasoningEffort) {
41179
+ lines.push(
41180
+ `model_reasoning_effort = ${tomlString(config2.reasoningEffort)}`
41181
+ );
41182
+ }
41112
41183
  lines.push("");
41113
41184
  lines.push(`[model_providers.${CODEX_HTTP_PROVIDER_ID}]`);
41114
41185
  lines.push('name = "OpenAI"');
@@ -41118,6 +41189,15 @@ function renderCodexConfigToml(config2) {
41118
41189
  lines.push('wire_api = "responses"');
41119
41190
  lines.push(`env_key = ${tomlString(CODEX_API_KEY_ENV)}`);
41120
41191
  lines.push("supports_websockets = false");
41192
+ lines.push("");
41193
+ lines.push(`[model_providers.${CODEX_OPENROUTER_PROVIDER_ID}]`);
41194
+ lines.push('name = "OpenRouter"');
41195
+ lines.push(
41196
+ `base_url = ${tomlString(openRouterBaseUrlForCodexConfig(config2.env))}`
41197
+ );
41198
+ lines.push('wire_api = "responses"');
41199
+ lines.push(`env_key = ${tomlString(CODEX_API_KEY_ENV)}`);
41200
+ lines.push("supports_websockets = false");
41121
41201
  for (const [name, server] of Object.entries(config2.mcpServers ?? {})) {
41122
41202
  lines.push("");
41123
41203
  lines.push(`[mcp_servers.${tomlKey(name)}]`);
@@ -41145,6 +41225,12 @@ function codexProcessEnv(env) {
41145
41225
  function openaiBaseUrlForCodexConfig(env) {
41146
41226
  return env[MODEL_GATEWAY_OPENAI_BASE_URL_ENV] ?? CODEX_OPENAI_BASE_URL;
41147
41227
  }
41228
+ function openRouterBaseUrlForCodexConfig(env) {
41229
+ return env[MODEL_GATEWAY_OPENROUTER_BASE_URL_ENV] ?? CODEX_OPENROUTER_BASE_URL;
41230
+ }
41231
+ function codexProviderIdForModel(config2) {
41232
+ return config2.model?.provider === "openrouter" ? CODEX_OPENROUTER_PROVIDER_ID : CODEX_HTTP_PROVIDER_ID;
41233
+ }
41148
41234
  function codexHomeDir() {
41149
41235
  const home = process.env.HOME;
41150
41236
  if (!home) {
@@ -41199,6 +41285,7 @@ var CodexAgentBridgeSessionImpl = class {
41199
41285
  // set means an interrupt/steer would race an unsettled item (FRA-3049 analog).
41200
41286
  pendingToolItemIds = /* @__PURE__ */ new Set();
41201
41287
  settlementWaiters = /* @__PURE__ */ new Set();
41288
+ callbackQueue = Promise.resolve();
41202
41289
  // Messages held in "deferred" mode while a turn is in flight; flushed as a
41203
41290
  // fresh turn once the active turn completes.
41204
41291
  deferredMessages = [];
@@ -41470,10 +41557,12 @@ var CodexAgentBridgeSessionImpl = class {
41470
41557
  return;
41471
41558
  case "notification":
41472
41559
  this.trackNotification(message.notification);
41473
- void this.input.onNotification(message.notification);
41560
+ this.enqueueCallback(
41561
+ () => this.input.onNotification(message.notification)
41562
+ );
41474
41563
  return;
41475
41564
  case "serverRequest":
41476
- void this.input.onServerRequest(message.request);
41565
+ this.enqueueCallback(() => this.input.onServerRequest(message.request));
41477
41566
  return;
41478
41567
  case "elicitation":
41479
41568
  this.writeFrame({
@@ -41499,6 +41588,18 @@ var CodexAgentBridgeSessionImpl = class {
41499
41588
  return;
41500
41589
  }
41501
41590
  }
41591
+ enqueueCallback(callback) {
41592
+ this.callbackQueue = this.callbackQueue.then(async () => {
41593
+ try {
41594
+ await callback();
41595
+ } catch (error51) {
41596
+ try {
41597
+ await this.input.onError(error51);
41598
+ } catch {
41599
+ }
41600
+ }
41601
+ });
41602
+ }
41502
41603
  // Track turn/item lifecycle so steer/interrupt target the live turn and gate on
41503
41604
  // tool-item settlement.
41504
41605
  trackNotification(notification) {
@@ -41636,17 +41737,20 @@ function createCodexCommandHandler(input) {
41636
41737
  var CodexCommandHandler = class {
41637
41738
  constructor(input) {
41638
41739
  this.input = input;
41740
+ this.codexConfig = input.codex;
41639
41741
  this.outputBuffer = new AgentBridgeOutputBuffer(input);
41640
41742
  }
41641
41743
  input;
41642
41744
  context = null;
41643
41745
  session = null;
41746
+ codexConfig;
41644
41747
  injectedCommands = /* @__PURE__ */ new Set();
41645
41748
  // itemId -> JSON-RPC request id of the parked approval request, so an `answer`
41646
41749
  // command keyed by toolCallId (= itemId) can resolve the right server request.
41647
41750
  pendingApprovals = /* @__PURE__ */ new Map();
41648
41751
  outputBuffer;
41649
41752
  projector = new CodexProjector();
41753
+ skipResumeForNextSession = false;
41650
41754
  // ---------------------------------------------------------------------------
41651
41755
  // Lifecycle (public API)
41652
41756
  // ---------------------------------------------------------------------------
@@ -41701,6 +41805,7 @@ var CodexCommandHandler = class {
41701
41805
  }
41702
41806
  this.injectedCommands.add(delivery.commandId);
41703
41807
  try {
41808
+ this.applySelectionForMessage(delivery);
41704
41809
  await this.emitUserMessageEntry(
41705
41810
  activeContext,
41706
41811
  delivery.commandId,
@@ -41834,9 +41939,10 @@ var CodexCommandHandler = class {
41834
41939
  if (this.session) {
41835
41940
  return this.session;
41836
41941
  }
41837
- const resumeThreadId = this.storedResumeThreadId();
41942
+ const resumeThreadId = this.skipResumeForNextSession ? void 0 : this.storedResumeThreadId();
41943
+ this.skipResumeForNextSession = false;
41838
41944
  const session = codexAgentBridgeRuntime.start({
41839
- codex: this.input.codex,
41945
+ codex: this.codexConfig,
41840
41946
  ...resumeThreadId ? { resumeThreadId } : {},
41841
41947
  onNotification: (notification) => this.handleNotification(notification),
41842
41948
  onServerRequest: (request) => this.handleServerRequest(request),
@@ -41853,6 +41959,28 @@ var CodexCommandHandler = class {
41853
41959
  this.session = session;
41854
41960
  return session;
41855
41961
  }
41962
+ applySelectionForMessage(delivery) {
41963
+ const selection = deliverySelection2(delivery);
41964
+ if (!selection.model && selection.reasoningEffort === void 0) {
41965
+ return;
41966
+ }
41967
+ const next = {
41968
+ ...this.codexConfig,
41969
+ ...selection.model ? { model: selection.model } : {},
41970
+ ...selection.reasoningEffort ? { reasoningEffort: selection.reasoningEffort } : {}
41971
+ };
41972
+ if (sameCodexConfigSelection(this.codexConfig, next)) {
41973
+ return;
41974
+ }
41975
+ this.codexConfig = next;
41976
+ this.skipResumeForNextSession = true;
41977
+ this.session?.close();
41978
+ this.session = null;
41979
+ this.pendingApprovals.clear();
41980
+ this.input.writeOutput?.(
41981
+ `agent_bridge_codex_model_selection_changed provider=${next.model?.provider ?? ""} model=${next.model?.id ?? ""} reasoning_effort=${next.reasoningEffort ?? ""}`
41982
+ );
41983
+ }
41856
41984
  storedResumeThreadId() {
41857
41985
  const store = this.input.sessionResume;
41858
41986
  const activeContext = this.context;
@@ -41899,6 +42027,21 @@ function deliveryMessage2(delivery) {
41899
42027
  }
41900
42028
  return null;
41901
42029
  }
42030
+ function deliverySelection2(delivery) {
42031
+ const payload = delivery.payload;
42032
+ if (!payload || typeof payload !== "object") {
42033
+ return {};
42034
+ }
42035
+ const model = "model" in payload ? AgentBridgeModelSelectionSchema.safeParse(payload.model) : null;
42036
+ const reasoningEffort = "reasoningEffort" in payload ? AgentBridgeCodexReasoningEffortSchema.safeParse(payload.reasoningEffort) : null;
42037
+ return {
42038
+ ...model?.success ? { model: model.data } : {},
42039
+ ...reasoningEffort?.success ? { reasoningEffort: reasoningEffort.data } : {}
42040
+ };
42041
+ }
42042
+ function sameCodexConfigSelection(current, next) {
42043
+ return current.model?.provider === next.model?.provider && current.model?.id === next.model?.id && current.reasoningEffort === next.reasoningEffort;
42044
+ }
41902
42045
  function deliveryMode2(delivery) {
41903
42046
  const payload = delivery.payload;
41904
42047
  if (payload && typeof payload === "object" && "deliveryMode" in payload) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.316",
3
+ "version": "0.1.317",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"