chatroom-cli 1.104.1 → 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
@@ -100828,6 +100828,24 @@ class AgentOperationalReadModel {
100828
100828
  }
100829
100829
  return changed;
100830
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
+ }
100831
100849
  get(chatroomId, role) {
100832
100850
  return this.rows.get(roleKey(chatroomId, role));
100833
100851
  }
@@ -116153,26 +116171,34 @@ async function stopCoordinatorForWorkingDir(coordinators, checkpointOutboxRegist
116153
116171
  await deltaOutboxRegistry?.stop(normalized);
116154
116172
  }
116155
116173
  async function drainPendingFileTreeReleaseRequests(session2, coordinators, checkpointOutboxRegistry, deltaOutboxRegistry) {
116156
- const releases = await session2.backend.query(api.workspaceFiles.getPendingFileTreeReleaseRequests, {
116157
- sessionId: session2.sessionId,
116158
- machineId: session2.machineId
116159
- });
116160
- if (!releases?.length)
116161
- return;
116162
- const releasesByDir = new Set;
116163
- for (const release of releases) {
116164
- releasesByDir.add(normalizeWorkingDirForLookup(release.workingDir));
116165
- }
116166
- for (const normalized of releasesByDir) {
116167
- 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, {
116168
116176
  sessionId: session2.sessionId,
116169
- machineId: session2.machineId,
116170
- workingDir: normalized
116171
- })).then(() => {
116172
- console.log(`[${formatTimestamp()}] \uD83C\uDF33 File tree coordinator stopped: ${normalized}`);
116173
- }).catch((err) => {
116174
- logSubscriptionWarn(`File tree release failed for ${normalized}`, err);
116177
+ machineId: session2.machineId
116175
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;
116176
116202
  }
116177
116203
  }
116178
116204
  async function processOnePendingFileTreeRequest(session2, coordinators, ensureCoordinator, normalized, force, checkpointOutboxRegistry, deltaOutboxRegistry) {
@@ -117512,6 +117538,25 @@ var init_task_delivery_processor = __esm(() => {
117512
117538
  init_task_delivery_logic();
117513
117539
  });
117514
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
+
117515
117560
  // src/daemon/infrastructure/agent-operational/enrich-snapshot-with-operational.ts
117516
117561
  function enrichSnapshotWithOperational(snapshot) {
117517
117562
  const op = getNativeDeliverySession()?.agentOperationalReadModel?.get(snapshot.chatroomId, snapshot.agentConfig.role);
@@ -117532,14 +117577,123 @@ var init_enrich_snapshot_with_operational = __esm(() => {
117532
117577
  init_native_delivery_session_registry();
117533
117578
  });
117534
117579
 
117535
- // src/daemon/infrastructure/agent-operational/subscribe-machine-agent-operational-status.ts
117536
- function subscribeMachineAgentOperationalStatus(client4, options, onRows) {
117537
- return client4.onUpdate(api.machines.subscribeMachineAgentOperationalStatus, { sessionId: options.sessionId, machineId: options.machineId }, (result) => {
117538
- if (Array.isArray(result))
117539
- 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
117540
117585
  });
117586
+ return result;
117541
117587
  }
117542
- var init_subscribe_machine_agent_operational_status = __esm(() => {
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
+ });
117652
+ });
117653
+ }
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(() => {
117543
117697
  init_api3();
117544
117698
  });
117545
117699
 
