openmausbot 0.1.82 → 0.1.84

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 (54) hide show
  1. package/dist/assets/index-BbU5REzd.js +310 -0
  2. package/dist/assets/{index-CKysBq-V.css → index-CLGfYlx_.css} +1 -1
  3. package/dist/assets/{index-5HVwp5m2.js → index-DNa2umw-.js} +1 -1
  4. package/dist/index.html +2 -2
  5. package/dist-server/container-mcp.js +20 -4
  6. package/dist-server/drivers/agents-proxy.js +30 -4
  7. package/dist-server/index.js +1716 -581
  8. package/dist-server/mcp-gate.js +2 -1
  9. package/dist-server/openmausbot.js +224 -63
  10. package/dist-server/pair-cli.js +224 -63
  11. package/dist-server/server/auto-approve.js +15 -1
  12. package/dist-server/server/auto-vm-claims.js +22 -0
  13. package/dist-server/server/browser-bundle-release.js +8 -7
  14. package/dist-server/server/browser-engine.js +1 -1
  15. package/dist-server/server/channel-queue.js +58 -0
  16. package/dist-server/server/checkpoints.js +9 -5
  17. package/dist-server/server/chief-of-staff.js +5 -2
  18. package/dist-server/server/computer-wait.js +33 -0
  19. package/dist-server/server/config.js +58 -3
  20. package/dist-server/server/contracts.js +0 -7
  21. package/dist-server/server/delta-context.js +258 -0
  22. package/dist-server/server/drivers/acp/gemini.js +11 -1
  23. package/dist-server/server/drivers/acp/qwen.js +16 -1
  24. package/dist-server/server/drivers/agents-proxy.js +32 -4
  25. package/dist-server/server/drivers/claude.js +26 -8
  26. package/dist-server/server/drivers/codex.js +79 -6
  27. package/dist-server/server/drivers/pi.js +2 -1
  28. package/dist-server/server/env-path.js +6 -1
  29. package/dist-server/server/incidents.js +104 -0
  30. package/dist-server/server/index.js +886 -134
  31. package/dist-server/server/local-routing.js +10 -4
  32. package/dist-server/server/notify.js +3 -1
  33. package/dist-server/server/peer-roster.js +37 -1
  34. package/dist-server/server/recent-work.js +4 -1
  35. package/dist-server/server/redact.js +5 -48
  36. package/dist-server/server/room-handoffs.js +79 -16
  37. package/dist-server/server/skill-fetch.js +1 -1
  38. package/dist-server/server/steer-queue.js +29 -0
  39. package/dist-server/server/store.js +43 -3
  40. package/dist-server/server/thread-retention.js +50 -0
  41. package/dist-server/server/turn-context.js +7 -0
  42. package/dist-server/server/turn-resources.js +6 -0
  43. package/dist-server/shared/approval-mode.js +8 -5
  44. package/dist-server/shared/inspector.js +1 -0
  45. package/dist-server/shared/json.js +1 -0
  46. package/dist-server/shared/notification.js +1 -0
  47. package/dist-server/shared/redact.js +61 -0
  48. package/dist-server/shared/routines.js +1 -0
  49. package/dist-server/shared/runtime-events.js +1 -0
  50. package/dist-server/shared/webhooks.js +1 -0
  51. package/dist-server/shared/wire.js +8 -0
  52. package/dist-server/vps-container-mcp.js +20 -4
  53. package/package.json +1 -1
  54. package/dist/assets/index-BLLsDK2F.js +0 -309
@@ -166,7 +166,8 @@ function parseCmdShim(shim, env) {
166
166
  return null;
167
167
  }
168
168
  const dir = dirname(shim);
169
- const targets = [...text.matchAll(/"%~?dp0%?\\?([^"]+)"/g)].map((m) => join(dir, m[1])).filter((p) => isFile(p) && basename(p).toLowerCase() !== "node.exe");
169
+ const npmEntry = /^SET "NP[MX]_CLI_JS=%~dp0\\([^"]+)"/im.exec(text);
170
+ const targets = [...npmEntry ? [npmEntry] : [], ...text.matchAll(/"%~?dp0%?\\?([^"]+)"/g)].map((m) => join(dir, m[1])).filter((p) => isFile(p) && basename(p).toLowerCase() !== "node.exe");
170
171
  const script = targets.find((p) => /\.[cm]?js$/i.test(p));
171
172
  if (script) {
172
173
  const node = nodeExe(dir, env);
@@ -17568,15 +17568,23 @@ var init_image_generation = __esm({
17568
17568
  }
17569
17569
  });
17570
17570
 
17571
+ // shared/wire.ts
17572
+ var EFFORT_LEVELS;
17573
+ var init_wire = __esm({
17574
+ "shared/wire.ts"() {
17575
+ "use strict";
17576
+ EFFORT_LEVELS = ["none", "low", "medium", "high", "xhigh", "max"];
17577
+ }
17578
+ });
17579
+
17571
17580
  // server/contracts.ts
17572
17581
  function isModelVariant(value) {
17573
17582
  return typeof value === "string" && value.length > 0 && value.length <= 256 && value.trim() === value && !new RegExp("\\p{Cc}", "u").test(value);
17574
17583
  }
