openmausbot 0.1.87 → 0.1.88

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.
Files changed (149) hide show
  1. package/README.md +2 -1
  2. package/dist/assets/{abnfDiagram-O67JEVCF-BTiuL79F.js → abnfDiagram-O67JEVCF-qd9VD3GV.js} +1 -1
  3. package/dist/assets/{arc-C88Blc2v.js → arc-3RwkUjRe.js} +1 -1
  4. package/dist/assets/{architectureDiagram-NJMV4G6O-BZsJIZrb.js → architectureDiagram-NJMV4G6O-CFKSJS7a.js} +1 -1
  5. package/dist/assets/{blockDiagram-BEXU5L5S-CVeMe9Ah.js → blockDiagram-BEXU5L5S-CG1rEfWD.js} +1 -1
  6. package/dist/assets/{c4Diagram-YGBWAQC7-Cedk3Bhx.js → c4Diagram-YGBWAQC7-CBW9N664.js} +1 -1
  7. package/dist/assets/channel-CnRnO3tF.js +1 -0
  8. package/dist/assets/{chunk-2Q5K7J3B-D-VRqzTB.js → chunk-2Q5K7J3B-2mRfTksB.js} +1 -1
  9. package/dist/assets/{chunk-3FUC2YCW-BChov01Y.js → chunk-3FUC2YCW-Cv1dpErj.js} +2 -2
  10. package/dist/assets/{chunk-5VM5RSS4-C-TfwvHy.js → chunk-5VM5RSS4-B7IACJp-.js} +1 -1
  11. package/dist/assets/{chunk-GTNCS2PH-Db7CGj5Y.js → chunk-GTNCS2PH-An0hZtYa.js} +1 -1
  12. package/dist/assets/{chunk-GWA4HPMP-CNvIfqKT.js → chunk-GWA4HPMP-BcJB2nEm.js} +1 -1
  13. package/dist/assets/{chunk-JWPE2WC7-C_bEp5tq.js → chunk-JWPE2WC7-CV_W7TN7.js} +1 -1
  14. package/dist/assets/{chunk-NETBCI7D-Coi4BOls.js → chunk-NETBCI7D-Bcs_kwnA.js} +1 -1
  15. package/dist/assets/{chunk-WEXAMYUT-CzylEuL3.js → chunk-WEXAMYUT-lrx_DxFP.js} +1 -1
  16. package/dist/assets/{chunk-XXDRQBXY-m7p7ztaD.js → chunk-XXDRQBXY-DabHlLGM.js} +1 -1
  17. package/dist/assets/{classDiagram-v2-NBCMYWYE-BMy6o9x2.js → classDiagram-v2-NBCMYWYE-BnHj6P7d.js} +1 -1
  18. package/dist/assets/{cose-bilkent-JH36ORCC-BDQ__0_J.js → cose-bilkent-JH36ORCC-CfLp6UDi.js} +1 -1
  19. package/dist/assets/{cynefin-OW5HDTMX-Djv4ghUb.js → cynefin-OW5HDTMX-Dm4dbVA1.js} +1 -1
  20. package/dist/assets/{cynefinDiagram-VND7K2PF-BULrlGYH.js → cynefinDiagram-VND7K2PF-B9mH-PID.js} +1 -1
  21. package/dist/assets/{dagre-6A5THRUB-D-jrT_hU.js → dagre-6A5THRUB-DDc_NVQJ.js} +1 -1
  22. package/dist/assets/{diagram-22UHCM2B-p2UhQmfL.js → diagram-22UHCM2B-lwr8Ip8-.js} +1 -1
  23. package/dist/assets/{diagram-3UASUU5V-DHvGWZ7q.js → diagram-3UASUU5V-BLLe6dmI.js} +1 -1
  24. package/dist/assets/{diagram-ATOU4E4O-ChhKDot-.js → diagram-ATOU4E4O-6eUIq4lz.js} +1 -1
  25. package/dist/assets/{diagram-CDSNMT55-B-T7A43R.js → diagram-CDSNMT55-O-pRN7VQ.js} +1 -1
  26. package/dist/assets/{diagram-MLGK6HIB-CJm8ENNY.js → diagram-MLGK6HIB-BietvGAI.js} +1 -1
  27. package/dist/assets/{diagram-MPIPVDR6-510tlza8.js → diagram-MPIPVDR6-Bd2Cl62X.js} +1 -1
  28. package/dist/assets/{ebnfDiagram-ZINNZB2B-PkvRPHel.js → ebnfDiagram-ZINNZB2B-B6iDy69W.js} +1 -1
  29. package/dist/assets/{elk-276RUBZZ-BVBVPoX3.js → elk-276RUBZZ-DQVHfKe0.js} +1 -1
  30. package/dist/assets/{erDiagram-OPXOYQCR-BgYMVm7L.js → erDiagram-OPXOYQCR-BWdVp2tQ.js} +1 -1
  31. package/dist/assets/{flowDiagram-KWPJA3E3-BGqsnc_3.js → flowDiagram-KWPJA3E3-WLE6rKB4.js} +1 -1
  32. package/dist/assets/{ganttDiagram-FUAMR5RP-D_-UeReH.js → ganttDiagram-FUAMR5RP-BbjS-4gn.js} +1 -1
  33. package/dist/assets/{gitGraphDiagram-X574FWY7-D0uooONx.js → gitGraphDiagram-X574FWY7-Dpy2QSGq.js} +1 -1
  34. package/dist/assets/index-BIMdIbaw.css +1 -0
  35. package/dist/assets/index-CHnODCr2.js +583 -0
  36. package/dist/assets/{index-zRsJERGJ.js → index-CIaHn5NS.js} +1 -1
  37. package/dist/assets/{infoDiagram-VRGFBTTK-B9e1z77f.js → infoDiagram-VRGFBTTK-D_jKWlKe.js} +1 -1
  38. package/dist/assets/{ishikawaDiagram-OU5B5YK6-BB4vNwvD.js → ishikawaDiagram-OU5B5YK6-DLJohSuK.js} +1 -1
  39. package/dist/assets/{journeyDiagram-ZHPQQLJL-DpkosOTB.js → journeyDiagram-ZHPQQLJL-DPOFj0qN.js} +1 -1
  40. package/dist/assets/{kanban-definition-PNTS6WVX-DbDP4kUu.js → kanban-definition-PNTS6WVX-BI7v-xpK.js} +1 -1
  41. package/dist/assets/{linear-DBJGPmjT.js → linear-C2pWPSxO.js} +1 -1
  42. package/dist/assets/{mermaid.core-DWPRi-ue.js → mermaid.core-CR-j5WQU.js} +5 -5
  43. package/dist/assets/{mindmap-definition-NLK3R4M7-nszBbJmx.js → mindmap-definition-NLK3R4M7-lz9GvXRh.js} +1 -1
  44. package/dist/assets/{pegDiagram-GJSIUBJH-CWykJWu_.js → pegDiagram-GJSIUBJH-Dl4_ia61.js} +1 -1
  45. package/dist/assets/{pieDiagram-5QR66LMP-g3Da-Vnv.js → pieDiagram-5QR66LMP-DWuT3n88.js} +1 -1
  46. package/dist/assets/{quadrantDiagram-O4NWA36T-Wzrlpzgh.js → quadrantDiagram-O4NWA36T-DXWe9Jx7.js} +1 -1
  47. package/dist/assets/{railroadDiagram-XR7U4H2S-moHTFMC0.js → railroadDiagram-XR7U4H2S-COY1IBVY.js} +1 -1
  48. package/dist/assets/{requirementDiagram-PLB6GJNP-CwfXdFH8.js → requirementDiagram-PLB6GJNP-DnyVuhsQ.js} +1 -1
  49. package/dist/assets/{sankeyDiagram-IPEJSGJF-3ZROYvnq.js → sankeyDiagram-IPEJSGJF-BSc4NdGK.js} +1 -1
  50. package/dist/assets/{sequenceDiagram-PO4LG4MO-E1TBebP8.js → sequenceDiagram-PO4LG4MO-kqEU2EGq.js} +1 -1
  51. package/dist/assets/{sizeCapture-INFHLROL-DHKEU5pu.js → sizeCapture-INFHLROL-BvB4bkWD.js} +1 -1
  52. package/dist/assets/{stateDiagram-v2-GCMORJYK-BguEj09D.js → stateDiagram-v2-GCMORJYK-BIrqNv7y.js} +1 -1
  53. package/dist/assets/{swimlanes-2SLR337P-C7IDYnhd.js → swimlanes-2SLR337P-CFnalQUE.js} +1 -1
  54. package/dist/assets/swimlanesDiagram-TC7HE7FX-C4a8qNGj.js +8 -0
  55. package/dist/assets/{timeline-definition-EJHVYXUP-DCW-F5PW.js → timeline-definition-EJHVYXUP-CsSWJnSQ.js} +1 -1
  56. package/dist/assets/{usecaseDiagram-POWQR4AR-xBMFtWYV.js → usecaseDiagram-POWQR4AR-DkAmJ1EE.js} +1 -1
  57. package/dist/assets/{vennDiagram-UO4OBE2U-B5nIkuH8.js → vennDiagram-UO4OBE2U-C3vd9drL.js} +1 -1
  58. package/dist/assets/{wardleyDiagram-VNRHLVJA-DYFAhdbr.js → wardleyDiagram-VNRHLVJA-j26CM-pi.js} +1 -1
  59. package/dist/assets/{xychartDiagram-PMCCYNJV-DeXwX6Cz.js → xychartDiagram-PMCCYNJV-BYu1Q_at.js} +1 -1
  60. package/dist/index.html +2 -2
  61. package/dist-server/companion/src/routes.js +8 -1
  62. package/dist-server/connector-proxy.js +105 -1
  63. package/dist-server/container-mcp.js +3 -1
  64. package/dist-server/drivers/agents-proxy.js +277 -22
  65. package/dist-server/index.js +23150 -19947
  66. package/dist-server/local-computer-proxy.js +2 -0
  67. package/dist-server/mcp-gate.js +2 -0
  68. package/dist-server/mcp-server.js +5 -3
  69. package/dist-server/message-search.worker.js +52 -0
  70. package/dist-server/openmausbot.js +540 -298
  71. package/dist-server/pair-cli.js +540 -298
  72. package/dist-server/server/admission.js +81 -0
  73. package/dist-server/server/aside-queue.js +294 -0
  74. package/dist-server/server/attachments.js +43 -1
  75. package/dist-server/server/bot-attachment.js +107 -0
  76. package/dist-server/server/bot-overview.js +19 -0
  77. package/dist-server/server/cli-api-setup.js +1 -0
  78. package/dist-server/server/composio.js +297 -1
  79. package/dist-server/server/config.js +25 -3
  80. package/dist-server/server/connector-advertisement.js +165 -0
  81. package/dist-server/server/connector-proxy.js +14 -2
  82. package/dist-server/server/connector-verdict.js +31 -4
  83. package/dist-server/server/container-computer.js +60 -0
  84. package/dist-server/server/contracts.js +22 -0
  85. package/dist-server/server/drivers/acp/core.js +24 -6
  86. package/dist-server/server/drivers/acp/cursor.js +3 -7
  87. package/dist-server/server/drivers/acp/droid.js +4 -7
  88. package/dist-server/server/drivers/acp/gemini.js +4 -4
  89. package/dist-server/server/drivers/acp/grok.js +4 -9
  90. package/dist-server/server/drivers/acp/hermes.js +3 -5
  91. package/dist-server/server/drivers/acp/opencode-go.js +2 -5
  92. package/dist-server/server/drivers/acp/qwen.js +9 -15
  93. package/dist-server/server/drivers/agents-call.js +137 -10
  94. package/dist-server/server/drivers/agents-catalog.js +100 -6
  95. package/dist-server/server/drivers/boxagent.js +2 -16
  96. package/dist-server/server/drivers/claude.js +31 -17
  97. package/dist-server/server/drivers/codex-catalog.js +14 -6
  98. package/dist-server/server/drivers/codex-identity.js +2 -1
  99. package/dist-server/server/drivers/codex-release.js +48 -0
  100. package/dist-server/server/drivers/codex.js +7 -25
  101. package/dist-server/server/drivers/openai-chat.js +26 -2
  102. package/dist-server/server/drivers/pi.js +237 -30
  103. package/dist-server/server/drivers/prompt-split.js +32 -9
  104. package/dist-server/server/drivers/session-idle.js +29 -0
  105. package/dist-server/server/env-path.js +15 -0
  106. package/dist-server/server/guarded-requests.js +2 -2
  107. package/dist-server/server/harness-capabilities.js +46 -0
  108. package/dist-server/server/index.js +1037 -209
  109. package/dist-server/server/message-db.js +22 -42
  110. package/dist-server/server/message-file.js +9 -1
  111. package/dist-server/server/message-search-query.js +43 -0
  112. package/dist-server/server/message-search-worker.js +80 -0
  113. package/dist-server/server/message-search.worker.js +21 -0
  114. package/dist-server/server/model-requests.js +248 -0
  115. package/dist-server/server/options-card.js +21 -0
  116. package/dist-server/server/org-library.js +15 -1
  117. package/dist-server/server/peer-delivery.js +60 -0
  118. package/dist-server/server/peer-roster.js +57 -0
  119. package/dist-server/server/presets.js +32 -32
  120. package/dist-server/server/profile-requests.js +66 -39
  121. package/dist-server/server/profile-revision.js +9 -1
  122. package/dist-server/server/profile-versions.js +6 -3
  123. package/dist-server/server/routine-requests.js +29 -7
  124. package/dist-server/server/skill-fetch.js +72 -14
  125. package/dist-server/server/skills.js +1 -0
  126. package/dist-server/server/store.js +32 -2
  127. package/dist-server/server/system-prompt.js +26 -2
  128. package/dist-server/server/team-setup-requests.js +124 -23
  129. package/dist-server/server/thread-events.js +3 -1
  130. package/dist-server/server/tightening-requests.js +405 -0
  131. package/dist-server/server/tts/chatterbox.js +27 -5
  132. package/dist-server/server/usage-ledger.js +7 -1
  133. package/dist-server/server/workspace-backup.js +40 -3
  134. package/dist-server/server/workspace-backup.worker.js +10 -0
  135. package/dist-server/shared/ask-question.js +19 -0
  136. package/dist-server/shared/credential-request.js +5 -1
  137. package/dist-server/shared/line-diff.js +23 -0
  138. package/dist-server/shared/model-request.js +1 -0
  139. package/dist-server/shared/options-card.js +51 -0
  140. package/dist-server/shared/profile-request.js +5 -4
  141. package/dist-server/shared/tightening-request.js +87 -0
  142. package/dist-server/src/lib/composer-attachments.js +25 -3
  143. package/dist-server/vps-container-mcp.js +3 -1
  144. package/dist-server/workspace-backup.worker.js +19474 -0
  145. package/package.json +1 -1
  146. package/dist/assets/channel-taCNRlUU.js +0 -1
  147. package/dist/assets/index-BwdMAQ6p.css +0 -1
  148. package/dist/assets/index-ByJennr7.js +0 -581
  149. package/dist/assets/swimlanesDiagram-TC7HE7FX-BpEdoB2e.js +0 -8