@@ -117724,14 +117878,14 @@ var init_task_inbox_delivery = __esm(() => {
117724
117878
  function taskSignalCursorAt(timestamp) {
117725
117879
  return `${String(Math.max(0, Math.floor(timestamp))).padStart(16, "0")}:`;
117726
117880
  }
117727
- function abortError() {
117881
+ function abortError2() {
117728
117882
  const error51 = new Error("Task inbox stopped");
117729
117883
  error51.name = "AbortError";
117730
117884
  return error51;
117731
117885
  }
117732
- function throwIfAborted(signal) {
117886
+ function throwIfAborted2(signal) {
117733
117887
  if (signal?.aborted)
117734
- throw abortError();
117888
+ throw abortError2();
117735
117889
  }
117736
117890
  function waitForTaskSignalPage(options, afterSignalKey) {
117737
117891
  return new Promise((resolve8, reject) => {
@@ -117750,11 +117904,11 @@ function waitForTaskSignalPage(options, afterSignalKey) {
117750
117904
  fn2();
117751
117905
  };
117752
117906
  const onAbort = () => {
117753
- settle2(() => reject(abortError()));
117907
+ settle2(() => reject(abortError2()));
117754
117908
  };
117755
117909
  options.signal?.addEventListener("abort", onAbort, { once: true });
117756
117910
  try {
117757
- throwIfAborted(options.signal);
117911
+ throwIfAborted2(options.signal);
117758
117912
  } catch (error51) {
117759
117913
  settle2(() => reject(error51));
117760
117914
  return;
@@ -117763,7 +117917,7 @@ function waitForTaskSignalPage(options, afterSignalKey) {
117763
117917
  sessionId: options.sessionId,
117764
117918
  machineId: options.machineId,
117765
117919
  afterKey: afterSignalKey,
117766
- limit: options.signalPageLimit ?? DEFAULT_SIGNAL_PAGE_LIMIT
117920
+ limit: options.signalPageLimit ?? DEFAULT_SIGNAL_PAGE_LIMIT2
117767
117921
  }, (result) => {
117768
117922
  if (!result || typeof result !== "object")
117769
117923
  return;
@@ -117794,7 +117948,7 @@ async function fetchSnapshotsForSignalPage(options, page) {
117794
117948
  const snapshots = [];
117795
117949
  let afterSignalKey = page.afterSignalKey;
117796
117950
  while (true) {
117797
- throwIfAborted(options.signal);
117951
+ throwIfAborted2(options.signal);
117798
117952
  const result = await options.client.query(api.tasks.listTasksForMachineSignalRange, {
117799
117953
  sessionId: options.sessionId,
117800
117954
  machineId: options.machineId,
@@ -117820,7 +117974,7 @@ async function runTaskInbox(options, onUpdate) {
117820
117974
  });
117821
117975
  }
117822
117976
  }
117823
- var DEFAULT_SIGNAL_PAGE_LIMIT = 100, DEFAULT_TASK_PAGE_LIMIT = 500;
117977
+ var DEFAULT_SIGNAL_PAGE_LIMIT2 = 100, DEFAULT_TASK_PAGE_LIMIT = 500;
117824
117978
  var init_task = __esm(() => {
117825
117979
  init_api3();
117826
117980
  });
@@ -117859,11 +118013,28 @@ async function runInboxLoopWithRestart(options, onUpdate, isStopped) {
117859
118013
  }
117860
118014
  }
117861
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
+ }
117862
118031
  var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInboxEffect = (wsClient2) => exports_Effect.gen(function* () {
117863
118032
  const session2 = yield* DaemonSessionService;
117864
118033
  const agentMgr = yield* DaemonAgentProcessManagerService;
117865
118034
  const lifecycleOutboxService = yield* AgentLifecycleOutboxService;
117866
- const lifecycleOutbox = { enqueue: (fact) => exports_Effect.runPromise(lifecycleOutboxService.enqueue(fact)) };
118035
+ const lifecycleOutbox = {
118036
+ enqueue: (fact) => exports_Effect.runPromise(lifecycleOutboxService.enqueue(fact))
118037
+ };
117867
118038
  const effectContext2 = yield* exports_Effect.context();
117868
118039
  const runtime4 = yield* exports_Effect.runtime();
117869
118040
  const sessionDeps = {
@@ -117882,6 +118053,13 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
117882
118053
  inboxType: "task",
117883
118054
  scopeKey: session2.machineId
117884
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);
117885
118063
  const abort = new AbortController;
117886
118064
  let stopped = false;
117887
118065
  const taskSnapshotState = new MachineTaskSnapshotState;
@@ -117903,7 +118081,7 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
117903
118081
  client: wsClient2,
117904
118082
  sessionId: session2.sessionId,
117905
118083
  machineId: session2.machineId,
117906
- serviceStartedAt: Date.now(),
118084
+ serviceStartedAt,
117907
118085
  initialAfterSignalKey: persisted?.state.afterSignalKey,
117908
118086
  signal: abort.signal
117909
118087
  };
@@ -117924,6 +118102,24 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
117924
118102
  inboxUpdateInFlight = false;
117925
118103
  }
117926
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
+ }
117927
118123
  yield* exports_Effect.tryPromise(() => bootstrapMachineAssignedTaskSnapshots({
117928
118124
  sessionDeps,
117929
118125
  runtime: runtime4,
@@ -117936,19 +118132,32 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
117936
118132
  console.warn("[TaskInbox] bootstrap failed:", error51);
117937
118133
  return exports_Effect.void;
117938
118134
  }));
117939
- const unsubscribeOperational = subscribeMachineAgentOperationalStatus(wsClient2, {
118135
+ const operationalInboxOptions = {
118136
+ client: wsClient2,
117940
118137
  sessionId: session2.sessionId,
117941
118138
  machineId: session2.machineId,
118139
+ serviceStartedAt,
118140
+ initialAfterSignalKey: initialOperationalKey,
117942
118141
  signal: abort.signal
117943
- }, (rows) => {
117944
- if (stopped)
117945
- return;
117946
- const changed = agentOperationalReadModel.replace(rows);
117947
- const snapshots = changed.flatMap(({ chatroomId, role }) => taskSnapshotState.listForRole(chatroomId, role));
117948
- if (snapshots.length === 0)
117949
- return;
117950
- processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, session2.machineId, "operational-status", { snapshots: enrichSnapshotsWithOperational(snapshots) }).catch((error51) => console.warn("[TaskInbox] operational-status reconcile failed:", error51));
117951
- }) ?? (() => {});
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
+ };
117952
118161
  const reconcileTimer = setInterval(() => {
117953
118162
  if (stopped || inboxUpdateInFlight || reconcileInFlight)
117954
118163
  return;
@@ -117960,10 +118169,10 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
117960
118169
  });
117961
118170
  }, NATIVE_DELIVERY_RECONCILE_MS);
117962
118171
  runInboxLoopWithRestart(inboxOptions, inboxHandler, () => stopped);
118172
+ runOperationalInboxLoopWithRestart(operationalInboxOptions, operationalInboxHandler, () => stopped);
117963
118173
  return {
117964
118174
  stop() {
117965
118175
  stopped = true;
117966
- unsubscribeOperational();
117967
118176
  abort.abort();
117968
118177
  clearInterval(reconcileTimer);
117969
118178
  unregisterNativeDeliverySession();
@@ -117979,8 +118188,10 @@ var init_task_inbox_runtime = __esm(() => {
117979
118188
  init_native_delivery_session_registry();
117980
118189
  init_task_delivery_processor();
117981
118190
  init_task_delivery_logic();
118191
+ init_ack_machine_operational_signals();
117982
118192
  init_enrich_snapshot_with_operational();
117983
- init_subscribe_machine_agent_operational_status();
118193
+ init_fetch_machine_agent_operational_status();
118194
+ init_operational_inbox();
117984
118195
  init_fetch_machine_assigned_task_snapshots();
117985
118196
  init_inbox();
117986
118197
  init_task_inbox_delivery();
@@ -118483,6 +118694,9 @@ function createDaemonRuntime(deps) {
118483
118694
  break;
118484
118695
  }
118485
118696
  });
118697
+ fileTreeHandle.drainPendingFileTreeReleaseRequests().catch((err) => {
118698
+ console.warn(`[${formatTimestamp()}] ⚠️ Startup file-tree release drain failed: ${getErrorMessage(err)}`);
118699
+ });
118486
118700
  workspaceListSubscriptionHandle = yield* startWorkspaceListSubscriptionEffect();
118487
118701
  registerWorkspaceGitInboundHandler(async (event) => {
118488
118702
  switch (event.type) {
@@ -119210,31 +119424,22 @@ var init_file_content_request = __esm(() => {
119210
119424
  });
119211
119425
 
119212
119426
  // src/daemon/infrastructure/convex/subscribers/file-tree-release-request.ts
119213
- function requestId(req) {
119214
- if (req._id == null)
119215
- return "unknown";
119216
- return typeof req._id === "string" ? req._id : req._id.toString();
119217
- }
119218
- function pendingReleasesSnapshot(requests) {
119219
- return requests.filter((req) => req != null && typeof req === "object").map((req) => `${requestId(req)}:${req.workingDir ?? ""}:${req.updatedAt ?? 0}`).sort().join("|");
119220
- }
119221
119427
  function startFileTreeReleaseRequestSubscriber(deps, onEvent) {
119222
- let lastSnapshot = "";
119223
- const unsub = deps.wsClient.onUpdate(api.workspaceFiles.getPendingFileTreeReleaseRequests, { sessionId: deps.sessionId, machineId: deps.machineId }, (requests) => {
119224
- if (!requests?.length) {
119225
- lastSnapshot = "";
119226
- return;
119227
- }
119228
- const snapshot = pendingReleasesSnapshot(requests);
119229
- if (!snapshot || snapshot === lastSnapshot)
119428
+ let lastRevision = null;
119429
+ const maybeWake = (revision, requestId) => {
119430
+ if (lastRevision === revision)
119230
119431
  return;
119231
- lastSnapshot = snapshot;
119232
- const first = requests.find((req) => req != null && typeof req === "object");
119233
- 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;
119234
119438
  return;
119235
- onEvent({ type: "file-tree.release", requestId: requestId(first) });
119439
+ }
119440
+ maybeWake(head5.revision, `rev-${head5.revision}`);
119236
119441
  }, (err) => {
119237
- 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)}`);
119238
119443
  });
119239
119444
  return {
119240
119445
  async stop() {
@@ -119247,13 +119452,13 @@ var init_file_tree_release_request = __esm(() => {
119247
119452
  });
119248
119453
 
119249
119454
  // src/daemon/infrastructure/convex/subscribers/file-tree-request.ts
119250
- function requestId2(req) {
119455
+ function requestId(req) {
119251
119456
  if (req._id == null)
119252
119457
  return "unknown";
119253
119458
  return typeof req._id === "string" ? req._id : req._id.toString();
119254
119459
  }
119255
119460
  function pendingRequestsSnapshot(requests) {
119256
- 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("|");
119257
119462
  }
119258
119463
  function startFileTreeRequestSubscriber(deps, onEvent) {
119259
119464
  let lastSnapshot = "";
@@ -119269,7 +119474,7 @@ function startFileTreeRequestSubscriber(deps, onEvent) {
119269
119474
  const first = requests.find((req) => req != null && typeof req === "object");
119270
119475
  if (!first)
119271
119476
  return;
119272
- onEvent({ type: "file-tree.request", requestId: requestId2(first) });
119477
+ onEvent({ type: "file-tree.request", requestId: requestId(first) });
119273
119478
  }, (err) => {
119274
119479
  console.warn(`[daemon] file-tree-request subscriber error: ${err instanceof Error ? err.message : String(err)}`);
119275
119480
  });
@@ -119306,7 +119511,7 @@ var init_file_write_request = __esm(() => {
119306
119511
  });
119307
119512
 
119308
119513
  // src/daemon/infrastructure/convex/subscribers/git-request.ts
119309
- function requestId3(req) {
119514
+ function requestId2(req) {
119310
119515
  return typeof req._id === "string" ? req._id : req._id.toString();
119311
119516
  }
119312
119517
  function startGitRequestSubscriber(deps, onEvent) {
@@ -119317,7 +119522,7 @@ function startGitRequestSubscriber(deps, onEvent) {
119317
119522
  for (const req of requests) {
119318
119523
  if (req == null || typeof req !== "object" || !("_id" in req))
119319
119524
  continue;
119320
- const id3 = requestId3(req);
119525
+ const id3 = requestId2(req);
119321
119526
  if (seen.has(id3))
119322
119527
  continue;
119323
119528
  seen.add(id3);
@@ -132159,19 +132364,19 @@ var require_cluster_adapter = __commonJS((exports) => {
132159
132364
  }
132160
132365
  onResponse(response) {
132161
132366
  var _a4, _b2;
132162
- const requestId4 = response.data.requestId;
132163
- 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);
132164
132369
  switch (response.type) {
132165
132370
  case MessageType.BROADCAST_CLIENT_COUNT: {
132166
- (_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);
132167
132372
  break;
132168
132373
  }
132169
132374
  case MessageType.BROADCAST_ACK: {
132170
- (_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);
132171
132376
  break;
132172
132377
  }
132173
132378
  case MessageType.FETCH_SOCKETS_RESPONSE: {
132174
- const request2 = this.requests.get(requestId4);
132379
+ const request2 = this.requests.get(requestId3);
132175
132380
  if (!request2) {
132176
132381
  return;
132177
132382
  }
@@ -132180,12 +132385,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132180
132385
  if (request2.current === request2.expected) {
132181
132386
  clearTimeout(request2.timeout);
132182
132387
  request2.resolve(request2.responses);
132183
- this.requests.delete(requestId4);
132388
+ this.requests.delete(requestId3);
132184
132389
  }
132185
132390
  break;
132186
132391
  }
132187
132392
  case MessageType.SERVER_SIDE_EMIT_RESPONSE: {
132188
- const request2 = this.requests.get(requestId4);
132393
+ const request2 = this.requests.get(requestId3);
132189
132394
  if (!request2) {
132190
132395
  return;
132191
132396
  }
@@ -132194,7 +132399,7 @@ var require_cluster_adapter = __commonJS((exports) => {
132194
132399
  if (request2.current === request2.expected) {
132195
132400
  clearTimeout(request2.timeout);
132196
132401
  request2.resolve(null, request2.responses);
132197
- this.requests.delete(requestId4);
132402
+ this.requests.delete(requestId3);
132198
132403
  }
132199
132404
  break;
132200
132405
  }
@@ -132237,8 +132442,8 @@ var require_cluster_adapter = __commonJS((exports) => {
132237
132442
  var _a4;
132238
132443
  const onlyLocal = (_a4 = opts === null || opts === undefined ? undefined : opts.flags) === null || _a4 === undefined ? undefined : _a4.local;
132239
132444
  if (!onlyLocal) {
132240
- const requestId4 = randomId();
132241
- this.ackRequests.set(requestId4, {
132445
+ const requestId3 = randomId();
132446
+ this.ackRequests.set(requestId3, {
132242
132447
  clientCountCallback,
132243
132448
  ack
132244
132449
  });
@@ -132246,12 +132451,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132246
132451
  type: MessageType.BROADCAST,
132247
132452
  data: {
132248
132453
  packet,
132249
- requestId: requestId4,
132454
+ requestId: requestId3,
132250
132455
  opts: encodeOptions(opts)
132251
132456
  }
132252
132457
  });
132253
132458
  setTimeout(() => {
132254
- this.ackRequests.delete(requestId4);
132459
+ this.ackRequests.delete(requestId3);
132255
132460
  }, opts.flags.timeout);
132256
132461
  }
132257
132462
  super.broadcastWithAck(packet, opts, clientCountCallback, ack);
@@ -132320,13 +132525,13 @@ var require_cluster_adapter = __commonJS((exports) => {
132320
132525
  if (((_a4 = opts.flags) === null || _a4 === undefined ? undefined : _a4.local) || expectedResponseCount <= 0) {
132321
132526
  return localSockets;
132322
132527
  }
132323
- const requestId4 = randomId();
132528
+ const requestId3 = randomId();
132324
132529
  return new Promise((resolve8, reject) => {
132325
132530
  const timeout3 = setTimeout(() => {
132326
- const storedRequest2 = this.requests.get(requestId4);
132531
+ const storedRequest2 = this.requests.get(requestId3);
132327
132532
  if (storedRequest2) {
132328
132533
  reject(new Error(`timeout reached: only ${storedRequest2.current} responses received out of ${storedRequest2.expected}`));
132329
- this.requests.delete(requestId4);
132534
+ this.requests.delete(requestId3);
132330
132535
  }
132331
132536
  }, opts.flags.timeout || DEFAULT_TIMEOUT);
132332
132537
  const storedRequest = {
@@ -132337,12 +132542,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132337
132542
  expected: expectedResponseCount,
132338
132543
  responses: localSockets
132339
132544
  };
132340
- this.requests.set(requestId4, storedRequest);
132545
+ this.requests.set(requestId3, storedRequest);
132341
132546
  this.publish({
132342
132547
  type: MessageType.FETCH_SOCKETS,
132343
132548
  data: {
132344
132549
  opts: encodeOptions(opts),
132345
- requestId: requestId4
132550
+ requestId: requestId3
132346
132551
  }
132347
132552
  });
132348
132553
  });
@@ -132363,12 +132568,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132363
132568
  if (expectedResponseCount <= 0) {
132364
132569
  return ack(null, []);
132365
132570
  }
132366
- const requestId4 = randomId();
132571
+ const requestId3 = randomId();
132367
132572
  const timeout3 = setTimeout(() => {
132368
- const storedRequest2 = this.requests.get(requestId4);
132573
+ const storedRequest2 = this.requests.get(requestId3);
132369
132574
  if (storedRequest2) {
132370
132575
  ack(new Error(`timeout reached: only ${storedRequest2.current} responses received out of ${storedRequest2.expected}`), storedRequest2.responses);
132371
- this.requests.delete(requestId4);
132576
+ this.requests.delete(requestId3);
132372
132577
  }
132373
132578
  }, DEFAULT_TIMEOUT);
132374
132579
  const storedRequest = {
@@ -132379,11 +132584,11 @@ var require_cluster_adapter = __commonJS((exports) => {
132379
132584
  expected: expectedResponseCount,
132380
132585
  responses: []
132381
132586
  };
132382
- this.requests.set(requestId4, storedRequest);
132587
+ this.requests.set(requestId3, storedRequest);
132383
132588
  this.publish({
132384
132589
  type: MessageType.SERVER_SIDE_EMIT,
132385
132590
  data: {
132386
- requestId: requestId4,
132591
+ requestId: requestId3,
132387
132592
  packet
132388
132593
  }
132389
132594
  });
@@ -132500,12 +132705,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132500
132705
  if (expectedResponseCount <= 0) {
132501
132706
  return ack(null, []);
132502
132707
  }
132503
- const requestId4 = randomId();
132708
+ const requestId3 = randomId();
132504
132709
  const timeout3 = setTimeout(() => {
132505
- const storedRequest2 = this.customRequests.get(requestId4);
132710
+ const storedRequest2 = this.customRequests.get(requestId3);
132506
132711
  if (storedRequest2) {
132507
132712
  ack(new Error(`timeout reached: missing ${storedRequest2.missingUids.size} responses`), storedRequest2.responses);
132508
- this.customRequests.delete(requestId4);
132713
+ this.customRequests.delete(requestId3);
132509
132714
  }
132510
132715
  }, DEFAULT_TIMEOUT);
132511
132716
  const storedRequest = {
@@ -132515,11 +132720,11 @@ var require_cluster_adapter = __commonJS((exports) => {
132515
132720
  missingUids: new Set([...this.nodesMap.keys()]),
132516
132721
  responses: []
132517
132722
  };
132518
- this.customRequests.set(requestId4, storedRequest);
132723
+ this.customRequests.set(requestId3, storedRequest);
132519
132724
  this.publish({
132520
132725
  type: MessageType.SERVER_SIDE_EMIT,
132521
132726
  data: {
132522
- requestId: requestId4,
132727
+ requestId: requestId3,
132523
132728
  packet
132524
132729
  }
132525
132730
  });
@@ -132540,13 +132745,13 @@ var require_cluster_adapter = __commonJS((exports) => {
132540
132745
  if (((_a4 = opts.flags) === null || _a4 === undefined ? undefined : _a4.local) || expectedResponseCount <= 0) {
132541
132746
  return localSockets;
132542
132747
  }
132543
- const requestId4 = randomId();
132748
+ const requestId3 = randomId();
132544
132749
  return new Promise((resolve8, reject) => {
132545
132750
  const timeout3 = setTimeout(() => {
132546
- const storedRequest2 = this.customRequests.get(requestId4);
132751
+ const storedRequest2 = this.customRequests.get(requestId3);
132547
132752
  if (storedRequest2) {
132548
132753
  reject(new Error(`timeout reached: missing ${storedRequest2.missingUids.size} responses`));
132549
- this.customRequests.delete(requestId4);
132754
+ this.customRequests.delete(requestId3);
132550
132755
  }
132551
132756
  }, opts.flags.timeout || DEFAULT_TIMEOUT);
132552
132757
  const storedRequest = {
@@ -132556,22 +132761,22 @@ var require_cluster_adapter = __commonJS((exports) => {
132556
132761
  missingUids: new Set([...this.nodesMap.keys()]),
132557
132762
  responses: localSockets
132558
132763
  };
132559
- this.customRequests.set(requestId4, storedRequest);
132764
+ this.customRequests.set(requestId3, storedRequest);
132560
132765
  this.publish({
132561
132766
  type: MessageType.FETCH_SOCKETS,
132562
132767
  data: {
132563
132768
  opts: encodeOptions(opts),
132564
- requestId: requestId4
132769
+ requestId: requestId3
132565
132770
  }
132566
132771
  });
132567
132772
  });
132568
132773
  }
132569
132774
  onResponse(response) {
132570
- const requestId4 = response.data.requestId;
132571
- 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);
132572
132777
  switch (response.type) {
132573
132778
  case MessageType.FETCH_SOCKETS_RESPONSE: {
132574
- const request2 = this.customRequests.get(requestId4);
132779
+ const request2 = this.customRequests.get(requestId3);
132575
132780
  if (!request2) {
132576
132781
  return;
132577
132782
  }
@@ -132580,12 +132785,12 @@ var require_cluster_adapter = __commonJS((exports) => {
132580
132785
  if (request2.missingUids.size === 0) {
132581
132786
  clearTimeout(request2.timeout);
132582
132787
  request2.resolve(request2.responses);
132583
- this.customRequests.delete(requestId4);
132788
+ this.customRequests.delete(requestId3);
132584
132789
  }
132585
132790
  break;
132586
132791
  }
132587
132792
  case MessageType.SERVER_SIDE_EMIT_RESPONSE: {
132588
- const request2 = this.customRequests.get(requestId4);
132793
+ const request2 = this.customRequests.get(requestId3);
132589
132794
  if (!request2) {
132590
132795
  return;
132591
132796
  }
@@ -132594,7 +132799,7 @@ var require_cluster_adapter = __commonJS((exports) => {
132594
132799
  if (request2.missingUids.size === 0) {
132595
132800
  clearTimeout(request2.timeout);
132596
132801
  request2.resolve(null, request2.responses);
132597
- this.customRequests.delete(requestId4);
132802
+ this.customRequests.delete(requestId3);
132598
132803
  }
132599
132804
  break;
132600
132805
  }
@@ -132603,7 +132808,7 @@ var require_cluster_adapter = __commonJS((exports) => {
132603
132808
  }
132604
132809
  }
132605
132810
  removeNode(uid) {
132606
- this.customRequests.forEach((request2, requestId4) => {
132811
+ this.customRequests.forEach((request2, requestId3) => {
132607
132812
  request2.missingUids.delete(uid);
132608
132813
  if (request2.missingUids.size === 0) {
132609
132814
  clearTimeout(request2.timeout);
@@ -132612,7 +132817,7 @@ var require_cluster_adapter = __commonJS((exports) => {
132612
132817
  } else if (request2.type === MessageType.SERVER_SIDE_EMIT) {
132613
132818
  request2.resolve(null, request2.responses);
132614
132819
  }
132615
- this.customRequests.delete(requestId4);
132820
+ this.customRequests.delete(requestId3);
132616
132821
  }
132617
132822
  });
132618
132823
  this.nodesMap.delete(uid);
@@ -135186,4 +135391,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
135186
135391
  });
135187
135392
  program2.parse();
135188
135393
 
135189
- //# debugId=398908BA09BE4DBA64756E2164756E21
135394
+ //# debugId=540831143AEEA0CF64756E2164756E21