17575
- var EFFORT_LEVELS, eventCounter, newEventId, newId;
17584
+ var eventCounter, newEventId, newId;
17576
17585
  var init_contracts = __esm({
17577
17586
  "server/contracts.ts"() {
17578
17587
  "use strict";
17579
- EFFORT_LEVELS = ["none", "low", "medium", "high", "xhigh", "max"];
17580
17588
  eventCounter = 0;
17581
17589
  newEventId = () => `ev-${Date.now().toString(36)}-${(eventCounter++).toString(36)}`;
17582
17590
  newId = () => crypto.randomUUID();
@@ -17863,6 +17871,17 @@ function saveConfig(patch, options = {}) {
17863
17871
  }
17864
17872
  disk.instances = diskInstances;
17865
17873
  }
17874
+ if (checkedPatch.openaiCompat?.url !== void 0 && checkedPatch.instances?.openaiCompat === void 0) {
17875
+ const instances = jsonObjectSchema.safeParse(disk.instances);
17876
+ const entry = jsonObjectSchema.safeParse(instances.success ? instances.data.openaiCompat : void 0);
17877
+ const config2 = jsonObjectSchema.safeParse(entry.success ? entry.data.config : void 0);
17878
+ const environment = jsonObjectSchema.safeParse(entry.success ? entry.data.environment : void 0);
17879
+ if (entry.success && entry.data.driver === "openai-compat" && config2.success && !config2.data.key && (!config2.data.apiKeyEnv || config2.data.apiKeyEnv === "OPENAI_COMPAT_API_KEY") && !(environment.success && Object.hasOwn(environment.data, "OPENAI_COMPAT_API_KEY"))) {
17880
+ const nextConfig = { ...config2.data };
17881
+ delete nextConfig.url;
17882
+ disk.instances.openaiCompat = { ...entry.data, config: nextConfig };
17883
+ }
17884
+ }
17866
17885
  mkdirSync6(DATA_DIR, { recursive: true });
17867
17886
  writeFileAtomic(p, JSON.stringify(disk, null, 2), { mode: 384 });
17868
17887
  }
@@ -17937,13 +17956,14 @@ function instanceConfigs(cfg) {
17937
17956
  }
17938
17957
  return map3;
17939
17958
  }