@@ -17791,6 +17791,14 @@ var init_wire = __esm({
17791
17791
  function isModelVariant(value) {
17792
17792
  return typeof value === "string" && value.length > 0 && value.length <= 256 && value.trim() === value && !new RegExp("\\p{Cc}", "u").test(value);
17793
17793
  }
17794
+ function titleCaseModelId(id, wordBreaks) {
17795
+ return id.split(wordBreaks).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
17796
+ }
17797
+ function qualifiedModelLabel(id, qualifier, options = {}) {
17798
+ const { redundantWhen = () => false, decorate = (facet) => ` \u2014 ${facet}` } = options;
17799
+ if (!qualifier || redundantWhen(id, qualifier)) return id;
17800
+ return `${id}${decorate(qualifier)}`;
17801
+ }
17794
17802
  var eventCounter, newEventId, newId;
17795
17803
  var init_contracts = __esm({
17796
17804
  "server/contracts.ts"() {
@@ -18923,7 +18931,16 @@ function loadConfig() {
18923
18931
  let cfg = {};
18924
18932
  try {
18925
18933
  cfg = parseStoredConfig(parseJson(readFileSync3(join9(DATA_DIR, "config.json"), "utf8")));
18926
- } catch {
18934
+ lastIgnoredConfigWarning = "";
18935
+ } catch (error51) {
18936
+ if (error51?.code !== "ENOENT") {
18937
+ const reason = error51 instanceof SyntaxError ? "invalid JSON" : error51 instanceof Error ? error51.message : "unable to read configuration";
18938
+ const warning = `config: ignoring ${join9(DATA_DIR, "config.json")} and using defaults: ${reason}`;
18939
+ if (warning !== lastIgnoredConfigWarning) console.warn(warning);
18940
+ lastIgnoredConfigWarning = warning;
18941
+ } else {
18942
+ lastIgnoredConfigWarning = "";
18943
+ }
18927
18944
  }
18928
18945
  cfg.mistral = { ...cfg.mistral };
18929
18946
  if (process.env.MISTRAL_API_KEY !== void 0) cfg.mistral.key = process.env.MISTRAL_API_KEY;
@@ -19150,7 +19167,7 @@ function instanceConfigs(cfg) {
19150
19167
  }
19151
19168
  return map3;
19152
19169
  }
19153
- var optionalText, SSH_ALIAS, LEGACY_BROWSER_PROFILE_ID, BROWSER_PROFILE_ID, MIN_ROOM_TURN_TIMEOUT_MINUTES, MAX_ROOM_TURN_TIMEOUT_MINUTES, DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES, DEFAULT_ROOM_HANDOFF_MIN_RUNWAY_MINUTES, DEFAULT_ROOM_HANDOFF_HARD_CAP_MINUTES, DEFAULT_MAX_CONCURRENT_BOT_THREADS, MAX_CONCURRENT_BOT_THREADS, MIN_THREAD_EVENT_LOG_BYTES, MAX_THREAD_EVENT_LOG_BYTES, MIN_LOCAL_VM_MAX_INSTANCES, MAX_LOCAL_VM_MAX_INSTANCES, CDP_PORT, CDP_URL, vpsConfigSchema, browserEngineConfigSchema, roomConfigSchema, localVmConfigSchema, browserProfileSchema, legacyBrowserProfileSchema, legacyBrowserProfilesSchema, storedBrowserProfilesSchema, browserProfilesSchema, featureConfigSchema, onboardingConfigSchema, instanceConfigSchema, instanceConfigMapSchema, defaultModelSelectionSchema, threadsConfigSchema, newBotsConfigSchema, newBotsPatchSchema, threadsPatchSchema, appConfigSchema, storedAppConfigSchema, appConfigPatchSchema, jsonObjectSchema, DATA_DIR, LEGACY_DATA_DIR, EVENTS_DIR, NATIVE_DIR, WORKSPACE_CREDENTIAL_ENV, CONTROL_PLANE_ENV, CONTROL_PLANE_ENV_PREFIX, PROVIDER_CREDENTIAL_ENV, configSaveListeners;
19170
+ var optionalText, SSH_ALIAS, LEGACY_BROWSER_PROFILE_ID, BROWSER_PROFILE_ID, MIN_ROOM_TURN_TIMEOUT_MINUTES, MAX_ROOM_TURN_TIMEOUT_MINUTES, DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES, DEFAULT_ROOM_HANDOFF_MIN_RUNWAY_MINUTES, DEFAULT_ROOM_HANDOFF_HARD_CAP_MINUTES, DEFAULT_MAX_CONCURRENT_BOT_THREADS, MAX_CONCURRENT_BOT_THREADS, MIN_THREAD_EVENT_LOG_BYTES, MAX_THREAD_EVENT_LOG_BYTES, MIN_LOCAL_VM_MAX_INSTANCES, MAX_LOCAL_VM_MAX_INSTANCES, CDP_PORT, CDP_URL, vpsConfigSchema, browserEngineConfigSchema, roomConfigSchema, localVmConfigSchema, browserProfileSchema, legacyBrowserProfileSchema, legacyBrowserProfilesSchema, storedBrowserProfilesSchema, browserProfilesSchema, featureConfigSchema, onboardingConfigSchema, instanceConfigSchema, instanceConfigMapSchema, defaultModelSelectionSchema, threadsConfigSchema, newBotsConfigSchema, newBotsPatchSchema, threadsPatchSchema, appConfigSchema, storedAppConfigSchema, appConfigPatchSchema, jsonObjectSchema, DATA_DIR, LEGACY_DATA_DIR, EVENTS_DIR, NATIVE_DIR, lastIgnoredConfigWarning, WORKSPACE_CREDENTIAL_ENV, CONTROL_PLANE_ENV, CONTROL_PLANE_ENV_PREFIX, PROVIDER_CREDENTIAL_ENV, configSaveListeners;
19154
19171
  var init_config = __esm({
19155
19172
  "server/config.ts"() {
19156
19173
  "use strict";
@@ -19177,7 +19194,7 @@ var init_config = __esm({
19177
19194
  MIN_THREAD_EVENT_LOG_BYTES = 256 * 1024;
19178
19195
  MAX_THREAD_EVENT_LOG_BYTES = 4 * 1024 * 1024 * 1024;
19179
19196
  MIN_LOCAL_VM_MAX_INSTANCES = 1;
19180
- MAX_LOCAL_VM_MAX_INSTANCES = 4;
19197
+ MAX_LOCAL_VM_MAX_INSTANCES = 8;
19181
19198
  CDP_PORT = /^[0-9]{1,5}$/;
19182
19199
  CDP_URL = /^(https?|wss?):\/\/\S+$/i;
19183
19200
  vpsConfigSchema = external_exports.object({
@@ -19432,6 +19449,7 @@ var init_config = __esm({
19432
19449
  LEGACY_DATA_DIR = join9(homedir4(), ".opengrokbot");
19433
19450
  EVENTS_DIR = join9(DATA_DIR, "events");
19434
19451
  NATIVE_DIR = join9(DATA_DIR, "native");
19452
+ lastIgnoredConfigWarning = "";
19435
19453
  WORKSPACE_CREDENTIAL_ENV = [
19436
19454
  "XAI_API_KEY",
19437
19455
  "MISTRAL_API_KEY",
@@ -19877,6 +19895,8 @@ function knownDirs() {
19877
19895
  join11(home, ".volta", "bin"),
19878
19896
  join11(home, ".bun", "bin"),
19879
19897
  join11(home, ".asdf", "shims"),
19898
+ join11(home, ".local", "share", "mise", "shims"),
19899
+ // mise installer
19880
19900
  join11(home, ".deno", "bin"),
19881
19901
  join11(home, "bin"),
19882
19902
  ...nvmBinDirs()
@@ -19952,6 +19972,12 @@ function probeLoginShellPath() {
19952
19972
  }
19953
19973
  );
19954
19974
  }
19975
+ function userHome(env = process.env) {
19976
+ return process.platform === "win32" ? env.USERPROFILE || env.HOME || homedir5() : env.HOME || env.USERPROFILE || homedir5();
19977
+ }
19978
+ function harnessHome(name, env = process.env) {
19979
+ return join11(userHome(env), `.${name}`);
19980
+ }
19955
19981
  function findCliCandidates(name) {
19956
19982
  if (!name || /[\n\r]/.test(name)) return [];
19957
19983
  if (/[/\\]/.test(name) || /^[a-zA-Z]:/.test(name)) return [name];
@@ -20900,7 +20926,7 @@ var init_local_inject = __esm({
20900
20926
 
20901
20927
  // server/drivers/prompt-split.ts
20902
20928
  import { createHash as createHash3 } from "node:crypto";
20903
- import { mkdirSync as mkdirSync9, readFileSync as readFileSync7 } from "node:fs";
20929
+ import { mkdirSync as mkdirSync9, readFileSync as readFileSync7, rmSync as rmSync4 } from "node:fs";
20904
20930
  import { join as join15 } from "node:path";
20905
20931
  function promptHalves(turn) {
20906
20932
  const { systemStable, systemVolatile } = turn;
@@ -20927,7 +20953,11 @@ function readPromptSplitReceipt(scope, key) {
20927
20953
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
20928
20954
  const record3 = raw;
20929
20955
  if (typeof record3.stable === "string" && typeof record3.volatile === "string") {
20930
- return { stable: record3.stable, volatile: record3.volatile };
20956
+ return {
20957
+ stable: record3.stable,
20958
+ volatile: record3.volatile,
20959
+ ...typeof record3.turnsSinceFull === "number" ? { turnsSinceFull: record3.turnsSinceFull } : {}
20960
+ };
20931
20961
  }
20932
20962
  }
20933
20963
  } catch {
@@ -20938,13 +20968,21 @@ function writePromptSplitReceipt(scope, key, receipt) {
20938
20968
  mkdirSync9(join15(DATA_DIR, "prompt-split"), { recursive: true });
20939
20969
  writeFileAtomic(receiptPath(scope, key), JSON.stringify(receipt), { mode: 384 });
20940
20970
  }
20941
- function splitSessionPrompt(stable, volatile, previous, fullSystem, text4, perTurnVolatile = false) {
20942
- const receipt = promptSplitFingerprints(stable, volatile);
20943
- if (previous === null || previous.stable !== receipt.stable) {
20944
- return { text: fullSystem ? fullSystem + "\n\n" + text4 : text4, receipt };
20971
+ function deletePromptSplitReceipt(scope, key) {
20972
+ try {
20973
+ rmSync4(receiptPath(scope, key));
20974
+ } catch {
20975
+ }
20976
+ }
20977
+ function splitSessionPrompt(stable, volatile, previous, fullSystem, text4, perTurnVolatile = false, reAnchorAfterTurns = 0) {
20978
+ const fingerprints = promptSplitFingerprints(stable, volatile);
20979
+ const turnsSinceFull = typeof previous?.turnsSinceFull === "number" ? previous.turnsSinceFull : 0;
20980
+ const reAnchor = reAnchorAfterTurns > 0 && previous !== null && turnsSinceFull >= reAnchorAfterTurns;
20981
+ if (previous === null || previous.stable !== fingerprints.stable || reAnchor) {
20982
+ return { text: fullSystem ? fullSystem + "\n\n" + text4 : text4, receipt: { ...fingerprints, turnsSinceFull: 0 } };
20945
20983
  }
20946
- const note = previous.volatile === receipt.volatile && !perTurnVolatile ? "" : volatileContextNote(volatile, previous.volatile !== EMPTY_FINGERPRINT);
20947
- return { text: withContextNote(note, text4), receipt };
20984
+ const note = previous.volatile === fingerprints.volatile && !perTurnVolatile ? "" : volatileContextNote(volatile, previous.volatile !== EMPTY_FINGERPRINT);
20985
+ return { text: withContextNote(note, text4), receipt: { ...fingerprints, turnsSinceFull: turnsSinceFull + 1 } };
20948
20986
  }
20949
20987
  var VOLATILE_CONTEXT_NOTE_PREFIX, VOLATILE_CONTEXT_CLEARED_NOTE, digest, EMPTY_FINGERPRINT, receiptPath;
20950
20988
  var init_prompt_split = __esm({
@@ -21051,6 +21089,19 @@ function stripOmbAskBlock(output) {
21051
21089
  if (!OMB_ASK_FENCE.test(output)) return output;
21052
21090
  return output.replace(OMB_ASK_FENCE_GLOBAL, "").replace(/\n{3,}/g, "\n\n").trim();
21053
21091
  }
21092
+ function ombAskProtocolPrompt() {
21093
+ return [
21094
+ "",
21095
+ "## Asking the person a question",
21096
+ "When a decision belongs to the person, end your reply with a fenced block exactly like this:",
21097
+ "",
21098
+ "```omb-ask",
21099
+ '{"questions":[{"question":"Ship the release now?","header":"Release","options":[{"label":"Ship now"},{"label":"Wait for the QA signoff"}]}]}',
21100
+ "```",
21101
+ "",
21102
+ `The block must be the last thing in your reply. You may ask up to ${MAX_QUESTIONS} questions at once, each with up to ${MAX_OPTIONS} options; the person can always answer in their own words. Their answers arrive on your next prompt as \`Q:\`/\`A:\` lines \u2014 never invent them.`
21103
+ ].join("\n");
21104
+ }
21054
21105
  function askQuestionSummary(questions) {
21055
21106
  const first = questions[0]?.question ?? "";
21056
21107
  const rest = questions.length - 1;
@@ -21199,7 +21250,7 @@ var init_ask_question = __esm({
21199
21250
  });
21200
21251
 
21201
21252
  // server/thread-log-rotation.ts
21202
- import { closeSync as closeSync4, fstatSync, openSync as openSync4, readSync as readSync2, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync3, writeSync } from "node:fs";
21253
+ import { closeSync as closeSync4, fstatSync, openSync as openSync4, readSync as readSync2, renameSync as renameSync5, rmSync as rmSync5, statSync as statSync3, writeSync } from "node:fs";
21203
21254
  function currentThreadLogCap() {
21204
21255
  try {
21205
21256
  return capProvider();
@@ -21251,7 +21302,7 @@ function trimToTail(file2, keepBytes) {
21251
21302
  renameSync5(staging, file2);
21252
21303
  } catch {
21253
21304
  try {
21254
- rmSync4(staging, { force: true });
21305
+ rmSync5(staging, { force: true });
21255
21306
  } catch {
21256
21307
  }
21257
21308
  }
@@ -21423,6 +21474,33 @@ var init_resume_recovery = __esm({
21423
21474
  }
21424
21475
  });
21425
21476
 
21477
+ // server/drivers/session-idle.ts
21478
+ function usableMilliseconds(raw) {
21479
+ const value = Number(raw);
21480
+ return Number.isFinite(value) && value > 0 && value <= MAX_TIMER_MS ? value : null;
21481
+ }
21482
+ function sessionIdlePolicy(driverPrefix, env = process.env) {
21483
+ const minimumMs = Math.max(
21484
+ MINIMUM_IDLE_MS,
21485
+ usableMilliseconds(
21486
+ env[`OMB_${driverPrefix}_SESSION_IDLE_MIN_MS`] ?? env.OMB_SESSION_IDLE_MIN_MS
21487
+ ) ?? 0
21488
+ );
21489
+ const configured = usableMilliseconds(
21490
+ env[`OMB_${driverPrefix}_SESSION_IDLE_MS`] ?? env.OMB_SESSION_IDLE_MS
21491
+ ) ?? DEFAULT_IDLE_MS;
21492
+ return { idleMs: Math.max(minimumMs, configured), minimumMs };
21493
+ }
21494
+ var DEFAULT_IDLE_MS, MINIMUM_IDLE_MS, MAX_TIMER_MS;
21495
+ var init_session_idle = __esm({
21496
+ "server/drivers/session-idle.ts"() {
21497
+ "use strict";
21498
+ DEFAULT_IDLE_MS = 10 * 6e4;
21499
+ MINIMUM_IDLE_MS = 1e4;
21500
+ MAX_TIMER_MS = 2147483647;
21501
+ }
21502
+ });
21503
+
21426
21504
  // server/drivers/acp/core.ts
21427
21505
  import { homedir as homedir7 } from "node:os";
21428
21506
  import { lstat, mkdir as mkdir3, readFile, realpath, stat as stat2, writeFile } from "node:fs/promises";
@@ -21542,6 +21620,17 @@ function versionFromProbe(stdout2, stderr) {
21542
21620
  const err = (stderr ?? "").trim().split(/\r\n|\n|\r/, 1)[0]?.trim() ?? "";
21543
21621
  return err || null;
21544
21622
  }
21623
+ function parseVersionTriple(value) {
21624
+ const match = /(\d+)\.(\d+)\.(\d+)/.exec(value);
21625
+ if (!match) return null;
21626
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
21627
+ }
21628
+ function versionAtLeast(installed, floor) {
21629
+ for (let i2 = 0; i2 < 3; i2 += 1) {
21630
+ if (installed[i2] !== floor[i2]) return installed[i2] > floor[i2];
21631
+ }
21632
+ return true;
21633
+ }
21545
21634
  function createAcpDriver(support11) {
21546
21635
  const DRIVER_KIND8 = support11.driverKind;
21547
21636
  const SOURCE = support11.nativeSource;
@@ -21587,9 +21676,7 @@ function createAcpDriver(support11) {
21587
21676
  const listeners = /* @__PURE__ */ new Set();
21588
21677
  const active = /* @__PURE__ */ new Map();
21589
21678
  const sessions = /* @__PURE__ */ new Map();
21590
- const configuredIdleMinimum = Number(process.env.OMB_ACP_SESSION_IDLE_MIN_MS);
21591
- const sessionIdleMinimum = Number.isFinite(configuredIdleMinimum) && configuredIdleMinimum > 0 ? configuredIdleMinimum : 1e4;
21592
- const SESSION_IDLE_MS = Math.max(sessionIdleMinimum, Number(process.env.OMB_ACP_SESSION_IDLE_MS) || 10 * 6e4);
21679
+ const { idleMs: SESSION_IDLE_MS } = sessionIdlePolicy("ACP");
21593
21680
  const closeSession = (threadId, why) => {
21594
21681
  const session = sessions.get(threadId);
21595
21682
  if (!session || session.closing) return;
@@ -22421,7 +22508,8 @@ function createAcpDriver(support11) {
22421
22508
  readPromptSplitReceipt(DRIVER_KIND8, receiptKey),
22422
22509
  promptTurn.system,
22423
22510
  promptTurn.text,
22424
- Boolean(turn.mentionTurn)
22511
+ Boolean(turn.mentionTurn),
22512
+ ACP_PROMPT_RE_ANCHOR_TURNS
22425
22513
  );
22426
22514
  promptInput = { ...promptTurn, system: "", text: composed.text };
22427
22515
  pendingSplitReceipt = { key: receiptKey, receipt: composed.receipt };
@@ -22559,7 +22647,7 @@ ${promptInput.text}` : promptInput.text;
22559
22647
  }
22560
22648
  };
22561
22649
  }
22562
- var envOr, INIT_TIMEOUT, SESSION_CONFIG_TIMEOUT, NEW_SESSION_TIMEOUT, LOAD_SESSION_TIMEOUT, promptIdleTimeoutMs, CLIENT_FILE_MAX_BYTES, TOOL_LOG_TEXT_LIMIT;
22650
+ var envOr, INIT_TIMEOUT, SESSION_CONFIG_TIMEOUT, NEW_SESSION_TIMEOUT, LOAD_SESSION_TIMEOUT, ACP_PROMPT_RE_ANCHOR_TURNS, promptIdleTimeoutMs, CLIENT_FILE_MAX_BYTES, TOOL_LOG_TEXT_LIMIT;
22563
22651
  var init_core3 = __esm({
22564
22652
  "server/drivers/acp/core.ts"() {
22565
22653
  "use strict";
@@ -22577,11 +22665,13 @@ var init_core3 = __esm({
22577
22665
  init_mcp_tool_images();
22578
22666
  init_redact2();
22579
22667
  init_resume_recovery();
22668
+ init_session_idle();
22580
22669
  envOr = (key, fallback) => Number(process.env[key] ?? fallback);
22581
22670
  INIT_TIMEOUT = envOr("OPENMAUS_ACP_INIT_TIMEOUT_MS", 3e5);
22582
22671
  SESSION_CONFIG_TIMEOUT = envOr("OPENMAUS_ACP_SESSION_CONFIG_TIMEOUT_MS", 3e5);
22583
22672
  NEW_SESSION_TIMEOUT = envOr("OPENMAUS_ACP_NEW_SESSION_TIMEOUT_MS", 3e5);
22584
22673
  LOAD_SESSION_TIMEOUT = envOr("OPENMAUS_ACP_LOAD_SESSION_TIMEOUT_MS", 12e4);
22674
+ ACP_PROMPT_RE_ANCHOR_TURNS = 8;
22585
22675
  promptIdleTimeoutMs = () => {
22586
22676
  const raw = process.env.OPENMAUS_ACP_PROMPT_IDLE_TIMEOUT_MS;
22587
22677
  if (raw === void 0) return 18e4;
@@ -23705,7 +23795,7 @@ function decodeConfig(raw) {
23705
23795
  ...typeof o.askTimeoutMs === "number" ? { askTimeoutMs: o.askTimeoutMs } : {}
23706
23796
  };
23707
23797
  }
23708
- var DRIVER_KIND, BOX_API, MODELS, ASK_PROTOCOL, ASK_FENCE_ANY, catalog, providerFor, BoxAgentDriver;
23798
+ var DRIVER_KIND, BOX_API, MODELS, ASK_FENCE_ANY, catalog, providerFor, BoxAgentDriver;
23709
23799
  var init_boxagent = __esm({
23710
23800
  "server/drivers/boxagent.ts"() {
23711
23801
  "use strict";
@@ -23722,17 +23812,6 @@ var init_boxagent = __esm({
23722
23812
  { id: "gpt-5.4", label: "GPT-5.4 (Codex) \xB7 on the box" }
23723
23813
  ]
23724
23814
  };
23725
- ASK_PROTOCOL = [
23726
- "",
23727
- "## Asking the person a question",
23728
- "When a decision belongs to the person, end your reply with a fenced block exactly like this:",
23729
- "",
23730
- "```omb-ask",
23731
- '{"questions":[{"question":"Ship the release now?","header":"Release","options":[{"label":"Ship now"},{"label":"Wait for the QA signoff"}]}]}',
23732
- "```",
23733
- "",
23734
- "The block must be the last thing in your reply. You may ask up to 6 questions at once, each with up to 12 options; the person can always answer in their own words. Their answers arrive on your next prompt as `Q:`/`A:` lines \u2014 never invent them."
23735
- ].join("\n");
23736
23815
  ASK_FENCE_ANY = /(^|\n)[ \t]{0,3}(`{3,}|~{3,})[ \t]*omb-ask\b/;
23737
23816
  catalog = null;
23738
23817
  providerFor = (model) => {
@@ -23793,7 +23872,7 @@ var init_boxagent = __esm({
23793
23872
  const prompt = [
23794
23873
  turn.system,
23795
23874
  "You are working on the assigned cloud computer \u2014 use its desktop, Chrome, and shell within the access described above.",
23796
- ASK_PROTOCOL,
23875
+ ombAskProtocolPrompt(),
23797
23876
  ...correction ? [correction] : [],
23798
23877
  "",
23799
23878
  turn.text
@@ -24542,7 +24621,7 @@ var init_retry = __esm({
24542
24621
 
24543
24622
  // server/drivers/claude.ts
24544
24623
  import { createHash as createHash7, randomBytes as randomBytes2 } from "node:crypto";
24545
- import { chmodSync as chmodSync4, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync2, readFileSync as readFileSync8, rmSync as rmSync5, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
24624
+ import { chmodSync as chmodSync4, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync2, readFileSync as readFileSync8, rmSync as rmSync6, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
24546
24625
  import { createServer as createNetServer } from "node:net";
24547
24626
  import { homedir as homedir9, tmpdir as tmpdir3 } from "node:os";
24548
24627
  import { join as join21, dirname as dirname9, isAbsolute as isAbsolute5, normalize } from "node:path";
@@ -24584,6 +24663,10 @@ function claudeAuthFailure(frame, text4) {
24584
24663
  if (frame.is_api_error_message !== true && typeof frame.error !== "string") return false;
24585
24664
  return frame.error === "authentication_failed" || classifyError({ text: text4 }).reason === "auth";
24586
24665
  }
24666
+ function claudeVersionTooOld(frame, text4) {
24667
+ if (frame.is_api_error_message !== true && typeof frame.error !== "string") return false;
24668
+ return /\bClaude Code v?\d+(?:\.\d+)+ does not support this model\b/i.test(text4);
24669
+ }
24587
24670
  function claudeEnvironment(model, source = process.env, configDir, instanceEnvironment = {}) {
24588
24671
  const env = { ...source, PATH: augmentedPath(), NPM_CONFIG_LOGLEVEL: "error" };
24589
24672
  if (configDir?.trim()) {
@@ -24655,15 +24738,7 @@ function autoCompactWindow(env) {
24655
24738
  return String(Math.min(1e6, Math.max(1e5, Math.floor(parsed))));
24656
24739
  }
24657
24740
  function parseClaudeCliVersion(stdout2) {
24658
- const match = /(\d+)\.(\d+)\.(\d+)/.exec(stdout2 ?? "");
24659
- if (!match) return null;
24660
- return [Number(match[1]), Number(match[2]), Number(match[3])];
24661
- }
24662
- function versionAtLeast(installed, floor) {
24663
- for (let i2 = 0; i2 < 3; i2 += 1) {
24664
- if (installed[i2] !== floor[i2]) return installed[i2] > floor[i2];
24665
- }
24666
- return true;
24741
+ return parseVersionTriple(stdout2 ?? "");
24667
24742
  }
24668
24743
  function claudeCliSupports(version2, flag) {
24669
24744
  return version2 === null || versionAtLeast(version2, CLAUDE_FLAG_FLOORS[flag]);
@@ -24731,7 +24806,7 @@ function readClaudeModelCatalog(env = process.env) {
24731
24806
  function removePrivateTempDir(filePath) {
24732
24807
  if (!filePath) return true;
24733
24808
  try {
24734
- rmSync5(dirname9(filePath), { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
24809
+ rmSync6(dirname9(filePath), { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
24735
24810
  return true;
24736
24811
  } catch {
24737
24812
  return false;
@@ -25026,6 +25101,8 @@ var init_claude = __esm({
25026
25101
  init_contracts();
25027
25102
  init_tool_summary();
25028
25103
  init_retry();
25104
+ init_session_idle();
25105
+ init_core3();
25029
25106
  init_local_inject();
25030
25107
  init_native();
25031
25108
  init_permission_command();
@@ -25124,9 +25201,7 @@ var init_claude = __esm({
25124
25201
  const listeners = /* @__PURE__ */ new Set();
25125
25202
  const active = /* @__PURE__ */ new Map();
25126
25203
  const sessions = /* @__PURE__ */ new Map();
25127
- const configuredIdleMinimum = Number(process.env.OMB_CLAUDE_SESSION_IDLE_MIN_MS);
25128
- const sessionIdleMinimum = Number.isFinite(configuredIdleMinimum) && configuredIdleMinimum > 0 ? configuredIdleMinimum : 1e4;
25129
- const SESSION_IDLE_MS = Math.max(sessionIdleMinimum, Number(process.env.OMB_CLAUDE_SESSION_IDLE_MS) || 10 * 6e4);
25204
+ const { idleMs: SESSION_IDLE_MS } = sessionIdlePolicy("CLAUDE");
25130
25205
  const stopSession = (session) => {
25131
25206
  void killCliTree(session.child).then((stopped) => {
25132
25207
  if (stopped) void session.finishClose?.();
@@ -25387,7 +25462,7 @@ var init_claude = __esm({
25387
25462
  retryState.delete(threadId);
25388
25463
  if (mcpConfigPath) {
25389
25464
  try {
25390
- rmSync5(dirname9(mcpConfigPath), { recursive: true, force: true });
25465
+ rmSync6(dirname9(mcpConfigPath), { recursive: true, force: true });
25391
25466
  } catch {
25392
25467
  }
25393
25468
  }
@@ -25395,7 +25470,7 @@ var init_claude = __esm({
25395
25470
  }
25396
25471
  if (mcpConfigPath) {
25397
25472
  try {
25398
- rmSync5(dirname9(mcpConfigPath), { recursive: true, force: true });
25473
+ rmSync6(dirname9(mcpConfigPath), { recursive: true, force: true });
25399
25474
  } catch {
25400
25475
  }
25401
25476
  }
@@ -25407,7 +25482,7 @@ var init_claude = __esm({
25407
25482
  broker = void 0;
25408
25483
  if (mcpConfigPath) {
25409
25484
  try {
25410
- rmSync5(dirname9(mcpConfigPath), { recursive: true, force: true });
25485
+ rmSync6(dirname9(mcpConfigPath), { recursive: true, force: true });
25411
25486
  } catch {
25412
25487
  }
25413
25488
  mcpConfigPath = null;
@@ -25524,7 +25599,7 @@ var init_claude = __esm({
25524
25599
  session.broker?.pause();
25525
25600
  if (session.mcpConfigPath) {
25526
25601
  try {
25527
- rmSync5(dirname9(session.mcpConfigPath), { recursive: true, force: true });
25602
+ rmSync6(dirname9(session.mcpConfigPath), { recursive: true, force: true });
25528
25603
  } catch {
25529
25604
  }
25530
25605
  session.mcpConfigPath = null;
@@ -25535,6 +25610,7 @@ var init_claude = __esm({
25535
25610
  active.delete(threadId);
25536
25611
  session.turn = null;
25537
25612
  retryState.delete(threadId);
25613
+ if (stopReason === "update_required") closeSession(threadId, "update required");
25538
25614
  emit({ ...base2(threadId, t2.turnId), type: "turn.completed", ok, stopReason, cost, ...usage ? { usage } : {} });
25539
25615
  if (session.child.exitCode === null && !session.closing) armIdle(threadId);
25540
25616
  };
@@ -25580,6 +25656,11 @@ var init_claude = __esm({
25580
25656
  emit({ ...base2(threadId, currentTurnId()), type: "runtime.error", message: text4, setup: true });
25581
25657
  break;
25582
25658
  }
25659
+ if (claudeVersionTooOld(o, text4)) {
25660
+ if (session.turn) session.turn.updateRequired = true;
25661
+ emit({ ...base2(threadId, currentTurnId()), type: "runtime.error", message: text4, setup: true, claudeUpdate: true });
25662
+ break;
25663
+ }
25583
25664
  if (text4.trim()) {
25584
25665
  const synthetic = o.is_api_error_message === true || typeof o.error === "string" ? { synthetic: true } : {};
25585
25666
  if (!session.turn?.sawStreamDelta) {
@@ -25629,7 +25710,7 @@ var init_claude = __esm({
25629
25710
  if (o.origin?.kind === "task-notification") break;
25630
25711
  settle(
25631
25712
  o.is_error !== true,
25632
- session.turn?.authFailed ? "auth_required" : o.stop_reason ?? o.terminal_reason ?? null,
25713
+ session.turn?.authFailed ? "auth_required" : session.turn?.updateRequired ? "update_required" : o.stop_reason ?? o.terminal_reason ?? null,
25633
25714
  o.total_cost_usd ?? null,
25634
25715
  o.usage ? {
25635
25716
  input: (o.usage.input_tokens || 0) + (o.usage.cache_read_input_tokens || 0) + (o.usage.cache_creation_input_tokens || 0),
@@ -25684,7 +25765,7 @@ var init_claude = __esm({
25684
25765
  failedBroker?.close();
25685
25766
  if (session.mcpConfigPath) {
25686
25767
  try {
25687
- rmSync5(dirname9(session.mcpConfigPath), { recursive: true, force: true });
25768
+ rmSync6(dirname9(session.mcpConfigPath), { recursive: true, force: true });
25688
25769
  } catch {
25689
25770
  }
25690
25771
  session.mcpConfigPath = null;
@@ -25762,7 +25843,7 @@ var init_claude = __esm({
25762
25843
  session.broker = void 0;
25763
25844
  if (session.mcpConfigPath) {
25764
25845
  try {
25765
- rmSync5(dirname9(session.mcpConfigPath), { recursive: true, force: true });
25846
+ rmSync6(dirname9(session.mcpConfigPath), { recursive: true, force: true });
25766
25847
  } catch {
25767
25848
  }
25768
25849
  session.mcpConfigPath = null;
@@ -25814,7 +25895,7 @@ var init_claude = __esm({
25814
25895
  session.broker?.close();
25815
25896
  if (session.mcpConfigPath) {
25816
25897
  try {
25817
- rmSync5(dirname9(session.mcpConfigPath), { recursive: true, force: true });
25898
+ rmSync6(dirname9(session.mcpConfigPath), { recursive: true, force: true });
25818
25899
  } catch {
25819
25900
  }
25820
25901
  }
@@ -26028,9 +26109,9 @@ function mcpServerNamesInToml(toml) {
26028
26109
  return names;
26029
26110
  }
26030
26111
  function codexConfigMcpServerNames(env) {
26031
- const codexHome3 = env.CODEX_HOME || join22(env.HOME || env.USERPROFILE || homedir10(), ".codex");
26112
+ const codexHome2 = env.CODEX_HOME || join22(env.HOME || env.USERPROFILE || homedir10(), ".codex");
26032
26113
  try {
26033
- return mcpServerNamesInToml(readFileSync9(join22(codexHome3, "config.toml"), "utf8"));
26114
+ return mcpServerNamesInToml(readFileSync9(join22(codexHome2, "config.toml"), "utf8"));
26034
26115
  } catch {
26035
26116
  return /* @__PURE__ */ new Set();
26036
26117
  }
@@ -26049,10 +26130,124 @@ var init_codex_mcp_names = __esm({
26049
26130
  }
26050
26131
  });
26051
26132
 
26133
+ // server/drivers/codex-identity.ts
26134
+ import { homedir as homedir11 } from "node:os";
26135
+ import { isAbsolute as isAbsolute6, join as join23, resolve as resolve7 } from "node:path";
26136
+ function codexHome(env) {
26137
+ if (env.CODEX_HOME) return isAbsolute6(env.CODEX_HOME) ? resolve7(env.CODEX_HOME) : null;
26138
+ const home = userHome(env);
26139
+ return isAbsolute6(home) ? join23(home, ".codex") : null;
26140
+ }
26141
+ async function codexAccountEmail(cli, env, timeoutMs = 3e3) {
26142
+ const cwd = env.HOME || env.USERPROFILE || homedir11();
26143
+ if (!isAbsolute6(cwd) || !codexHome(env)) return null;
26144
+ return new Promise((resolveEmail) => {
26145
+ let child;
26146
+ try {
26147
+ child = spawnCli(cli, ["app-server"], { cwd, env, stdio: ["pipe", "pipe", "pipe"] });
26148
+ } catch {
26149
+ resolveEmail(null);
26150
+ return;
26151
+ }
26152
+ let finishing = false;
26153
+ let buffer = "";
26154
+ let outputBytes = 0;
26155
+ let initialized = false;
26156
+ const finish = async (email3) => {
26157
+ if (finishing) return;
26158
+ finishing = true;
26159
+ clearTimeout(timer);
26160
+ let stopped = await killCliTree(child, 1e3);
26161
+ if (!stopped && child.pid) {
26162
+ try {
26163
+ if (process.platform === "win32") child.kill("SIGKILL");
26164
+ else process.kill(-child.pid, "SIGKILL");
26165
+ } catch {
26166
+ try {
26167
+ child.kill("SIGKILL");
26168
+ } catch {
26169
+ }
26170
+ }
26171
+ stopped = await killCliTree(child, 1e3);
26172
+ }
26173
+ resolveEmail(stopped ? email3 : null);
26174
+ };
26175
+ const timer = setTimeout(() => {
26176
+ void finish(null);
26177
+ }, timeoutMs);
26178
+ timer.unref();
26179
+ const send = (message2) => {
26180
+ try {
26181
+ child.stdin.write(`${JSON.stringify(message2)}
26182
+ `);
26183
+ } catch {
26184
+ void finish(null);
26185
+ }
26186
+ };
26187
+ child.stdin.on("error", () => {
26188
+ void finish(null);
26189
+ });
26190
+ child.stderr.resume();
26191
+ child.on("error", () => {
26192
+ void finish(null);
26193
+ });
26194
+ child.on("close", () => {
26195
+ void finish(null);
26196
+ });
26197
+ child.stdout.setEncoding("utf8");
26198
+ child.stdout.on("data", (chunk) => {
26199
+ if (finishing) return;
26200
+ outputBytes += Buffer.byteLength(chunk);
26201
+ if (outputBytes > MAX_OUTPUT3) {
26202
+ void finish(null);
26203
+ return;
26204
+ }
26205
+ buffer += chunk;
26206
+ let newline;
26207
+ while (!finishing && (newline = buffer.indexOf("\n")) !== -1) {
26208
+ const line = buffer.slice(0, newline);
26209
+ buffer = buffer.slice(newline + 1);
26210
+ if (!line.trim()) continue;
26211
+ let message2;
26212
+ try {
26213
+ message2 = JSON.parse(line);
26214
+ } catch {
26215
+ void finish(null);
26216
+ return;
26217
+ }
26218
+ if (!initialized && message2?.id === 1) {
26219
+ if (message2.error || !message2.result) {
26220
+ void finish(null);
26221
+ return;
26222
+ }
26223
+ initialized = true;
26224
+ send({ method: "initialized", params: {} });
26225
+ send({ id: 2, method: "account/read", params: { refreshToken: false } });
26226
+ } else if (initialized && message2?.id === 2) {
26227
+ const account = message2.error ? null : message2.result?.account;
26228
+ const email3 = account?.type === "chatgpt" ? account.email : null;
26229
+ void finish(typeof email3 === "string" && email3.length <= 254 && EMAIL.test(email3) && !/[\p{Cc}\p{Cf}]/u.test(email3) ? email3 : null);
26230
+ }
26231
+ }
26232
+ });
26233
+ send({ id: 1, method: "initialize", params: { clientInfo: { name: "openmausbot", version: "1" } } });
26234
+ });
26235
+ }
26236
+ var MAX_OUTPUT3, EMAIL;
26237
+ var init_codex_identity = __esm({
26238
+ "server/drivers/codex-identity.ts"() {
26239
+ "use strict";
26240
+ init_env_path();
26241
+ init_procs();
26242
+ MAX_OUTPUT3 = 16384;
26243
+ EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
26244
+ }
26245
+ });
26246
+
26052
26247
  // server/drivers/codex-catalog.ts
26053
26248
  import { readdirSync as readdirSync2, readFileSync as readFileSync10 } from "node:fs";
26054
- import { homedir as homedir11 } from "node:os";
26055
- import { basename as basename7, join as join23 } from "node:path";
26249
+ import { homedir as homedir12 } from "node:os";
26250
+ import { basename as basename7, join as join24 } from "node:path";
26056
26251
  function encodeCodexSelection(provider, model) {
26057
26252
  return `${provider}${SEP}${model}`;
26058
26253
  }
@@ -26067,7 +26262,7 @@ function decodeCodexSelection(id) {
26067
26262
  function readCodexAppServerModelCatalog(cli, env, timeoutMs = 8e3) {
26068
26263
  return new Promise((resolve12) => {
26069
26264
  const child = spawnCli(cli, ["app-server"], {
26070
- cwd: homedir11(),
26265
+ cwd: homedir12(),
26071
26266
  env,
26072
26267
  stdio: ["pipe", "pipe", "pipe"]
26073
26268
  });
@@ -26166,10 +26361,6 @@ function readCodexAppServerModelCatalog(cli, env, timeoutMs = 8e3) {
26166
26361
  request("initialize", { clientInfo: { name: "openmausbot", version: "1" } }, "initialize");
26167
26362
  });
26168
26363
  }
26169
- function codexHome(env) {
26170
- if (env.CODEX_HOME) return env.CODEX_HOME;
26171
- return join23(env.HOME || env.USERPROFILE || homedir11(), ".codex");
26172
- }
26173
26364
  function unquote(raw) {
26174
26365
  let value = raw.trim();
26175
26366
  const hash2 = value.indexOf(" #");
@@ -26250,15 +26441,18 @@ function niceLabel(model, provider, known, named) {
26250
26441
  const encoded = encodeCodexSelection(provider, model);
26251
26442
  if (named.has(encoded)) return named.get(encoded);
26252
26443
  const host = providerName(provider, known);
26253
- return host === provider ? model : `${model} (${host})`;
26444
+ return qualifiedModelLabel(model, host, {
26445
+ redundantWhen: () => host === provider,
26446
+ decorate: (facet) => ` (${facet})`
26447
+ });
26254
26448
  }
26255
26449
  function collectCatalogNames(home) {
26256
26450
  const named = /* @__PURE__ */ new Map();
26257
- for (const file2 of listDir(join23(home, "model-catalogs"))) {
26451
+ for (const file2 of listDir(join24(home, "model-catalogs"))) {
26258
26452
  if (!file2.endsWith(".json")) continue;
26259
26453
  const provider = basename7(file2, ".json").replace(/-models$/, "");
26260
26454
  if (!PROVIDER_ID.test(provider)) continue;
26261
- const raw = readText(join23(home, "model-catalogs", file2));
26455
+ const raw = readText(join24(home, "model-catalogs", file2));
26262
26456
  if (!raw) continue;
26263
26457
  let parsed;
26264
26458
  try {
@@ -26310,7 +26504,8 @@ async function probeProviderModels(provider, env, fetchImpl) {
26310
26504
  async function readCodexModelCatalog(env = process.env, fetchImpl = fetch, cli) {
26311
26505
  const official = (cli ? await readCodexAppServerModelCatalog(cli, env) : null) ?? STATIC_CODEX_MODELS;
26312
26506
  const home = codexHome(env);
26313
- const mainText = readText(join23(home, "config.toml"));
26507
+ if (!home) return mergeLocalInject(official, env, fetchImpl);
26508
+ const mainText = readText(join24(home, "config.toml"));
26314
26509
  if (!mainText) return mergeLocalInject(official, env, fetchImpl);
26315
26510
  const main2 = parseCodexToml(mainText);
26316
26511
  const known = new Map(main2.providers.map((provider) => [provider.id, provider]));
@@ -26325,7 +26520,7 @@ async function readCodexModelCatalog(env = process.env, fetchImpl = fetch, cli)
26325
26520
  remember(main2.modelProvider, main2.model);
26326
26521
  for (const file2 of listDir(home)) {
26327
26522
  if (!file2.endsWith(".config.toml")) continue;
26328
- const profile = parseCodexToml(readText(join23(home, file2)) ?? "");
26523
+ const profile = parseCodexToml(readText(join24(home, file2)) ?? "");
26329
26524
  for (const provider of profile.providers) {
26330
26525
  if (!known.has(provider.id)) known.set(provider.id, provider);
26331
26526
  }
@@ -26368,11 +26563,17 @@ var STATIC_CODEX_MODELS, OFFICIAL_CODEX_PROVIDER, SEP, MODEL_ID2, PROVIDER_ID;
26368
26563
  var init_codex_catalog = __esm({
26369
26564
  "server/drivers/codex-catalog.ts"() {
26370
26565
  "use strict";
26566
+ init_contracts();
26371
26567
  init_procs();
26568
+ init_codex_identity();
26372
26569
  init_local_inject();
26373
26570
  STATIC_CODEX_MODELS = {
26374
26571
  default: "gpt-5.6-sol",
26375
26572
  options: [
26573
+ // Only used when live discovery fails; these rows do not establish account access.
26574
+ { id: "gpt-6-astra", label: "GPT-6 Astra (availability unverified)" },
26575
+ { id: "gpt-6-sol", label: "GPT-6 Sol (availability unverified)" },
26576
+ { id: "gpt-6-luna", label: "GPT-6 Luna (availability unverified)" },
26376
26577
  { id: "gpt-5.6-sol", label: "GPT-5.6 Sol" },
26377
26578
  { id: "gpt-5.6-terra", label: "GPT-5.6 Terra" },
26378
26579
  { id: "gpt-5.6-luna", label: "GPT-5.6 Luna" },
@@ -26392,7 +26593,7 @@ var init_codex_catalog = __esm({
26392
26593
  // server/drivers/codex-instructions.ts
26393
26594
  import { createHash as createHash8 } from "node:crypto";
26394
26595
  import { mkdirSync as mkdirSync11, readFileSync as readFileSync11 } from "node:fs";
26395
- import { join as join24 } from "node:path";
26596
+ import { join as join25 } from "node:path";
26396
26597
  function parseReceipt(raw) {
26397
26598
  if (!raw) return null;
26398
26599
  const trimmed = raw.trim();
@@ -26425,8 +26626,8 @@ function codexDeveloperInstructions(config2, botInstructions) {
26425
26626
  ${configured}` : botInstructions;
26426
26627
  }
26427
26628
  async function syncCodexInstructions(key, nativeThreadId, instructions, volatile, resumed, request, mentionTurn = false) {
26428
- const directory = join24(DATA_DIR, "codex-instructions");
26429
- const path3 = join24(directory, `${digest2(JSON.stringify([key, nativeThreadId]))}.sha256`);
26629
+ const directory = join25(DATA_DIR, "codex-instructions");
26630
+ const path3 = join25(directory, `${digest2(JSON.stringify([key, nativeThreadId]))}.sha256`);
26430
26631
  const fingerprint = digest2(instructions);
26431
26632
  const volatileFingerprint = digest2(volatile);
26432
26633
  let previous;
@@ -26482,15 +26683,15 @@ var init_codex_instructions = __esm({
26482
26683
  // server/drivers/codex-device-auth.ts
26483
26684
  import { randomUUID as randomUUID9 } from "node:crypto";
26484
26685
  import { realpathSync as realpathSync3 } from "node:fs";
26485
- import { homedir as homedir12 } from "node:os";
26486
- import { basename as basename8, dirname as dirname10, isAbsolute as isAbsolute6, join as join25, resolve as resolve7 } from "node:path";
26686
+ import { homedir as homedir13 } from "node:os";
26687
+ import { basename as basename8, dirname as dirname10, isAbsolute as isAbsolute7, join as join26, resolve as resolve8 } from "node:path";
26487
26688
  import { stripVTControlCharacters as stripVTControlCharacters5 } from "node:util";
26488
26689
  function canonicalPath2(path3) {
26489
26690
  try {
26490
26691
  return realpathSync3(path3);
26491
26692
  } catch {
26492
26693
  const parent = dirname10(path3);
26493
- return parent === path3 ? path3 : join25(canonicalPath2(parent), basename8(path3));
26694
+ return parent === path3 ? path3 : join26(canonicalPath2(parent), basename8(path3));
26494
26695
  }
26495
26696
  }
26496
26697
  function codexDevicePrompt(output) {
@@ -26512,13 +26713,13 @@ function loginFailure(output) {
26512
26713
  }
26513
26714
  return "ChatGPT sign-in did not finish. Check the server's connection and that device-code login is enabled in ChatGPT, then try again.";
26514
26715
  }
26515
- var DEVICE_URL, MAX_OUTPUT3, authenticatingHomes2, CodexDeviceAuthController;
26716
+ var DEVICE_URL, MAX_OUTPUT4, authenticatingHomes2, CodexDeviceAuthController;
26516
26717
  var init_codex_device_auth = __esm({
26517
26718
  "server/drivers/codex-device-auth.ts"() {
26518
26719
  "use strict";
26519
26720
  init_procs();
26520
26721
  DEVICE_URL = "https://auth.openai.com/codex/device";
26521
- MAX_OUTPUT3 = 16384;
26722
+ MAX_OUTPUT4 = 16384;
26522
26723
  authenticatingHomes2 = /* @__PURE__ */ new Set();
26523
26724
  CodexDeviceAuthController = class {
26524
26725
  flow = null;
@@ -26537,11 +26738,11 @@ var init_codex_device_auth = __esm({
26537
26738
  await this.flow?.stopping;
26538
26739
  if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing in.");
26539
26740
  const env = this.options.environment();
26540
- const home = env.HOME || env.USERPROFILE || homedir12();
26541
- if (!isAbsolute6(home) || env.CODEX_HOME && !isAbsolute6(env.CODEX_HOME)) {
26741
+ const home = env.HOME || env.USERPROFILE || homedir13();
26742
+ if (!isAbsolute7(home) || env.CODEX_HOME && !isAbsolute7(env.CODEX_HOME)) {
26542
26743
  throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing in.");
26543
26744
  }
26544
- const homeKey = canonicalPath2(resolve7(env.CODEX_HOME || join25(home, ".codex")));
26745
+ const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join26(home, ".codex")));
26545
26746
  if (authenticatingHomes2.has(homeKey)) {
26546
26747
  throw new Error("A ChatGPT sign-in is already running for this server account. Finish or cancel it before starting another.");
26547
26748
  }
@@ -26616,11 +26817,11 @@ var init_codex_device_auth = __esm({
26616
26817
  await this.flow?.stopping;
26617
26818
  if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
26618
26819
  const env = this.options.environment();
26619
- const home = env.HOME || env.USERPROFILE || homedir12();
26620
- if (!isAbsolute6(home) || env.CODEX_HOME && !isAbsolute6(env.CODEX_HOME)) {
26820
+ const home = env.HOME || env.USERPROFILE || homedir13();
26821
+ if (!isAbsolute7(home) || env.CODEX_HOME && !isAbsolute7(env.CODEX_HOME)) {
26621
26822
  throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing out.");
26622
26823
  }
26623
- const homeKey = canonicalPath2(resolve7(env.CODEX_HOME || join25(home, ".codex")));
26824
+ const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join26(home, ".codex")));
26624
26825
  if (authenticatingHomes2.has(homeKey)) {
26625
26826
  throw new Error("A ChatGPT sign-in is running for this server account. Finish or cancel it before signing out.");
26626
26827
  }
@@ -26663,7 +26864,7 @@ var init_codex_device_auth = __esm({
26663
26864
  child.stdin.end();
26664
26865
  let output = "";
26665
26866
  const receive = (chunk) => {
26666
- if (output.length < MAX_OUTPUT3) output += chunk.toString("utf8").slice(0, MAX_OUTPUT3 - output.length);
26867
+ if (output.length < MAX_OUTPUT4) output += chunk.toString("utf8").slice(0, MAX_OUTPUT4 - output.length);
26667
26868
  };
26668
26869
  child.stdout.on("data", receive);
26669
26870
  child.stderr.on("data", receive);
@@ -26698,7 +26899,7 @@ var init_codex_device_auth = __esm({
26698
26899
  let output = "";
26699
26900
  const receive = (chunk) => {
26700
26901
  if (flow.status.phase !== "waiting") return;
26701
- if (output.length + chunk.length > MAX_OUTPUT3) {
26902
+ if (output.length + chunk.length > MAX_OUTPUT4) {
26702
26903
  this.finish(flow, "failed", "Codex returned an unexpected sign-in response. Update the server's Codex CLI and try again.");
26703
26904
  return;
26704
26905
  }
@@ -26777,116 +26978,51 @@ var init_codex_device_auth = __esm({
26777
26978
  }
26778
26979
  });
26779
26980
 
26780
- // server/drivers/codex-identity.ts
26781
- import { homedir as homedir13 } from "node:os";
26782
- import { isAbsolute as isAbsolute7, join as join26, resolve as resolve8 } from "node:path";
26783
- function codexHome2(env) {
26784
- if (env.CODEX_HOME) return isAbsolute7(env.CODEX_HOME) ? resolve8(env.CODEX_HOME) : null;
26785
- const home = env.HOME || env.USERPROFILE || homedir13();
26786
- return isAbsolute7(home) ? join26(home, ".codex") : null;
26981
+ // server/drivers/codex-release.ts
26982
+ function parseCodexReleaseVersion(value) {
26983
+ const match = /^(?:.*\bcodex-cli\s+)?v?(\d+)\.(\d+)\.(\d+)(-[0-9a-z.-]+)?(?:\+[0-9a-z.-]+)?$/i.exec(value.trim());
26984
+ return match ? { parts: match.slice(1, 4).map(Number), prerelease: Boolean(match[4]) } : null;
26787
26985
  }
26788
- async function codexAccountEmail(cli, env, timeoutMs = 3e3) {
26789
- const cwd = env.HOME || env.USERPROFILE || homedir13();
26790
- if (!isAbsolute7(cwd) || !codexHome2(env)) return null;
26791
- return new Promise((resolveEmail) => {
26792
- let child;
26793
- try {
26794
- child = spawnCli(cli, ["app-server"], { cwd, env, stdio: ["pipe", "pipe", "pipe"] });
26795
- } catch {
26796
- resolveEmail(null);
26797
- return;
26798
- }
26799
- let finishing = false;
26800
- let buffer = "";
26801
- let outputBytes = 0;
26802
- let initialized = false;
26803
- const finish = async (email3) => {
26804
- if (finishing) return;
26805
- finishing = true;
26806
- clearTimeout(timer);
26807
- let stopped = await killCliTree(child, 1e3);
26808
- if (!stopped && child.pid) {
26809
- try {
26810
- if (process.platform === "win32") child.kill("SIGKILL");
26811
- else process.kill(-child.pid, "SIGKILL");
26812
- } catch {
26813
- try {
26814
- child.kill("SIGKILL");
26815
- } catch {
26816
- }
26817
- }
26818
- stopped = await killCliTree(child, 1e3);
26819
- }
26820
- resolveEmail(stopped ? email3 : null);
26821
- };
26822
- const timer = setTimeout(() => {
26823
- void finish(null);
26824
- }, timeoutMs);
26825
- timer.unref();
26826
- const send = (message2) => {
26986
+ function codexVersionBehind(installed, latest) {
26987
+ const a2 = parseCodexReleaseVersion(installed);
26988
+ const b2 = parseCodexReleaseVersion(latest);
26989
+ if (!a2 || !b2 || b2.prerelease) return false;
26990
+ for (let i2 = 0; i2 < 3; i2++) {
26991
+ if (a2.parts[i2] !== b2.parts[i2]) return a2.parts[i2] < b2.parts[i2];
26992
+ }
26993
+ return a2.prerelease;
26994
+ }
26995
+ function createCodexReleaseReader(fetchImpl = fetch, now = Date.now) {
26996
+ let cached3;
26997
+ let expires = 0;
26998
+ return () => {
26999
+ if (cached3 && now() < expires) return cached3;
27000
+ expires = now() + 60 * 60 * 1e3;
27001
+ cached3 = (async () => {
26827
27002
  try {
26828
- child.stdin.write(`${JSON.stringify(message2)}
26829
- `);
27003
+ const response = await fetchImpl("https://registry.npmjs.org/@openai/codex/latest", {
27004
+ signal: AbortSignal.timeout(3e3),
27005
+ headers: { Accept: "application/json" }
27006
+ });
27007
+ if (!response.ok) throw new Error("Release lookup failed");
27008
+ const payload = await response.json();
27009
+ const version2 = typeof payload.version === "string" ? payload.version : "";
27010
+ const parsed = parseCodexReleaseVersion(version2);
27011
+ if (!parsed || parsed.prerelease) throw new Error("Invalid stable release");
27012
+ return version2;
26830
27013
  } catch {
26831
- void finish(null);
26832
- }
26833
- };
26834
- child.stdin.on("error", () => {
26835
- void finish(null);
26836
- });
26837
- child.stderr.resume();
26838
- child.on("error", () => {
26839
- void finish(null);
26840
- });
26841
- child.on("close", () => {
26842
- void finish(null);
26843
- });
26844
- child.stdout.setEncoding("utf8");
26845
- child.stdout.on("data", (chunk) => {
26846
- if (finishing) return;
26847
- outputBytes += Buffer.byteLength(chunk);
26848
- if (outputBytes > MAX_OUTPUT4) {
26849
- void finish(null);
26850
- return;
26851
- }
26852
- buffer += chunk;
26853
- let newline;
26854
- while (!finishing && (newline = buffer.indexOf("\n")) !== -1) {
26855
- const line = buffer.slice(0, newline);
26856
- buffer = buffer.slice(newline + 1);
26857
- if (!line.trim()) continue;
26858
- let message2;
26859
- try {
26860
- message2 = JSON.parse(line);
26861
- } catch {
26862
- void finish(null);
26863
- return;
26864
- }
26865
- if (!initialized && message2?.id === 1) {
26866
- if (message2.error || !message2.result) {
26867
- void finish(null);
26868
- return;
26869
- }
26870
- initialized = true;
26871
- send({ method: "initialized", params: {} });
26872
- send({ id: 2, method: "account/read", params: { refreshToken: false } });
26873
- } else if (initialized && message2?.id === 2) {
26874
- const account = message2.error ? null : message2.result?.account;
26875
- const email3 = account?.type === "chatgpt" ? account.email : null;
26876
- void finish(typeof email3 === "string" && email3.length <= 254 && EMAIL.test(email3) && !/[\p{Cc}\p{Cf}]/u.test(email3) ? email3 : null);
26877
- }
27014
+ expires = now() + 5 * 60 * 1e3;
27015
+ return null;
26878
27016
  }
26879
- });
26880
- send({ id: 1, method: "initialize", params: { clientInfo: { name: "openmausbot", version: "1" } } });
26881
- });
27017
+ })();
27018
+ return cached3;
27019
+ };
26882
27020
  }
26883
- var MAX_OUTPUT4, EMAIL;
26884
- var init_codex_identity = __esm({
26885
- "server/drivers/codex-identity.ts"() {
27021
+ var readLatestCodexRelease;
27022
+ var init_codex_release = __esm({
27023
+ "server/drivers/codex-release.ts"() {
26886
27024
  "use strict";
26887
- init_procs();
26888
- MAX_OUTPUT4 = 16384;
26889
- EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
27025
+ readLatestCodexRelease = createCodexReleaseReader();
26890
27026
  }
26891
27027
  });
26892
27028
 
@@ -26896,18 +27032,6 @@ import { homedir as homedir14 } from "node:os";
26896
27032
  function missingNativeCodexThread(error51, cursor3) {
26897
27033
  return error51 instanceof CodexRpcError && error51.code === -32600 && error51.message === `no rollout found for thread id ${cursor3}`;
26898
27034
  }
26899
- function codexPredatesAstra(version2) {
26900
- const value = version2.trim();
26901
- const match = /\bcodex-cli\s+v?(\d+)\.(\d+)\.(\d+)(?:[-+][0-9a-z.-]+)?(?![\d.])\b/i.exec(value) ?? /^v?(\d+)\.(\d+)\.(\d+)(?:[-+][0-9a-z.-]+)?$/i.exec(value);
26902
- if (!match) return false;
26903
- const installed = match.slice(1, 4).map(Number);
26904
- for (let i2 = 0; i2 < ASTRA_MIN_CODEX_VERSION.length; i2 += 1) {
26905
- if (installed[i2] !== ASTRA_MIN_CODEX_VERSION[i2]) {
26906
- return installed[i2] < ASTRA_MIN_CODEX_VERSION[i2];
26907
- }
26908
- }
26909
- return false;
26910
- }
26911
27035
  function codexUpdateCommand(cli, platform = process.platform) {
26912
27036
  if (cli === "codex") return "codex update";
26913
27037
  const trimmed = cli.trim();
@@ -26916,13 +27040,12 @@ function codexUpdateCommand(cli, platform = process.platform) {
26916
27040
  const command = (tokens.length > 0 ? tokens : [trimmed]).map(quote2).join(" ");
26917
27041
  return platform === "win32" ? `& ${command} update` : `${command} update`;
26918
27042
  }
26919
- function codexAstraUpdate(version2, models2, cli) {
26920
- if (models2.options.some((model) => model.id === ASTRA_MODEL_ID) || !codexPredatesAstra(version2)) {
26921
- return void 0;
26922
- }
27043
+ async function codexReleaseUpdate(version2, cli) {
27044
+ const latest = await readLatestCodexRelease();
27045
+ if (!latest || !codexVersionBehind(version2, latest)) return void 0;
26923
27046
  return {
26924
- title: "Update Codex for GPT-6 Astra",
26925
- message: "This Codex version predates Astra support. Update it, then refresh models. Astra must also be available to your signed-in ChatGPT account.",
27047
+ title: `Update Codex to ${latest}`,
27048
+ message: `A newer stable Codex CLI is available (installed: ${version2}). Update it, then refresh models. Model availability also depends on your signed-in account.`,
26926
27049
  command: codexUpdateCommand(cli)
26927
27050
  };
26928
27051
  }
@@ -27224,7 +27347,7 @@ function mountMcpServer(appServerArgs, env, name, server, preApproved = true) {
27224
27347
  appServerArgs.push("-c", `${prefix}.default_tools_approval_mode="auto"`);
27225
27348
  }
27226
27349
  }
27227
- var DRIVER_KIND3, ASTRA_MODEL_ID, ASTRA_MIN_CODEX_VERSION, CodexRpcError, DENY_TIMEOUT_NOTE2, skippedSseServers, renamedMcpServers, plainRecord, containsControlCharacter, CodexDriver;
27350
+ var DRIVER_KIND3, CodexRpcError, DENY_TIMEOUT_NOTE2, skippedSseServers, renamedMcpServers, plainRecord, containsControlCharacter, CodexDriver;
27228
27351
  var init_codex = __esm({
27229
27352
  "server/drivers/codex.ts"() {
27230
27353
  "use strict";
@@ -27248,10 +27371,9 @@ var init_codex = __esm({
27248
27371
  init_resume_recovery();
27249
27372
  init_mcp_tool_images();
27250
27373
  init_ask_question();
27374
+ init_codex_release();
27251
27375
  init_codex_catalog();
27252
27376
  DRIVER_KIND3 = "codex";
27253
- ASTRA_MODEL_ID = "gpt-6-astra";
27254
- ASTRA_MIN_CODEX_VERSION = [0, 153, 1];
27255
27377
  CodexRpcError = class extends Error {
27256
27378
  code;
27257
27379
  constructor(error51) {
@@ -28090,7 +28212,7 @@ ${stderr ?? ""}`))
28090
28212
  version: version2,
28091
28213
  authenticated,
28092
28214
  ...email3 ? { account: { email: email3 } } : {},
28093
- update: codexAstraUpdate(version2, models2, config2.cli),
28215
+ update: await codexReleaseUpdate(version2, config2.cli),
28094
28216
  billing: "subscription"
28095
28217
  };
28096
28218
  };
@@ -37738,7 +37860,8 @@ function createOpenAIChatRuntime(options) {
37738
37860
  const done = new Promise((resolve12) => {
37739
37861
  resolveDone = resolve12;
37740
37862
  });
37741
- active.set(turn.threadId, { abort, turnId, done, approval });
37863
+ const turnEntry = { abort, turnId, done, approval, asides: [] };
37864
+ active.set(turn.threadId, turnEntry);
37742
37865
  emit({ ...base2(turn.threadId, turnId), type: "turn.started" });
37743
37866
  emit({ ...base2(turn.threadId, turnId), type: "session.started", sessionId: null, model });
37744
37867
  void (async () => {
@@ -37759,6 +37882,8 @@ function createOpenAIChatRuntime(options) {
37759
37882
  }
37760
37883
  for (let round = 0; round < 16; round++) {
37761
37884
  abort.signal.throwIfAborted();
37885
+ const parked = turnEntry.asides.splice(0);
37886
+ if (parked.length) messages.push({ role: "user", content: parked.join("\n\n") });
37762
37887
  native("out", options.nativeLog.outgoing(turn, messages, model));
37763
37888
  let attempt = 0;
37764
37889
  let completion;
@@ -37984,7 +38109,10 @@ function createOpenAIChatRuntime(options) {
37984
38109
  sessionModelSwitch: "in-session",
37985
38110
  customMcp: options.tools !== false,
37986
38111
  agentsMcp: options.tools !== false,
37987
- composioMcp: options.tools !== false
38112
+ composioMcp: options.tools !== false,
38113
+ // The runtime owns the whole tool loop, so it can always take a
38114
+ // user message mid-turn: park it, deliver before the next completion.
38115
+ queueing: true
37988
38116
  },
37989
38117
  sendTurn,
37990
38118
  interruptTurn: async (threadId, turnId) => {
@@ -37994,6 +38122,12 @@ function createOpenAIChatRuntime(options) {
37994
38122
  await turn.done;
37995
38123
  },
37996
38124
  respondToRequest: async (threadId, requestId, decision) => active.get(threadId)?.approval.answer(requestId, decision.behavior, decision.message) ?? "unavailable",
38125
+ steer: async (threadId, text4) => {
38126
+ const running2 = active.get(threadId);
38127
+ if (!running2) return "refused";
38128
+ running2.asides.push(text4);
38129
+ return "steered";
38130
+ },
37997
38131
  hasSession: (threadId) => active.has(threadId),
37998
38132
  stopAll: async () => {
37999
38133
  const turns = [...active.values()];
@@ -38103,12 +38237,7 @@ var init_grok = __esm({
38103
38237
 
38104
38238
  // server/drivers/acp/grok.ts
38105
38239
  import { existsSync as existsSync11, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "node:fs";
38106
- import { homedir as homedir15 } from "node:os";
38107
38240
  import { join as join30 } from "node:path";
38108
- function grokHome(env) {
38109
- if (env.GROK_HOME) return env.GROK_HOME;
38110
- return join30(env.HOME || env.USERPROFILE || homedir15(), ".grok");
38111
- }
38112
38241
  function unquote2(raw) {
38113
38242
  const value = raw.trim();
38114
38243
  if (value.length >= 2 && value.startsWith('"') && value.endsWith('"')) {
@@ -38117,7 +38246,7 @@ function unquote2(raw) {
38117
38246
  return value;
38118
38247
  }
38119
38248
  function readGrokModelCatalog(env = process.env) {
38120
- const path3 = join30(grokHome(env), "config.toml");
38249
+ const path3 = join30(env.GROK_HOME || harnessHome("grok", env), "config.toml");
38121
38250
  let text4 = "";
38122
38251
  try {
38123
38252
  text4 = readFileSync16(path3, "utf8");
@@ -38190,7 +38319,7 @@ function ensureGrokInjectSlug(modelId, env = process.env) {
38190
38319
  if (!inject) return modelId;
38191
38320
  const host = localHost(inject.host);
38192
38321
  if (!host) return modelId;
38193
- const path3 = join30(grokHome(env), "config.toml");
38322
+ const path3 = join30(env.GROK_HOME || harnessHome("grok", env), "config.toml");
38194
38323
  let text4 = "";
38195
38324
  try {
38196
38325
  text4 = readFileSync16(path3, "utf8");
@@ -38257,6 +38386,7 @@ var STATIC_GROK_MODELS, SLUG, support2, GrokAgentDriver;
38257
38386
  var init_grok2 = __esm({
38258
38387
  "server/drivers/acp/grok.ts"() {
38259
38388
  "use strict";
38389
+ init_env_path();
38260
38390
  init_local_inject();
38261
38391
  init_core3();
38262
38392
  STATIC_GROK_MODELS = {
@@ -38337,7 +38467,7 @@ var init_grok2 = __esm({
38337
38467
  // an unauthenticated CLI is a user action, not something to paper over.
38338
38468
  pickAuthMethod: (methods) => methods.some((m2) => m2.id === "cached_token") ? "cached_token" : null,
38339
38469
  authFailure: "fail",
38340
- isAuthenticated: () => existsSync11(join30(homedir15(), ".grok", "auth.json")),
38470
+ isAuthenticated: (env) => existsSync11(join30(harnessHome("grok", env), "auth.json")),
38341
38471
  // `--append-system-prompt`/`--rules` are accepted by the CLI but do NOT
38342
38472
  // reach the agent-stdio system prompt (verified against 1.0.0), so the
38343
38473
  // persona is prepended codex-style.
@@ -38351,11 +38481,10 @@ ${turn.text}` : turn.text
38351
38481
 
38352
38482
  // server/drivers/acp/gemini.ts
38353
38483
  import { existsSync as existsSync12, readFileSync as readFileSync17 } from "node:fs";
38354
- import { homedir as homedir16 } from "node:os";
38355
38484
  import { join as join31 } from "node:path";
38356
- function liveOauthCredential() {
38485
+ function liveOauthCredential(env) {
38357
38486
  try {
38358
- const creds = JSON.parse(readFileSync17(join31(homedir16(), ".gemini", "oauth_creds.json"), "utf8"));
38487
+ const creds = JSON.parse(readFileSync17(join31(userHome(env), ".gemini", "oauth_creds.json"), "utf8"));
38359
38488
  if (typeof creds.access_token !== "string" || creds.access_token.trim().length === 0) return false;
38360
38489
  const hasRefresh = typeof creds.refresh_token === "string" && creds.refresh_token.trim().length > 0;
38361
38490
  if (creds.expiry_date !== void 0) {
@@ -38368,7 +38497,7 @@ function liveOauthCredential() {
38368
38497
  }
38369
38498
  }
38370
38499
  function geminiIsAuthenticated(env) {
38371
- return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync12(join31(homedir16(), ".gemini", "oauth_creds.json")) && liveOauthCredential();
38500
+ return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync12(join31(userHome(env), ".gemini", "oauth_creds.json")) && liveOauthCredential(env);
38372
38501
  }
38373
38502
  function geminiApprovalArgs(fullAuto, approvalMode) {
38374
38503
  if (fullAuto) return ["--yolo"];
@@ -38379,6 +38508,7 @@ var AUTH_PREFERENCE, nonBlank, support3, GeminiAgentDriver;
38379
38508
  var init_gemini = __esm({
38380
38509
  "server/drivers/acp/gemini.ts"() {
38381
38510
  "use strict";
38511
+ init_env_path();
38382
38512
  init_core3();
38383
38513
  AUTH_PREFERENCE = ["gemini-api-key", "oauth-personal", "vertex-ai"];
38384
38514
  nonBlank = (value) => Boolean(value?.trim());
@@ -38416,13 +38546,13 @@ ${turn.text}` : turn.text
38416
38546
 
38417
38547
  // server/drivers/acp/kimi.ts
38418
38548
  import { existsSync as existsSync13, mkdirSync as mkdirSync15, readFileSync as readFileSync18, writeFileSync as writeFileSync10 } from "node:fs";
38419
- import { homedir as homedir17 } from "node:os";
38549
+ import { homedir as homedir15 } from "node:os";
38420
38550
  import { join as join32 } from "node:path";
38421
38551
  function isLocalInjectAlias(slug) {
38422
38552
  return LOCAL_PROVIDER_PREFIXES.some((prefix) => slug.startsWith(prefix));
38423
38553
  }
38424
38554
  function kimiDataRoot(env) {
38425
- return env.KIMI_CODE_HOME || join32(env.HOME || env.USERPROFILE || homedir17(), ".kimi-code");
38555
+ return env.KIMI_CODE_HOME || join32(env.HOME || env.USERPROFILE || homedir15(), ".kimi-code");
38426
38556
  }
38427
38557
  function credentialsPath(env) {
38428
38558
  return join32(kimiDataRoot(env), "credentials", "kimi-code.json");
@@ -38898,26 +39028,22 @@ ${turn.text}` : turn.text
38898
39028
 
38899
39029
  // server/drivers/acp/droid.ts
38900
39030
  import { existsSync as existsSync14, mkdirSync as mkdirSync16, readFileSync as readFileSync19, writeFileSync as writeFileSync11 } from "node:fs";
38901
- import { homedir as homedir18 } from "node:os";
38902
39031
  import { join as join33 } from "node:path";
38903
39032
  function authFilePaths(env) {
38904
- const home = env.FACTORY_HOME_OVERRIDE || env.HOME || homedir18();
39033
+ const home = env.FACTORY_HOME_OVERRIDE || userHome(env);
38905
39034
  return AUTH_FILES.map((name) => join33(home, ".factory", name));
38906
39035
  }
38907
39036
  function droidInjectId(host, model) {
38908
39037
  const safe = `${host}-${model}`.replace(/[^a-zA-Z0-9._+-]+/g, "-").replace(/-+/g, "-");
38909
39038
  return `${INJECT_ID_PREFIX}${safe}`;
38910
39039
  }
38911
- function factoryHome(env) {
38912
- return env.FACTORY_HOME_OVERRIDE || env.HOME || env.USERPROFILE || homedir18();
38913
- }
38914
39040
  function ensureDroidInjectModel(modelId, env = process.env) {
38915
39041
  const inject = decodeInjectId(modelId);
38916
39042
  if (!inject) return modelId;
38917
39043
  const host = localHost(inject.host);
38918
39044
  if (!host) return modelId;
38919
39045
  const id = droidInjectId(inject.host, inject.model);
38920
- const dir = join33(factoryHome(env), ".factory");
39046
+ const dir = join33(env.FACTORY_HOME_OVERRIDE || userHome(env), ".factory");
38921
39047
  mkdirSync16(dir, { recursive: true });
38922
39048
  const path3 = join33(dir, "settings.json");
38923
39049
  let settings2 = {};
@@ -38959,7 +39085,7 @@ function applyDroidLocalAuthEnv(env, modelId) {
38959
39085
  env.FACTORY_API_KEY = "openmausbot-local";
38960
39086
  }
38961
39087
  function readSettings(env) {
38962
- return JSON.parse(readFileSync19(join33(factoryHome(env), ".factory", "settings.json"), "utf8"));
39088
+ return JSON.parse(readFileSync19(join33(env.FACTORY_HOME_OVERRIDE || userHome(env), ".factory", "settings.json"), "utf8"));
38963
39089
  }
38964
39090
  async function resolveModels(env) {
38965
39091
  let catalog2 = MODELS3;
@@ -38997,6 +39123,7 @@ var AUTH_FILES, INJECT_ID_PREFIX, MODE_DEFAULT, MODE_FULL_AUTO, MODELS3, support
38997
39123
  var init_droid = __esm({
38998
39124
  "server/drivers/acp/droid.ts"() {
38999
39125
  "use strict";
39126
+ init_env_path();
39000
39127
  init_local_inject();
39001
39128
  init_core3();
39002
39129
  AUTH_FILES = ["auth.v2.file", "auth.v2.loginkeychain", "auth.v2.keyring"];
@@ -39110,8 +39237,8 @@ function asRecord(value) {
39110
39237
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
39111
39238
  }
39112
39239
  function labelFor(id, explicit) {
39113
- if (explicit?.trim()) return explicit.trim();
39114
- return id.split(/[-_./]+/g).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
39240
+ const trimmed = explicit?.trim();
39241
+ return trimmed || titleCaseModelId(id, /[-_./]+/);
39115
39242
  }
39116
39243
  function pushModel(options, seen, id, label, custom2 = false) {
39117
39244
  if (!SLUG3.test(id) || seen.has(id)) return;
@@ -39277,6 +39404,7 @@ var STATIC_CURSOR_MODELS, SLUG3, EXEC_TIMEOUT_MS, nonBlank2, support6, CursorAge
39277
39404
  var init_cursor = __esm({
39278
39405
  "server/drivers/acp/cursor.ts"() {
39279
39406
  "use strict";
39407
+ init_contracts();
39280
39408
  init_procs();
39281
39409
  init_core3();
39282
39410
  STATIC_CURSOR_MODELS = {
@@ -39350,10 +39478,10 @@ ${turn.text}` : turn.text
39350
39478
 
39351
39479
  // server/drivers/acp/opencode-go.ts
39352
39480
  import { existsSync as existsSync15, mkdirSync as mkdirSync17, readFileSync as readFileSync20, writeFileSync as writeFileSync12 } from "node:fs";
39353
- import { homedir as homedir19 } from "node:os";
39481
+ import { homedir as homedir16 } from "node:os";
39354
39482
  import { join as join34 } from "node:path";
39355
39483
  function labelForModel(id) {
39356
- return id.split(/[-_.]+/g).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
39484
+ return titleCaseModelId(id, /[-_.]+/);
39357
39485
  }
39358
39486
  function providerLabel(id) {
39359
39487
  if (id === "opencode") return "Zen";
@@ -39453,7 +39581,7 @@ async function discoverOpenCodeModels(environment, cli = "opencode") {
39453
39581
  }
39454
39582
  }
39455
39583
  function opencodeConfigDir(env) {
39456
- const home = env.HOME || env.USERPROFILE || homedir19();
39584
+ const home = env.HOME || env.USERPROFILE || homedir16();
39457
39585
  return join34(env.XDG_CONFIG_HOME || join34(home, ".config"), "opencode");
39458
39586
  }
39459
39587
  function ensureOpenCodeInjectModel(modelId, env = process.env) {
@@ -39500,7 +39628,7 @@ function ensureOpenCodeInjectModel(modelId, env = process.env) {
39500
39628
  return native;
39501
39629
  }
39502
39630
  function storedAuthPaths(env) {
39503
- const home = env.HOME || env.USERPROFILE || homedir19();
39631
+ const home = env.HOME || env.USERPROFILE || homedir16();
39504
39632
  const roots = [
39505
39633
  env.XDG_DATA_HOME || join34(home, ".local", "share"),
39506
39634
  process.platform === "darwin" ? join34(home, "Library", "Application Support") : process.platform === "win32" ? env.LOCALAPPDATA || join34(home, "AppData", "Local") : ""
@@ -39568,6 +39696,7 @@ var init_opencode_go = __esm({
39568
39696
  "use strict";
39569
39697
  init_local_inject();
39570
39698
  init_core3();
39699
+ init_contracts();
39571
39700
  init_procs();
39572
39701
  STATIC_MODELS = {
39573
39702
  default: "opencode/x-preview-f-free",
@@ -39660,23 +39789,14 @@ ${turn.text}` : turn.text
39660
39789
  // server/drivers/acp/qwen.ts
39661
39790
  import { chmodSync as chmodSync5, existsSync as existsSync16, mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync13 } from "node:fs";
39662
39791
  import { createHash as createHash12 } from "node:crypto";
39663
- import { homedir as homedir20 } from "node:os";
39664
39792
  import { join as join35 } from "node:path";
39665
- function qwenHome(env) {
39666
- const home = process.platform === "win32" ? env.USERPROFILE || env.HOME || homedir20() : env.HOME || env.USERPROFILE || homedir20();
39667
- return join35(home, ".qwen");
39668
- }
39669
39793
  function isRecord3(value) {
39670
39794
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
39671
39795
  }
39672
- function qwenModelLabel(id, name) {
39673
- if (!name || name.toLocaleLowerCase().endsWith(id.toLocaleLowerCase())) return id;
39674
- return `${id} \u2014 ${name}`;
39675
- }
39676
39796
  function readQwenRoutes(env) {
39677
39797
  let settings2;
39678
39798
  try {
39679
- settings2 = JSON.parse(readFileSync21(join35(qwenHome(env), "settings.json"), "utf8"));
39799
+ settings2 = JSON.parse(readFileSync21(join35(harnessHome("qwen", env), "settings.json"), "utf8"));
39680
39800
  } catch {
39681
39801
  return [];
39682
39802
  }
@@ -39744,7 +39864,9 @@ function readQwenRoutes(env) {
39744
39864
  function readQwenModelCatalog(env = process.env) {
39745
39865
  const options = readQwenRoutes(env).map(({ id, model, label, provider }) => ({
39746
39866
  id,
39747
- label: qwenModelLabel(model, label),
39867
+ label: qualifiedModelLabel(model, label, {
39868
+ redundantWhen: (id2, name) => name.toLocaleLowerCase().endsWith(id2.toLocaleLowerCase())
39869
+ }),
39748
39870
  custom: true,
39749
39871
  provider
39750
39872
  }));
@@ -39758,7 +39880,7 @@ function ensureQwenInjectModel(modelId, env = process.env) {
39758
39880
  if (!inject) return modelId;
39759
39881
  const host = localHost(inject.host);
39760
39882
  if (!host) return modelId;
39761
- const dir = qwenHome(env);
39883
+ const dir = harnessHome("qwen", env);
39762
39884
  mkdirSync18(dir, { recursive: true });
39763
39885
  const path3 = join35(dir, "settings.json");
39764
39886
  let settings2 = {};
@@ -39840,6 +39962,8 @@ var EMPTY, PROTOCOLS, support8, QwenAgentDriver;
39840
39962
  var init_qwen = __esm({
39841
39963
  "server/drivers/acp/qwen.ts"() {
39842
39964
  "use strict";
39965
+ init_contracts();
39966
+ init_env_path();
39843
39967
  init_local_inject();
39844
39968
  init_core3();
39845
39969
  EMPTY = { default: "", options: [] };
@@ -46766,7 +46890,7 @@ var init_browser = __esm({
46766
46890
  // server/drivers/acp/hermes.ts
46767
46891
  import { spawn as spawn6 } from "node:child_process";
46768
46892
  import { mkdirSync as mkdirSync19, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "node:fs";
46769
- import { homedir as homedir21 } from "node:os";
46893
+ import { homedir as homedir17 } from "node:os";
46770
46894
  import { join as join36 } from "node:path";
46771
46895
  function bindHermesScreenshotCompat(env, modelId) {
46772
46896
  delete env[HERMES_OPENMAUS_SCREENSHOT_COMPAT];
@@ -46776,9 +46900,6 @@ function bindHermesScreenshotCompat(env, modelId) {
46776
46900
  env[HERMES_OPENMAUS_SCREENSHOT_COMPAT] = "1";
46777
46901
  env[HERMES_OPENMAUS_SCREENSHOT_COMPAT_MODEL] = inject.model;
46778
46902
  }
46779
- function hermesHome(env) {
46780
- return env.HERMES_HOME || join36(env.HOME || env.USERPROFILE || homedir21(), ".hermes");
46781
- }
46782
46903
  function quoteYaml(value) {
46783
46904
  if (/^[\w./:+-]+$/.test(value)) return value;
46784
46905
  return JSON.stringify(value);
@@ -46817,7 +46938,7 @@ function ensureHermesInjectProvider(modelId, env = process.env) {
46817
46938
  if (!inject) return modelId;
46818
46939
  const host = localHost(inject.host);
46819
46940
  if (!host) return modelId;
46820
- const dir = hermesHome(env);
46941
+ const dir = env.HERMES_HOME || harnessHome("hermes", env);
46821
46942
  mkdirSync19(dir, { recursive: true });
46822
46943
  const path3 = join36(dir, "config.yaml");
46823
46944
  let text4 = "";
@@ -46887,7 +47008,7 @@ function hermesConfigDefault(text4) {
46887
47008
  return null;
46888
47009
  }
46889
47010
  function hermesConfiguredModel(env = process.env) {
46890
- const dir = hermesHome(env);
47011
+ const dir = env.HERMES_HOME || harnessHome("hermes", env);
46891
47012
  let secrets = "";
46892
47013
  try {
46893
47014
  secrets = readFileSync22(join36(dir, ".env"), "utf8");
@@ -46988,7 +47109,7 @@ async function fetchHermesAcpModels(cli, env) {
46988
47109
  }
46989
47110
  if (msg?.id === initId) {
46990
47111
  if (!msg.result) return done([]);
46991
- sessionId = send("session/new", { cwd: env.HOME || env.USERPROFILE || homedir21(), mcpServers: [] });
47112
+ sessionId = send("session/new", { cwd: env.HOME || env.USERPROFILE || homedir17(), mcpServers: [] });
46992
47113
  } else if (sessionId && msg?.id === sessionId) {
46993
47114
  const list = Array.isArray(msg.result?.models?.availableModels) ? msg.result.models.availableModels : [];
46994
47115
  done(
@@ -47032,6 +47153,7 @@ var init_hermes = __esm({
47032
47153
  "server/drivers/acp/hermes.ts"() {
47033
47154
  "use strict";
47034
47155
  init_browser();
47156
+ init_env_path();
47035
47157
  init_procs();
47036
47158
  init_local_inject();
47037
47159
  init_core3();
@@ -47241,8 +47363,8 @@ var init_openai_compat = __esm({
47241
47363
  });
47242
47364
 
47243
47365
  // server/drivers/pi.ts
47244
- import { chmodSync as chmodSync6, existsSync as existsSync17, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync3, readFileSync as readFileSync23, rmSync as rmSync6, writeFileSync as writeFileSync15 } from "node:fs";
47245
- import { homedir as homedir22, tmpdir as tmpdir4 } from "node:os";
47366
+ import { chmodSync as chmodSync6, existsSync as existsSync17, mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync3, readFileSync as readFileSync23, rmSync as rmSync7, writeFileSync as writeFileSync15 } from "node:fs";
47367
+ import { homedir as homedir18, tmpdir as tmpdir4 } from "node:os";
47246
47368
  import { join as join37 } from "node:path";
47247
47369
  function readPiPromptImages(turn) {
47248
47370
  return (turn.images ?? []).map((image) => ({
@@ -47344,7 +47466,7 @@ async function applyPiLocalCatalog(catalog2, env = process.env, fetchImpl = fetc
47344
47466
  return preferPiInjectRows(await mergeLocalInject(catalog2, env, fetchImpl));
47345
47467
  }
47346
47468
  function piAgentDir(env) {
47347
- return join37(env.HOME || env.USERPROFILE || homedir22(), ".pi", "agent");
47469
+ return join37(env.HOME || env.USERPROFILE || homedir18(), ".pi", "agent");
47348
47470
  }
47349
47471
  function ensurePiInjectModel(modelId, env = process.env) {
47350
47472
  const split = splitPiModel(modelId);
@@ -47409,7 +47531,7 @@ function ensurePiInjectModel(modelId, env = process.env) {
47409
47531
  return split;
47410
47532
  }
47411
47533
  function readPiDefaultModel(env) {
47412
- const home = env.HOME || env.USERPROFILE || homedir22();
47534
+ const home = env.HOME || env.USERPROFILE || homedir18();
47413
47535
  try {
47414
47536
  const s2 = JSON.parse(readFileSync23(`${home}/.pi/agent/settings.json`, "utf8"));
47415
47537
  return s2.defaultProvider && s2.defaultModel ? `${s2.defaultProvider}/${s2.defaultModel}` : "";
@@ -47486,13 +47608,14 @@ function piEnvironment(source) {
47486
47608
  for (const key of PROVIDER_CREDENTIAL_ENV) delete env[key];
47487
47609
  return env;
47488
47610
  }
47489
- var DRIVER_KIND6, PI_ARGS, PI_MODEL_UPDATE_ARGS, NODE_ENV_FLAG2, EMPTY3, PiDriver;
47611
+ var DRIVER_KIND6, PI_ARGS, PI_MODEL_UPDATE_ARGS, NODE_ENV_FLAG2, PI_PROMPT_RE_ANCHOR_TURNS, PI_AGENT_END_GRACE_MS, PiRpcRefusalError, EMPTY3, PiDriver;
47490
47612
  var init_pi = __esm({
47491
47613
  "server/drivers/pi.ts"() {
47492
47614
  "use strict";
47493
47615
  init_config();
47494
47616
  init_env_path();
47495
47617
  init_procs();
47618
+ init_prompt_split();
47496
47619
  init_proxy_paths();
47497
47620
  init_tool_summary();
47498
47621
  init_wire();
@@ -47504,6 +47627,10 @@ var init_pi = __esm({
47504
47627
  PI_ARGS = ["--mode", "rpc", "--no-session"];
47505
47628
  PI_MODEL_UPDATE_ARGS = ["update", "--models", "--no-approve"];
47506
47629
  NODE_ENV_FLAG2 = { ELECTRON_RUN_AS_NODE: "1" };
47630
+ PI_PROMPT_RE_ANCHOR_TURNS = 8;
47631
+ PI_AGENT_END_GRACE_MS = 6e4;
47632
+ PiRpcRefusalError = class extends Error {
47633
+ };
47507
47634
  EMPTY3 = { default: "", options: [] };
47508
47635
  PiDriver = {
47509
47636
  driverKind: DRIVER_KIND6,
@@ -47568,6 +47695,10 @@ var init_pi = __esm({
47568
47695
  const pending = /* @__PURE__ */ new Map();
47569
47696
  const askTimers = /* @__PURE__ */ new Set();
47570
47697
  let settled = false;
47698
+ let endStopReason;
47699
+ let endUsage;
47700
+ let endErrorMessage;
47701
+ let agentEndTimer = null;
47571
47702
  const images = readPiPromptImages(turn);
47572
47703
  if (typeof turn.model === "string" && turn.model) {
47573
47704
  ensurePiInjectModel(turn.model, { ...process.env, ...input.environment });
@@ -47580,7 +47711,7 @@ var init_pi = __esm({
47580
47711
  writeFileSync15(join37(mcpTempDir, "mcp.json"), JSON.stringify({ mcpServers }), { mode: 384 });
47581
47712
  } catch (err) {
47582
47713
  try {
47583
- rmSync6(mcpTempDir, { recursive: true, force: true });
47714
+ rmSync7(mcpTempDir, { recursive: true, force: true });
47584
47715
  } catch {
47585
47716
  }
47586
47717
  throw err;
@@ -47601,7 +47732,7 @@ var init_pi = __esm({
47601
47732
  } catch (err) {
47602
47733
  if (mcpTempDir) {
47603
47734
  try {
47604
- rmSync6(mcpTempDir, { recursive: true, force: true });
47735
+ rmSync7(mcpTempDir, { recursive: true, force: true });
47605
47736
  } catch {
47606
47737
  }
47607
47738
  }
@@ -47610,7 +47741,9 @@ var init_pi = __esm({
47610
47741
  })();
47611
47742
  let buf = "";
47612
47743
  let assistantText = "";
47744
+ let compactionObserved = false;
47613
47745
  const responseWaiters = /* @__PURE__ */ new Map();
47746
+ let steerSeq = 0;
47614
47747
  const rejectWaiters = (err) => {
47615
47748
  for (const waiter of responseWaiters.values()) {
47616
47749
  clearTimeout(waiter.timer);
@@ -47618,13 +47751,13 @@ var init_pi = __esm({
47618
47751
  }
47619
47752
  responseWaiters.clear();
47620
47753
  };
47621
- const awaitResponse = (command, timeoutMs = 2e4) => new Promise((resolve12, reject) => {
47754
+ const awaitResponse = (command, timeoutMs = 2e4, key = command) => new Promise((resolve12, reject) => {
47622
47755
  const timer = setTimeout(() => {
47623
- responseWaiters.delete(command);
47756
+ responseWaiters.delete(key);
47624
47757
  reject(new Error(`pi ${command} timed out`));
47625
47758
  }, timeoutMs);
47626
47759
  timer.unref?.();
47627
- responseWaiters.set(command, { resolve: resolve12, reject, timer });
47760
+ responseWaiters.set(key, { resolve: resolve12, reject, timer });
47628
47761
  });
47629
47762
  child.stdin.on("error", () => rejectWaiters(new Error("pi stdin closed")));
47630
47763
  const send = (obj) => {
@@ -47640,6 +47773,10 @@ var init_pi = __esm({
47640
47773
  const settle = (ok, stopReason, usage) => {
47641
47774
  if (settled) return;
47642
47775
  settled = true;
47776
+ if (agentEndTimer) {
47777
+ clearTimeout(agentEndTimer);
47778
+ agentEndTimer = null;
47779
+ }
47643
47780
  for (const timer of askTimers) clearTimeout(timer);
47644
47781
  askTimers.clear();
47645
47782
  pending.clear();
@@ -47661,12 +47798,25 @@ var init_pi = __esm({
47661
47798
  }
47662
47799
  if (mcpTempDir) {
47663
47800
  try {
47664
- rmSync6(mcpTempDir, { recursive: true, force: true });
47801
+ rmSync7(mcpTempDir, { recursive: true, force: true });
47665
47802
  } catch {
47666
47803
  }
47667
47804
  }
47668
47805
  active.delete(threadId);
47669
47806
  };
47807
+ const finishRun = () => {
47808
+ const sr = endStopReason;
47809
+ if (sr === "error" || sr === "failed") {
47810
+ emit({
47811
+ ...base2(threadId, turnId),
47812
+ type: "runtime.error",
47813
+ message: String(endErrorMessage ?? "pi turn failed").slice(0, 2e3)
47814
+ });
47815
+ settle(false, "failed", endUsage);
47816
+ return;
47817
+ }
47818
+ settle(true, sr === "cancelled" || sr === "aborted" ? "cancelled" : "end_turn", endUsage);
47819
+ };
47670
47820
  const stop = () => {
47671
47821
  try {
47672
47822
  send({ type: "abort" });
@@ -47678,17 +47828,35 @@ var init_pi = __esm({
47678
47828
  }
47679
47829
  settle(true, "cancelled");
47680
47830
  };
47681
- active.set(threadId, { stop, turnId, pending, child });
47831
+ const steerActiveTurn = async (text4) => {
47832
+ if (settled || child.exitCode !== null || child.signalCode !== null) return "refused";
47833
+ let ack;
47834
+ try {
47835
+ const id = `steer:${++steerSeq}`;
47836
+ ack = awaitResponse("steer", 2e4, id);
47837
+ send({ type: "steer", id, message: text4 });
47838
+ } catch {
47839
+ return "refused";
47840
+ }
47841
+ try {
47842
+ await ack;
47843
+ return "steered";
47844
+ } catch (error51) {
47845
+ return error51 instanceof PiRpcRefusalError ? "refused" : "indeterminate";
47846
+ }
47847
+ };
47848
+ active.set(threadId, { stop, turnId, pending, child, steer: steerActiveTurn });
47682
47849
  const onEvent = (evt) => {
47683
47850
  appendNative(threadId, { dir: "in", source: "pi.rpc", msg: evt });
47684
47851
  switch (evt.type) {
47685
47852
  case "response": {
47686
- if (evt.command && responseWaiters.has(evt.command)) {
47687
- const waiter = responseWaiters.get(evt.command);
47688
- responseWaiters.delete(evt.command);
47853
+ const key = typeof evt.id === "string" && responseWaiters.has(evt.id) ? evt.id : evt.command;
47854
+ if (key && responseWaiters.has(key)) {
47855
+ const waiter = responseWaiters.get(key);
47856
+ responseWaiters.delete(key);
47689
47857
  clearTimeout(waiter.timer);
47690
47858
  if (evt.success) waiter.resolve(evt.data);
47691
- else waiter.reject(new Error(`pi ${evt.command} failed`));
47859
+ else waiter.reject(new PiRpcRefusalError(`pi ${evt.command} failed`));
47692
47860
  }
47693
47861
  return;
47694
47862
  }
@@ -47779,21 +47947,43 @@ var init_pi = __esm({
47779
47947
  }
47780
47948
  return;
47781
47949
  }
47782
- case "turn_end":
47783
- case "agent_end": {
47950
+ case "compaction_start":
47951
+ case "compaction_end":
47952
+ case "auto_compaction_start":
47953
+ case "auto_compaction_end": {
47954
+ if (sessionReady && sessionFile) {
47955
+ compactionObserved = true;
47956
+ deletePromptSplitReceipt("pi", JSON.stringify([threadId, sessionFile]));
47957
+ }
47958
+ return;
47959
+ }
47960
+ case "turn_end": {
47961
+ if (settled) return;
47784
47962
  const sr = evt.message?.stopReason;
47785
47963
  if (sr === "toolUse" || sr === "tool_use" || sr === "tool_calls") return;
47786
- const usage = evt.usage ?? evt.message?.usage;
47787
- if (sr === "error" || sr === "failed") {
47788
- emit({
47789
- ...base2(threadId, turnId),
47790
- type: "runtime.error",
47791
- message: String(evt.message?.errorMessage ?? "pi turn failed").slice(0, 2e3)
47792
- });
47793
- settle(false, "failed", usage);
47794
- return;
47964
+ endStopReason = sr;
47965
+ endUsage = evt.usage ?? evt.message?.usage;
47966
+ endErrorMessage = evt.message?.errorMessage;
47967
+ if (agentEndTimer) clearTimeout(agentEndTimer);
47968
+ agentEndTimer = setTimeout(finishRun, PI_AGENT_END_GRACE_MS);
47969
+ agentEndTimer.unref?.();
47970
+ return;
47971
+ }
47972
+ case "agent_end": {
47973
+ if (evt.isTerminal === false || evt.willRetry === true) return;
47974
+ if (agentEndTimer) {
47975
+ clearTimeout(agentEndTimer);
47976
+ agentEndTimer = null;
47795
47977
  }
47796
- settle(true, sr === "cancelled" || sr === "aborted" ? "cancelled" : "end_turn", usage);
47978
+ finishRun();
47979
+ return;
47980
+ }
47981
+ case "agent_settled": {
47982
+ if (agentEndTimer) {
47983
+ clearTimeout(agentEndTimer);
47984
+ agentEndTimer = null;
47985
+ }
47986
+ finishRun();
47797
47987
  return;
47798
47988
  }
47799
47989
  default:
@@ -47827,12 +48017,14 @@ var init_pi = __esm({
47827
48017
  emit({ ...base2(threadId, turnId), type: "turn.started" });
47828
48018
  const sessionPath = typeof turn.resumeCursor === "string" ? turn.resumeCursor : null;
47829
48019
  let sessionFile = sessionPath;
48020
+ let sessionReady = false;
47830
48021
  try {
47831
48022
  const command = sessionPath ? "switch_session" : "new_session";
47832
48023
  const hsPromise = awaitResponse(command);
47833
48024
  send(sessionPath ? { type: "switch_session", sessionPath } : { type: "new_session" });
47834
48025
  const hs = await hsPromise;
47835
48026
  if (hs?.sessionFile) sessionFile = hs.sessionFile;
48027
+ sessionReady = true;
47836
48028
  emit({
47837
48029
  ...base2(threadId, turnId),
47838
48030
  type: "session.started",
@@ -47858,12 +48050,54 @@ var init_pi = __esm({
47858
48050
  } catch {
47859
48051
  }
47860
48052
  }
47861
- const message2 = turn.system ? `${turn.system}
48053
+ const halves = promptHalves(turn);
48054
+ let message2;
48055
+ let pendingReceipt = null;
48056
+ if (halves.stable !== null && sessionReady && sessionFile) {
48057
+ const receiptKey = JSON.stringify([threadId, sessionFile]);
48058
+ const composed = splitSessionPrompt(
48059
+ halves.stable,
48060
+ halves.volatile,
48061
+ readPromptSplitReceipt("pi", receiptKey),
48062
+ turn.system,
48063
+ turn.text,
48064
+ Boolean(turn.mentionTurn),
48065
+ PI_PROMPT_RE_ANCHOR_TURNS
48066
+ );
48067
+ message2 = composed.text;
48068
+ pendingReceipt = { key: receiptKey, receipt: composed.receipt };
48069
+ } else {
48070
+ message2 = turn.system ? `${turn.system}
47862
48071
 
47863
48072
  ${turn.text}` : turn.text;
48073
+ }
47864
48074
  try {
48075
+ const accepted = awaitResponse("prompt", 12e4);
47865
48076
  send({ type: "prompt", message: message2, ...images.length ? { images } : {} });
47866
- } catch {
48077
+ void accepted.then(
48078
+ () => {
48079
+ if (!pendingReceipt || compactionObserved) return;
48080
+ try {
48081
+ writePromptSplitReceipt("pi", pendingReceipt.key, pendingReceipt.receipt);
48082
+ } catch {
48083
+ }
48084
+ },
48085
+ (err) => {
48086
+ if (settled) return;
48087
+ emit({
48088
+ ...base2(threadId, turnId),
48089
+ type: "runtime.error",
48090
+ message: String(err?.message ?? err).slice(0, 2e3)
48091
+ });
48092
+ settle(false);
48093
+ }
48094
+ );
48095
+ } catch (err) {
48096
+ emit({
48097
+ ...base2(threadId, turnId),
48098
+ type: "runtime.error",
48099
+ message: String(err?.message ?? err).slice(0, 2e3)
48100
+ });
47867
48101
  settle(false);
47868
48102
  }
47869
48103
  return { turnId };
@@ -47930,7 +48164,10 @@ ${turn.text}` : turn.text;
47930
48164
  // Reasoning effort pins pi's thinking level per turn (none → off).
47931
48165
  // xhigh/max only land on models that expose them; pi rejects an
47932
48166
  // unsupported level and the turn keeps the engine default.
47933
- effortLevels: EFFORT_LEVELS
48167
+ effortLevels: EFFORT_LEVELS,
48168
+ // pi's RPC mode takes a mid-turn steer frame the runtime queues
48169
+ // into the running agent without aborting the current step.
48170
+ queueing: true
47934
48171
  },
47935
48172
  sendTurn,
47936
48173
  interruptTurn: async (threadId) => active.get(threadId)?.stop(),
@@ -47949,6 +48186,10 @@ ${turn.text}` : turn.text;
47949
48186
  });
47950
48187
  return decision.behavior === "allow" ? "allowed-once" : decision.behavior === "answer" ? "answered" : "rejected";
47951
48188
  },
48189
+ steer: async (threadId, text4) => {
48190
+ const entry = active.get(threadId);
48191
+ return entry?.steer ? await entry.steer(text4) : "refused";
48192
+ },
47952
48193
  hasSession: (threadId) => active.has(threadId),
47953
48194
  stopAll: async () => {
47954
48195
  for (const { stop } of active.values()) stop();
@@ -48092,13 +48333,13 @@ var init_mistral = __esm({
48092
48333
 
48093
48334
  // server/drivers/minimax.ts
48094
48335
  import { readFileSync as readFileSync24 } from "node:fs";
48095
- import { homedir as homedir23 } from "node:os";
48336
+ import { homedir as homedir19 } from "node:os";
48096
48337
  import { join as join38 } from "node:path";
48097
48338
  function normalizedApiUrl(value) {
48098
48339
  const root = value.trim().replace(/\/+$/, "");
48099
48340
  return root.endsWith("/v1") ? root : `${root}/v1`;
48100
48341
  }
48101
- function loadLocalMiniMaxConfig(home = homedir23()) {
48342
+ function loadLocalMiniMaxConfig(home = homedir19()) {
48102
48343
  try {
48103
48344
  const raw = localConfigSchema.parse(JSON.parse(readFileSync24(join38(home, ".mmx", "config.json"), "utf8")));
48104
48345
  const configuredUrl = raw.base_url?.trim() ? raw.base_url : raw.region === "cn" ? CN_URL : DEFAULT_URL3;
@@ -48358,7 +48599,8 @@ var init_cli_api_setup = __esm({
48358
48599
  API_ENDPOINTS = [
48359
48600
  { id: "openai", label: "OpenAI API", url: "https://api.openai.com/v1", keyUrl: "https://platform.openai.com/api-keys" },
48360
48601
  { id: "openrouter", label: "OpenRouter", url: "https://openrouter.ai/api/v1", keyUrl: "https://openrouter.ai/settings/keys" },
48361
- { id: "groq", label: "Groq", url: "https://api.groq.com/openai/v1", keyUrl: "https://console.groq.com/keys" }
48602
+ { id: "groq", label: "Groq", url: "https://api.groq.com/openai/v1", keyUrl: "https://console.groq.com/keys" },
48603
+ { id: "requesty", label: "Requesty", url: "https://router.requesty.ai/v1", keyUrl: "https://app.requesty.ai/api-keys" }
48362
48604
  ];
48363
48605
  SetupApiError = class extends Error {
48364
48606
  };
@@ -48823,8 +49065,8 @@ __export(browser_engine_exports, {
48823
49065
  });
48824
49066
  import { spawn as spawn8 } from "node:child_process";
48825
49067
  import { createHash as createHash13, randomBytes as randomBytes3, randomUUID as randomUUID14 } from "node:crypto";
48826
- import { chmodSync as chmodSync7, constants as constants2, copyFileSync, existsSync as existsSync18, mkdirSync as mkdirSync21, readFileSync as readFileSync26, readdirSync as readdirSync3, renameSync as renameSync6, rmSync as rmSync7, statSync as statSync5, unlinkSync as unlinkSync7, writeFileSync as writeFileSync16 } from "node:fs";
48827
- import { homedir as homedir24, tmpdir as tmpdir5 } from "node:os";
49068
+ import { chmodSync as chmodSync7, constants as constants2, copyFileSync, existsSync as existsSync18, mkdirSync as mkdirSync21, readFileSync as readFileSync26, readdirSync as readdirSync3, renameSync as renameSync6, rmSync as rmSync8, statSync as statSync5, unlinkSync as unlinkSync7, writeFileSync as writeFileSync16 } from "node:fs";
49069
+ import { homedir as homedir20, tmpdir as tmpdir5 } from "node:os";
48828
49070
  import { delimiter as delimiter6, dirname as dirname12, join as join42, resolve as resolve10 } from "node:path";
48829
49071
  function browserRestoreKey(session) {
48830
49072
  if (!/^[A-Za-z0-9_.-]{1,96}$/.test(session)) throw new Error("Invalid browser session.");
@@ -48833,7 +49075,7 @@ function browserRestoreKey(session) {
48833
49075
  function browserSessionsDirectory(env) {
48834
49076
  const namespace = env.AGENT_BROWSER_NAMESPACE;
48835
49077
  if (namespace && !/^[a-z0-9]+(?:[-_][a-z0-9]+)*$/.test(namespace)) throw new Error("Invalid browser namespace.");
48836
- const home = (process.platform === "win32" ? env.USERPROFILE : env.HOME) || homedir24();
49078
+ const home = (process.platform === "win32" ? env.USERPROFILE : env.HOME) || homedir20();
48837
49079
  const stateRoot = namespace ? join42(home, ".agent-browser", "namespaces", namespace, "state") : join42(home, ".agent-browser");
48838
49080
  return join42(stateRoot, "sessions");
48839
49081
  }
@@ -49215,7 +49457,7 @@ function agentBrowserFrame(input) {
49215
49457
  } catch {
49216
49458
  fail(new Error("the browser reported a picture it did not write"));
49217
49459
  } finally {
49218
- rmSync7(file2, { force: true });
49460
+ rmSync8(file2, { force: true });
49219
49461
  }
49220
49462
  };
49221
49463
  child.on("error", (error51) => done(error51 instanceof Error ? error51 : new Error(String(error51))));
@@ -49299,7 +49541,7 @@ var import_qrcode_terminal = __toESM(require_main(), 1);
49299
49541
  import { spawn as spawn9 } from "node:child_process";
49300
49542
  import { randomBytes as randomBytes4 } from "node:crypto";
49301
49543
  import { closeSync as closeSync6, existsSync as existsSync19, mkdirSync as mkdirSync22, openSync as openSync6, readFileSync as readFileSync27 } from "node:fs";
49302
- import { homedir as homedir25 } from "node:os";
49544
+ import { homedir as homedir21 } from "node:os";
49303
49545
  import { dirname as dirname13, join as join43, resolve as resolve11 } from "node:path";
49304
49546
  import { createInterface as createInterface2 } from "node:readline/promises";
49305
49547
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -52793,7 +53035,7 @@ function parseArgs(argv, env = process.env) {
52793
53035
  const options = {
52794
53036
  command: command === "--help" || command === "-h" ? "help" : command,
52795
53037
  port: Number(env.OMB_PORT || 8799),
52796
- dataDir: env.OMB_DATA_DIR || join43(homedir25(), ".openmausbot"),
53038
+ dataDir: env.OMB_DATA_DIR || join43(homedir21(), ".openmausbot"),
52797
53039
  tailscale: false,
52798
53040
  tunnel: false,
52799
53041
  client: false,
@@ -53721,7 +53963,7 @@ async function runOnboardingCommand(options, io = defaultIo(), startServer = run
53721
53963
  }
53722
53964
  if (options.command === "setup") {
53723
53965
  io.log("\nAll set. Start with: openmausbot (or npx openmausbot without a global install).");
53724
- if (options.dataDir !== join43(homedir25(), ".openmausbot") || options.port !== 8799) {
53966
+ if (options.dataDir !== join43(homedir21(), ".openmausbot") || options.port !== 8799) {
53725
53967
  io.log(`Use the same --data-dir (${options.dataDir}) and --port (${options.port}) options when starting.`);
53726
53968
  }
53727
53969
  return 0;