chatroom-cli 1.103.2 → 1.105.0

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.
package/dist/index.js CHANGED
@@ -29328,8 +29328,13 @@ var init_claude_model_variants = __esm(() => {
29328
29328
  {},
29329
29329
  ...CLAUDE_EFFORT_VALUES.map((effort) => ({ effort }))
29330
29330
  ];
29331
- CLAUDE_SPAWN_ALIASES = ["opus", "sonnet", "haiku"];
29331
+ CLAUDE_SPAWN_ALIASES = [];
29332
29332
  CLAUDE_CATALOG_BASE_MODEL_IDS = [
29333
+ "opus",
29334
+ "sonnet",
29335
+ "haiku",
29336
+ "claude-opus-5",
29337
+ "claude-sonnet-5",
29333
29338
  "claude-opus-4-8",
29334
29339
  "claude-opus-4-6",
29335
29340
  "claude-sonnet-4-6",
@@ -100823,6 +100828,24 @@ class AgentOperationalReadModel {
100823
100828
  }
100824
100829
  return changed;
100825
100830
  }
100831
+ applySignalPage(rows, removed) {
100832
+ const changed = [];
100833
+ for (const row of rows) {
100834
+ const key = roleKey(row.chatroomId, row.role);
100835
+ const prev = this.rows.get(key);
100836
+ if (!prev || prev.revisionKey !== row.revisionKey) {
100837
+ changed.push({ chatroomId: row.chatroomId, role: row.role });
100838
+ }
100839
+ this.rows.set(key, row);
100840
+ }
100841
+ for (const item of removed) {
100842
+ const key = roleKey(item.chatroomId, item.role);
100843
+ if (this.rows.has(key))
100844
+ changed.push(item);
100845
+ this.rows.delete(key);
100846
+ }
100847
+ return changed;
100848
+ }
100826
100849
  get(chatroomId, role) {
100827
100850
  return this.rows.get(roleKey(chatroomId, role));
100828
100851
  }
@@ -100836,9 +100859,11 @@ function snapshotKey(taskId, role) {
100836
100859
 
100837
100860
  class MachineTaskSnapshotState {
100838
100861
  snapshots = new Map;
100862
+ initialized = false;
100839
100863
  replace(snapshots) {
100840
100864
  this.snapshots.clear();
100841
100865
  this.upsert(snapshots);
100866
+ this.initialized = true;
100842
100867
  }
100843
100868
  applySignalPage(signals, snapshots) {
100844
100869
  const snapshotsByKey = new Map(snapshots.map((snapshot) => [
@@ -100859,6 +100884,13 @@ class MachineTaskSnapshotState {
100859
100884
  const roleLower = role.toLowerCase();
100860
100885
  return [...this.snapshots.values()].filter((snapshot) => snapshot.chatroomId === chatroomId && snapshot.agentConfig.role.toLowerCase() === roleLower);
100861
100886
  }
100887
+ isInitialized() {
100888
+ return this.initialized;
100889
+ }
100890
+ getForRole(chatroomId, role, taskId) {
100891
+ const snapshot = this.snapshots.get(snapshotKey(taskId, role));
100892
+ return snapshot?.chatroomId === chatroomId ? snapshot : null;
100893
+ }
100862
100894
  listAll() {
100863
100895
  return [...this.snapshots.values()];
100864
100896
  }
@@ -103195,6 +103227,27 @@ var init_native_harness_session_exit = __esm(() => {
103195
103227
  init_native_task_delivery_coordinator();
103196
103228
  });
103197
103229
 
103230
+ // src/daemon/entry/native-delivery/native-turn-end-inbox.ts
103231
+ function decideNativeTurnEndFromInbox(params) {
103232
+ const session2 = getNativeDeliverySession();
103233
+ if (!params.taskId || !session2)
103234
+ return "unknown";
103235
+ const { taskSnapshotState } = session2;
103236
+ if (!taskSnapshotState.isInitialized())
103237
+ return "unknown";
103238
+ const task = taskSnapshotState.getForRole(params.chatroomId, params.role, params.taskId);
103239
+ return task ? ACTIVE_TASK_DECISIONS[task.status] : "handoff-completed";
103240
+ }
103241
+ var ACTIVE_TASK_DECISIONS;
103242
+ var init_native_turn_end_inbox = __esm(() => {
103243
+ init_native_delivery_session_registry();
103244
+ ACTIVE_TASK_DECISIONS = {
103245
+ pending: "unknown",
103246
+ acknowledged: "unknown",
103247
+ in_progress: "needs-handoff-reminder"
103248
+ };
103249
+ });
103250
+
103198
103251
  // src/daemon/domain/entities/native-turn-phase.ts
103199
103252
  var init_native_turn_phase = () => {};
103200
103253
 
@@ -103659,6 +103712,25 @@ class AgentProcessManager {
103659
103712
  console.log(`[AgentProcessManager] ✅ Handled rapid resume storm for ${opts.role}`);
103660
103713
  return;
103661
103714
  }
103715
+ const inboxDecision = decideNativeTurnEndFromInbox({
103716
+ chatroomId: opts.chatroomId,
103717
+ role: opts.role,
103718
+ taskId: slot?.lastInFlightTaskId
103719
+ });
103720
+ if (inboxDecision === "needs-handoff-reminder") {
103721
+ await this.injectHarnessReminder(opts.chatroomId, opts.role, NATIVE_HANDOFF_REMINDER);
103722
+ console.log(`[AgentProcessManager] ⏩ Handoff reminder injected for ${opts.role} (inbox)`);
103723
+ return;
103724
+ }
103725
+ if (inboxDecision === "handoff-completed") {
103726
+ if (slot) {
103727
+ setNativeTurnPhase(slot, defaultNativeTurnPhase());
103728
+ this.clearLastInFlightTask(opts.chatroomId, opts.role);
103729
+ }
103730
+ notifyNativeTurnIdle({ chatroomId: opts.chatroomId, role: opts.role });
103731
+ console.log(`[AgentProcessManager] ✅ Native agent_end handled for ${opts.role} (inbox)`);
103732
+ return;
103733
+ }
103662
103734
  try {
103663
103735
  const result = await this.deps.backend.mutation(api.participants.handleNativeAgentEnd, {
103664
103736
  sessionId: this.deps.sessionId,
@@ -104989,6 +105061,7 @@ var init_agent_process_manager = __esm(() => {
104989
105061
  init_orphan_tracker();
104990
105062
  init_native_harness_session_exit();
104991
105063
  init_native_task_delivery_coordinator();
105064
+ init_native_turn_end_inbox();
104992
105065
  init_native_turn_phase2();
104993
105066
  init_native_spawn_presence();
104994
105067
  init_no_op_session_monitor();
@@ -116098,26 +116171,34 @@ async function stopCoordinatorForWorkingDir(coordinators, checkpointOutboxRegist
116098
116171
  await deltaOutboxRegistry?.stop(normalized);
116099
116172
  }
116100
116173
  async function drainPendingFileTreeReleaseRequests(session2, coordinators, checkpointOutboxRegistry, deltaOutboxRegistry) {
116101
- const releases = await session2.backend.query(api.workspaceFiles.getPendingFileTreeReleaseRequests, {
116102
- sessionId: session2.sessionId,
116103
- machineId: session2.machineId
116104
- });
116105
- if (!releases?.length)
116106
- return;
116107
- const releasesByDir = new Set;
116108
- for (const release of releases) {
116109
- releasesByDir.add(normalizeWorkingDirForLookup(release.workingDir));
116110
- }
116111
- for (const normalized of releasesByDir) {
116112
- await stopCoordinatorForWorkingDir(coordinators, checkpointOutboxRegistry, deltaOutboxRegistry, normalized).then(() => session2.backend.mutation(api.workspaceFiles.fulfillFileTreeReleaseRequest, {
116174
+ while (true) {
116175
+ const releases = await session2.backend.query(api.workspaceFiles.getPendingFileTreeReleaseRequests, {
116113
116176
  sessionId: session2.sessionId,
116114
- machineId: session2.machineId,
116115
- workingDir: normalized
116116
- })).then(() => {
116117
- console.log(`[${formatTimestamp()}] \uD83C\uDF33 File tree coordinator stopped: ${normalized}`);
116118
- }).catch((err) => {
116119
- logSubscriptionWarn(`File tree release failed for ${normalized}`, err);
116177
+ machineId: session2.machineId
116120
116178
  });
116179
+ if (!releases?.length)
116180
+ return;
116181
+ const releasesByDir = new Set;
116182
+ for (const release of releases) {
116183
+ releasesByDir.add(normalizeWorkingDirForLookup(release.workingDir));
116184
+ }
116185
+ let successCount = 0;
116186
+ for (const normalized of releasesByDir) {
116187
+ try {
116188
+ await stopCoordinatorForWorkingDir(coordinators, checkpointOutboxRegistry, deltaOutboxRegistry, normalized);
116189
+ await session2.backend.mutation(api.workspaceFiles.fulfillFileTreeReleaseRequest, {
116190
+ sessionId: session2.sessionId,
116191
+ machineId: session2.machineId,
116192
+ workingDir: normalized
116193
+ });
116194
+ console.log(`[${formatTimestamp()}] \uD83C\uDF33 File tree coordinator stopped: ${normalized}`);
116195
+ successCount++;
116196
+ } catch (err) {
116197
+ logSubscriptionWarn(`File tree release failed for ${normalized}`, err);
116198
+ }
116199
+ }
116200
+ if (successCount === 0)
116201
+ return;
116121
116202
  }
116122
116203
  }
116123
116204
  async function processOnePendingFileTreeRequest(session2, coordinators, ensureCoordinator, normalized, force, checkpointOutboxRegistry, deltaOutboxRegistry) {
@@ -117457,6 +117538,25 @@ var init_task_delivery_processor = __esm(() => {
117457
117538
  init_task_delivery_logic();
117458
117539
  });
117459
117540
 
117541
+ // src/daemon/infrastructure/agent-operational/ack-machine-operational-signals.ts
117542
+ async function ackMachineOperationalSignals(sessionDeps, machineId, throughSignalKey) {
117543
+ while (true) {
117544
+ const result = await sessionDeps.backend.mutation(api.machines.ackMachineOperationalSignals, {
117545
+ sessionId: sessionDeps.sessionId,
117546
+ machineId,
117547
+ throughSignalKey
117548
+ });
117549
+ if (!result.hasMore)
117550
+ return;
117551
+ if (result.deletedCount === 0) {
117552
+ throw new Error("Operational signal ack reported more work without progress");
117553
+ }
117554
+ }
117555
+ }
117556
+ var init_ack_machine_operational_signals = __esm(() => {
117557
+ init_api3();
117558
+ });
117559
+
117460
117560
  // src/daemon/infrastructure/agent-operational/enrich-snapshot-with-operational.ts
117461
117561
  function enrichSnapshotWithOperational(snapshot) {
117462
117562
  const op = getNativeDeliverySession()?.agentOperationalReadModel?.get(snapshot.chatroomId, snapshot.agentConfig.role);
@@ -117477,14 +117577,123 @@ var init_enrich_snapshot_with_operational = __esm(() => {
117477
117577
  init_native_delivery_session_registry();
117478
117578
  });
117479
117579
 
117480
- // src/daemon/infrastructure/agent-operational/subscribe-machine-agent-operational-status.ts
117481
- function subscribeMachineAgentOperationalStatus(client4, options, onRows) {
117482
- return client4.onUpdate(api.machines.subscribeMachineAgentOperationalStatus, { sessionId: options.sessionId, machineId: options.machineId }, (result) => {
117483
- if (Array.isArray(result))
117484
- onRows(result);
117580
+ // src/daemon/infrastructure/agent-operational/fetch-machine-agent-operational-status.ts
117581
+ async function fetchMachineAgentOperationalStatus(sessionDeps, machineId) {
117582
+ const result = await sessionDeps.backend.query(api.machines.listMachineAgentOperationalStatus, {
117583
+ sessionId: sessionDeps.sessionId,
117584
+ machineId
117585
+ });
117586
+ return result;
117587
+ }
117588
+ var init_fetch_machine_agent_operational_status = __esm(() => {
117589
+ init_api3();
117590
+ });
117591
+
117592
+ // src/daemon/infrastructure/agent-operational/operational-inbox.ts
117593
+ function operationalSignalCursorAt(timestamp) {
117594
+ return `${String(Math.max(0, Math.floor(timestamp))).padStart(16, "0")}:`;
117595
+ }
117596
+ function abortError() {
117597
+ const error51 = new Error("Operational inbox stopped");
117598
+ error51.name = "AbortError";
117599
+ return error51;
117600
+ }
117601
+ function throwIfAborted(signal) {
117602
+ if (signal?.aborted)
117603
+ throw abortError();
117604
+ }
117605
+ function waitForOperationalSignalPage(options, afterSignalKey) {
117606
+ return new Promise((resolve8, reject) => {
117607
+ let unsubscribe;
117608
+ let settled = false;
117609
+ const cleanup = () => {
117610
+ unsubscribe?.();
117611
+ unsubscribe = undefined;
117612
+ options.signal?.removeEventListener("abort", onAbort);
117613
+ };
117614
+ const settle2 = (fn2) => {
117615
+ if (settled)
117616
+ return;
117617
+ settled = true;
117618
+ cleanup();
117619
+ fn2();
117620
+ };
117621
+ const onAbort = () => {
117622
+ settle2(() => reject(abortError()));
117623
+ };
117624
+ options.signal?.addEventListener("abort", onAbort, { once: true });
117625
+ try {
117626
+ throwIfAborted(options.signal);
117627
+ } catch (error51) {
117628
+ settle2(() => reject(error51));
117629
+ return;
117630
+ }
117631
+ unsubscribe = options.client.onUpdate(api.machines.subscribeMachineOperationalSignalsSince, {
117632
+ sessionId: options.sessionId,
117633
+ machineId: options.machineId,
117634
+ afterKey: afterSignalKey,
117635
+ limit: options.signalPageLimit ?? DEFAULT_SIGNAL_PAGE_LIMIT
117636
+ }, (result) => {
117637
+ if (!result || typeof result !== "object")
117638
+ return;
117639
+ const page = result;
117640
+ const items = page.items;
117641
+ const highKey = page.highKey;
117642
+ if (!items?.length || !highKey)
117643
+ return;
117644
+ settle2(() => resolve8({
117645
+ items,
117646
+ afterSignalKey,
117647
+ highSignalKey: highKey
117648
+ }));
117649
+ }, (error51) => {
117650
+ settle2(() => reject(error51));
117651
+ });
117485
117652
  });
117486
117653
  }
117487
- var init_subscribe_machine_agent_operational_status = __esm(() => {
117654
+ async function* createOperationalSignalIterator(options) {
117655
+ let afterSignalKey = options.initialAfterSignalKey ?? operationalSignalCursorAt(options.serviceStartedAt ?? Date.now());
117656
+ while (!options.signal?.aborted) {
117657
+ const page = await waitForOperationalSignalPage(options, afterSignalKey);
117658
+ yield page;
117659
+ afterSignalKey = page.highSignalKey;
117660
+ }
117661
+ }
117662
+ async function fetchRowsForSignalPage(options, page) {
117663
+ const rows = [];
117664
+ const removed = [];
117665
+ let afterSignalKey = page.afterSignalKey;
117666
+ while (true) {
117667
+ throwIfAborted(options.signal);
117668
+ const result = await options.client.query(api.machines.listOperationalStatusForMachineSignalRange, {
117669
+ sessionId: options.sessionId,
117670
+ machineId: options.machineId,
117671
+ afterSignalKey,
117672
+ throughSignalKey: page.highSignalKey,
117673
+ limit: options.operationalPageLimit ?? DEFAULT_OPERATIONAL_PAGE_LIMIT
117674
+ });
117675
+ rows.push(...result.rows);
117676
+ removed.push(...result.removed);
117677
+ if (!result.hasMore || !result.nextSignalKey)
117678
+ break;
117679
+ afterSignalKey = result.nextSignalKey;
117680
+ }
117681
+ return { rows, removed };
117682
+ }
117683
+ async function runOperationalInbox(options, onUpdate) {
117684
+ for await (const page of createOperationalSignalIterator(options)) {
117685
+ const hydrated = await fetchRowsForSignalPage(options, page);
117686
+ await onUpdate({
117687
+ signals: page.items,
117688
+ rows: hydrated.rows,
117689
+ removed: hydrated.removed,
117690
+ afterSignalKey: page.afterSignalKey,
117691
+ throughSignalKey: page.highSignalKey
117692
+ });
117693
+ }
117694
+ }
117695
+ var DEFAULT_SIGNAL_PAGE_LIMIT = 100, DEFAULT_OPERATIONAL_PAGE_LIMIT = 500;
117696
+ var init_operational_inbox = __esm(() => {
117488
117697
  init_api3();
117489
117698
  });
117490
117699
 
@@ -117669,14 +117878,14 @@ var init_task_inbox_delivery = __esm(() => {
117669
117878
  function taskSignalCursorAt(timestamp) {
117670
117879
  return `${String(Math.max(0, Math.floor(timestamp))).padStart(16, "0")}:`;
117671
117880
  }
117672
- function abortError() {
117881
+ function abortError2() {
117673
117882
  const error51 = new Error("Task inbox stopped");
117674
117883
  error51.name = "AbortError";
117675
117884
  return error51;
117676
117885
  }
117677
- function throwIfAborted(signal) {
117886
+ function throwIfAborted2(signal) {
117678
117887
  if (signal?.aborted)
117679
- throw abortError();
117888
+ throw abortError2();
117680
117889
  }
117681
117890
  function waitForTaskSignalPage(options, afterSignalKey) {
117682
117891
  return new Promise((resolve8, reject) => {
@@ -117695,11 +117904,11 @@ function waitForTaskSignalPage(options, afterSignalKey) {
117695
117904
  fn2();
117696
117905
  };
117697
117906
  const onAbort = () => {
117698
- settle2(() => reject(abortError()));
117907
+ settle2(() => reject(abortError2()));
117699
117908
  };
117700
117909
  options.signal?.addEventListener("abort", onAbort, { once: true });
117701
117910
  try {
117702
- throwIfAborted(options.signal);
117911
+ throwIfAborted2(options.signal);
117703
117912
  } catch (error51) {
117704
117913
  settle2(() => reject(error51));
117705
117914
  return;
@@ -117708,7 +117917,7 @@ function waitForTaskSignalPage(options, afterSignalKey) {
117708
117917
  sessionId: options.sessionId,
117709
117918
  machineId: options.machineId,
117710
117919
  afterKey: afterSignalKey,
117711
- limit: options.signalPageLimit ?? DEFAULT_SIGNAL_PAGE_LIMIT
117920
+ limit: options.signalPageLimit ?? DEFAULT_SIGNAL_PAGE_LIMIT2
117712
117921
  }, (result) => {
117713
117922
  if (!result || typeof result !== "object")
117714
117923
  return;
@@ -117739,7 +117948,7 @@ async function fetchSnapshotsForSignalPage(options, page) {
117739
117948
  const snapshots = [];
117740
117949
  let afterSignalKey = page.afterSignalKey;
117741
117950
  while (true) {
117742
- throwIfAborted(options.signal);
117951
+ throwIfAborted2(options.signal);
117743
117952
  const result = await options.client.query(api.tasks.listTasksForMachineSignalRange, {
117744
117953
  sessionId: options.sessionId,
117745
117954
  machineId: options.machineId,
@@ -117765,7 +117974,7 @@ async function runTaskInbox(options, onUpdate) {
117765
117974
  });
117766
117975
  }
117767
117976
  }
117768
- var DEFAULT_SIGNAL_PAGE_LIMIT = 100, DEFAULT_TASK_PAGE_LIMIT = 500;
117977
+ var DEFAULT_SIGNAL_PAGE_LIMIT2 = 100, DEFAULT_TASK_PAGE_LIMIT = 500;
117769
117978
  var init_task = __esm(() => {
117770
117979
  init_api3();
117771
117980
  });
@@ -117804,11 +118013,28 @@ async function runInboxLoopWithRestart(options, onUpdate, isStopped) {
117804
118013
  }
117805
118014
  }
117806
118015
  }
118016
+ async function runOperationalInboxLoopWithRestart(options, onUpdate, isStopped) {
118017
+ let backoffMs = INBOX_RESTART_INITIAL_MS;
118018
+ while (!isStopped()) {
118019
+ try {
118020
+ await runOperationalInbox(options, onUpdate);
118021
+ return;
118022
+ } catch (error51) {
118023
+ if (isStopped() || isAbortError2(error51))
118024
+ return;
118025
+ console.warn(`[OperationalInbox] loop error, restarting in ${backoffMs}ms:`, error51);
118026
+ await new Promise((resolve8) => setTimeout(resolve8, backoffMs));
118027
+ backoffMs = Math.min(backoffMs * 2, INBOX_RESTART_MAX_MS);
118028
+ }
118029
+ }
118030
+ }
117807
118031
  var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInboxEffect = (wsClient2) => exports_Effect.gen(function* () {
117808
118032
  const session2 = yield* DaemonSessionService;
117809
118033
  const agentMgr = yield* DaemonAgentProcessManagerService;
117810
118034
  const lifecycleOutboxService = yield* AgentLifecycleOutboxService;
117811
- const lifecycleOutbox = { enqueue: (fact) => exports_Effect.runPromise(lifecycleOutboxService.enqueue(fact)) };
118035
+ const lifecycleOutbox = {
118036
+ enqueue: (fact) => exports_Effect.runPromise(lifecycleOutboxService.enqueue(fact))
118037
+ };
117812
118038
  const effectContext2 = yield* exports_Effect.context();
117813
118039
  const runtime4 = yield* exports_Effect.runtime();
117814
118040
  const sessionDeps = {
@@ -117827,6 +118053,13 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
117827
118053
  inboxType: "task",
117828
118054
  scopeKey: session2.machineId
117829
118055
  });
118056
+ const persistedOperational = inboxStore.get({
118057
+ inboxType: "operational",
118058
+ scopeKey: session2.machineId
118059
+ });
118060
+ const serviceStartedAt = Date.now();
118061
+ const persistedOperationalKey = persistedOperational?.state.afterSignalKey;
118062
+ const initialOperationalKey = persistedOperationalKey ?? operationalSignalCursorAt(serviceStartedAt);
117830
118063
  const abort = new AbortController;
117831
118064
  let stopped = false;
117832
118065
  const taskSnapshotState = new MachineTaskSnapshotState;
@@ -117848,7 +118081,7 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
117848
118081
  client: wsClient2,
117849
118082
  sessionId: session2.sessionId,
117850
118083
  machineId: session2.machineId,
117851
- serviceStartedAt: Date.now(),
118084
+ serviceStartedAt,
117852
118085
  initialAfterSignalKey: persisted?.state.afterSignalKey,
117853
118086
  signal: abort.signal
117854
118087
  };
@@ -117869,6 +118102,24 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
117869
118102
  inboxUpdateInFlight = false;
117870
118103
  }
117871
118104
  };
118105
+ const bootstrapSucceeded = yield* exports_Effect.tryPromise(async () => {
118106
+ const rows = await fetchMachineAgentOperationalStatus(sessionDeps, session2.machineId);
118107
+ agentOperationalReadModel.replace(rows);
118108
+ return true;
118109
+ }).pipe(exports_Effect.catchAll((error51) => {
118110
+ console.warn("[OperationalInbox] bootstrap failed:", error51);
118111
+ return exports_Effect.succeed(false);
118112
+ }));
118113
+ if (persistedOperationalKey) {
118114
+ ackMachineOperationalSignals(sessionDeps, session2.machineId, persistedOperationalKey).catch((error51) => console.warn("[OperationalInbox] startup signal cleanup failed:", error51));
118115
+ } else if (bootstrapSucceeded) {
118116
+ try {
118117
+ inboxStore.save({ inboxType: "operational", scopeKey: session2.machineId }, { afterSignalKey: initialOperationalKey });
118118
+ ackMachineOperationalSignals(sessionDeps, session2.machineId, initialOperationalKey).catch((error51) => console.warn("[OperationalInbox] startup signal cleanup failed:", error51));
118119
+ } catch (error51) {
118120
+ console.warn("[OperationalInbox] failed to persist bootstrap baseline:", error51);
118121
+ }
118122
+ }
117872
118123
  yield* exports_Effect.tryPromise(() => bootstrapMachineAssignedTaskSnapshots({
117873
118124
  sessionDeps,
117874
118125
  runtime: runtime4,
@@ -117881,19 +118132,32 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
117881
118132
  console.warn("[TaskInbox] bootstrap failed:", error51);
117882
118133
  return exports_Effect.void;
117883
118134
  }));
117884
- const unsubscribeOperational = subscribeMachineAgentOperationalStatus(wsClient2, {
118135
+ const operationalInboxOptions = {
118136
+ client: wsClient2,
117885
118137
  sessionId: session2.sessionId,
117886
118138
  machineId: session2.machineId,
118139
+ serviceStartedAt,
118140
+ initialAfterSignalKey: initialOperationalKey,
117887
118141
  signal: abort.signal
117888
- }, (rows) => {
117889
- if (stopped)
117890
- return;
117891
- const changed = agentOperationalReadModel.replace(rows);
117892
- const snapshots = changed.flatMap(({ chatroomId, role }) => taskSnapshotState.listForRole(chatroomId, role));
117893
- if (snapshots.length === 0)
117894
- return;
117895
- processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, session2.machineId, "operational-status", { snapshots: enrichSnapshotsWithOperational(snapshots) }).catch((error51) => console.warn("[TaskInbox] operational-status reconcile failed:", error51));
117896
- }) ?? (() => {});
118142
+ };
118143
+ const operationalInboxHandler = async (update6) => {
118144
+ inboxUpdateInFlight = true;
118145
+ try {
118146
+ const changed = agentOperationalReadModel.applySignalPage(update6.rows, update6.removed);
118147
+ const snapshots = changed.flatMap(({ chatroomId, role }) => taskSnapshotState.listForRole(chatroomId, role));
118148
+ if (snapshots.length > 0) {
118149
+ await processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, session2.machineId, "operational-status", { snapshots: enrichSnapshotsWithOperational(snapshots) });
118150
+ }
118151
+ inboxStore.save({ inboxType: "operational", scopeKey: session2.machineId }, { afterSignalKey: update6.throughSignalKey });
118152
+ try {
118153
+ await ackMachineOperationalSignals(sessionDeps, session2.machineId, update6.throughSignalKey);
118154
+ } catch (error51) {
118155
+ console.warn("[OperationalInbox] signal cleanup failed:", error51);
118156
+ }
118157
+ } finally {
118158
+ inboxUpdateInFlight = false;
118159
+ }
118160
+ };
117897
118161
  const reconcileTimer = setInterval(() => {
117898
118162
  if (stopped || inboxUpdateInFlight || reconcileInFlight)
117899
118163
  return;
@@ -117905,10 +118169,10 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
117905
118169
  });
117906
118170
  }, NATIVE_DELIVERY_RECONCILE_MS);
117907
118171
  runInboxLoopWithRestart(inboxOptions, inboxHandler, () => stopped);
118172
+ runOperationalInboxLoopWithRestart(operationalInboxOptions, operationalInboxHandler, () => stopped);
117908
118173
  return {
117909
118174
  stop() {
117910
118175
  stopped = true;
117911
- unsubscribeOperational();
117912
118176
  abort.abort();
117913
118177
  clearInterval(reconcileTimer);
117914
118178
  unregisterNativeDeliverySession();
@@ -117924,8 +118188,10 @@ var init_task_inbox_runtime = __esm(() => {
117924
118188
  init_native_delivery_session_registry();
117925
118189
  init_task_delivery_processor();
117926
118190
  init_task_delivery_logic();
118191
+ init_ack_machine_operational_signals();
117927
118192
  init_enrich_snapshot_with_operational();
117928
- init_subscribe_machine_agent_operational_status();
118193
+ init_fetch_machine_agent_operational_status();
118194
+ init_operational_inbox();
117929
118195
  init_fetch_machine_assigned_task_snapshots();
117930
118196
  init_inbox();
117931
118197
  init_task_inbox_delivery();
@@ -118428,6 +118694,9 @@ function createDaemonRuntime(deps) {
118428
118694
  break;
118429
118695
  }
118430
118696
  });
118697
+ fileTreeHandle.drainPendingFileTreeReleaseRequests().catch((err) => {
118698
+ console.warn(`[${formatTimestamp()}] ⚠️ Startup file-tree release drain failed: ${getErrorMessage(err)}`);
118699
+ });
118431
118700
  workspaceListSubscriptionHandle = yield* startWorkspaceListSubscriptionEffect();
118432
118701
  registerWorkspaceGitInboundHandler(async (event) => {
118433
118702
  switch (event.type) {
@@ -119155,31 +119424,22 @@ var init_file_content_request = __esm(() => {
119155
119424
  });
119156
119425
 
119157
119426
  // src/daemon/infrastructure/convex/subscribers/file-tree-release-request.ts
119158
- function requestId(req) {
119159
- if (req._id == null)
119160
- return "unknown";
119161
- return typeof req._id === "string" ? req._id : req._id.toString();
119162
- }
119163
- function pendingReleasesSnapshot(requests) {
119164
- return requests.filter((req) => req != null && typeof req === "object").map((req) => `${requestId(req)}:${req.workingDir ?? ""}:${req.updatedAt ?? 0}`).sort().join("|");
119165
- }
119166
119427
  function startFileTreeReleaseRequestSubscriber(deps, onEvent) {
119167
- let lastSnapshot = "";
119168
- const unsub = deps.wsClient.onUpdate(api.workspaceFiles.getPendingFileTreeReleaseRequests, { sessionId: deps.sessionId, machineId: deps.machineId }, (requests) => {
119169
- if (!requests?.length) {
119170
- lastSnapshot = "";
119428
+ let lastRevision = null;
119429
+ const maybeWake = (revision, requestId) => {
119430
+ if (lastRevision === revision)
119171
119431
  return;
119172
- }
119173
- const snapshot = pendingReleasesSnapshot(requests);
119174
- if (!snapshot || snapshot === lastSnapshot)
119175
- return;
119176
- lastSnapshot = snapshot;
119177
- const first = requests.find((req) => req != null && typeof req === "object");
119178
- if (!first)
119432
+ lastRevision = revision;
119433
+ onEvent({ type: "file-tree.release", requestId });
119434
+ };
119435
+ const unsub = deps.wsClient.onUpdate(api.workspaceFiles.subscribeMachineFileTreeReleaseHead, { sessionId: deps.sessionId, machineId: deps.machineId }, (head5) => {
119436
+ if (!head5) {
119437
+ lastRevision = null;
119179
119438
  return;
119180
- onEvent({ type: "file-tree.release", requestId: requestId(first) });
119439
+ }
119440
+ maybeWake(head5.revision, `rev-${head5.revision}`);
119181
119441
  }, (err) => {
119182
- console.warn(`[daemon] file-tree-release subscriber error: ${err instanceof Error ? err.message : String(err)}`);
119442
+ console.warn(`[daemon] file-tree-release head subscriber error: ${err instanceof Error ? err.message : String(err)}`);
119183
119443
  });
119184
119444
  return {
119185
119445
  async stop() {
@@ -119192,13 +119452,13 @@ var init_file_tree_release_request = __esm(() => {
119192
119452
  });
119193
119453
 
119194
119454
  // src/daemon/infrastructure/convex/subscribers/file-tree-request.ts
119195
- function requestId2(req) {
119455
+ function requestId(req) {
119196
119456
  if (req._id == null)
119197
119457
  return "unknown";
119198
119458
  return typeof req._id === "string" ? req._id : req._id.toString();
119199
119459
  }
119200
119460
  function pendingRequestsSnapshot(requests) {
119201
- return requests.filter((req) => req != null && typeof req === "object").map((req) => `${requestId2(req)}:${req.workingDir ?? ""}:${req.force ? "1" : "0"}:${req.updatedAt ?? 0}`).sort().join("|");
119461
+ return requests.filter((req) => req != null && typeof req === "object").map((req) => `${requestId(req)}:${req.workingDir ?? ""}:${req.force ? "1" : "0"}:${req.updatedAt ?? 0}`).sort().join("|");
119202
119462
  }
119203
119463
  function startFileTreeRequestSubscriber(deps, onEvent) {
119204
119464
  let lastSnapshot = "";
@@ -119214,7 +119474,7 @@ function startFileTreeRequestSubscriber(deps, onEvent) {
119214
119474
  const first = requests.find((req) => req != null && typeof req === "object");
119215
119475
  if (!first)
119216
119476
  return;
119217
- onEvent({ type: "file-tree.request", requestId: requestId2(first) });
119477
+ onEvent({ type: "file-tree.request", requestId: requestId(first) });
119218
119478
  }, (err) => {
119219
119479
  console.warn(`[daemon] file-tree-request subscriber error: ${err instanceof Error ? err.message : String(err)}`);
119220
119480
  });
@@ -119251,7 +119511,7 @@ var init_file_write_request = __esm(() => {
119251
119511
  });
119252
119512
 
119253
119513
  // src/daemon/infrastructure/convex/subscribers/git-request.ts
119254
- function requestId3(req) {
119514
+ function requestId2(req) {
119255
119515
  return typeof req._id === "string" ? req._id : req._id.toString();
119256
119516
  }
119257
119517
  function startGitRequestSubscriber(deps, onEvent) {
@@ -119262,7 +119522,7 @@ function startGitRequestSubscriber(deps, onEvent) {
119262
119522
  for (const req of requests) {
119263
119523
  if (req == null || typeof req !== "object" || !("_id" in req))
119264
119524
  continue;
119265
- const id3 = requestId3(req);
119525
+ const id3 = requestId2(req);
119266
119526
  if (seen.has(id3))
119267
119527
  continue;
119268
119528
  seen.add(id3);
@@ -132104,19 +132364,19 @@ var require_cluster_adapter = __commonJS((exports) => {
132104
132364
  }
132105
132365
  onResponse(response) {
132106
132366
  var _a4, _b2;
132107
- const requestId4 = response.data.requestId;
132108
- debug13("[%s] received response %s to request %s", this.uid, response.type, requestId4);
132367
+ const requestId3 = response.data.requestId;
132368
+ debug13("[%s] received response %s to request %s", this.uid, response.type, requestId3);
132109
132369
  switch (response.type) {
132110
132370
  case MessageType.BROADCAST_CLIENT_COUNT: {
132111
- (_a4 = this.ackRequests.get(requestId4)) === null || _a4 === undefined || _a4.clientCountCallback(response.data.clientCount);
132371
+ (_a4 = this.ackRequests.get(requestId3)) === null || _a4 === undefined || _a4.clientCountCallback(response.data.clientCount);
132112
132372
  break;
132113
132373
  }
132114
132374
  case MessageType.BROADCAST_ACK: {
132115
- (_b2 = this.ackRequests.get(requestId4)) === null || _b2 === undefined || _b2.ack(response.data.packet);
132375
+ (_b2 = this.ackRequests.get(requestId3)) === null || _b2 === undefined || _b2.ack(response.data.packet);
132116
132376
  break;
132117
132377
  }
132118
132378
  case MessageType.FETCH_SOCKETS_RESPONSE: {
132119
- const request2 = this.requests.get(requestId4);
132379
+ const request2 = this.requests.get(requestId3);
132120
132380
  if (!request2) {
132121
132381
  return;
132122
132382
  }
@@ -132125,12 +132385,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132125
132385
  if (request2.current === request2.expected) {
132126
132386
  clearTimeout(request2.timeout);
132127
132387
  request2.resolve(request2.responses);
132128
- this.requests.delete(requestId4);
132388
+ this.requests.delete(requestId3);
132129
132389
  }
132130
132390
  break;
132131
132391
  }
132132
132392
  case MessageType.SERVER_SIDE_EMIT_RESPONSE: {
132133
- const request2 = this.requests.get(requestId4);
132393
+ const request2 = this.requests.get(requestId3);
132134
132394
  if (!request2) {
132135
132395
  return;
132136
132396
  }
@@ -132139,7 +132399,7 @@ var require_cluster_adapter = __commonJS((exports) => {
132139
132399
  if (request2.current === request2.expected) {
132140
132400
  clearTimeout(request2.timeout);
132141
132401
  request2.resolve(null, request2.responses);
132142
- this.requests.delete(requestId4);
132402
+ this.requests.delete(requestId3);
132143
132403
  }
132144
132404
  break;
132145
132405
  }
@@ -132182,8 +132442,8 @@ var require_cluster_adapter = __commonJS((exports) => {
132182
132442
  var _a4;
132183
132443
  const onlyLocal = (_a4 = opts === null || opts === undefined ? undefined : opts.flags) === null || _a4 === undefined ? undefined : _a4.local;
132184
132444
  if (!onlyLocal) {
132185
- const requestId4 = randomId();
132186
- this.ackRequests.set(requestId4, {
132445
+ const requestId3 = randomId();
132446
+ this.ackRequests.set(requestId3, {
132187
132447
  clientCountCallback,
132188
132448
  ack
132189
132449
  });
@@ -132191,12 +132451,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132191
132451
  type: MessageType.BROADCAST,
132192
132452
  data: {
132193
132453
  packet,
132194
- requestId: requestId4,
132454
+ requestId: requestId3,
132195
132455
  opts: encodeOptions(opts)
132196
132456
  }
132197
132457
  });
132198
132458
  setTimeout(() => {
132199
- this.ackRequests.delete(requestId4);
132459
+ this.ackRequests.delete(requestId3);
132200
132460
  }, opts.flags.timeout);
132201
132461
  }
132202
132462
  super.broadcastWithAck(packet, opts, clientCountCallback, ack);
@@ -132265,13 +132525,13 @@ var require_cluster_adapter = __commonJS((exports) => {
132265
132525
  if (((_a4 = opts.flags) === null || _a4 === undefined ? undefined : _a4.local) || expectedResponseCount <= 0) {
132266
132526
  return localSockets;
132267
132527
  }
132268
- const requestId4 = randomId();
132528
+ const requestId3 = randomId();
132269
132529
  return new Promise((resolve8, reject) => {
132270
132530
  const timeout3 = setTimeout(() => {
132271
- const storedRequest2 = this.requests.get(requestId4);
132531
+ const storedRequest2 = this.requests.get(requestId3);
132272
132532
  if (storedRequest2) {
132273
132533
  reject(new Error(`timeout reached: only ${storedRequest2.current} responses received out of ${storedRequest2.expected}`));
132274
- this.requests.delete(requestId4);
132534
+ this.requests.delete(requestId3);
132275
132535
  }
132276
132536
  }, opts.flags.timeout || DEFAULT_TIMEOUT);
132277
132537
  const storedRequest = {
@@ -132282,12 +132542,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132282
132542
  expected: expectedResponseCount,
132283
132543
  responses: localSockets
132284
132544
  };
132285
- this.requests.set(requestId4, storedRequest);
132545
+ this.requests.set(requestId3, storedRequest);
132286
132546
  this.publish({
132287
132547
  type: MessageType.FETCH_SOCKETS,
132288
132548
  data: {
132289
132549
  opts: encodeOptions(opts),
132290
- requestId: requestId4
132550
+ requestId: requestId3
132291
132551
  }
132292
132552
  });
132293
132553
  });
@@ -132308,12 +132568,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132308
132568
  if (expectedResponseCount <= 0) {
132309
132569
  return ack(null, []);
132310
132570
  }
132311
- const requestId4 = randomId();
132571
+ const requestId3 = randomId();
132312
132572
  const timeout3 = setTimeout(() => {
132313
- const storedRequest2 = this.requests.get(requestId4);
132573
+ const storedRequest2 = this.requests.get(requestId3);
132314
132574
  if (storedRequest2) {
132315
132575
  ack(new Error(`timeout reached: only ${storedRequest2.current} responses received out of ${storedRequest2.expected}`), storedRequest2.responses);
132316
- this.requests.delete(requestId4);
132576
+ this.requests.delete(requestId3);
132317
132577
  }
132318
132578
  }, DEFAULT_TIMEOUT);
132319
132579
  const storedRequest = {
@@ -132324,11 +132584,11 @@ var require_cluster_adapter = __commonJS((exports) => {
132324
132584
  expected: expectedResponseCount,
132325
132585
  responses: []
132326
132586
  };
132327
- this.requests.set(requestId4, storedRequest);
132587
+ this.requests.set(requestId3, storedRequest);
132328
132588
  this.publish({
132329
132589
  type: MessageType.SERVER_SIDE_EMIT,
132330
132590
  data: {
132331
- requestId: requestId4,
132591
+ requestId: requestId3,
132332
132592
  packet
132333
132593
  }
132334
132594
  });
@@ -132445,12 +132705,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132445
132705
  if (expectedResponseCount <= 0) {
132446
132706
  return ack(null, []);
132447
132707
  }
132448
- const requestId4 = randomId();
132708
+ const requestId3 = randomId();
132449
132709
  const timeout3 = setTimeout(() => {
132450
- const storedRequest2 = this.customRequests.get(requestId4);
132710
+ const storedRequest2 = this.customRequests.get(requestId3);
132451
132711
  if (storedRequest2) {
132452
132712
  ack(new Error(`timeout reached: missing ${storedRequest2.missingUids.size} responses`), storedRequest2.responses);
132453
- this.customRequests.delete(requestId4);
132713
+ this.customRequests.delete(requestId3);
132454
132714
  }
132455
132715
  }, DEFAULT_TIMEOUT);
132456
132716
  const storedRequest = {
@@ -132460,11 +132720,11 @@ var require_cluster_adapter = __commonJS((exports) => {
132460
132720
  missingUids: new Set([...this.nodesMap.keys()]),
132461
132721
  responses: []
132462
132722
  };
132463
- this.customRequests.set(requestId4, storedRequest);
132723
+ this.customRequests.set(requestId3, storedRequest);
132464
132724
  this.publish({
132465
132725
  type: MessageType.SERVER_SIDE_EMIT,
132466
132726
  data: {
132467
- requestId: requestId4,
132727
+ requestId: requestId3,
132468
132728
  packet
132469
132729
  }
132470
132730
  });
@@ -132485,13 +132745,13 @@ var require_cluster_adapter = __commonJS((exports) => {
132485
132745
  if (((_a4 = opts.flags) === null || _a4 === undefined ? undefined : _a4.local) || expectedResponseCount <= 0) {
132486
132746
  return localSockets;
132487
132747
  }
132488
- const requestId4 = randomId();
132748
+ const requestId3 = randomId();
132489
132749
  return new Promise((resolve8, reject) => {
132490
132750
  const timeout3 = setTimeout(() => {
132491
- const storedRequest2 = this.customRequests.get(requestId4);
132751
+ const storedRequest2 = this.customRequests.get(requestId3);
132492
132752
  if (storedRequest2) {
132493
132753
  reject(new Error(`timeout reached: missing ${storedRequest2.missingUids.size} responses`));
132494
- this.customRequests.delete(requestId4);
132754
+ this.customRequests.delete(requestId3);
132495
132755
  }
132496
132756
  }, opts.flags.timeout || DEFAULT_TIMEOUT);
132497
132757
  const storedRequest = {
@@ -132501,22 +132761,22 @@ var require_cluster_adapter = __commonJS((exports) => {
132501
132761
  missingUids: new Set([...this.nodesMap.keys()]),
132502
132762
  responses: localSockets
132503
132763
  };
132504
- this.customRequests.set(requestId4, storedRequest);
132764
+ this.customRequests.set(requestId3, storedRequest);
132505
132765
  this.publish({
132506
132766
  type: MessageType.FETCH_SOCKETS,
132507
132767
  data: {
132508
132768
  opts: encodeOptions(opts),
132509
- requestId: requestId4
132769
+ requestId: requestId3
132510
132770
  }
132511
132771
  });
132512
132772
  });
132513
132773
  }
132514
132774
  onResponse(response) {
132515
- const requestId4 = response.data.requestId;
132516
- debug13("[%s] received response %s to request %s", this.uid, response.type, requestId4);
132775
+ const requestId3 = response.data.requestId;
132776
+ debug13("[%s] received response %s to request %s", this.uid, response.type, requestId3);
132517
132777
  switch (response.type) {
132518
132778
  case MessageType.FETCH_SOCKETS_RESPONSE: {
132519
- const request2 = this.customRequests.get(requestId4);
132779
+ const request2 = this.customRequests.get(requestId3);
132520
132780
  if (!request2) {
132521
132781
  return;
132522
132782
  }
@@ -132525,12 +132785,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132525
132785
  if (request2.missingUids.size === 0) {
132526
132786
  clearTimeout(request2.timeout);
132527
132787
  request2.resolve(request2.responses);
132528
- this.customRequests.delete(requestId4);
132788
+ this.customRequests.delete(requestId3);
132529
132789
  }
132530
132790
  break;
132531
132791
  }
132532
132792
  case MessageType.SERVER_SIDE_EMIT_RESPONSE: {
132533
- const request2 = this.customRequests.get(requestId4);
132793
+ const request2 = this.customRequests.get(requestId3);
132534
132794
  if (!request2) {
132535
132795
  return;
132536
132796
  }
@@ -132539,7 +132799,7 @@ var require_cluster_adapter = __commonJS((exports) => {
132539
132799
  if (request2.missingUids.size === 0) {
132540
132800
  clearTimeout(request2.timeout);
132541
132801
  request2.resolve(null, request2.responses);
132542
- this.customRequests.delete(requestId4);
132802
+ this.customRequests.delete(requestId3);
132543
132803
  }
132544
132804
  break;
132545
132805
  }
@@ -132548,7 +132808,7 @@ var require_cluster_adapter = __commonJS((exports) => {
132548
132808
  }
132549
132809
  }
132550
132810
  removeNode(uid) {
132551
- this.customRequests.forEach((request2, requestId4) => {
132811
+ this.customRequests.forEach((request2, requestId3) => {
132552
132812
  request2.missingUids.delete(uid);
132553
132813
  if (request2.missingUids.size === 0) {
132554
132814
  clearTimeout(request2.timeout);
@@ -132557,7 +132817,7 @@ var require_cluster_adapter = __commonJS((exports) => {
132557
132817
  } else if (request2.type === MessageType.SERVER_SIDE_EMIT) {
132558
132818
  request2.resolve(null, request2.responses);
132559
132819
  }
132560
- this.customRequests.delete(requestId4);
132820
+ this.customRequests.delete(requestId3);
132561
132821
  }
132562
132822
  });
132563
132823
  this.nodesMap.delete(uid);
@@ -135131,4 +135391,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
135131
135391
  });
135132
135392
  program2.parse();
135133
135393
 
135134
- //# debugId=56DD8E367644E33A64756E2164756E21
135394
+ //# debugId=540831143AEEA0CF64756E2164756E21