17940
- var optionalText, SSH_ALIAS, LEGACY_BROWSER_PROFILE_ID, BROWSER_PROFILE_ID, MIN_ROOM_TURN_TIMEOUT_MINUTES, MAX_ROOM_TURN_TIMEOUT_MINUTES, MAX_CONCURRENT_BOT_THREADS, MIN_THREAD_EVENT_LOG_BYTES, MAX_THREAD_EVENT_LOG_BYTES, MIN_LOCAL_VM_MAX_INSTANCES, MAX_LOCAL_VM_MAX_INSTANCES, vpsConfigSchema, roomConfigSchema, localVmConfigSchema, browserProfileSchema, legacyBrowserProfileSchema, legacyBrowserProfilesSchema, storedBrowserProfilesSchema, browserProfilesSchema, featureConfigSchema, onboardingConfigSchema, instanceConfigSchema, instanceConfigMapSchema, defaultModelSelectionSchema, appConfigSchema, storedAppConfigSchema, appConfigPatchSchema, jsonObjectSchema, DATA_DIR, LEGACY_DATA_DIR, EVENTS_DIR, NATIVE_DIR, WORKSPACE_CREDENTIAL_ENV, PROVIDER_CREDENTIAL_ENV;
17959
+ 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, MAX_CONCURRENT_BOT_THREADS, MIN_THREAD_EVENT_LOG_BYTES, MAX_THREAD_EVENT_LOG_BYTES, MIN_LOCAL_VM_MAX_INSTANCES, MAX_LOCAL_VM_MAX_INSTANCES, vpsConfigSchema, roomConfigSchema, localVmConfigSchema, browserProfileSchema, legacyBrowserProfileSchema, legacyBrowserProfilesSchema, storedBrowserProfilesSchema, browserProfilesSchema, featureConfigSchema, onboardingConfigSchema, instanceConfigSchema, instanceConfigMapSchema, defaultModelSelectionSchema, appConfigSchema, storedAppConfigSchema, appConfigPatchSchema, jsonObjectSchema, DATA_DIR, LEGACY_DATA_DIR, EVENTS_DIR, NATIVE_DIR, WORKSPACE_CREDENTIAL_ENV, PROVIDER_CREDENTIAL_ENV;
17941
17960
  var init_config = __esm({
17942
17961
  "server/config.ts"() {
17943
17962
  "use strict";
17944
17963
  init_zod();
17945
17964
  init_image_generation();
17946
17965
  init_atomic();
17966
+ init_wire();
17947
17967
  init_contracts();
17948
17968
  init_mcp_registry();
17949
17969
  init_schema();
@@ -17953,6 +17973,9 @@ var init_config = __esm({
17953
17973
  BROWSER_PROFILE_ID = /^[a-z0-9_-]{1,40}$/;
17954
17974
  MIN_ROOM_TURN_TIMEOUT_MINUTES = 1;
17955
17975
  MAX_ROOM_TURN_TIMEOUT_MINUTES = 1440;
17976
+ DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES = 30;
17977
+ DEFAULT_ROOM_HANDOFF_MIN_RUNWAY_MINUTES = 10;
17978
+ DEFAULT_ROOM_HANDOFF_HARD_CAP_MINUTES = 240;
17956
17979
  MAX_CONCURRENT_BOT_THREADS = 10;
17957
17980
  MIN_THREAD_EVENT_LOG_BYTES = 256 * 1024;
17958
17981
  MAX_THREAD_EVENT_LOG_BYTES = 4 * 1024 * 1024 * 1024;
@@ -17964,8 +17987,16 @@ var init_config = __esm({
17964
17987
  }).optional()
17965
17988
  });
17966
17989
  roomConfigSchema = external_exports.object({
17967
- turnTimeoutMinutes: external_exports.number().int().min(MIN_ROOM_TURN_TIMEOUT_MINUTES).max(MAX_ROOM_TURN_TIMEOUT_MINUTES)
17968
- });
17990
+ turnTimeoutMinutes: external_exports.number().int().min(MIN_ROOM_TURN_TIMEOUT_MINUTES).max(MAX_ROOM_TURN_TIMEOUT_MINUTES),
17991
+ /** Room handoff tree lifetime. Active execution pauses this clock; the
17992
+ * hard cap is wall-clock and bounds trees that never stop executing. */
17993
+ handoffLifetimeMinutes: external_exports.number().int().min(1).max(MAX_ROOM_TURN_TIMEOUT_MINUTES).optional(),
17994
+ handoffMinRunwayMinutes: external_exports.number().int().min(1).max(MAX_ROOM_TURN_TIMEOUT_MINUTES).optional(),
17995
+ handoffHardCapMinutes: external_exports.number().int().min(1).max(7 * MAX_ROOM_TURN_TIMEOUT_MINUTES).optional()
17996
+ }).refine(
17997
+ (rooms) => (rooms.handoffMinRunwayMinutes ?? DEFAULT_ROOM_HANDOFF_MIN_RUNWAY_MINUTES) <= (rooms.handoffLifetimeMinutes ?? DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES) && (rooms.handoffLifetimeMinutes ?? DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES) <= (rooms.handoffHardCapMinutes ?? DEFAULT_ROOM_HANDOFF_HARD_CAP_MINUTES),
17998
+ { message: "rooms handoff bounds must satisfy handoffMinRunwayMinutes <= handoffLifetimeMinutes <= handoffHardCapMinutes" }
17999
+ );
17969
18000
  localVmConfigSchema = external_exports.object({
17970
18001
  mode: external_exports.enum(["shared", "per-bot"]).optional(),
17971
18002
  maxInstances: external_exports.number().int().min(MIN_LOCAL_VM_MAX_INSTANCES).max(MAX_LOCAL_VM_MAX_INSTANCES).optional()
@@ -18137,7 +18168,10 @@ var init_config = __esm({
18137
18168
  maxConcurrentPerBot: external_exports.number().int().min(1).max(MAX_CONCURRENT_BOT_THREADS),
18138
18169
  /** Cap each per-thread events/ and native/ NDJSON log at this many
18139
18170
  * bytes; absent (the default) keeps today's unbounded growth (#1280). */
18140
- eventLogMaxBytes: external_exports.number().int().min(MIN_THREAD_EVENT_LOG_BYTES).max(MAX_THREAD_EVENT_LOG_BYTES).optional()
18171
+ eventLogMaxBytes: external_exports.number().int().min(MIN_THREAD_EVENT_LOG_BYTES).max(MAX_THREAD_EVENT_LOG_BYTES).optional(),
18172
+ /** Days a closed or archived thread's event logs survive (#1280).
18173
+ * Absent keeps them forever. */
18174
+ eventLogRetentionDays: external_exports.number().int().min(1).max(3650).optional()
18141
18175
  }).strict().optional(),
18142
18176
  localVm: localVmConfigSchema.optional(),
18143
18177
  features: featureConfigSchema.optional(),
@@ -18246,7 +18280,7 @@ function ownerPredatesThisBoot(owner) {
18246
18280
  return false;
18247
18281
  }
18248
18282
  function ownerIsAlive(owner) {
18249
- return !ownerPredatesThisBoot(owner) && processIsAlive2(owner.pid);
18283
+ return !ownerPredatesThisBoot(owner) && processIsAlive2(owner.pid) && ownerIdentityMatches(owner);
18250
18284
  }
18251
18285
  function isLeaseOwner(value) {
18252
18286
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
@@ -18296,6 +18330,51 @@ function processIsAlive2(pid) {
18296
18330
  throw leaseError("OpenMausBot could not verify the data-directory lease owner; refusing to start.", error51);
18297
18331
  }
18298
18332
  }
18333
+ function parseWmiDateTime(value) {
18334
+ const raw = String(value).trim();
18335
+ const match = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\.(\d{6})([+-]\d{3})$/.exec(raw);
18336
+ if (!match) return null;
18337
+ const [_, year, month, day, hour, minute, second, micro, offset] = match;
18338
+ const ms = Date.UTC(
18339
+ Number(year),
18340
+ Number(month) - 1,
18341
+ Number(day),
18342
+ Number(hour),
18343
+ Number(minute),
18344
+ Number(second),
18345
+ Math.floor(Number(micro) / 1e3)
18346
+ );
18347
+ const offsetMinutes = Number(offset);
18348
+ return ms - offsetMinutes * 60 * 1e3;
18349
+ }
18350
+ function processCreationTimeMs(pid) {
18351
+ if (process.platform !== "win32") return null;
18352
+ try {
18353
+ const output = execFileSync2(
18354
+ "wmic",
18355
+ ["process", "where", `ProcessId=${pid}`, "get", "CreationDate", "/format:csv"],
18356
+ { encoding: "utf8", timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }
18357
+ );
18358
+ for (const line of output.split(/\r?\n/)) {
18359
+ const trimmed = line.trim();
18360
+ if (!trimmed) continue;
18361
+ const lower = trimmed.toLowerCase();
18362
+ if (lower === "node,creationdate" || lower.startsWith("node,")) continue;
18363
+ const parts = trimmed.split(",");
18364
+ const raw = parts[parts.length - 1].trim();
18365
+ const parsed = parseWmiDateTime(raw);
18366
+ if (parsed !== null) return parsed;
18367
+ }
18368
+ } catch {
18369
+ }
18370
+ return null;
18371
+ }
18372
+ function ownerIdentityMatches(owner) {
18373
+ if (process.platform !== "win32") return true;
18374
+ const created = processCreationTimeMs(owner.pid);
18375
+ if (created === null) return true;
18376
+ return created < owner.createdAt;
18377
+ }
18299
18378
  function unlinkExact(path3, message2) {
18300
18379
  try {
18301
18380
  unlinkSync2(path3);
@@ -18701,7 +18780,8 @@ function parseCmdShim(shim, env) {
18701
18780
  return null;
18702
18781
  }
18703
18782
  const dir = dirname4(shim);
18704
- const targets = [...text4.matchAll(/"%~?dp0%?\\?([^"]+)"/g)].map((m) => join8(dir, m[1])).filter((p) => isFile(p) && basename2(p).toLowerCase() !== "node.exe");
18783
+ const npmEntry = /^SET "NP[MX]_CLI_JS=%~dp0\\([^"]+)"/im.exec(text4);
18784
+ const targets = [...npmEntry ? [npmEntry] : [], ...text4.matchAll(/"%~?dp0%?\\?([^"]+)"/g)].map((m) => join8(dir, m[1])).filter((p) => isFile(p) && basename2(p).toLowerCase() !== "node.exe");
18705
18785
  const script = targets.find((p) => /\.[cm]?js$/i.test(p));
18706
18786
  if (script) {
18707
18787
  const node = nodeExe(dir, env);
@@ -19574,9 +19654,9 @@ var init_local_inject = __esm({
19574
19654
  // shared/approval-mode.ts
19575
19655
  function supportsApprovalMode(driverKind, mode) {
19576
19656
  if (mode === "custom") return driverKind === "codex";
19577
- if (mode === "edits") return ["claudeAgent", "grokAgent", "antigravityAgent"].includes(driverKind ?? "");
19657
+ if (mode === "edits") return ["claudeAgent", "grokAgent", "antigravityAgent", "qwenAgent", "geminiAgent"].includes(driverKind ?? "");
19578
19658
  if (mode !== "full") return true;
19579
- return ["codex", "claudeAgent", "antigravityAgent", "cursorAgent", "grokAgent", "opencodeGo"].includes(driverKind ?? "");
19659
+ return ["codex", "claudeAgent", "antigravityAgent", "cursorAgent", "grokAgent", "opencodeGo", "qwenAgent", "geminiAgent"].includes(driverKind ?? "");
19580
19660
  }
19581
19661
  var init_approval_mode = __esm({
19582
19662
  "shared/approval-mode.ts"() {
@@ -19584,12 +19664,7 @@ var init_approval_mode = __esm({
19584
19664
  }
19585
19665
  });
19586
19666
 
19587
- // server/redact.ts
19588
- function isSecretName(name) {
19589
- const lower = name.toLowerCase();
19590
- if (SECRET_KEY_PARTS.some((part) => lower.includes(part))) return true;
19591
- return /(^|[_.-])keys?$/.test(lower);
19592
- }
19667
+ // shared/redact.ts
19593
19668
  function redactSecretsInText(text4) {
19594
19669
  if (!text4 || text4.length < 8) return text4;
19595
19670
  let out = text4;
@@ -19604,33 +19679,10 @@ ${close}`);
19604
19679
  out = out.replace(URL_USERINFO, (_m, lead, secret, at) => `${lead}${mask(secret)}${at}`);
19605
19680
  return out;
19606
19681
  }
19607
- function redactSecrets(input, depth = 0) {
19608
- if (typeof input === "string") return redactSecretsInText(input);
19609
- if (depth > 12 || input === null || typeof input !== "object") return input;
19610
- if (Array.isArray(input)) {
19611
- return input.map((item) => {
19612
- if (item !== null && typeof item === "object" && !Array.isArray(item) && typeof item.name === "string" && typeof item.value === "string") {
19613
- const entry = item;
19614
- return isSecretName(entry.name) ? { ...entry, value: mask(entry.value) } : { ...entry, value: redactSecretsInText(entry.value) };
19615
- }
19616
- return redactSecrets(item, depth + 1);
19617
- });
19618
- }
19619
- const out = {};
19620
- for (const [key, value] of Object.entries(input)) {
19621
- if (typeof value === "string" && isSecretName(key)) {
19622
- out[key] = mask(value);
19623
- continue;
19624
- }
19625
- out[key] = redactSecrets(value, depth + 1);
19626
- }
19627
- return out;
19628
- }
19629
- var SECRET_KEY_PARTS, REDACTION_MARKER, mask, KEY_PREFIXES, BEARER, PEM_BLOCK, KEY_VALUE, KEY_SUFFIX_ASSIGNMENT, SECRET_FLAG, URL_USERINFO;
19682
+ var REDACTION_MARKER, mask, KEY_PREFIXES, BEARER, PEM_BLOCK, KEY_VALUE, KEY_SUFFIX_ASSIGNMENT, SECRET_FLAG, URL_USERINFO;
19630
19683
  var init_redact = __esm({
19631
- "server/redact.ts"() {
19684
+ "shared/redact.ts"() {
19632
19685
  "use strict";
19633
- SECRET_KEY_PARTS = ["token", "secret", "password", "passwd", "apikey", "api_key", "authorization", "auth_token"];
19634
19686
  REDACTION_MARKER = /^«redacted \d+ chars»$/;
19635
19687
  mask = (value) => REDACTION_MARKER.test(value) ? value : `\xABredacted ${value.length} chars\xBB`;
19636
19688
  KEY_PREFIXES = [
@@ -19668,6 +19720,44 @@ var init_redact = __esm({
19668
19720
  }
19669
19721
  });
19670
19722
 
19723
+ // server/redact.ts
19724
+ function isSecretName(name) {
19725
+ const lower = name.toLowerCase();
19726
+ if (SECRET_KEY_PARTS.some((part) => lower.includes(part))) return true;
19727
+ return /(^|[_.-])keys?$/.test(lower);
19728
+ }
19729
+ function redactSecrets(input, depth = 0) {
19730
+ if (typeof input === "string") return redactSecretsInText(input);
19731
+ if (depth > 12 || input === null || typeof input !== "object") return input;
19732
+ if (Array.isArray(input)) {
19733
+ return input.map((item) => {
19734
+ if (item !== null && typeof item === "object" && !Array.isArray(item) && typeof item.name === "string" && typeof item.value === "string") {
19735
+ const entry = item;
19736
+ return isSecretName(entry.name) ? { ...entry, value: mask(entry.value) } : { ...entry, value: redactSecretsInText(entry.value) };
19737
+ }
19738
+ return redactSecrets(item, depth + 1);
19739
+ });
19740
+ }
19741
+ const out = {};
19742
+ for (const [key, value] of Object.entries(input)) {
19743
+ if (typeof value === "string" && isSecretName(key)) {
19744
+ out[key] = mask(value);
19745
+ continue;
19746
+ }
19747
+ out[key] = redactSecrets(value, depth + 1);
19748
+ }
19749
+ return out;
19750
+ }
19751
+ var SECRET_KEY_PARTS;
19752
+ var init_redact2 = __esm({
19753
+ "server/redact.ts"() {
19754
+ "use strict";
19755
+ init_redact();
19756
+ init_redact();
19757
+ SECRET_KEY_PARTS = ["token", "secret", "password", "passwd", "apikey", "api_key", "authorization", "auth_token"];
19758
+ }
19759
+ });
19760
+
19671
19761
  // server/thread-log-rotation.ts
19672
19762
  import { closeSync as closeSync4, fstatSync, openSync as openSync4, readSync as readSync2, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync3, writeSync } from "node:fs";
19673
19763
  function currentThreadLogCap() {
@@ -19753,7 +19843,7 @@ var init_native = __esm({
19753
19843
  "server/drivers/native.ts"() {
19754
19844
  "use strict";
19755
19845
  init_config();
19756
- init_redact();
19846
+ init_redact2();
19757
19847
  init_thread_log_rotation();
19758
19848
  }
19759
19849
  });
@@ -19816,7 +19906,7 @@ var QUESTION_LIMIT, LIMIT, cut;
19816
19906
  var init_tool_summary = __esm({
19817
19907
  "server/tool-summary.ts"() {
19818
19908
  "use strict";
19819
- init_redact();
19909
+ init_redact2();
19820
19910
  QUESTION_LIMIT = 300;
19821
19911
  LIMIT = 200;
19822
19912
  cut = (text4, limit) => redactSecretsInText(text4).trim().slice(0, limit);
@@ -23360,7 +23450,10 @@ var init_claude = __esm({
23360
23450
  const turnId = logicalTurnId ?? newId();
23361
23451
  const retryAbort = new AbortController();
23362
23452
  const retry = retryState.get(threadId) ?? { attempt: 0, cancelled: false };
23363
- if (!relaunch) retry.cancelled = false;
23453
+ if (!relaunch) {
23454
+ retry.cancelled = false;
23455
+ retry.rebuilt = false;
23456
+ }
23364
23457
  retryState.set(threadId, retry);
23365
23458
  const retryScale = Number(process.env.FAKE_CLAUDE_RETRY_SCALE ?? "1");
23366
23459
  const sessionId = typeof turn.resumeCursor === "string" ? turn.resumeCursor : null;
@@ -23688,7 +23781,7 @@ var init_claude = __esm({
23688
23781
  session.sawInit = true;
23689
23782
  session.nativePermissionMode = typeof o.permissionMode === "string" ? o.permissionMode : null;
23690
23783
  if (typeof o.session_id === "string") session.sessionId = o.session_id;
23691
- emit({ ...base2(threadId, currentTurnId()), type: "session.started", sessionId: o.session_id, model: o.model });
23784
+ emit({ ...base2(threadId, currentTurnId()), type: "session.started", sessionId: o.session_id, model: o.model, ...retry.rebuilt ? { rebuilt: true } : {} });
23692
23785
  } else if (o.subtype === "thinking_tokens") {
23693
23786
  emit({ ...base2(threadId, currentTurnId()), type: "item.updated", itemType: "reasoning", tokens: o.estimated_tokens });
23694
23787
  }
@@ -23715,11 +23808,12 @@ var init_claude = __esm({
23715
23808
  break;
23716
23809
  }
23717
23810
  if (text4.trim()) {
23811
+ const synthetic = o.is_api_error_message === true || typeof o.error === "string" ? { synthetic: true } : {};
23718
23812
  if (!session.turn?.sawStreamDelta) {
23719
- emit({ ...base2(threadId, currentTurnId()), type: "content.delta", streamKind: "assistant_text", delta: text4 });
23813
+ emit({ ...base2(threadId, currentTurnId()), ...synthetic, type: "content.delta", streamKind: "assistant_text", delta: text4 });
23720
23814
  }
23721
23815
  if (session.turn) session.turn.sawStreamDelta = false;
23722
- emit({ ...base2(threadId, currentTurnId()), type: "item.completed", itemType: "assistant_text", text: text4 });
23816
+ emit({ ...base2(threadId, currentTurnId()), ...synthetic, type: "item.completed", itemType: "assistant_text", text: text4 });
23723
23817
  }
23724
23818
  for (const b of Array.isArray(msg.content) ? msg.content : []) {
23725
23819
  if (b.type === "tool_use") {
@@ -23901,6 +23995,7 @@ var init_claude = __esm({
23901
23995
  }
23902
23996
  sessions.delete(threadId);
23903
23997
  session.turn = null;
23998
+ retry2.rebuilt = recovery.replayed;
23904
23999
  retryState.set(threadId, retry2);
23905
24000
  active.set(threadId, { stop: () => {
23906
24001
  retry2.cancelled = true;
@@ -23968,8 +24063,8 @@ var init_claude = __esm({
23968
24063
  };
23969
24064
  const steer = async (threadId, text4) => {
23970
24065
  const s = sessions.get(threadId);
23971
- if (!s || !s.turn || s.turn.settled || s.closing || s.child.exitCode !== null) return false;
23972
- return writeUser(s, threadId, claudeUserMessage(text4, void 0));
24066
+ if (!s || !s.turn || s.turn.settled || s.closing || s.child.exitCode !== null) return "refused";
24067
+ return await writeUser(s, threadId, claudeUserMessage(text4, void 0)) ? "steered" : "refused";
23973
24068
  };
23974
24069
  const login = new ClaudeLoginController({ cli: config2.cli, environment, onAuthenticated: async () => {
23975
24070
  await refreshModels();
@@ -24066,6 +24161,15 @@ var init_claude = __esm({
24066
24161
  nativeImageInput: true,
24067
24162
  effortLevels: ["low", "medium", "high", "xhigh", "max"],
24068
24163
  queueing: true,
24164
+ // Only while this CLI can be told to refresh a resumed session's
24165
+ // recorded system prompt (--system-prompt-snapshot). Keeping a
24166
+ // session across an update from outside it means the harness keeps
24167
+ // its prompt too; an older CLI would answer a delegated return with
24168
+ // the instructions of the turn that started the session, where a
24169
+ // fresh session rebuilt them. Unknown version: not yet.
24170
+ get strictResume() {
24171
+ return cliVersionChecked && cliVersion !== null && claudeCliSupports(cliVersion, "--system-prompt-snapshot");
24172
+ },
24069
24173
  // Harness turns reassert a per-bot mode and restore the broker even
24070
24174
  // when an old instance was configured with bypassPermissions.
24071
24175
  localComputerMcp: true
@@ -25482,9 +25586,23 @@ var init_codex = __esm({
25482
25586
  return stopped;
25483
25587
  });
25484
25588
  let completeStoppedTurn;
25589
+ let interruptRequested = false;
25485
25590
  const stop = async () => {
25486
25591
  stopRequested = true;
25487
25592
  stopSignal.abort();
25593
+ if (!state.settled && !interruptRequested && codexThreadId && codexTurnId && child.exitCode === null && child.signalCode === null) {
25594
+ interruptRequested = true;
25595
+ const graceMs = Math.max(1, Number(process.env.FAKE_CODEX_INTERRUPT_GRACE_MS ?? 750) || 750);
25596
+ try {
25597
+ await request("turn/interrupt", { threadId: codexThreadId, turnId: codexTurnId }, graceMs);
25598
+ } catch {
25599
+ }
25600
+ const deadline = Date.now() + graceMs;
25601
+ while (!state.settled && Date.now() < deadline) {
25602
+ await new Promise((wake) => setTimeout(wake, 15));
25603
+ }
25604
+ if (state.settled) return true;
25605
+ }
25488
25606
  const stopped = await terminate();
25489
25607
  if (stopped) completeStoppedTurn?.();
25490
25608
  return stopped;
@@ -25505,6 +25623,23 @@ var init_codex = __esm({
25505
25623
  emit({ ...base2(threadId, turnId), type: "runtime.error", message: "codex did not shut down after termination was requested" });
25506
25624
  }
25507
25625
  };
25626
+ const steerActiveTurn = async (text4) => {
25627
+ if (state.settled || abandoned || stopRequested || !codexThreadId || !codexTurnId) return "refused";
25628
+ if (child.exitCode !== null || child.signalCode !== null) return "refused";
25629
+ try {
25630
+ const steerTimeoutMs = Math.max(1, Number(process.env.FAKE_CODEX_STEER_TIMEOUT_MS ?? 1e4) || 1e4);
25631
+ await request("turn/steer", {
25632
+ threadId: codexThreadId,
25633
+ input: [{ type: "text", text: text4 }],
25634
+ expectedTurnId: codexTurnId
25635
+ }, steerTimeoutMs);
25636
+ return "steered";
25637
+ } catch (error51) {
25638
+ const message2 = error51 instanceof Error ? error51.message : String(error51);
25639
+ if (state.settled || message2.includes("timed out")) return "indeterminate";
25640
+ return "refused";
25641
+ }
25642
+ };
25508
25643
  const controlsHost = turn.integrations?.localComputer?.scope === "local-computer";
25509
25644
  const handleServerRequest = (msg) => {
25510
25645
  const method = msg.method;
@@ -25794,6 +25929,10 @@ var init_codex = __esm({
25794
25929
  void stop();
25795
25930
  return;
25796
25931
  }
25932
+ if (stopRequested) {
25933
+ void settle(false, "interrupted");
25934
+ return;
25935
+ }
25797
25936
  const recentStderr = stderrSinceOutput.trim();
25798
25937
  const hadStreamedOutput = codexTurnId !== null || state.sawStreamDelta;
25799
25938
  const verdict = signal !== null ? { transient: false, reason: "interrupted" } : classifyError({ exitCode: code, stderr: recentStderr });
@@ -25832,7 +25971,7 @@ var init_codex = __esm({
25832
25971
  });
25833
25972
  void settle(false, "exit_before_result");
25834
25973
  });
25835
- active.set(threadId, { stop, turnId, asks });
25974
+ active.set(threadId, { stop, turnId, asks, steer: steerActiveTurn });
25836
25975
  if (attempt === 0) emit({ ...base2(threadId, turnId), type: "turn.started" });
25837
25976
  try {
25838
25977
  await request("initialize", {
@@ -25864,6 +26003,7 @@ var init_codex = __esm({
25864
26003
  const cursor3 = typeof turn.resumeCursor === "string" ? turn.resumeCursor : null;
25865
26004
  let startedModel = null;
25866
26005
  let resumedNativeThread = false;
26006
+ let rebuiltFromReplay = false;
25867
26007
  let promptText = turn.text;
25868
26008
  if (cursor3) {
25869
26009
  const resumeThread = () => request("thread/resume", {
@@ -25889,9 +26029,11 @@ var init_codex = __esm({
25889
26029
  promptSubmitted,
25890
26030
  producedOutput: state.sawStreamDelta
25891
26031
  });
25892
- if (!config2.managed || recoveredMissingSession || stopRequested || state.settled || !turn.recoveryText?.trim() || !missingNativeCodexThread(error51, cursor3) || !mayReplay(failure)) throw error51;
26032
+ if (!config2.managed && !turn.recoveryIsReplay || recoveredMissingSession || stopRequested || state.settled || !turn.recoveryText?.trim() || !missingNativeCodexThread(error51, cursor3) || !mayReplay(failure)) throw error51;
25893
26033
  recoveredMissingSession = true;
25894
- promptText = recoveryPromptFor({ recoveryText: turn.recoveryText, currentText: turn.text, failure }).text;
26034
+ const rebuild = recoveryPromptFor({ recoveryText: turn.recoveryText, currentText: turn.text, failure });
26035
+ rebuiltFromReplay = rebuild.replayed;
26036
+ promptText = rebuild.text;
25895
26037
  }
25896
26038
  }
25897
26039
  if (!codexThreadId) {
@@ -25917,7 +26059,7 @@ var init_codex = __esm({
25917
26059
  }
25918
26060
  if (!codexThreadId) throw new Error("Codex did not return a native thread id");
25919
26061
  await syncCodexInstructions(threadId, codexThreadId, developerInstructions, resumedNativeThread, request);
25920
- emit({ ...base2(threadId, turnId), type: "session.started", sessionId: codexThreadId, model: startedModel ?? turn.model ?? null });
26062
+ emit({ ...base2(threadId, turnId), type: "session.started", sessionId: codexThreadId, model: startedModel ?? turn.model ?? null, ...rebuiltFromReplay ? { rebuilt: true } : {} });
25921
26063
  const turnInput = [
25922
26064
  ...promptText ? [{ type: "text", text: promptText }] : [],
25923
26065
  ...(turn.images ?? []).map((image) => ({ type: "localImage", path: image.path }))
@@ -26041,6 +26183,7 @@ ${stderr ?? ""}`))
26041
26183
  provider: DRIVER_KIND3,
26042
26184
  capabilities: {
26043
26185
  sessionModelSwitch: "unsupported",
26186
+ queueing: true,
26044
26187
  computerMcp: true,
26045
26188
  localComputerMcp: true,
26046
26189
  composioMcp: true,
@@ -26050,12 +26193,17 @@ ${stderr ?? ""}`))
26050
26193
  browserMcp: true,
26051
26194
  images: true,
26052
26195
  nativeImageInput: true,
26053
- effortLevels: ["low", "medium", "high", "xhigh", "max"]
26196
+ effortLevels: ["low", "medium", "high", "xhigh", "max"],
26197
+ strictResume: true
26054
26198
  },
26055
26199
  sendTurn,
26056
26200
  interruptTurn: async (threadId) => {
26057
26201
  await active.get(threadId)?.stop();
26058
26202
  },
26203
+ steer: async (threadId, text4) => {
26204
+ const turn = active.get(threadId);
26205
+ return turn?.steer ? await turn.steer(text4) : "refused";
26206
+ },
26059
26207
  respondToRequest: async (threadId, requestId, decision) => {
26060
26208
  const turn = active.get(threadId);
26061
26209
  const finish = turn?.asks.get(requestId);
@@ -34674,7 +34822,7 @@ var init_openai_chat = __esm({
34674
34822
  "server/drivers/openai-chat.ts"() {
34675
34823
  "use strict";
34676
34824
  init_contracts();
34677
- init_redact();
34825
+ init_redact2();
34678
34826
  init_tool_summary();
34679
34827
  init_chat_mcp_tools();
34680
34828
  init_chat_tool_approval();
@@ -35013,6 +35161,11 @@ function liveOauthCredential() {
35013
35161
  function geminiIsAuthenticated(env) {
35014
35162
  return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync12(join24(homedir15(), ".gemini", "oauth_creds.json")) && liveOauthCredential();
35015
35163
  }
35164
+ function geminiApprovalArgs(fullAuto, approvalMode) {
35165
+ if (fullAuto) return ["--yolo"];
35166
+ if (approvalMode === "edits") return ["--approval-mode", "auto_edit"];
35167
+ return [];
35168
+ }
35016
35169
  var AUTH_PREFERENCE, nonBlank, support3, GeminiAgentDriver;
35017
35170
  var init_gemini = __esm({
35018
35171
  "server/drivers/acp/gemini.ts"() {
@@ -35035,7 +35188,7 @@ var init_gemini = __esm({
35035
35188
  loginNote: "Gemini CLI needs a GEMINI_API_KEY, a Vertex AI setup, or an enterprise Code Assist login \u2014 consumer Google logins stopped working on 2026-06-18 (use the Antigravity engine for those accounts)",
35036
35189
  // --acp is the stable Gemini CLI surface. --experimental-acp remains an
35037
35190
  // alias for older releases, but using it now emits a deprecation warning.
35038
- spawnArgs: (_config, turn) => ["--acp", ...turn.model ? ["-m", turn.model] : []],
35191
+ spawnArgs: (config2, turn) => ["--acp", ...geminiApprovalArgs(config2.fullAuto, turn.approvalMode), ...turn.model ? ["-m", turn.model] : []],
35039
35192
  credentialEnv: ["GEMINI_API_KEY", "GOOGLE_API_KEY"],
35040
35193
  pickAuthMethod: (methods) => {
35041
35194
  const ids = methods.map((m) => m.id).filter((id) => typeof id === "string");
@@ -36468,6 +36621,12 @@ function resolveQwenTurnModel(model, env) {
36468
36621
  if (!matches.length) throw new Error("This Qwen model is no longer configured. Refresh models and select it again.");
36469
36622
  return matches[0].id;
36470
36623
  }
36624
+ function qwenApprovalArgs(fullAuto, approvalMode) {
36625
+ if (fullAuto) return ["--yolo"];
36626
+ if (approvalMode === "auto") return ["--approval-mode", "auto"];
36627
+ if (approvalMode === "edits") return ["--approval-mode", "auto-edit"];
36628
+ return [];
36629
+ }
36471
36630
  var EMPTY, PROTOCOLS, support8, QwenAgentDriver;
36472
36631
  var init_qwen = __esm({
36473
36632
  "server/drivers/acp/qwen.ts"() {
@@ -36496,7 +36655,7 @@ var init_qwen = __esm({
36496
36655
  },
36497
36656
  // A raw -m only changes the model within the saved provider. ACP switches
36498
36657
  // the complete route and confirms it before any prompt leaves OMB.
36499
- spawnArgs: () => ["--acp"],
36658
+ spawnArgs: (config2, turn) => ["--acp", ...qwenApprovalArgs(config2.fullAuto, turn.approvalMode)],
36500
36659
  selectModel: { configId: "model" },
36501
36660
  pickAuthMethod: () => null,
36502
36661
  authFailure: "continue",
@@ -44122,6 +44281,7 @@ var init_pi = __esm({
44122
44281
  init_procs();
44123
44282
  init_proxy_paths();
44124
44283
  init_tool_summary();
44284
+ init_wire();
44125
44285
  init_contracts();
44126
44286
  init_local_inject();
44127
44287
  init_native();
@@ -45205,12 +45365,13 @@ var init_browser_bundle_release = __esm({
45205
45365
  "server/browser-bundle-release.ts"() {
45206
45366
  "use strict";
45207
45367
  init_browser_engine_release();
45208
- CHROME_VERSION = "152.0.7977.82";
45368
+ CHROME_VERSION = "153.0.8010.47";
45209
45369
  CHROME_ASSETS = {
45210
- "darwin-arm64": { platform: "mac-arm64", bytes: 97760996, sha256: "1615f063c894aa824fd55c89f8f05e9904f63cce0c95d0cbce7394d77884fba5", executableSha256: "ac18537fb2bc2b72b0440893b6ea5d4ef3bacc6220b1e9a1693c73f8b1045fbe" },
45211
- "darwin-x64": { platform: "mac-x64", bytes: 102895824, sha256: "c903707292c6aaed7c6e572c0bb5e6645454e45d9e0e6db27e876b18e9165f31", executableSha256: "2faefd55d4e47764956e31e338d362a1e794037fa772a426ffd510f122f33f19" },
45212
- "linux-x64": { platform: "linux64", bytes: 119454769, sha256: "0ca12ea26b502a83e32db334a17883c315348845efc071d908de7a6d94a97eff", executableSha256: "1301a5024fef1d58c4cfbde5d44794cb18c5b2cbbe4f3c64f81cc4eaa683c45f" },
45213
- "win32-x64": { platform: "win64", bytes: 119768220, sha256: "86fb1fa7fbbda65f6f1572062c358803e61a6e6d9489e6619b37a61d609fa845", executableSha256: "ec0744f041cb6c35c439c85a5ac42d77b507838cd59cac005e25114025336c98" }
45370
+ "darwin-arm64": { platform: "mac-arm64", bytes: 98668949, sha256: "6d28839675b6f22dbd7ba8775dbdabcae7a5be37b482380b27b12f05b748b955", executableSha256: "111ee425ea5b0a01dcb19fda16452a9be0319749cba374b1c987d2437d8dcedb" },
45371
+ "darwin-x64": { platform: "mac-x64", bytes: 103712919, sha256: "aa178547f9751fbcf413e0f57915ddb72e83064d4d1c4a29dc1719b169f9cc2f", executableSha256: "33452695b1b6f18db2f796a422eca69b69ca8aacce36d1ff8c6f5d69eac1a635" },
45372
+ "linux-arm64": { platform: "linux-arm64", bytes: 120245582, sha256: "af0931a58d6bab688112d5ca1f7abd6d95c0b8a296ef34637f272795787774d7", executableSha256: "b6a9f0483c976fddc72c34ce1c983a1275163cdfb95576874bfed5ff07c53807" },
45373
+ "linux-x64": { platform: "linux64", bytes: 119695587, sha256: "7728775cf4a35464cd81c8eea2d44d6d32ccc0bd1edfa75aea7f32d146963d63", executableSha256: "ea90dee9cbd7b17f197eb6c386bd9f1ff636734ee99753cd2408658c45358bf2" },
45374
+ "win32-x64": { platform: "win64", bytes: 120466147, sha256: "9f405cfaf7bc08bf9e046e653cd3086c0faa1d4e25907de857f7e7f093a20122", executableSha256: "01176f6928faeb37ff018bc8884bbca8a0197f51b659d467f2501ab2c64f9fcf" }
45214
45375
  };
45215
45376
  }
45216
45377
  });
@@ -45592,7 +45753,7 @@ function agentBrowserIntegration(input) {
45592
45753
  for (const name of ["PATH", "AGENT_BROWSER_EXECUTABLE_PATH"]) {
45593
45754
  if (sourceEnv[name]) env[name] = sourceEnv[name];
45594
45755
  }
45595
- const bundle = packagedBrowser({ env: sourceEnv });
45756
+ const bundle = packagedBrowser({ env: sourceEnv, platform: input.platform, arch: input.arch });
45596
45757
  if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle && resolve10(input.binaryPath) === bundle.engine && completePackage(bundle, existsSync18)) {
45597
45758
  env.AGENT_BROWSER_EXECUTABLE_PATH = bundle.chrome;
45598
45759
  }