oh-my-opencode 5.0.0-beta.24 → 5.0.0-beta.26

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 (57) hide show
  1. package/dist/cli/index.js +98 -28
  2. package/dist/cli-node/index.js +98 -28
  3. package/dist/features/team-mode/tools/messaging-fallback-wake.d.ts +15 -0
  4. package/dist/index.js +369 -163
  5. package/dist/tui.js +78 -12
  6. package/package.json +15 -15
  7. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  8. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  9. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  10. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  11. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  12. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  13. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  14. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  15. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  16. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  17. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  18. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  19. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  20. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  21. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  22. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  23. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  24. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  25. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  26. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  27. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  28. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
  29. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  30. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  31. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  32. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  33. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  34. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  35. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  36. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  37. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  38. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  39. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  40. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  41. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  42. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  43. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  44. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  45. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  46. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  47. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  48. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  49. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  50. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +1 -1
  51. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  52. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  53. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  54. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  55. package/packages/omo-codex/plugin/package-lock.json +13 -13
  56. package/packages/omo-codex/plugin/package.json +1 -1
  57. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
package/dist/index.js CHANGED
@@ -11040,6 +11040,9 @@ var init_message_inspection_error = () => {};
11040
11040
  function getPromptGateMessagesFetchTimeoutMs() {
11041
11041
  return promptGateMessagesFetchTimeoutMsForTesting ?? DEFAULT_PROMPT_GATE_MESSAGES_FETCH_TIMEOUT_MS;
11042
11042
  }
11043
+ function getPromptGateRevalidationTimeoutMs() {
11044
+ return promptGateRevalidationTimeoutMsForTesting ?? DEFAULT_PROMPT_REVALIDATION_TIMEOUT_MS;
11045
+ }
11043
11046
  async function withDispatchTimeout(operation, dispatchTimeoutMs, operationName) {
11044
11047
  if (dispatchTimeoutMs <= 0) {
11045
11048
  return operation;
@@ -11058,7 +11061,7 @@ async function withDispatchTimeout(operation, dispatchTimeoutMs, operationName)
11058
11061
  }
11059
11062
  }
11060
11063
  }
11061
- var DEFAULT_PROMPT_ASYNC_POST_DISPATCH_HOLD_MS = 2000, DEFAULT_PROMPT_SEMANTIC_DEDUPE_HOLD_MS = 15000, DEFAULT_PROMPT_DISPATCH_TIMEOUT_MS = 30000, DEFAULT_PROMPT_GATE_MESSAGES_FETCH_TIMEOUT_MS = 5000, DEFAULT_PROMPT_QUEUE_RETRY_MS = 250, promptGateMessagesFetchTimeoutMsForTesting;
11064
+ var DEFAULT_PROMPT_ASYNC_POST_DISPATCH_HOLD_MS = 2000, DEFAULT_PROMPT_SEMANTIC_DEDUPE_HOLD_MS = 15000, DEFAULT_PROMPT_DISPATCH_TIMEOUT_MS = 30000, DEFAULT_PROMPT_GATE_MESSAGES_FETCH_TIMEOUT_MS = 5000, DEFAULT_PROMPT_REVALIDATION_TIMEOUT_MS = 5000, DEFAULT_PROMPT_QUEUE_RETRY_MS = 250, promptGateMessagesFetchTimeoutMsForTesting, promptGateRevalidationTimeoutMsForTesting;
11062
11065
 
11063
11066
  // packages/utils/src/prompt-async-gate/pending-tool-turn.ts
11064
11067
  function getPromptQuery(input) {
@@ -11304,6 +11307,7 @@ async function dispatchAfterSessionIdle(args) {
11304
11307
  checkStatus,
11305
11308
  checkToolState,
11306
11309
  shouldDispatch,
11310
+ retryDispatchFailure,
11307
11311
  dispatch
11308
11312
  } = args;
11309
11313
  const existing = getActiveReservation(sessionID);
@@ -11358,7 +11362,9 @@ async function dispatchAfterSessionIdle(args) {
11358
11362
  });
11359
11363
  return { status: "active" };
11360
11364
  }
11361
- if (shouldDispatch?.() === false) {
11365
+ const dispatchDecision = shouldDispatch?.();
11366
+ const resolvedDispatchDecision = dispatchDecision !== undefined && typeof dispatchDecision !== "boolean" ? await withDispatchTimeout(dispatchDecision, Math.min(dispatchTimeoutMs, getPromptGateRevalidationTimeoutMs()), `[prompt-async-gate] ${sessionName} shouldDispatch`) : dispatchDecision;
11367
+ if (resolvedDispatchDecision === false) {
11362
11368
  log(`[prompt-async-gate] ${sessionName} cancelled before dispatch`, { sessionID, source });
11363
11369
  return { status: "cancelled" };
11364
11370
  }
@@ -11374,6 +11380,7 @@ async function dispatchAfterSessionIdle(args) {
11374
11380
  log(`[prompt-async-gate] ${sessionName} dispatched`, { sessionID, source });
11375
11381
  return { status: "dispatched", response };
11376
11382
  } catch (error) {
11383
+ const queueRetryable = dispatchAttempted && retryDispatchFailure?.(error) === true;
11377
11384
  if (dispatchAttempted) {
11378
11385
  rememberRecentPromptDispatch({
11379
11386
  sessionID,
@@ -11384,7 +11391,12 @@ async function dispatchAfterSessionIdle(args) {
11384
11391
  }
11385
11392
  const errorText = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
11386
11393
  log(`[prompt-async-gate] ${sessionName} failed`, { sessionID, source, error: errorText });
11387
- return { status: "failed", error, dispatchAttempted };
11394
+ return {
11395
+ status: "failed",
11396
+ error,
11397
+ dispatchAttempted,
11398
+ ...queueRetryable ? { queueRetryable: true } : {}
11399
+ };
11388
11400
  } finally {
11389
11401
  finishPromptReservation(sessionID, reservation, dispatchAttempted, postDispatchHoldMs);
11390
11402
  }
@@ -11446,6 +11458,7 @@ function schedulePromptQueueDrain(sessionID, delayMs) {
11446
11458
  promptQueueTimers.set(sessionID, timer);
11447
11459
  }
11448
11460
  function removePromptQueueEntry(sessionID, entry) {
11461
+ promptQueueRetryStates.delete(entry.id);
11449
11462
  const queue = promptQueues.get(sessionID);
11450
11463
  if (!queue) {
11451
11464
  return;
@@ -11483,6 +11496,7 @@ async function drainPromptQueue(sessionID, awaitedEntry) {
11483
11496
  promptQueueDraining.add(sessionID);
11484
11497
  clearPromptQueueTimer(sessionID);
11485
11498
  let awaitedResult;
11499
+ const deferredRetryIds = new Set;
11486
11500
  try {
11487
11501
  while (true) {
11488
11502
  const queue = promptQueues.get(sessionID);
@@ -11490,6 +11504,20 @@ async function drainPromptQueue(sessionID, awaitedEntry) {
11490
11504
  if (!entry) {
11491
11505
  break;
11492
11506
  }
11507
+ const retryState = promptQueueRetryStates.get(entry.id);
11508
+ if (entry.durableRetry && retryState?.retryAfter !== undefined && retryState.retryAfter > Date.now()) {
11509
+ if (deferredRetryIds.has(entry.id)) {
11510
+ const nextRetryAt = Math.min(...queue.flatMap((queued) => {
11511
+ const retryAfter = promptQueueRetryStates.get(queued.id)?.retryAfter;
11512
+ return retryAfter === undefined ? [] : [retryAfter];
11513
+ }));
11514
+ schedulePromptQueueDrain(sessionID, nextRetryAt - Date.now());
11515
+ break;
11516
+ }
11517
+ deferredRetryIds.add(entry.id);
11518
+ setPromptQueue(sessionID, [...queue.slice(1), entry]);
11519
+ continue;
11520
+ }
11493
11521
  promptQueueInFlight.set(sessionID, entry);
11494
11522
  const result = await dispatchAfterSessionIdle({
11495
11523
  sessionName: entry.sessionName,
@@ -11505,12 +11533,45 @@ async function drainPromptQueue(sessionID, awaitedEntry) {
11505
11533
  checkStatus: entry.checkStatus,
11506
11534
  checkToolState: entry.checkToolState,
11507
11535
  shouldDispatch: entry.shouldDispatch,
11536
+ retryDispatchFailure: entry.retryDispatchFailure,
11508
11537
  dispatch: entry.dispatch
11509
11538
  });
11510
11539
  if (promptQueueInFlight.get(sessionID)?.id === entry.id) {
11511
11540
  promptQueueInFlight.delete(sessionID);
11512
11541
  }
11513
- if (result.status === "active" || result.status === "reserved") {
11542
+ const retryableQueuedFailure = result.status === "failed" && (!result.dispatchAttempted || result.queueRetryable === true);
11543
+ if (retryableQueuedFailure) {
11544
+ const failureCount = (promptQueueRetryStates.get(entry.id)?.failureCount ?? 0) + 1;
11545
+ if (entry.durableRetry) {
11546
+ const exponentialBackoffMs = entry.queueRetryMs * 2 ** Math.min(failureCount, 7);
11547
+ const retryDelayMs = Math.max(entry.postDispatchHoldMs, Math.min(exponentialBackoffMs, MAX_DURABLE_RETRY_BACKOFF_MS));
11548
+ promptQueueRetryStates.set(entry.id, {
11549
+ failureCount,
11550
+ retryAfter: Date.now() + retryDelayMs
11551
+ });
11552
+ const currentQueue = promptQueues.get(sessionID);
11553
+ if (currentQueue && currentQueue.length > 1) {
11554
+ setPromptQueue(sessionID, [...currentQueue.slice(1), entry]);
11555
+ continue;
11556
+ }
11557
+ schedulePromptQueueDrain(sessionID, retryDelayMs);
11558
+ break;
11559
+ }
11560
+ if (failureCount >= MAX_QUEUED_RETRYABLE_FAILURES) {
11561
+ log("[prompt-async-gate] dropping queued prompt after repeated retryable failures", {
11562
+ sessionID,
11563
+ source: entry.source,
11564
+ failureCount
11565
+ });
11566
+ removePromptQueueEntry(sessionID, entry);
11567
+ if (awaitedEntry?.id === entry.id) {
11568
+ awaitedResult = result;
11569
+ }
11570
+ continue;
11571
+ }
11572
+ promptQueueRetryStates.set(entry.id, { failureCount });
11573
+ }
11574
+ if (result.status === "active" || result.status === "reserved" || retryableQueuedFailure) {
11514
11575
  const queued = queuedResult(entry, 1, result.status === "reserved" ? result.reservedBy : entry.source);
11515
11576
  if (awaitedEntry?.id === entry.id) {
11516
11577
  awaitedResult = queued;
@@ -11571,7 +11632,7 @@ async function enqueueInternalPrompt(entry) {
11571
11632
  const result = await drainPromptQueue(entry.sessionID, entry);
11572
11633
  return result ?? queuedResult(entry, 1);
11573
11634
  }
11574
- var promptQueues, promptQueueDraining, promptQueueInFlight, promptQueueTimers, promptQueueSequence = 0;
11635
+ var promptQueues, promptQueueDraining, promptQueueInFlight, promptQueueTimers, promptQueueRetryStates, MAX_QUEUED_RETRYABLE_FAILURES = 3, MAX_DURABLE_RETRY_BACKOFF_MS = 30000, promptQueueSequence = 0;
11575
11636
  var init_queue = __esm(() => {
11576
11637
  init_session_idle_dispatch();
11577
11638
  init_reservations();
@@ -11579,6 +11640,7 @@ var init_queue = __esm(() => {
11579
11640
  promptQueueDraining = new Set;
11580
11641
  promptQueueInFlight = new Map;
11581
11642
  promptQueueTimers = new Map;
11643
+ promptQueueRetryStates = new Map;
11582
11644
  setExpiredReservationHandler((sessionID) => {
11583
11645
  schedulePromptQueueDrain(sessionID, 0);
11584
11646
  });
@@ -11826,6 +11888,7 @@ async function dispatchInternalPrompt(args) {
11826
11888
  checkStatus: args.checkStatus !== false,
11827
11889
  checkToolState: args.checkToolState !== false,
11828
11890
  shouldDispatch: args.shouldDispatch,
11891
+ retryDispatchFailure: args.retryDispatchFailure,
11829
11892
  dispatch: (dispatchInput) => dispatchWithPathCompatibility(dispatch, dispatchInput)
11830
11893
  });
11831
11894
  if (deferResult.status === "failed" && resolved.route === "live" && deferResult.error instanceof Error && deferResult.error.message.startsWith(dispatchTimeoutPrefix)) {
@@ -11853,7 +11916,9 @@ async function dispatchInternalPrompt(args) {
11853
11916
  queueRetryMs,
11854
11917
  checkStatus: args.checkStatus !== false,
11855
11918
  checkToolState: args.checkToolState !== false,
11919
+ durableRetry: args.durableRetry === true,
11856
11920
  shouldDispatch: args.shouldDispatch,
11921
+ retryDispatchFailure: args.retryDispatchFailure,
11857
11922
  dispatch: async (_dispatchInput) => dispatchWithPathCompatibility(dispatch, input)
11858
11923
  });
11859
11924
  }
@@ -11875,6 +11940,7 @@ async function dispatchInternalPrompt(args) {
11875
11940
  checkStatus: args.checkStatus !== false,
11876
11941
  checkToolState: args.checkToolState !== false,
11877
11942
  shouldDispatch: args.shouldDispatch,
11943
+ retryDispatchFailure: args.retryDispatchFailure,
11878
11944
  dispatch: (dispatchInput) => dispatchWithPathCompatibility(dispatch, dispatchInput)
11879
11945
  });
11880
11946
  if (directResult.status === "failed" && resolved.route === "live" && directResult.error instanceof Error && directResult.error.message.startsWith(dispatchTimeoutPrefix)) {
@@ -86987,7 +87053,17 @@ function isPreSendConnectionFailure2(error) {
86987
87053
  if (error.name === "AbortError") {
86988
87054
  return false;
86989
87055
  }
86990
- const CONNECTION_CODES = new Set(["ECONNREFUSED", "ENOTFOUND", "EAI_AGAIN"]);
87056
+ const CONNECTION_CODES = new Set([
87057
+ "ECONNREFUSED",
87058
+ "ENOTFOUND",
87059
+ "EAI_AGAIN",
87060
+ "ENETUNREACH",
87061
+ "EHOSTUNREACH",
87062
+ "ENETDOWN",
87063
+ "EHOSTDOWN",
87064
+ "EADDRNOTAVAIL",
87065
+ "UND_ERR_CONNECT_TIMEOUT"
87066
+ ]);
86991
87067
  const self = error;
86992
87068
  if (self.code && CONNECTION_CODES.has(self.code)) {
86993
87069
  return true;
@@ -86999,12 +87075,6 @@ function isPreSendConnectionFailure2(error) {
86999
87075
  return true;
87000
87076
  }
87001
87077
  }
87002
- if (error instanceof TypeError) {
87003
- const msg = error.message;
87004
- if (msg.includes("fetch failed") || msg.includes("Unable to connect")) {
87005
- return true;
87006
- }
87007
- }
87008
87078
  return false;
87009
87079
  }
87010
87080
  function markLiveRouteUnavailable2(reason) {
@@ -98635,7 +98705,7 @@ function getCachedVersion(options = {}) {
98635
98705
  // package.json
98636
98706
  var package_default = {
98637
98707
  name: "oh-my-opencode",
98638
- version: "5.0.0-beta.24",
98708
+ version: "5.0.0-beta.26",
98639
98709
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
98640
98710
  main: "./dist/index.js",
98641
98711
  types: "dist/index.d.ts",
@@ -98816,7 +98886,7 @@ var package_default = {
98816
98886
  zod: "^4.4.3"
98817
98887
  },
98818
98888
  devDependencies: {
98819
- "@code-yeongyu/senpi": "2026.8.28",
98889
+ "@code-yeongyu/senpi": "2026.8.28-2",
98820
98890
  "@oh-my-opencode/agents-md-core": "workspace:*",
98821
98891
  "@oh-my-opencode/ast-grep-mcp": "workspace:*",
98822
98892
  "@oh-my-opencode/boulder-state": "workspace:*",
@@ -98857,18 +98927,18 @@ var package_default = {
98857
98927
  typescript: "^7.0.2"
98858
98928
  },
98859
98929
  optionalDependencies: {
98860
- "oh-my-opencode-darwin-arm64": "5.0.0-beta.24",
98861
- "oh-my-opencode-darwin-x64": "5.0.0-beta.24",
98862
- "oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.24",
98863
- "oh-my-opencode-linux-arm64": "5.0.0-beta.24",
98864
- "oh-my-opencode-linux-arm64-musl": "5.0.0-beta.24",
98865
- "oh-my-opencode-linux-x64": "5.0.0-beta.24",
98866
- "oh-my-opencode-linux-x64-baseline": "5.0.0-beta.24",
98867
- "oh-my-opencode-linux-x64-musl": "5.0.0-beta.24",
98868
- "oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.24",
98869
- "oh-my-opencode-windows-arm64": "5.0.0-beta.24",
98870
- "oh-my-opencode-windows-x64": "5.0.0-beta.24",
98871
- "oh-my-opencode-windows-x64-baseline": "5.0.0-beta.24"
98930
+ "oh-my-opencode-darwin-arm64": "5.0.0-beta.26",
98931
+ "oh-my-opencode-darwin-x64": "5.0.0-beta.26",
98932
+ "oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.26",
98933
+ "oh-my-opencode-linux-arm64": "5.0.0-beta.26",
98934
+ "oh-my-opencode-linux-arm64-musl": "5.0.0-beta.26",
98935
+ "oh-my-opencode-linux-x64": "5.0.0-beta.26",
98936
+ "oh-my-opencode-linux-x64-baseline": "5.0.0-beta.26",
98937
+ "oh-my-opencode-linux-x64-musl": "5.0.0-beta.26",
98938
+ "oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.26",
98939
+ "oh-my-opencode-windows-arm64": "5.0.0-beta.26",
98940
+ "oh-my-opencode-windows-x64": "5.0.0-beta.26",
98941
+ "oh-my-opencode-windows-x64-baseline": "5.0.0-beta.26"
98872
98942
  },
98873
98943
  overrides: {
98874
98944
  "@earendil-works/pi-agent-core": "0.84.2",
@@ -98886,7 +98956,7 @@ var package_default = {
98886
98956
  "@code-yeongyu/comment-checker"
98887
98957
  ],
98888
98958
  patchedDependencies: {
98889
- "@code-yeongyu/senpi@2026.8.28": "patches/@code-yeongyu%2Fsenpi@2026.8.28.patch"
98959
+ "@code-yeongyu/senpi@2026.8.28-2": "patches/@code-yeongyu%2Fsenpi@2026.8.28-2.patch"
98890
98960
  }
98891
98961
  };
98892
98962
 
@@ -106651,8 +106721,53 @@ init_store2();
106651
106721
  // packages/team-core/src/team-mailbox/inbox.ts
106652
106722
  init_paths3();
106653
106723
  init_types5();
106654
- import { readdir as readdir4, readFile as readFile7 } from "fs/promises";
106724
+ import { readdir as readdir5, readFile as readFile7 } from "fs/promises";
106725
+ import path17 from "path";
106726
+
106727
+ // packages/team-core/src/team-mailbox/reservation.ts
106728
+ init_paths3();
106729
+ import { mkdir as mkdir5, readdir as readdir4, rename as rename4, stat as stat4 } from "fs/promises";
106655
106730
  import path16 from "path";
106731
+ var RESERVED_PREFIX = ".delivering-";
106732
+ var RESERVED_SUFFIX = ".json";
106733
+ function isMissingPathError(error) {
106734
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
106735
+ }
106736
+ function buildDeliveryReservation(inboxDir, messageId) {
106737
+ const inboxPath = path16.join(inboxDir, `${messageId}.json`);
106738
+ const reservedPath = path16.join(inboxDir, `${RESERVED_PREFIX}${messageId}${RESERVED_SUFFIX}`);
106739
+ const processedDir = path16.join(inboxDir, "processed");
106740
+ const processedPath = path16.join(processedDir, `${messageId}.json`);
106741
+ return { reservedPath, inboxPath, processedPath, processedDir };
106742
+ }
106743
+ async function reserveMessageForDelivery(teamRunId, recipientName, messageId, config3) {
106744
+ const inboxDir = getInboxDir(resolveBaseDir(config3), teamRunId, recipientName);
106745
+ const reservation = buildDeliveryReservation(inboxDir, messageId);
106746
+ try {
106747
+ await stat4(reservation.reservedPath);
106748
+ return reservation;
106749
+ } catch (error) {
106750
+ if (!isMissingPathError(error))
106751
+ throw error;
106752
+ }
106753
+ try {
106754
+ await rename4(reservation.inboxPath, reservation.reservedPath);
106755
+ return reservation;
106756
+ } catch (error) {
106757
+ if (isMissingPathError(error))
106758
+ return null;
106759
+ throw error;
106760
+ }
106761
+ }
106762
+ async function commitDeliveryReservation(reservation) {
106763
+ await mkdir5(reservation.processedDir, { recursive: true, mode: 448 });
106764
+ await rename4(reservation.reservedPath, reservation.processedPath);
106765
+ }
106766
+ async function releaseDeliveryReservation(reservation) {
106767
+ await rename4(reservation.reservedPath, reservation.inboxPath);
106768
+ }
106769
+
106770
+ // packages/team-core/src/team-mailbox/inbox.ts
106656
106771
  function isInboxMessageFile(entry) {
106657
106772
  return entry.isFile() && entry.name.endsWith(".json") && !entry.name.startsWith(".");
106658
106773
  }
@@ -106660,7 +106775,7 @@ function isMissingDirectoryError(error) {
106660
106775
  return error instanceof Error && "code" in error && error.code === "ENOENT";
106661
106776
  }
106662
106777
  async function readInboxMessage(inboxDir, fileName, memberName, teamRunId) {
106663
- const filePath = path16.join(inboxDir, fileName);
106778
+ const filePath = path17.join(inboxDir, fileName);
106664
106779
  const messageContext = { memberName, teamRunId, fileName };
106665
106780
  try {
106666
106781
  const fileContent = await readFile7(filePath, "utf8");
@@ -106683,10 +106798,58 @@ async function readInboxMessage(inboxDir, fileName, memberName, teamRunId) {
106683
106798
  return null;
106684
106799
  }
106685
106800
  }
106801
+ async function readUnreadMessageById(teamRunId, memberName, messageId, config3) {
106802
+ const inboxDir = getInboxDir(resolveBaseDir(config3), teamRunId, memberName);
106803
+ const reservation = buildDeliveryReservation(inboxDir, messageId);
106804
+ const candidatePaths = [reservation.inboxPath, reservation.reservedPath];
106805
+ let fileContent;
106806
+ let fileName = `${messageId}.json`;
106807
+ for (const candidatePath of candidatePaths) {
106808
+ try {
106809
+ fileContent = await readFile7(candidatePath, "utf8");
106810
+ fileName = path17.basename(candidatePath);
106811
+ break;
106812
+ } catch (error) {
106813
+ if (isMissingDirectoryError(error)) {
106814
+ continue;
106815
+ }
106816
+ log5("team mailbox exact message read failed", {
106817
+ event: "team-mailbox-exact-message-read-failed",
106818
+ memberName,
106819
+ teamRunId,
106820
+ fileName: path17.basename(candidatePath),
106821
+ error: error instanceof Error ? error.message : String(error)
106822
+ });
106823
+ throw error;
106824
+ }
106825
+ }
106826
+ if (fileContent === undefined) {
106827
+ return;
106828
+ }
106829
+ const messageContext = { memberName, teamRunId, fileName };
106830
+ try {
106831
+ const parsedMessage = MessageSchema.safeParse(JSON.parse(fileContent));
106832
+ if (parsedMessage.success) {
106833
+ return parsedMessage.data;
106834
+ }
106835
+ log5("team mailbox skipped malformed exact message", {
106836
+ event: "team-mailbox-malformed-exact-message",
106837
+ ...messageContext,
106838
+ issues: parsedMessage.error.issues
106839
+ });
106840
+ } catch (error) {
106841
+ log5("team mailbox skipped malformed exact message", {
106842
+ event: "team-mailbox-malformed-exact-message",
106843
+ ...messageContext,
106844
+ error: error instanceof Error ? error.message : String(error)
106845
+ });
106846
+ }
106847
+ return;
106848
+ }
106686
106849
  async function listUnreadMessages(teamRunId, memberName, config3) {
106687
106850
  const inboxDir = getInboxDir(resolveBaseDir(config3), teamRunId, memberName);
106688
106851
  try {
106689
- const directoryEntries = await readdir4(inboxDir, { withFileTypes: true });
106852
+ const directoryEntries = await readdir5(inboxDir, { withFileTypes: true });
106690
106853
  const unreadMessages = await Promise.all(directoryEntries.filter(isInboxMessageFile).map((entry) => readInboxMessage(inboxDir, entry.name, memberName, teamRunId)));
106691
106854
  return unreadMessages.filter((message) => message !== null).sort((leftMessage, rightMessage) => leftMessage.timestamp - rightMessage.timestamp);
106692
106855
  } catch (error) {
@@ -107651,7 +107814,7 @@ function createGoalController(options) {
107651
107814
  const storeRef = (sessionID) => ({ baseDir, sessionID });
107652
107815
  const tuiMirrorPath = (sessionID) => join97(projectDir, ".omo", "ulw-loop", sessionID, "goals.json");
107653
107816
  const writeTuiMirror = (sessionID, goal2) => {
107654
- const path17 = tuiMirrorPath(sessionID);
107817
+ const path18 = tuiMirrorPath(sessionID);
107655
107818
  const snapshot = {
107656
107819
  version: 1,
107657
107820
  activeGoalId: goal2?.id,
@@ -107662,8 +107825,8 @@ function createGoalController(options) {
107662
107825
  successCriteria: []
107663
107826
  }]
107664
107827
  };
107665
- mkdirSync20(dirname31(path17), { recursive: true });
107666
- writeFileSync21(path17, `${JSON.stringify(snapshot, null, 2)}
107828
+ mkdirSync20(dirname31(path18), { recursive: true });
107829
+ writeFileSync21(path18, `${JSON.stringify(snapshot, null, 2)}
107667
107830
  `, "utf-8");
107668
107831
  };
107669
107832
  return {
@@ -108260,8 +108423,8 @@ import { execFileSync as execFileSync5 } from "child_process";
108260
108423
  import { existsSync as existsSync79, realpathSync as realpathSync18 } from "fs";
108261
108424
  import { dirname as dirname33, join as join101, resolve as resolve26, win32 as win329 } from "path";
108262
108425
  var worktreePathCache2 = new Map;
108263
- function normalizePath4(path17) {
108264
- const resolvedPath = process.platform !== "win32" && win329.isAbsolute(path17) ? path17 : resolve26(path17);
108426
+ function normalizePath4(path18) {
108427
+ const resolvedPath = process.platform !== "win32" && win329.isAbsolute(path18) ? path18 : resolve26(path18);
108265
108428
  if (!existsSync79(resolvedPath)) {
108266
108429
  return resolvedPath;
108267
108430
  }
@@ -108281,8 +108444,8 @@ function normalizePath4(path17) {
108281
108444
  }
108282
108445
  }
108283
108446
  }
108284
- function pathKey3(path17) {
108285
- const normalized = path17.replace(/\\/g, "/");
108447
+ function pathKey3(path18) {
108448
+ const normalized = path18.replace(/\\/g, "/");
108286
108449
  return process.platform === "win32" ? normalized.toLowerCase() : normalized;
108287
108450
  }
108288
108451
  function findAncestorDirectories2(startDirectory, targetPaths, stopDirectory) {
@@ -112044,26 +112207,26 @@ import * as fs18 from "fs/promises";
112044
112207
  import { homedir as homedir29 } from "os";
112045
112208
  import { dirname as dirname36, extname as extname2, isAbsolute as isAbsolute14, join as join108, relative as relative13 } from "path";
112046
112209
  var MAX_RECURSIVE_DEPTH = 10;
112047
- function isHttpUrl(path17) {
112048
- return path17.startsWith("http://") || path17.startsWith("https://");
112210
+ function isHttpUrl(path18) {
112211
+ return path18.startsWith("http://") || path18.startsWith("https://");
112049
112212
  }
112050
- function toAbsolutePath(path17, configDir) {
112051
- if (path17 === "~") {
112213
+ function toAbsolutePath(path18, configDir) {
112214
+ if (path18 === "~") {
112052
112215
  return homedir29();
112053
112216
  }
112054
- if (path17.startsWith("~/")) {
112055
- return join108(homedir29(), path17.slice(2));
112217
+ if (path18.startsWith("~/")) {
112218
+ return join108(homedir29(), path18.slice(2));
112056
112219
  }
112057
- if (isAbsolute14(path17)) {
112058
- return path17;
112220
+ if (isAbsolute14(path18)) {
112221
+ return path18;
112059
112222
  }
112060
- return join108(configDir, path17);
112223
+ return join108(configDir, path18);
112061
112224
  }
112062
- function isMarkdownPath(path17) {
112063
- return extname2(path17).toLowerCase() === ".md";
112225
+ function isMarkdownPath(path18) {
112226
+ return extname2(path18).toLowerCase() === ".md";
112064
112227
  }
112065
- function normalizePathForGlob(path17) {
112066
- return path17.split("\\").join("/");
112228
+ function normalizePathForGlob(path18) {
112229
+ return path18.split("\\").join("/");
112067
112230
  }
112068
112231
  function filterByGlob(skills2, sourceBaseDir, globPattern) {
112069
112232
  if (!globPattern)
@@ -112075,10 +112238,10 @@ function filterByGlob(skills2, sourceBaseDir, globPattern) {
112075
112238
  return import_picomatch2.default.isMatch(rel, globPattern, { dot: true, bash: true });
112076
112239
  });
112077
112240
  }
112078
- async function resolveRealPath(path17) {
112079
- return resolveSymlinkAsync(path17).catch((error) => {
112241
+ async function resolveRealPath(path18) {
112242
+ return resolveSymlinkAsync(path18).catch((error) => {
112080
112243
  if (error instanceof Error) {
112081
- return path17;
112244
+ return path18;
112082
112245
  }
112083
112246
  throw error;
112084
112247
  });
@@ -112088,11 +112251,11 @@ async function loadSourcePath(options) {
112088
112251
  return [];
112089
112252
  }
112090
112253
  const absolutePath = toAbsolutePath(options.sourcePath, options.configDir);
112091
- const stat5 = await fs18.stat(absolutePath).catch(() => null);
112092
- if (!stat5)
112254
+ const stat6 = await fs18.stat(absolutePath).catch(() => null);
112255
+ if (!stat6)
112093
112256
  return [];
112094
112257
  const realSourcePath = await resolveRealPath(absolutePath);
112095
- if (stat5.isFile()) {
112258
+ if (stat6.isFile()) {
112096
112259
  if (!isMarkdownPath(realSourcePath))
112097
112260
  return [];
112098
112261
  const loaded = await loadSkillFromPath({
@@ -112105,7 +112268,7 @@ async function loadSourcePath(options) {
112105
112268
  return [];
112106
112269
  return filterByGlob([loaded], dirname36(realSourcePath), options.globPattern);
112107
112270
  }
112108
- if (!stat5.isDirectory())
112271
+ if (!stat6.isDirectory())
112109
112272
  return [];
112110
112273
  const directorySkills = await loadSkillsFromDir({
112111
112274
  skillsDir: realSourcePath,
@@ -112138,15 +112301,15 @@ async function discoverConfigSourceSkills(options) {
112138
112301
  // packages/skills-loader-core/src/features/opencode-skill-loader/opencode-config-skills-reader.ts
112139
112302
  init_src2();
112140
112303
  import * as fs19 from "fs";
112141
- import * as path17 from "path";
112304
+ import * as path18 from "path";
112142
112305
  function getConfigPaths3(directory) {
112143
112306
  const globalConfigDirs = getOpenCodeConfigDirs2({ binary: "opencode" });
112144
112307
  return [
112145
- path17.join(directory, ".opencode", "opencode.json"),
112146
- path17.join(directory, ".opencode", "opencode.jsonc"),
112308
+ path18.join(directory, ".opencode", "opencode.json"),
112309
+ path18.join(directory, ".opencode", "opencode.jsonc"),
112147
112310
  ...globalConfigDirs.flatMap((dir) => [
112148
- path17.join(dir, "opencode.json"),
112149
- path17.join(dir, "opencode.jsonc")
112311
+ path18.join(dir, "opencode.json"),
112312
+ path18.join(dir, "opencode.jsonc")
112150
112313
  ])
112151
112314
  ];
112152
112315
  }
@@ -114486,8 +114649,8 @@ init_logger2();
114486
114649
  import { execFileSync as execFileSync6 } from "child_process";
114487
114650
  import { existsSync as existsSync84, realpathSync as realpathSync19 } from "fs";
114488
114651
  import { resolve as resolve29, win32 as win3210 } from "path";
114489
- function normalizePath5(path18) {
114490
- const resolvedPath = process.platform !== "win32" && win3210.isAbsolute(path18) ? path18 : resolve29(path18);
114652
+ function normalizePath5(path19) {
114653
+ const resolvedPath = process.platform !== "win32" && win3210.isAbsolute(path19) ? path19 : resolve29(path19);
114491
114654
  if (!existsSync84(resolvedPath)) {
114492
114655
  return resolvedPath;
114493
114656
  }
@@ -115140,8 +115303,8 @@ function normalizePlanPathKey(planPath) {
115140
115303
  const resolvedPath = looksLikeWindowsAbsolutePath(planPath) ? win3211.resolve(planPath) : posix10.resolve(planPath);
115141
115304
  return resolvedPath.replaceAll("\\", "/");
115142
115305
  }
115143
- function looksLikeWindowsAbsolutePath(path18) {
115144
- return /^[A-Za-z]:[\\/]/.test(path18) || /^[/\\]{2}[^/\\]/.test(path18);
115306
+ function looksLikeWindowsAbsolutePath(path19) {
115307
+ return /^[A-Za-z]:[\\/]/.test(path19) || /^[/\\]{2}[^/\\]/.test(path19);
115145
115308
  }
115146
115309
  function extractPlanPathsFromText(directory, text) {
115147
115310
  const matches = text.match(PLAN_PATH_PATTERN) ?? [];
@@ -122851,16 +123014,16 @@ class Diff {
122851
123014
  }
122852
123015
  }
122853
123016
  }
122854
- addToPath(path18, added, removed, oldPosInc, options) {
122855
- const last = path18.lastComponent;
123017
+ addToPath(path19, added, removed, oldPosInc, options) {
123018
+ const last = path19.lastComponent;
122856
123019
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
122857
123020
  return {
122858
- oldPos: path18.oldPos + oldPosInc,
123021
+ oldPos: path19.oldPos + oldPosInc,
122859
123022
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
122860
123023
  };
122861
123024
  } else {
122862
123025
  return {
122863
- oldPos: path18.oldPos + oldPosInc,
123026
+ oldPos: path19.oldPos + oldPosInc,
122864
123027
  lastComponent: { count: 1, added, removed, previousComponent: last }
122865
123028
  };
122866
123029
  }
@@ -125619,7 +125782,7 @@ var RG_FILES_FLAGS = [
125619
125782
  ];
125620
125783
 
125621
125784
  // packages/omo-opencode/src/tools/glob/cli.ts
125622
- import { stat as stat5 } from "fs/promises";
125785
+ import { stat as stat6 } from "fs/promises";
125623
125786
  function buildRgArgs2(options) {
125624
125787
  const args = [
125625
125788
  ...RG_FILES_FLAGS,
@@ -125665,7 +125828,7 @@ function buildPowerShellCommand(options) {
125665
125828
  }
125666
125829
  async function getFileMtime(filePath) {
125667
125830
  try {
125668
- const stats = await stat5(filePath);
125831
+ const stats = await stat6(filePath);
125669
125832
  return stats.mtime.getTime();
125670
125833
  } catch (error) {
125671
125834
  if (!(error instanceof Error)) {
@@ -126416,7 +126579,7 @@ Has Transcript: Yes (234 entries)`;
126416
126579
 
126417
126580
  // packages/omo-opencode/src/tools/session-manager/file-storage.ts
126418
126581
  import { existsSync as existsSync94 } from "fs";
126419
- import { readdir as readdir6, readFile as readFile10 } from "fs/promises";
126582
+ import { readdir as readdir7, readFile as readFile10 } from "fs/promises";
126420
126583
  import { join as join118 } from "path";
126421
126584
  function ignoreFileStorageError(error) {
126422
126585
  if (error instanceof Error)
@@ -126428,12 +126591,12 @@ async function getFileMainSessions(directory) {
126428
126591
  return [];
126429
126592
  const sessions = [];
126430
126593
  try {
126431
- const projectDirs = await readdir6(SESSION_STORAGE, { withFileTypes: true });
126594
+ const projectDirs = await readdir7(SESSION_STORAGE, { withFileTypes: true });
126432
126595
  for (const projectDir of projectDirs) {
126433
126596
  if (!projectDir.isDirectory())
126434
126597
  continue;
126435
126598
  const projectPath = join118(SESSION_STORAGE, projectDir.name);
126436
- const sessionFiles = await readdir6(projectPath);
126599
+ const sessionFiles = await readdir7(projectPath);
126437
126600
  for (const file2 of sessionFiles) {
126438
126601
  if (!file2.endsWith(".json"))
126439
126602
  continue;
@@ -126463,12 +126626,12 @@ async function getFileAllSessions() {
126463
126626
  const sessions = [];
126464
126627
  async function scanDirectory(dir) {
126465
126628
  try {
126466
- const entries = await readdir6(dir, { withFileTypes: true });
126629
+ const entries = await readdir7(dir, { withFileTypes: true });
126467
126630
  for (const entry of entries) {
126468
126631
  if (!entry.isDirectory())
126469
126632
  continue;
126470
126633
  const sessionPath = join118(dir, entry.name);
126471
- const files = await readdir6(sessionPath);
126634
+ const files = await readdir7(sessionPath);
126472
126635
  if (files.some((file2) => file2.endsWith(".json"))) {
126473
126636
  sessions.push(entry.name);
126474
126637
  continue;
@@ -126492,7 +126655,7 @@ async function getFileSessionMessages(sessionID) {
126492
126655
  return [];
126493
126656
  const messages = [];
126494
126657
  try {
126495
- const files = await readdir6(messageDir);
126658
+ const files = await readdir7(messageDir);
126496
126659
  for (const file2 of files) {
126497
126660
  if (!file2.endsWith(".json"))
126498
126661
  continue;
@@ -126530,7 +126693,7 @@ async function readParts2(messageID) {
126530
126693
  return [];
126531
126694
  const parts = [];
126532
126695
  try {
126533
- const files = await readdir6(partDir);
126696
+ const files = await readdir7(partDir);
126534
126697
  for (const file2 of files) {
126535
126698
  if (!file2.endsWith(".json"))
126536
126699
  continue;
@@ -126552,7 +126715,7 @@ async function getFileSessionTodos(sessionID) {
126552
126715
  if (!existsSync94(TODO_DIR2))
126553
126716
  return [];
126554
126717
  try {
126555
- const allFiles = await readdir6(TODO_DIR2);
126718
+ const allFiles = await readdir7(TODO_DIR2);
126556
126719
  const todoFiles = allFiles.filter((file2) => file2 === `${sessionID}.json`);
126557
126720
  for (const file2 of todoFiles) {
126558
126721
  try {
@@ -128614,8 +128777,8 @@ import { execFileSync as execFileSync7 } from "child_process";
128614
128777
  import { existsSync as existsSync96, realpathSync as realpathSync22 } from "fs";
128615
128778
  import { dirname as dirname43, join as join123, resolve as resolve39, win32 as win3213 } from "path";
128616
128779
  var worktreePathCache3 = new Map;
128617
- function normalizePath6(path18) {
128618
- const resolvedPath = process.platform !== "win32" && win3213.isAbsolute(path18) ? path18 : resolve39(path18);
128780
+ function normalizePath6(path19) {
128781
+ const resolvedPath = process.platform !== "win32" && win3213.isAbsolute(path19) ? path19 : resolve39(path19);
128619
128782
  if (!existsSync96(resolvedPath)) {
128620
128783
  return resolvedPath;
128621
128784
  }
@@ -128635,8 +128798,8 @@ function normalizePath6(path18) {
128635
128798
  }
128636
128799
  }
128637
128800
  }
128638
- function pathKey4(path18) {
128639
- const normalized = path18.replace(/\\/g, "/");
128801
+ function pathKey4(path19) {
128802
+ const normalized = path19.replace(/\\/g, "/");
128640
128803
  return process.platform === "win32" ? normalized.toLowerCase() : normalized;
128641
128804
  }
128642
128805
  function detectWorktreePath4(directory) {
@@ -128888,15 +129051,15 @@ function loadOpencodeProjectAgents(directory) {
128888
129051
  }
128889
129052
  // packages/claude-code-compat-core/src/features/claude-code-agent-loader/opencode-config-agents-reader.ts
128890
129053
  import * as fs20 from "fs";
128891
- import * as path18 from "path";
129054
+ import * as path19 from "path";
128892
129055
  function getConfigPaths4(directory) {
128893
129056
  const globalConfigDirs = getOpenCodeConfigDirs3({ binary: "opencode" });
128894
129057
  return [
128895
- path18.join(directory, ".opencode", "opencode.json"),
128896
- path18.join(directory, ".opencode", "opencode.jsonc"),
129058
+ path19.join(directory, ".opencode", "opencode.json"),
129059
+ path19.join(directory, ".opencode", "opencode.jsonc"),
128897
129060
  ...globalConfigDirs.flatMap((dir) => [
128898
- path18.join(dir, "opencode.json"),
128899
- path18.join(dir, "opencode.jsonc")
129061
+ path19.join(dir, "opencode.json"),
129062
+ path19.join(dir, "opencode.jsonc")
128900
129063
  ])
128901
129064
  ];
128902
129065
  }
@@ -128933,7 +129096,7 @@ function readOpencodeConfigAgents(directory) {
128933
129096
  const parseResult = parseJsoncSafe(content);
128934
129097
  if (!parseResult.data)
128935
129098
  continue;
128936
- const configDir = path18.dirname(configPath);
129099
+ const configDir = path19.dirname(configPath);
128937
129100
  const agentsToLoad = parseResult.data.agents || parseResult.data.agent;
128938
129101
  if (agentsToLoad && typeof agentsToLoad === "object") {
128939
129102
  for (const [agentName, agentData] of Object.entries(agentsToLoad)) {
@@ -130487,9 +130650,9 @@ function getMissingFilePathFromError(error) {
130487
130650
  if (!(error instanceof Error)) {
130488
130651
  return null;
130489
130652
  }
130490
- const path19 = Reflect.get(error, "path");
130491
- if (typeof path19 === "string" && path19.length > 0) {
130492
- return path19;
130653
+ const path20 = Reflect.get(error, "path");
130654
+ if (typeof path20 === "string" && path20.length > 0) {
130655
+ return path20;
130493
130656
  }
130494
130657
  if (error instanceof Error) {
130495
130658
  const match = /open '([^']+)'/.exec(error.message);
@@ -134562,11 +134725,11 @@ async function handleUpdate(args, config3, ctx, context) {
134562
134725
  }
134563
134726
  }
134564
134727
  // packages/omo-opencode/src/tools/hashline-edit/formatter-trigger.ts
134565
- import path19 from "path";
134728
+ import path20 from "path";
134566
134729
  init_bun_spawn_shim();
134567
134730
  var cachedFormattersByDirectory = new Map;
134568
134731
  function getFormatterCacheKey(directory) {
134569
- return path19.resolve(directory);
134732
+ return path20.resolve(directory);
134570
134733
  }
134571
134734
  function unwrapConfigResponse(response) {
134572
134735
  if ("data" in response)
@@ -134622,7 +134785,7 @@ function buildFormatterCommand(command, filePath) {
134622
134785
  return command.map((arg) => arg.replace(/\$FILE/g, filePath));
134623
134786
  }
134624
134787
  async function runFormattersForFile(client3, directory, filePath) {
134625
- const ext = path19.extname(filePath);
134788
+ const ext = path20.extname(filePath);
134626
134789
  if (!ext)
134627
134790
  return;
134628
134791
  const formatters = await resolveFormatters(client3, directory);
@@ -134704,8 +134867,8 @@ async function executeHashlineEditTool(args, context, pluginCtx) {
134704
134867
  try {
134705
134868
  const metadataContext = context;
134706
134869
  const filePath = args.filePath;
134707
- const { delete: deleteMode, rename: rename4 } = args;
134708
- if (deleteMode && rename4) {
134870
+ const { delete: deleteMode, rename: rename5 } = args;
134871
+ if (deleteMode && rename5) {
134709
134872
  return "Error: delete and rename cannot be used together";
134710
134873
  }
134711
134874
  if (deleteMode && args.edits.length > 0) {
@@ -134730,7 +134893,7 @@ async function executeHashlineEditTool(args, context, pluginCtx) {
134730
134893
  const oldEnvelope = canonicalizeFileText(rawOldContent);
134731
134894
  const applyResult = applyHashlineEditsWithReport(oldEnvelope.content, edits);
134732
134895
  const canonicalNewContent = applyResult.content;
134733
- if (canonicalNewContent === oldEnvelope.content && !rename4) {
134896
+ if (canonicalNewContent === oldEnvelope.content && !rename5) {
134734
134897
  let diagnostic = `No changes made to ${filePath}. The edits produced identical content.`;
134735
134898
  if (applyResult.noopEdits > 0) {
134736
134899
  diagnostic += ` No-op edits: ${applyResult.noopEdits}. Re-read the file and provide content that differs from current lines.`;
@@ -134746,23 +134909,23 @@ async function executeHashlineEditTool(args, context, pluginCtx) {
134746
134909
  const formattedEnvelope = canonicalizeFileText(formattedContent);
134747
134910
  const formattedMeta = buildSuccessMeta(filePath, oldEnvelope.content, formattedEnvelope.content, applyResult.noopEdits, applyResult.deduplicatedEdits);
134748
134911
  await publishToolMetadata(metadataContext, formattedMeta);
134749
- if (rename4 && rename4 !== filePath) {
134750
- await bunWrite(rename4, formattedContent);
134912
+ if (rename5 && rename5 !== filePath) {
134913
+ await bunWrite(rename5, formattedContent);
134751
134914
  await bunFile(filePath).delete();
134752
- return `Moved ${filePath} to ${rename4}`;
134915
+ return `Moved ${filePath} to ${rename5}`;
134753
134916
  }
134754
134917
  return `Updated ${filePath}`;
134755
134918
  }
134756
134919
  }
134757
- if (rename4 && rename4 !== filePath) {
134758
- await bunWrite(rename4, writeContent);
134920
+ if (rename5 && rename5 !== filePath) {
134921
+ await bunWrite(rename5, writeContent);
134759
134922
  await bunFile(filePath).delete();
134760
134923
  }
134761
- const effectivePath = rename4 && rename4 !== filePath ? rename4 : filePath;
134924
+ const effectivePath = rename5 && rename5 !== filePath ? rename5 : filePath;
134762
134925
  const meta = buildSuccessMeta(effectivePath, oldEnvelope.content, canonicalNewContent, applyResult.noopEdits, applyResult.deduplicatedEdits);
134763
134926
  await publishToolMetadata(metadataContext, meta);
134764
- if (rename4 && rename4 !== filePath) {
134765
- return `Moved ${filePath} to ${rename4}`;
134927
+ if (rename5 && rename5 !== filePath) {
134928
+ return `Moved ${filePath} to ${rename5}`;
134766
134929
  }
134767
134930
  return `Updated ${effectivePath}`;
134768
134931
  } catch (error) {
@@ -134904,8 +135067,8 @@ init_paths3();
134904
135067
  init_store2();
134905
135068
  init_locks();
134906
135069
  import { Buffer as Buffer2 } from "buffer";
134907
- import { mkdir as mkdir5, readdir as readdir7, stat as stat6 } from "fs/promises";
134908
- import path20 from "path";
135070
+ import { mkdir as mkdir6, readdir as readdir8, stat as stat7 } from "fs/promises";
135071
+ import path21 from "path";
134909
135072
 
134910
135073
  class BroadcastNotPermittedError extends Error {
134911
135074
  constructor(message = "broadcast requires lead role") {
@@ -134948,7 +135111,7 @@ class TeamDeletingError extends Error {
134948
135111
  this.name = "TeamDeletingError";
134949
135112
  }
134950
135113
  }
134951
- function isMissingPathError(error) {
135114
+ function isMissingPathError2(error) {
134952
135115
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
134953
135116
  }
134954
135117
  async function assertTeamAcceptsMessages(teamRunId, config3) {
@@ -134958,7 +135121,7 @@ async function assertTeamAcceptsMessages(teamRunId, config3) {
134958
135121
  throw new TeamDeletingError;
134959
135122
  }
134960
135123
  } catch (error) {
134961
- if (isMissingPathError(error)) {
135124
+ if (isMissingPathError2(error)) {
134962
135125
  return;
134963
135126
  }
134964
135127
  throw error;
@@ -134979,7 +135142,7 @@ function resolveRecipients(message, context) {
134979
135142
  }
134980
135143
  async function getUnreadSizeBytes(inboxDir) {
134981
135144
  try {
134982
- const directoryEntries = await readdir7(inboxDir, { withFileTypes: true });
135145
+ const directoryEntries = await readdir8(inboxDir, { withFileTypes: true });
134983
135146
  const unreadEntries = directoryEntries.filter((entry) => {
134984
135147
  if (!entry.isFile() || !entry.name.endsWith(".json"))
134985
135148
  return false;
@@ -134988,12 +135151,12 @@ async function getUnreadSizeBytes(inboxDir) {
134988
135151
  return !entry.name.startsWith(".");
134989
135152
  });
134990
135153
  const sizes = await Promise.all(unreadEntries.map(async (entry) => {
134991
- const fileStats = await stat6(path20.join(inboxDir, entry.name));
135154
+ const fileStats = await stat7(path21.join(inboxDir, entry.name));
134992
135155
  return fileStats.size;
134993
135156
  }));
134994
135157
  return sizes.reduce((totalBytes, fileSize) => totalBytes + fileSize, 0);
134995
135158
  } catch (error) {
134996
- if (isMissingPathError(error)) {
135159
+ if (isMissingPathError2(error)) {
134997
135160
  return 0;
134998
135161
  }
134999
135162
  throw error;
@@ -135001,10 +135164,10 @@ async function getUnreadSizeBytes(inboxDir) {
135001
135164
  }
135002
135165
  async function fileExists(filePath) {
135003
135166
  try {
135004
- await stat6(filePath);
135167
+ await stat7(filePath);
135005
135168
  return true;
135006
135169
  } catch (error) {
135007
- if (isMissingPathError(error)) {
135170
+ if (isMissingPathError2(error)) {
135008
135171
  return false;
135009
135172
  }
135010
135173
  throw error;
@@ -135027,15 +135190,15 @@ async function sendMessage(message, teamRunId, config3, context) {
135027
135190
  const reservedRecipients = context.reservedRecipients ?? new Set;
135028
135191
  for (const recipient of resolveRecipients(message, context)) {
135029
135192
  const inboxDir = getInboxDir(baseDir, teamRunId, recipient);
135030
- await mkdir5(inboxDir, { recursive: true, mode: 448 });
135193
+ await mkdir6(inboxDir, { recursive: true, mode: 448 });
135031
135194
  await withLock(`${inboxDir}.lock`, async () => {
135032
135195
  const unreadSizeBytes = await getUnreadSizeBytes(inboxDir);
135033
135196
  const nextUnreadSizeBytes = unreadSizeBytes + serializedMessageBytes;
135034
135197
  if (nextUnreadSizeBytes > config3.recipient_unread_max_bytes) {
135035
135198
  throw new RecipientBackpressureError;
135036
135199
  }
135037
- const unreservedPath = path20.join(inboxDir, `${message.messageId}.json`);
135038
- const reservedPath = path20.join(inboxDir, `.delivering-${message.messageId}.json`);
135200
+ const unreservedPath = path21.join(inboxDir, `${message.messageId}.json`);
135201
+ const reservedPath = path21.join(inboxDir, `.delivering-${message.messageId}.json`);
135039
135202
  if (await fileExists(unreservedPath) || await fileExists(reservedPath)) {
135040
135203
  throw new DuplicateMessageIdError;
135041
135204
  }
@@ -135050,49 +135213,6 @@ async function sendMessage(message, teamRunId, config3, context) {
135050
135213
  // packages/omo-opencode/src/features/team-mode/tools/messaging.ts
135051
135214
  init_types5();
135052
135215
 
135053
- // packages/team-core/src/team-mailbox/reservation.ts
135054
- init_paths3();
135055
- import { mkdir as mkdir6, readdir as readdir8, rename as rename4, stat as stat7 } from "fs/promises";
135056
- import path21 from "path";
135057
- var RESERVED_PREFIX = ".delivering-";
135058
- var RESERVED_SUFFIX = ".json";
135059
- function isMissingPathError2(error) {
135060
- return error instanceof Error && "code" in error && error.code === "ENOENT";
135061
- }
135062
- function buildReservation(inboxDir, messageId) {
135063
- const inboxPath = path21.join(inboxDir, `${messageId}.json`);
135064
- const reservedPath = path21.join(inboxDir, `${RESERVED_PREFIX}${messageId}${RESERVED_SUFFIX}`);
135065
- const processedDir = path21.join(inboxDir, "processed");
135066
- const processedPath = path21.join(processedDir, `${messageId}.json`);
135067
- return { reservedPath, inboxPath, processedPath, processedDir };
135068
- }
135069
- async function reserveMessageForDelivery(teamRunId, recipientName, messageId, config3) {
135070
- const inboxDir = getInboxDir(resolveBaseDir(config3), teamRunId, recipientName);
135071
- const reservation = buildReservation(inboxDir, messageId);
135072
- try {
135073
- await stat7(reservation.reservedPath);
135074
- return reservation;
135075
- } catch (error) {
135076
- if (!isMissingPathError2(error))
135077
- throw error;
135078
- }
135079
- try {
135080
- await rename4(reservation.inboxPath, reservation.reservedPath);
135081
- return reservation;
135082
- } catch (error) {
135083
- if (isMissingPathError2(error))
135084
- return null;
135085
- throw error;
135086
- }
135087
- }
135088
- async function commitDeliveryReservation(reservation) {
135089
- await mkdir6(reservation.processedDir, { recursive: true, mode: 448 });
135090
- await rename4(reservation.reservedPath, reservation.processedPath);
135091
- }
135092
- async function releaseDeliveryReservation(reservation) {
135093
- await rename4(reservation.reservedPath, reservation.inboxPath);
135094
- }
135095
-
135096
135216
  // packages/omo-opencode/src/features/team-mode/tools/messaging-live-delivery-reservation.ts
135097
135217
  init_logger2();
135098
135218
  async function releaseReservationSafely(reservation, input) {
@@ -135161,6 +135281,70 @@ function buildMemberPromptBody(member, text) {
135161
135281
  };
135162
135282
  }
135163
135283
 
135284
+ // packages/omo-opencode/src/features/team-mode/tools/messaging-fallback-wake.ts
135285
+ init_logger2();
135286
+ init_store2();
135287
+ async function enqueueFallbackMailboxWake(input) {
135288
+ const promptResult = await dispatchInternalPrompt({
135289
+ mode: "async",
135290
+ client: input.client,
135291
+ sessionID: input.recipientSessionId,
135292
+ source: "team-live-delivery-fallback",
135293
+ dedupeKey: `team-live-delivery-fallback:${input.messageId}`,
135294
+ queueBehavior: "enqueue",
135295
+ durableRetry: true,
135296
+ shouldDispatch: () => shouldDispatchFallbackMailboxWake(input),
135297
+ retryDispatchFailure: isPreSendConnectionFailure2,
135298
+ input: {
135299
+ path: { id: input.recipientSessionId },
135300
+ body: buildMemberPromptBody(input.recipientMember, "You have a new team message in your mailbox."),
135301
+ query: { directory: input.recipientMember.worktreePath ?? input.directory }
135302
+ }
135303
+ });
135304
+ if (isInternalPromptDispatchAccepted(promptResult))
135305
+ return;
135306
+ log2("[team-mailbox] fallback mailbox wake was not accepted", {
135307
+ status: promptResult.status,
135308
+ teamRunId: input.teamRunId,
135309
+ recipient: input.recipientName,
135310
+ recipientSessionId: input.recipientSessionId,
135311
+ messageId: input.messageId
135312
+ });
135313
+ }
135314
+ async function shouldDispatchFallbackMailboxWake(input) {
135315
+ try {
135316
+ const runtimeState = await loadRuntimeState(input.teamRunId, input.config);
135317
+ const recipient = runtimeState.members.find((member) => member.name === input.recipientName);
135318
+ const recipientIsActive = recipient?.status === "running" || recipient?.status === "idle";
135319
+ if (runtimeState.status !== "active" || recipient?.sessionId !== input.recipientSessionId || !recipientIsActive) {
135320
+ return false;
135321
+ }
135322
+ if (recipient.pendingInjectedMessageIds.includes(input.messageId)) {
135323
+ return false;
135324
+ }
135325
+ const unread = await readUnreadMessageById(input.teamRunId, input.recipientName, input.messageId, input.config);
135326
+ return unread !== undefined;
135327
+ } catch (error) {
135328
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
135329
+ log2("[team-mailbox] fallback mailbox wake cancelled because team state no longer exists", {
135330
+ teamRunId: input.teamRunId,
135331
+ recipient: input.recipientName,
135332
+ recipientSessionId: input.recipientSessionId,
135333
+ messageId: input.messageId
135334
+ });
135335
+ return false;
135336
+ }
135337
+ log2("[team-mailbox] fallback mailbox wake revalidation failed, retaining queued wake", {
135338
+ teamRunId: input.teamRunId,
135339
+ recipient: input.recipientName,
135340
+ recipientSessionId: input.recipientSessionId,
135341
+ messageId: input.messageId,
135342
+ error: error instanceof Error ? error.message : String(error)
135343
+ });
135344
+ throw error;
135345
+ }
135346
+ }
135347
+
135164
135348
  // packages/omo-opencode/src/features/team-mode/tools/messaging-live-delivery-state.ts
135165
135349
  init_logger2();
135166
135350
  init_store2();
@@ -135201,12 +135385,25 @@ async function deliverLiveToRecipient(input) {
135201
135385
  config: config3,
135202
135386
  directory
135203
135387
  } = input;
135388
+ const recipientSessionId = recipientMember.sessionId;
135204
135389
  if (recipientMember.pendingInjectedMessageIds.length > 0) {
135205
135390
  await releaseReservationSafely(reservation, {
135206
135391
  teamRunId,
135207
135392
  recipient: recipientName,
135208
135393
  messageId: message.messageId
135209
135394
  });
135395
+ if (recipientSessionId) {
135396
+ await enqueueFallbackMailboxWake({
135397
+ client: client3,
135398
+ recipientMember,
135399
+ recipientSessionId,
135400
+ directory,
135401
+ teamRunId,
135402
+ recipientName,
135403
+ messageId: message.messageId,
135404
+ config: config3
135405
+ });
135406
+ }
135210
135407
  return;
135211
135408
  }
135212
135409
  if (recipientMember.status !== "idle") {
@@ -135224,7 +135421,6 @@ async function deliverLiveToRecipient(input) {
135224
135421
  });
135225
135422
  return;
135226
135423
  }
135227
- const recipientSessionId = recipientMember.sessionId;
135228
135424
  if (!recipientSessionId) {
135229
135425
  log2("[team-mailbox] live delivery unavailable, falling back to inbox injection", {
135230
135426
  reason: "missing-session-id",
@@ -135285,6 +135481,16 @@ async function deliverLiveToRecipient(input) {
135285
135481
  recipient: recipientName,
135286
135482
  messageId: message.messageId
135287
135483
  });
135484
+ await enqueueFallbackMailboxWake({
135485
+ client: client3,
135486
+ recipientMember,
135487
+ recipientSessionId,
135488
+ directory,
135489
+ teamRunId,
135490
+ recipientName,
135491
+ messageId: message.messageId,
135492
+ config: config3
135493
+ });
135288
135494
  return;
135289
135495
  }
135290
135496
  await markLiveDeliveryAcceptedLike({