chatroom-cli 1.98.5 → 1.98.6

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
@@ -83544,7 +83544,9 @@ var DaemonMachineService, DaemonMachineServiceLive = (ops) => exports_Layer.succ
83544
83544
  clearStuckStoppingSlot: (chatroomId, role) => exports_Effect.promise(() => mgr.clearStuckStoppingSlot(chatroomId, role)),
83545
83545
  whenTurnEndsIdle: () => exports_Effect.promise(() => mgr.whenTurnEndsIdle()),
83546
83546
  resumeTurnForSlot: (args2) => exports_Effect.promise(() => mgr.resumeTurnForSlot(args2)),
83547
- setLastInFlightTask: (chatroomId, role, taskId) => exports_Effect.sync(() => mgr.setLastInFlightTask(chatroomId, role, taskId))
83547
+ setLastInFlightTask: (chatroomId, role, taskId) => exports_Effect.sync(() => mgr.setLastInFlightTask(chatroomId, role, taskId)),
83548
+ clearLastInFlightTaskIfMatches: (chatroomId, role, taskId) => exports_Effect.sync(() => mgr.clearLastInFlightTaskIfMatches(chatroomId, role, taskId)),
83549
+ reconcileNativeTurnPhaseIdle: (chatroomId, role) => exports_Effect.sync(() => mgr.reconcileNativeTurnPhaseIdle(chatroomId, role))
83548
83550
  }), DaemonSessionService, DaemonMutableStateService;
83549
83551
  var init_daemon_services = __esm(() => {
83550
83552
  init_esm();
@@ -98686,40 +98688,18 @@ var init_convex_id = __esm(() => {
98686
98688
  init_zod();
98687
98689
  });
98688
98690
 
98689
- // ../../services/backend/src/domain/usecase/machine/assigned-task-monitor-contract.ts
98690
- function parseAssignedTaskSignal(raw) {
98691
- return assignedTaskSignalSchema.parse(raw);
98691
+ // ../../services/backend/src/domain/usecase/machine/assigned-task-snapshot-contract.ts
98692
+ function parseAssignedTaskSnapshotRow(raw) {
98693
+ return assignedTaskSnapshotRowSchema.parse(raw);
98692
98694
  }
98693
- function parseAssignedTaskPresenceSignal(raw) {
98694
- const full = assignedTaskPresenceSignalSchema.safeParse(raw);
98695
- if (full.success)
98696
- return full.data;
98697
- const delta = assignedTaskPresenceDeltaSchema.safeParse(raw);
98698
- if (delta.success) {
98699
- const presenceUpdatedAt = Number(delta.data.presenceKey.split(":")[0]);
98700
- const resolvedAt = Number.isFinite(presenceUpdatedAt) ? presenceUpdatedAt : 0;
98701
- return {
98702
- taskId: delta.data.taskId,
98703
- chatroomId: "",
98704
- role: delta.data.role,
98705
- lastSeenAt: resolvedAt,
98706
- presenceUpdatedAt: resolvedAt,
98707
- presenceKey: delta.data.presenceKey
98708
- };
98709
- }
98710
- return assignedTaskPresenceSignalSchema.parse(raw);
98711
- }
98712
- function parseAssignedTaskMonitorRow(raw) {
98713
- return assignedTaskMonitorRowSchema.parse(raw);
98714
- }
98715
- function parseAssignedTaskMonitorRows(raw) {
98695
+ function parseAssignedTaskSnapshotRows(raw) {
98716
98696
  if (!Array.isArray(raw)) {
98717
98697
  throw new Error("Expected hydrate tasks array");
98718
98698
  }
98719
- return raw.map((row) => parseAssignedTaskMonitorRow(row));
98699
+ return raw.map((row) => parseAssignedTaskSnapshotRow(row));
98720
98700
  }
98721
- var ACTIVE_TASK_STATUSES, activeTaskStatusSchema, ASSIGNED_TASK_SIGNAL_TYPES, assignedTaskSignalTypeSchema, SESSION_AUGMENTATION_MODES, sessionAugmentationSchema, AGENT_DESIRED_STATES, agentDesiredStateSchema, AGENT_CIRCUIT_STATES, agentCircuitStateSchema, chatroomTaskIdSchema, chatroomRoomIdSchema, assignedTaskAgentConfigSchema, assignedTaskParticipantSchema, assignedTaskSignalBootstrapFields, assignedTaskSignalSchema, assignedTaskPresenceSignalSchema, assignedTaskPresenceDeltaSchema, assignedTaskMonitorRowSchema;
98722
- var init_assigned_task_monitor_contract = __esm(() => {
98701
+ var ACTIVE_TASK_STATUSES, activeTaskStatusSchema, ASSIGNED_TASK_SIGNAL_TYPES, assignedTaskSignalTypeSchema, SESSION_AUGMENTATION_MODES, sessionAugmentationSchema, AGENT_DESIRED_STATES, agentDesiredStateSchema, AGENT_CIRCUIT_STATES, agentCircuitStateSchema, chatroomTaskIdSchema, chatroomRoomIdSchema, assignedTaskAgentConfigSchema, assignedTaskParticipantSchema, assignedTaskSignalBootstrapFields, assignedTaskSignalSchema, assignedTaskPresenceSignalSchema, assignedTaskPresenceDeltaSchema, assignedTaskSnapshotRowSchema;
98702
+ var init_assigned_task_snapshot_contract = __esm(() => {
98723
98703
  init_zod();
98724
98704
  init_convex_id();
98725
98705
  ACTIVE_TASK_STATUSES = ["pending", "acknowledged", "in_progress"];
@@ -98782,7 +98762,7 @@ var init_assigned_task_monitor_contract = __esm(() => {
98782
98762
  role: exports_external.string(),
98783
98763
  presenceKey: exports_external.string()
98784
98764
  });
98785
- assignedTaskMonitorRowSchema = exports_external.object({
98765
+ assignedTaskSnapshotRowSchema = exports_external.object({
98786
98766
  taskId: chatroomTaskIdSchema,
98787
98767
  chatroomId: chatroomRoomIdSchema,
98788
98768
  status: activeTaskStatusSchema,
@@ -98943,6 +98923,19 @@ function getNativeDeliverySession() {
98943
98923
  }
98944
98924
  var registered = null;
98945
98925
 
98926
+ // src/daemon/entry/native-delivery/native-stale-turn-phase.ts
98927
+ function isStaleTurnInFlightWhileWaiting(task, slot) {
98928
+ if (!slot || isTurnPhaseIdle(slot.nativeTurnPhase ?? "idle"))
98929
+ return false;
98930
+ if (task.status !== "pending")
98931
+ return false;
98932
+ return task.participant?.lastSeenAction === NATIVE_WAITING_ACTION;
98933
+ }
98934
+ var init_native_stale_turn_phase = __esm(() => {
98935
+ init_participant();
98936
+ init_check_agent_slot();
98937
+ });
98938
+
98946
98939
  // src/daemon/domain/native-integration/predicates.ts
98947
98940
  function isStaleCliGetNextTaskWaiting(task) {
98948
98941
  const lastSeenAt = task.participant?.lastSeenAt ?? 0;
@@ -99002,8 +98995,21 @@ function explainNativeDeliveryBlock(task, opts) {
99002
98995
  return `acknowledged_wrong_role (assignedTo=${assignedTo ?? "none"}, role=${role})`;
99003
98996
  }
99004
98997
  }
98998
+ const inFlightBlock = explainInFlightDeliveryBlock(task, opts.slot);
98999
+ if (inFlightBlock)
99000
+ return inFlightBlock;
99005
99001
  return explainAgentReadyForNativeDeliveryBlock(task, opts.slot);
99006
99002
  }
99003
+ function explainInFlightDeliveryBlock(task, slot) {
99004
+ if (!slot?.lastInFlightTaskId || slot.lastInFlightTaskId !== task.taskId)
99005
+ return null;
99006
+ if (task.status === "pending")
99007
+ return null;
99008
+ if (task.status === "acknowledged") {
99009
+ return "already_delivered_to_slot (lastInFlightTaskId match, status=acknowledged)";
99010
+ }
99011
+ return null;
99012
+ }
99007
99013
  function explainLedgerDeliveryBlock(taskId, harnessSessionId, ledger) {
99008
99014
  if (ledger.isDelivered(taskId, harnessSessionId)) {
99009
99015
  return "already_delivered_this_session";
@@ -99403,28 +99409,21 @@ function mapAssignedTaskSnapshotList(rows) {
99403
99409
  return rows.map(mapAssignedTaskSnapshot);
99404
99410
  }
99405
99411
 
99406
- // src/infrastructure/stores/assigned-task-snapshot-store.ts
99407
- function replaceAssignedTaskSnapshots(next4) {
99408
- rows = [...next4];
99409
- hasSnapshot = true;
99410
- }
99411
- function clearAssignedTaskSnapshots() {
99412
- rows = [];
99413
- hasSnapshot = false;
99414
- }
99415
- function hasAssignedTaskSnapshot() {
99416
- return hasSnapshot;
99417
- }
99418
- function listAssignedTaskSnapshots() {
99419
- return [...rows];
99412
+ // src/daemon/infrastructure/inbox/fetch-machine-assigned-task-snapshots.ts
99413
+ async function fetchMachineAssignedTaskSnapshots(sessionDeps, machineId) {
99414
+ const result = await sessionDeps.backend.query(api.machines.listMachineAssignedTaskSnapshots, {
99415
+ sessionId: sessionDeps.sessionId,
99416
+ machineId
99417
+ });
99418
+ return mapAssignedTaskSnapshotList(parseAssignedTaskSnapshotRows(result?.tasks ?? []));
99420
99419
  }
99421
- function listAssignedTaskSnapshotsForRole(chatroomId, role) {
99420
+ function filterSnapshotsForRole(snapshots, chatroomId, role) {
99422
99421
  const roleLower = role.toLowerCase();
99423
- return rows.filter((row) => row.chatroomId === chatroomId && row.agentConfig.role.toLowerCase() === roleLower);
99422
+ return snapshots.filter((row) => row.chatroomId === chatroomId && row.agentConfig.role.toLowerCase() === roleLower);
99424
99423
  }
99425
- var rows, hasSnapshot = false;
99426
- var init_assigned_task_snapshot_store = __esm(() => {
99427
- rows = [];
99424
+ var init_fetch_machine_assigned_task_snapshots = __esm(() => {
99425
+ init_assigned_task_snapshot_contract();
99426
+ init_api3();
99428
99427
  });
99429
99428
 
99430
99429
  // src/daemon/entry/restart-orchestrator-in-flight.ts
@@ -99518,18 +99517,22 @@ class NativeTaskDeliveryCoordinator {
99518
99517
  if (!session2)
99519
99518
  return;
99520
99519
  const { runtime: runtime4, effectContext: effectContext2, agentMgr, sessionDeps, machineId } = session2;
99521
- const tasks = listAssignedTaskSnapshotsForRole(chatroomId, role);
99522
- if (tasks.length === 0) {
99523
- logNativeDeliveryNoTasks(role, chatroomId);
99524
- return;
99525
- }
99526
- this.reconcileAssignedTasks({
99527
- tasks,
99528
- runtime: runtime4,
99529
- effectContext: effectContext2,
99530
- agentMgr,
99531
- sessionDeps,
99532
- machineId
99520
+ fetchMachineAssignedTaskSnapshots(sessionDeps, machineId).then((all8) => {
99521
+ const tasks = filterSnapshotsForRole(all8, chatroomId, role);
99522
+ if (tasks.length === 0) {
99523
+ logNativeDeliveryNoTasks(role, chatroomId);
99524
+ return;
99525
+ }
99526
+ this.reconcileAssignedTasks({
99527
+ tasks,
99528
+ runtime: runtime4,
99529
+ effectContext: effectContext2,
99530
+ agentMgr,
99531
+ sessionDeps,
99532
+ machineId
99533
+ });
99534
+ }).catch((err) => {
99535
+ console.warn(`[NativeTaskDelivery] rehydrate failed for ${role}@${chatroomId}: ${getErrorMessage(err)}`);
99533
99536
  });
99534
99537
  }
99535
99538
  reconcileAssignedTasks(params) {
@@ -99549,7 +99552,18 @@ class NativeTaskDeliveryCoordinator {
99549
99552
  for (const row of pendingFirst) {
99550
99553
  const { role } = row.agentConfig;
99551
99554
  const slot = agentMgr.getSlot(row.chatroomId, role);
99552
- const blockReason = explainNativeDeliveryBlock(row, { slot });
99555
+ if (row.status === "pending" && slot?.lastInFlightTaskId === row.taskId) {
99556
+ exports_Effect.runSync(agentMgr.clearLastInFlightTaskIfMatches(row.chatroomId, role, row.taskId));
99557
+ }
99558
+ if (isStaleTurnInFlightWhileWaiting(row, slot)) {
99559
+ if (agentMgr.reconcileNativeTurnPhaseIdle) {
99560
+ exports_Effect.runSync(agentMgr.reconcileNativeTurnPhaseIdle(row.chatroomId, role));
99561
+ }
99562
+ logNativeDeliveryFallback("stale-turn-phase", role, row.chatroomId, row.taskId);
99563
+ }
99564
+ const blockReason = explainNativeDeliveryBlock(row, {
99565
+ slot: agentMgr.getSlot(row.chatroomId, role)
99566
+ });
99553
99567
  if (blockReason) {
99554
99568
  if (isDeliverableTaskStatus(row.status)) {
99555
99569
  logNativeDeliverySkip(role, row.chatroomId, row.taskId, blockReason);
@@ -99638,12 +99652,13 @@ function notifyNativeTurnIdle(params) {
99638
99652
  var coordinator;
99639
99653
  var init_native_task_delivery_coordinator = __esm(() => {
99640
99654
  init_esm();
99655
+ init_native_stale_turn_phase();
99641
99656
  init_native_task_injector_logic();
99642
99657
  init_native_task_injector();
99643
99658
  init_api3();
99644
99659
  init_assigned_task();
99645
- init_assigned_task_snapshot_store();
99646
99660
  init_convex_error();
99661
+ init_fetch_machine_assigned_task_snapshots();
99647
99662
  init_restart_orchestrator_in_flight();
99648
99663
  });
99649
99664
 
@@ -99718,7 +99733,7 @@ async function listDeliverableSnapshots(deps, event) {
99718
99733
  machineId: deps.session.machineId
99719
99734
  });
99720
99735
  const slot = deps.agentMgr.getSlot(event.chatroomId, event.role);
99721
- return mapAssignedTaskSnapshotList(parseAssignedTaskMonitorRows(result.tasks ?? [])).filter((t) => t.chatroomId === event.chatroomId && t.agentConfig.role.toLowerCase() === event.role.toLowerCase() && isDeliverableTaskStatus(t.status) && isAgentReadyForNativeDelivery(t, slot)).sort((a, b) => a.createdAt - b.createdAt);
99736
+ return mapAssignedTaskSnapshotList(parseAssignedTaskSnapshotRows(result.tasks ?? [])).filter((t) => t.chatroomId === event.chatroomId && t.agentConfig.role.toLowerCase() === event.role.toLowerCase() && isDeliverableTaskStatus(t.status) && isAgentReadyForNativeDelivery(t, slot)).sort((a, b) => a.createdAt - b.createdAt);
99722
99737
  }
99723
99738
  async function deliverOneTask(deps, event, snapshot) {
99724
99739
  const slot = deps.agentMgr.getSlot(event.chatroomId, event.role);
@@ -99740,6 +99755,11 @@ async function deliverOneTask(deps, event, snapshot) {
99740
99755
  console.warn(`[RestartOrchestrator] skip task ${snapshot.taskId} — ${ledgerBlock}`);
99741
99756
  return false;
99742
99757
  }
99758
+ const deliveryBlock = explainNativeDeliveryBlock(snapshot, { slot });
99759
+ if (deliveryBlock) {
99760
+ console.warn(`[RestartOrchestrator] skip task ${snapshot.taskId} — ${deliveryBlock}`);
99761
+ return false;
99762
+ }
99743
99763
  if (!ledger.tryAcquire(snapshot.taskId, harnessSessionId)) {
99744
99764
  console.warn(`[RestartOrchestrator] skip task ${snapshot.taskId} — delivery_ledger_busy`);
99745
99765
  return false;
@@ -99843,7 +99863,7 @@ var init_restart_orchestrator = __esm(() => {
99843
99863
  init_reliability();
99844
99864
  init_participant();
99845
99865
  init_build_agent_restart_event();
99846
- init_assigned_task_monitor_contract();
99866
+ init_assigned_task_snapshot_contract();
99847
99867
  init_esm();
99848
99868
  init_api3();
99849
99869
  init_native_ready_invariant();
@@ -101527,6 +101547,7 @@ class AgentProcessManager {
101527
101547
  }
101528
101548
  if (slot) {
101529
101549
  setNativeTurnPhase(slot, defaultNativeTurnPhase());
101550
+ this.clearLastInFlightTask(opts.chatroomId, opts.role);
101530
101551
  }
101531
101552
  notifyNativeTurnIdle({ chatroomId: opts.chatroomId, role: opts.role });
101532
101553
  console.log(`[AgentProcessManager] ✅ Native agent_end handled for ${opts.role}`);
@@ -101542,6 +101563,9 @@ class AgentProcessManager {
101542
101563
  }
101543
101564
  const stopReason = resolveStopReason(opts.code, opts.signal);
101544
101565
  const ctx = this.captureExitContext(slot, opts, stopReason);
101566
+ if (slot.harness && getHarnessCapabilities(slot.harness).supportsNativeIntegration) {
101567
+ setNativeTurnPhase(slot, defaultNativeTurnPhase());
101568
+ }
101545
101569
  this.maybeEmitProviderUnavailable(opts.chatroomId, opts.role, slot);
101546
101570
  notifyNativeHarnessSessionLostOnExit({
101547
101571
  chatroomId: opts.chatroomId,
@@ -101843,6 +101867,21 @@ class AgentProcessManager {
101843
101867
  const slot = this.getOrCreateSlot(agentKey3(chatroomId, role));
101844
101868
  slot.lastInFlightTaskId = taskId;
101845
101869
  }
101870
+ clearLastInFlightTaskIfMatches(chatroomId, role, taskId) {
101871
+ const slot = this.slots.get(agentKey3(chatroomId, role));
101872
+ if (slot?.lastInFlightTaskId === taskId)
101873
+ slot.lastInFlightTaskId = undefined;
101874
+ }
101875
+ reconcileNativeTurnPhaseIdle(chatroomId, role) {
101876
+ const slot = this.getSlot(chatroomId, role);
101877
+ if (slot)
101878
+ setNativeTurnPhase(slot, defaultNativeTurnPhase());
101879
+ }
101880
+ clearLastInFlightTask(chatroomId, role) {
101881
+ const slot = this.slots.get(agentKey3(chatroomId, role));
101882
+ if (slot)
101883
+ slot.lastInFlightTaskId = undefined;
101884
+ }
101846
101885
  listActive() {
101847
101886
  const result = [];
101848
101887
  for (const [key, slot] of this.slots) {
@@ -102512,6 +102551,9 @@ class AgentProcessManager {
102512
102551
  setNativeTurnPhase(slot, defaultNativeTurnPhase());
102513
102552
  }
102514
102553
  await this.emitNativeWaiting(opts.chatroomId, opts.role, opts.agentHarness);
102554
+ if (getHarnessCapabilities(opts.agentHarness).supportsNativeIntegration) {
102555
+ getNativeTaskDeliveryCoordinator().tryInjectNextForRole(opts.chatroomId, opts.role);
102556
+ }
102515
102557
  }
102516
102558
  async emitNativeWaiting(chatroomId, role, harness) {
102517
102559
  return emitNativeWaitingAfterSpawn({
@@ -114159,27 +114201,27 @@ function createFifoBatchedOutbox(o) {
114159
114201
  return running3;
114160
114202
  running3 = (async () => {
114161
114203
  while (true) {
114162
- const rows2 = o.store.claimNextBatch(o.deliveryKey, o.batchSize);
114163
- if (!rows2.length)
114204
+ const rows = o.store.claimNextBatch(o.deliveryKey, o.batchSize);
114205
+ if (!rows.length)
114164
114206
  break;
114165
114207
  try {
114166
- const results = await o.send(rows2.map((r) => o.deserialize(r.payloadJson)));
114208
+ const results = await o.send(rows.map((r) => o.deserialize(r.payloadJson)));
114167
114209
  let hasRetry = false;
114168
114210
  for (let i2 = 0;i2 < results.length; i2++) {
114169
- const item = o.deserialize(rows2[i2].payloadJson);
114211
+ const item = o.deserialize(rows[i2].payloadJson);
114170
114212
  const outcome = o.classifyOutcome?.(results[i2], item) ?? { kind: "success" };
114171
114213
  if (outcome.kind === "retry") {
114172
- o.store.updatePayload(rows2[i2].id, o.serialize(outcome.item));
114173
- o.store.markPending(rows2[i2].id);
114214
+ o.store.updatePayload(rows[i2].id, o.serialize(outcome.item));
114215
+ o.store.markPending(rows[i2].id);
114174
114216
  hasRetry = true;
114175
114217
  continue;
114176
114218
  }
114177
- o.store.markDone(rows2[i2].id);
114178
- waiters.get(rows2[i2].id)?.resolve(results[i2]);
114179
- waiters.delete(rows2[i2].id);
114219
+ o.store.markDone(rows[i2].id);
114220
+ waiters.get(rows[i2].id)?.resolve(results[i2]);
114221
+ waiters.delete(rows[i2].id);
114180
114222
  }
114181
- for (let i2 = results.length;i2 < rows2.length; i2++)
114182
- o.store.markPending(rows2[i2].id);
114223
+ for (let i2 = results.length;i2 < rows.length; i2++)
114224
+ o.store.markPending(rows[i2].id);
114183
114225
  if (hasRetry) {
114184
114226
  scheduleRetry();
114185
114227
  break;
@@ -114187,7 +114229,7 @@ function createFifoBatchedOutbox(o) {
114187
114229
  retryAttempt = 0;
114188
114230
  } catch (e) {
114189
114231
  o.onError?.(e);
114190
- for (const r of rows2)
114232
+ for (const r of rows)
114191
114233
  o.store.markPendingRetry(r.id, e);
114192
114234
  scheduleRetry();
114193
114235
  break;
@@ -115715,20 +115757,7 @@ var init_command_run_subscription = __esm(() => {
115715
115757
  dispatchedStop = new Set;
115716
115758
  });
115717
115759
 
115718
- // src/daemon/entry/assigned-task-monitor-registry.ts
115719
- function registerAssignedTaskMonitorHandler(h) {
115720
- handler6 = h;
115721
- }
115722
- function unregisterAssignedTaskMonitorHandler() {
115723
- handler6 = undefined;
115724
- }
115725
- async function dispatchAssignedTaskMonitorEvent(event) {
115726
- if (handler6)
115727
- await handler6(event);
115728
- }
115729
- var handler6;
115730
-
115731
- // src/daemon/entry/task-monitor/task-monitor-logic.ts
115760
+ // src/daemon/entry/task-delivery/task-delivery-logic.ts
115732
115761
  function isPendingAliveRunningTask(task) {
115733
115762
  const { agentConfig, status: status3 } = task;
115734
115763
  return status3 === "pending" && agentConfig.spawnedAgentPid != null && isAgentDesiredRunning(agentConfig.desiredState);
@@ -115787,9 +115816,29 @@ function listNativeTasksNeedingRevive(tasks, health, now, cooldown) {
115787
115816
  const { chatroomId, agentConfig } = task;
115788
115817
  if (!agentConfig.workingDir)
115789
115818
  return false;
115790
- if (!cooldown.canNudge(chatroomId, agentConfig.role, now))
115819
+ if (!cooldown.canAttempt(chatroomId, agentConfig.role, "revive", now))
115791
115820
  return false;
115792
- cooldown.recordNudge(chatroomId, agentConfig.role, now);
115821
+ cooldown.recordAttempt(chatroomId, agentConfig.role, "revive", now);
115822
+ return true;
115823
+ });
115824
+ }
115825
+ function isNativePendingTaskNeedingWake(task) {
115826
+ if (!isNativeHarness(task.agentConfig.agentHarness))
115827
+ return false;
115828
+ if (task.status !== "pending")
115829
+ return false;
115830
+ if (isAgentDesiredRunning(task.agentConfig.desiredState))
115831
+ return false;
115832
+ return Boolean(task.agentConfig.workingDir);
115833
+ }
115834
+ function listNativePendingTasksNeedingWake(tasks, cooldown, now) {
115835
+ return tasks.filter((task) => {
115836
+ if (!isNativePendingTaskNeedingWake(task))
115837
+ return false;
115838
+ const { chatroomId, agentConfig } = task;
115839
+ if (!cooldown.canAttempt(chatroomId, agentConfig.role, "wake", now))
115840
+ return false;
115841
+ cooldown.recordAttempt(chatroomId, agentConfig.role, "wake", now);
115793
115842
  return true;
115794
115843
  });
115795
115844
  }
@@ -115813,23 +115862,20 @@ function shouldNudgeNativePendingTask(task, now, pendingIdleThresholdMs, slot) {
115813
115862
  const idleSince = lastSeenAt > 0 ? now - lastSeenAt : now - task.createdAt;
115814
115863
  return idleSince > pendingIdleThresholdMs;
115815
115864
  }
115816
- function shouldEscalateNativeNudgeToRestart(chatroomId, role, failures3) {
115817
- return failures3 >= NATIVE_NUDGE_ESCALATION_THRESHOLD;
115818
- }
115819
115865
 
115820
- class NudgeCooldown {
115866
+ class RecoveryCooldown {
115821
115867
  cooldownMs;
115822
- lastNudgedAt = new Map;
115868
+ lastAttemptAt = new Map;
115823
115869
  constructor(cooldownMs = NUDGE_COOLDOWN_MS) {
115824
115870
  this.cooldownMs = cooldownMs;
115825
115871
  }
115826
- canNudge(chatroomId, role, now) {
115827
- const key = `${chatroomId}:${role}`;
115828
- const last2 = this.lastNudgedAt.get(key);
115872
+ canAttempt(chatroomId, role, kind, now) {
115873
+ const key = `${kind}:${chatroomId}:${role}`;
115874
+ const last2 = this.lastAttemptAt.get(key);
115829
115875
  return last2 === undefined || now - last2 >= this.cooldownMs;
115830
115876
  }
115831
- recordNudge(chatroomId, role, now) {
115832
- this.lastNudgedAt.set(`${chatroomId}:${role}`, now);
115877
+ recordAttempt(chatroomId, role, kind, now) {
115878
+ this.lastAttemptAt.set(`${kind}:${chatroomId}:${role}`, now);
115833
115879
  }
115834
115880
  }
115835
115881
  function isTaskReadyForNudge(task, now, cooldown, getSlot) {
@@ -115841,7 +115887,7 @@ function isTaskReadyForNudge(task, now, cooldown, getSlot) {
115841
115887
  return false;
115842
115888
  }
115843
115889
  const { chatroomId, agentConfig } = task;
115844
- if (!cooldown.canNudge(chatroomId, agentConfig.role, now))
115890
+ if (!cooldown.canAttempt(chatroomId, agentConfig.role, "nudge", now))
115845
115891
  return false;
115846
115892
  if (!agentConfig.workingDir)
115847
115893
  return false;
@@ -115851,12 +115897,12 @@ function listTasksReadyForNudge(tasks, now, cooldown, getSlot) {
115851
115897
  return tasks.filter((task) => {
115852
115898
  if (!isTaskReadyForNudge(task, now, cooldown, getSlot))
115853
115899
  return false;
115854
- cooldown.recordNudge(task.chatroomId, task.agentConfig.role, now);
115900
+ cooldown.recordAttempt(task.chatroomId, task.agentConfig.role, "nudge", now);
115855
115901
  return true;
115856
115902
  });
115857
115903
  }
115858
- var PENDING_IDLE_NUDGE_MS = 15000, NUDGE_COOLDOWN_MS = 60000, NATIVE_NUDGE_ESCALATION_THRESHOLD = 2;
115859
- var init_task_monitor_logic = __esm(() => {
115904
+ var PENDING_IDLE_NUDGE_MS = 15000, NUDGE_COOLDOWN_MS = 60000;
115905
+ var init_task_delivery_logic = __esm(() => {
115860
115906
  init_assigned_task();
115861
115907
  init_check_agent_slot();
115862
115908
  init_predicates();
@@ -115865,7 +115911,7 @@ var init_task_monitor_logic = __esm(() => {
115865
115911
  init_native_task_injector_logic();
115866
115912
  });
115867
115913
 
115868
- // src/daemon/entry/task-monitor-runtime.ts
115914
+ // src/daemon/entry/native-delivery/task-delivery-processor.ts
115869
115915
  function resolveTaskWantResume(task) {
115870
115916
  return sessionAugmentationToWantResume(resolveSessionAugmentationForTask({ content: task.taskContent ?? "", startInNewSession: task.startInNewSession }, task.agentConfig.role));
115871
115917
  }
@@ -115955,6 +116001,24 @@ function runNativeReviveEffect(task, runtime4, effectContext2, agentMgr) {
115955
116001
  });
115956
116002
  }).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[TaskMonitor] native revive failed for ${role}@${chatroomId}: ${getErrorMessage(err)}`)))));
115957
116003
  }
116004
+ function runNativeWakeEffect(task, runtime4, effectContext2, agentMgr) {
116005
+ const ctx = resolveTaskRunnerContextFromFull(task);
116006
+ if (!ctx)
116007
+ return;
116008
+ const { chatroomId, agentConfig, role, workingDir, wantResume } = ctx;
116009
+ console.log(`[TaskMonitor] native wake ${role}@${chatroomId} — desiredState=stopped with pending task ${task.taskId}`);
116010
+ exports_Runtime.runFork(runtime4)(exports_Effect.gen(function* () {
116011
+ yield* agentMgr.ensureRunning({
116012
+ chatroomId,
116013
+ role,
116014
+ agentHarness: agentConfig.agentHarness,
116015
+ model: agentConfig.model,
116016
+ workingDir,
116017
+ reason: "platform.pending_task_wake",
116018
+ wantResume
116019
+ });
116020
+ }).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[TaskMonitor] native wake failed for ${role}@${chatroomId}: ${getErrorMessage(err)}`)))));
116021
+ }
115958
116022
  async function fetchTaskForAction(sessionDeps, machineId, snapshotRow) {
115959
116023
  const result = await sessionDeps.backend.query(api.machines.getAssignedTaskForAction, {
115960
116024
  sessionId: sessionDeps.sessionId,
@@ -115976,43 +116040,9 @@ async function clearStuckStoppingSlotIfNeeded(agentMgr, chatroomId, role) {
115976
116040
  }
115977
116041
  async function nudgeStuckTasks(tasks, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId) {
115978
116042
  const getSlot = (chatroomId, role) => agentMgr.getSlot(chatroomId, role);
115979
- for (const row of listTasksReadyForNudge(tasks, now, cooldown, getSlot)) {
116043
+ const cliTasks = tasks.filter((task) => !isNativeHarness(task.agentConfig.agentHarness));
116044
+ for (const row of listTasksReadyForNudge(cliTasks, now, cooldown, getSlot)) {
115980
116045
  await clearStuckStoppingSlotIfNeeded(agentMgr, row.chatroomId, row.agentConfig.role);
115981
- if (isNativeHarness(row.agentConfig.agentHarness)) {
115982
- const { chatroomId, agentConfig } = row;
115983
- const { role } = agentConfig;
115984
- if (!isTeamAgentRole(role))
115985
- continue;
115986
- const deliveryState = getRoleDeliveryState();
115987
- const failures3 = deliveryState.recordNativeNudgeFailure(chatroomId, role);
115988
- if (shouldEscalateNativeNudgeToRestart(chatroomId, role, failures3)) {
115989
- const full2 = await fetchTaskForAction(sessionDeps, machineId, row);
115990
- if (!full2)
115991
- continue;
115992
- console.log(`[TaskMonitor] native nudge escalate restart ${role}@${chatroomId} — pending task ${row.taskId}`);
115993
- runCliNudgeEffect(full2, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
115994
- deliveryState.clearNativeNudgeFailures(chatroomId, role);
115995
- continue;
115996
- }
115997
- resetRoleDeliveryState(chatroomId, role);
115998
- await sessionDeps.backend.mutation(api.participants.join, {
115999
- sessionId: sessionDeps.sessionId,
116000
- chatroomId,
116001
- role,
116002
- action: NATIVE_WAITING_ACTION
116003
- });
116004
- console.log(`[TaskMonitor] native light nudge ${role}@${chatroomId} — redeliver pending task ${row.taskId}`);
116005
- logNativeDeliveryFallback("native-light-nudge", role, chatroomId, row.taskId);
116006
- getNativeTaskDeliveryCoordinator().reconcileAssignedTasks({
116007
- tasks: [row],
116008
- runtime: runtime4,
116009
- effectContext: effectContext2,
116010
- agentMgr,
116011
- sessionDeps,
116012
- machineId
116013
- });
116014
- continue;
116015
- }
116016
116046
  const full = await fetchTaskForAction(sessionDeps, machineId, row);
116017
116047
  if (!full)
116018
116048
  continue;
@@ -116030,7 +116060,19 @@ async function reviveNativeTasks(tasks, localHealth, now, cooldown, runtime4, ef
116030
116060
  runNativeReviveEffect(full, runtime4, effectContext2, agentMgr);
116031
116061
  }
116032
116062
  }
116033
- async function processTasksUpdate(tasks, runtime4, effectContext2, cooldown, agentMgr, sessionDeps, machineId, _pass) {
116063
+ async function wakeStoppedAgentsForPendingTasks(tasks, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId) {
116064
+ for (const row of listNativePendingTasksNeedingWake(tasks, cooldown, now)) {
116065
+ if (isRestartOrchestratorInFlight(row.chatroomId, row.agentConfig.role))
116066
+ continue;
116067
+ await clearStuckStoppingSlotIfNeeded(agentMgr, row.chatroomId, row.agentConfig.role);
116068
+ const full = await fetchTaskForAction(sessionDeps, machineId, row);
116069
+ if (!full)
116070
+ continue;
116071
+ runNativeWakeEffect(full, runtime4, effectContext2, agentMgr);
116072
+ }
116073
+ }
116074
+ async function processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, machineId, _pass, options) {
116075
+ const tasks = options?.snapshots ? [...options.snapshots] : await fetchMachineAssignedTaskSnapshots(sessionDeps, machineId);
116034
116076
  const filteredTasks = filterSnapshotsExcludingRestartInFlight(tasks);
116035
116077
  if (filteredTasks.length === 0)
116036
116078
  return;
@@ -116039,10 +116081,11 @@ async function processTasksUpdate(tasks, runtime4, effectContext2, cooldown, age
116039
116081
  getSlot: (chatroomId, role) => agentMgr.getSlot(chatroomId, role),
116040
116082
  isPidAlive: (pid) => isProcessAlive((p) => process.kill(p, 0), pid)
116041
116083
  };
116084
+ await wakeStoppedAgentsForPendingTasks(filteredTasks, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
116042
116085
  await reviveNativeTasks(filteredTasks, localHealth, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
116043
116086
  if (filteredTasks.length > 0) {
116044
116087
  const first = filteredTasks[0];
116045
- logNativeDeliveryFallback("signal-presence", first.agentConfig.role, first.chatroomId, first.taskId);
116088
+ logNativeDeliveryFallback(_pass, first.agentConfig.role, first.chatroomId, first.taskId);
116046
116089
  }
116047
116090
  getNativeTaskDeliveryCoordinator().reconcileAssignedTasks({
116048
116091
  tasks: filteredTasks,
@@ -116054,60 +116097,317 @@ async function processTasksUpdate(tasks, runtime4, effectContext2, cooldown, age
116054
116097
  });
116055
116098
  await nudgeStuckTasks(filteredTasks, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
116056
116099
  }
116057
- function listDeliverablePendingFromStore(agentMgr) {
116058
- if (!hasAssignedTaskSnapshot())
116059
- return [];
116060
- return listAssignedTaskSnapshots().filter((row) => {
116061
- if (row.status !== "pending")
116062
- return false;
116063
- const slot = agentMgr.getSlot(row.chatroomId, row.agentConfig.role);
116064
- return isAgentReadyForNativeDelivery(row, slot);
116065
- });
116100
+ var init_task_delivery_processor = __esm(() => {
116101
+ init_parse_session_augmentation();
116102
+ init_esm();
116103
+ init_native_task_delivery_coordinator();
116104
+ init_native_task_injector_logic();
116105
+ init_api3();
116106
+ init_convex_error();
116107
+ init_fetch_machine_assigned_task_snapshots();
116108
+ init_restart_orchestrator_in_flight();
116109
+ init_task_delivery_logic();
116110
+ });
116111
+
116112
+ // src/daemon/infrastructure/inbox/store/schema.ts
116113
+ var SCHEMA_VERSION = 1, MIGRATIONS;
116114
+ var init_schema = __esm(() => {
116115
+ MIGRATIONS = [
116116
+ `CREATE TABLE IF NOT EXISTS schema_meta (
116117
+ key TEXT PRIMARY KEY,
116118
+ value TEXT NOT NULL
116119
+ )`,
116120
+ `CREATE TABLE IF NOT EXISTS inbox_state (
116121
+ inbox_type TEXT NOT NULL,
116122
+ scope_key TEXT NOT NULL,
116123
+ state_json TEXT NOT NULL,
116124
+ created_at INTEGER NOT NULL,
116125
+ updated_at INTEGER NOT NULL,
116126
+ PRIMARY KEY (inbox_type, scope_key)
116127
+ )`,
116128
+ `CREATE INDEX IF NOT EXISTS idx_inbox_state_type_updated
116129
+ ON inbox_state(inbox_type, updated_at DESC)`,
116130
+ `CREATE INDEX IF NOT EXISTS idx_inbox_state_updated
116131
+ ON inbox_state(updated_at DESC)`
116132
+ ];
116133
+ });
116134
+
116135
+ // src/daemon/infrastructure/inbox/store/open-database.ts
116136
+ import { mkdirSync as mkdirSync8 } from "node:fs";
116137
+ import { dirname as dirname15 } from "node:path";
116138
+ import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
116139
+ function openDatabase(dbPath) {
116140
+ mkdirSync8(dirname15(dbPath), { recursive: true });
116141
+ const db = new DatabaseSync3(dbPath);
116142
+ for (const sql of MIGRATIONS) {
116143
+ db.exec(sql);
116144
+ }
116145
+ db.prepare(`INSERT INTO schema_meta(key, value) VALUES('version', ?)
116146
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(String(SCHEMA_VERSION));
116147
+ return db;
116066
116148
  }
116067
- function runLocalStoreReconcilePass(params) {
116068
- const { stopped, monitorPassInFlight, agentMgr, runtime: runtime4, effectContext: effectContext2, sessionDeps, machineId } = params;
116069
- if (stopped || monitorPassInFlight)
116070
- return;
116071
- const deliverable = filterSnapshotsExcludingRestartInFlight(listDeliverablePendingFromStore(agentMgr));
116072
- if (deliverable.length === 0)
116149
+ var init_open_database = __esm(() => {
116150
+ init_schema();
116151
+ });
116152
+
116153
+ // src/daemon/infrastructure/inbox/store/state-store.ts
116154
+ function assertKeyPart(value, name) {
116155
+ if (value.trim().length === 0) {
116156
+ throw new Error(`${name} cannot be empty`);
116157
+ }
116158
+ }
116159
+ function encodeState(state) {
116160
+ const encoded = JSON.stringify(state);
116161
+ if (encoded === undefined) {
116162
+ throw new Error("Inbox state must be JSON serializable");
116163
+ }
116164
+ return encoded;
116165
+ }
116166
+ function decodeRow(row) {
116167
+ return {
116168
+ inboxType: row.inbox_type,
116169
+ scopeKey: row.scope_key,
116170
+ state: JSON.parse(row.state_json),
116171
+ createdAt: row.created_at,
116172
+ updatedAt: row.updated_at
116173
+ };
116174
+ }
116175
+ function buildQuery(options) {
116176
+ const clauses = [];
116177
+ const params = [];
116178
+ if (options.inboxType !== undefined) {
116179
+ clauses.push("inbox_type = ?");
116180
+ params.push(options.inboxType);
116181
+ }
116182
+ if (options.scopeKey !== undefined) {
116183
+ clauses.push("scope_key = ?");
116184
+ params.push(options.scopeKey);
116185
+ }
116186
+ if (options.scopePrefix !== undefined) {
116187
+ clauses.push("scope_key LIKE ?");
116188
+ params.push(`${options.scopePrefix}%`);
116189
+ }
116190
+ if (options.updatedAfter !== undefined) {
116191
+ clauses.push("updated_at > ?");
116192
+ params.push(options.updatedAfter);
116193
+ }
116194
+ const where = clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "";
116195
+ const limit = Math.min(Math.max(options.limit ?? MAX_QUERY_LIMIT, 1), MAX_QUERY_LIMIT);
116196
+ return {
116197
+ sql: `SELECT inbox_type, scope_key, state_json, created_at, updated_at
116198
+ FROM inbox_state ${where}
116199
+ ORDER BY updated_at DESC, inbox_type ASC, scope_key ASC
116200
+ LIMIT ?`,
116201
+ params: [...params, limit]
116202
+ };
116203
+ }
116204
+ function getInboxState(db, key) {
116205
+ assertKeyPart(key.inboxType, "inboxType");
116206
+ assertKeyPart(key.scopeKey, "scopeKey");
116207
+ const row = db.prepare(`SELECT inbox_type, scope_key, state_json, created_at, updated_at
116208
+ FROM inbox_state
116209
+ WHERE inbox_type = ? AND scope_key = ?`).get(key.inboxType, key.scopeKey);
116210
+ return row ? decodeRow(row) : null;
116211
+ }
116212
+ function saveInboxState(db, key, state, updatedAt = Date.now()) {
116213
+ assertKeyPart(key.inboxType, "inboxType");
116214
+ assertKeyPart(key.scopeKey, "scopeKey");
116215
+ const stateJson = encodeState(state);
116216
+ db.prepare(`INSERT INTO inbox_state(inbox_type, scope_key, state_json, created_at, updated_at)
116217
+ VALUES(?, ?, ?, ?, ?)
116218
+ ON CONFLICT(inbox_type, scope_key) DO UPDATE SET
116219
+ state_json = excluded.state_json,
116220
+ updated_at = excluded.updated_at`).run(key.inboxType, key.scopeKey, stateJson, updatedAt, updatedAt);
116221
+ }
116222
+ function queryInboxState(db, options = {}) {
116223
+ const { sql, params } = buildQuery(options);
116224
+ return db.prepare(sql).all(...params).map((row) => decodeRow(row));
116225
+ }
116226
+ function deleteInboxState(db, key) {
116227
+ assertKeyPart(key.inboxType, "inboxType");
116228
+ assertKeyPart(key.scopeKey, "scopeKey");
116229
+ db.prepare("DELETE FROM inbox_state WHERE inbox_type = ? AND scope_key = ?").run(key.inboxType, key.scopeKey);
116230
+ }
116231
+ var MAX_QUERY_LIMIT = 1000;
116232
+
116233
+ // src/daemon/infrastructure/inbox/store/inbox-state-store.ts
116234
+ function createInboxStateStore(dbPath) {
116235
+ const db = openDatabase(dbPath);
116236
+ return {
116237
+ get: (key) => getInboxState(db, key),
116238
+ save: (key, state, updatedAt) => saveInboxState(db, key, state, updatedAt),
116239
+ query: (options) => queryInboxState(db, options),
116240
+ delete: (key) => deleteInboxState(db, key),
116241
+ close: () => db.close()
116242
+ };
116243
+ }
116244
+ var init_inbox_state_store = __esm(() => {
116245
+ init_open_database();
116246
+ });
116247
+
116248
+ // src/daemon/infrastructure/inbox/store/inbox-db-path.ts
116249
+ import { homedir as homedir10 } from "node:os";
116250
+ import { join as join26 } from "node:path";
116251
+ function resolveInboxDbPath(machineId) {
116252
+ return join26(homedir10(), ".chatroom", "daemon", machineId, "inboxes.sqlite");
116253
+ }
116254
+ var init_inbox_db_path = () => {};
116255
+
116256
+ // src/daemon/infrastructure/inbox/index.ts
116257
+ var init_inbox = __esm(() => {
116258
+ init_inbox_state_store();
116259
+ init_inbox_db_path();
116260
+ });
116261
+
116262
+ // src/daemon/infrastructure/inbox/task-inbox-delivery.ts
116263
+ async function handleTaskInboxUpdate(update6, deps) {
116264
+ if (update6.snapshots.length === 0)
116073
116265
  return;
116074
- const first = deliverable[0];
116075
- logNativeDeliveryFallback("periodic-reconcile", first.agentConfig.role, first.chatroomId, first.taskId);
116076
- getNativeTaskDeliveryCoordinator().reconcileAssignedTasks({
116077
- tasks: deliverable,
116078
- runtime: runtime4,
116079
- effectContext: effectContext2,
116080
- agentMgr,
116081
- sessionDeps,
116082
- machineId
116083
- });
116266
+ await processTasksUpdate(deps.runtime, deps.effectContext, deps.cooldown, deps.agentMgr, deps.sessionDeps, deps.machineId, "inbox-signal");
116084
116267
  }
116085
- function subscribeAssignedTaskSnapshotStore(wsClient2, args2, isStopped) {
116086
- return wsClient2.onUpdate(api.machines.listMachineAssignedTaskSnapshots, args2, (result) => {
116087
- if (isStopped())
116268
+ var init_task_inbox_delivery = __esm(() => {
116269
+ init_task_delivery_processor();
116270
+ });
116271
+
116272
+ // src/daemon/infrastructure/inbox/task.ts
116273
+ function taskSignalCursorAt(timestamp) {
116274
+ return `${String(Math.max(0, Math.floor(timestamp))).padStart(16, "0")}:`;
116275
+ }
116276
+ function abortError() {
116277
+ const error51 = new Error("Task inbox stopped");
116278
+ error51.name = "AbortError";
116279
+ return error51;
116280
+ }
116281
+ function throwIfAborted(signal) {
116282
+ if (signal?.aborted)
116283
+ throw abortError();
116284
+ }
116285
+ function waitForTaskSignalPage(options, afterSignalKey) {
116286
+ return new Promise((resolve8, reject) => {
116287
+ let unsubscribe;
116288
+ let settled = false;
116289
+ const cleanup = () => {
116290
+ unsubscribe?.();
116291
+ unsubscribe = undefined;
116292
+ options.signal?.removeEventListener("abort", onAbort);
116293
+ };
116294
+ const settle2 = (fn2) => {
116295
+ if (settled)
116296
+ return;
116297
+ settled = true;
116298
+ cleanup();
116299
+ fn2();
116300
+ };
116301
+ const onAbort = () => {
116302
+ settle2(() => reject(abortError()));
116303
+ };
116304
+ options.signal?.addEventListener("abort", onAbort, { once: true });
116305
+ try {
116306
+ throwIfAborted(options.signal);
116307
+ } catch (error51) {
116308
+ settle2(() => reject(error51));
116088
116309
  return;
116089
- const tasks = mapAssignedTaskSnapshotList(parseAssignedTaskMonitorRows(result?.tasks ?? []));
116090
- replaceAssignedTaskSnapshots(tasks);
116091
- }, (err) => {
116092
- console.warn(`[${formatTimestamp()}] ⚠️ Assigned-task snapshot subscription error: ${getErrorMessage(err)}`);
116310
+ }
116311
+ unsubscribe = options.client.onUpdate(api.messageList.subscribeTaskStatusSignalsSince, {
116312
+ sessionId: options.sessionId,
116313
+ machineId: options.machineId,
116314
+ afterKey: afterSignalKey,
116315
+ limit: options.signalPageLimit ?? DEFAULT_SIGNAL_PAGE_LIMIT
116316
+ }, (result) => {
116317
+ if (!result || typeof result !== "object")
116318
+ return;
116319
+ const page = result;
116320
+ const items = page.items;
116321
+ const highKey = page.highKey;
116322
+ if (!items?.length || !highKey)
116323
+ return;
116324
+ settle2(() => resolve8({
116325
+ items,
116326
+ afterSignalKey,
116327
+ highSignalKey: highKey
116328
+ }));
116329
+ }, (error51) => {
116330
+ settle2(() => reject(error51));
116331
+ });
116093
116332
  });
116094
116333
  }
116095
- function handleInboundAssignedTaskEvent(event, runMonitorPass) {
116096
- const row = listAssignedTaskSnapshots().find((snapshot) => snapshot.taskId === event.taskId && snapshot.agentConfig.role === event.role);
116097
- if (!row)
116334
+ async function* createTaskSignalIterator(options) {
116335
+ let afterSignalKey = options.initialAfterSignalKey ?? taskSignalCursorAt(options.serviceStartedAt ?? Date.now());
116336
+ while (!options.signal?.aborted) {
116337
+ const page = await waitForTaskSignalPage(options, afterSignalKey);
116338
+ yield page;
116339
+ afterSignalKey = page.highSignalKey;
116340
+ }
116341
+ }
116342
+ async function fetchSnapshotsForSignalPage(options, page) {
116343
+ const snapshots = [];
116344
+ let afterSignalKey = page.afterSignalKey;
116345
+ while (true) {
116346
+ throwIfAborted(options.signal);
116347
+ const result = await options.client.query(api.tasks.listTasksForMachineSignalRange, {
116348
+ sessionId: options.sessionId,
116349
+ machineId: options.machineId,
116350
+ afterSignalKey,
116351
+ throughSignalKey: page.highSignalKey,
116352
+ limit: options.taskPageLimit ?? DEFAULT_TASK_PAGE_LIMIT
116353
+ });
116354
+ snapshots.push(...result.snapshots);
116355
+ if (!result.hasMore || !result.nextSignalKey)
116356
+ break;
116357
+ afterSignalKey = result.nextSignalKey;
116358
+ }
116359
+ return snapshots;
116360
+ }
116361
+ async function runTaskInbox(options, onUpdate) {
116362
+ for await (const page of createTaskSignalIterator(options)) {
116363
+ const snapshots = await fetchSnapshotsForSignalPage(options, page);
116364
+ await onUpdate({
116365
+ signals: page.items,
116366
+ snapshots,
116367
+ afterSignalKey: page.afterSignalKey,
116368
+ throughSignalKey: page.highSignalKey
116369
+ });
116370
+ }
116371
+ }
116372
+ var DEFAULT_SIGNAL_PAGE_LIMIT = 100, DEFAULT_TASK_PAGE_LIMIT = 500;
116373
+ var init_task = __esm(() => {
116374
+ init_api3();
116375
+ });
116376
+
116377
+ // src/daemon/entry/task-inbox-runtime.ts
116378
+ async function bootstrapMachineAssignedTaskSnapshots(deps) {
116379
+ await deps.sessionDeps.backend.mutation(api.machines.syncMachineAssignedTaskSnapshotsMutation, {
116380
+ sessionId: deps.sessionDeps.sessionId,
116381
+ machineId: deps.machineId
116382
+ });
116383
+ const tasks = await fetchMachineAssignedTaskSnapshots(deps.sessionDeps, deps.machineId);
116384
+ if (!tasks.length)
116098
116385
  return;
116099
- const pass = event.type === "assigned-task.signal" ? "signal" : "presence";
116100
- runMonitorPass([row], pass);
116386
+ await processTasksUpdate(deps.runtime, deps.effectContext, deps.cooldown, deps.agentMgr, deps.sessionDeps, deps.machineId, "bootstrap", { snapshots: tasks });
116387
+ }
116388
+ function isAbortError(error51) {
116389
+ return error51 instanceof Error && error51.name === "AbortError";
116390
+ }
116391
+ async function runInboxLoopWithRestart(options, onUpdate, isStopped) {
116392
+ let backoffMs = INBOX_RESTART_INITIAL_MS;
116393
+ while (!isStopped()) {
116394
+ try {
116395
+ await runTaskInbox(options, onUpdate);
116396
+ return;
116397
+ } catch (error51) {
116398
+ if (isStopped() || isAbortError(error51))
116399
+ return;
116400
+ console.warn(`[TaskInbox] loop error, restarting in ${backoffMs}ms:`, error51);
116401
+ await new Promise((resolve8) => setTimeout(resolve8, backoffMs));
116402
+ backoffMs = Math.min(backoffMs * 2, INBOX_RESTART_MAX_MS);
116403
+ }
116404
+ }
116101
116405
  }
116102
- var startTaskMonitorEffect = (wsClient2) => exports_Effect.gen(function* () {
116406
+ var INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInboxEffect = (wsClient2) => exports_Effect.gen(function* () {
116103
116407
  const session2 = yield* DaemonSessionService;
116104
116408
  const agentMgr = yield* DaemonAgentProcessManagerService;
116105
116409
  const effectContext2 = yield* exports_Effect.context();
116106
116410
  const runtime4 = yield* exports_Effect.runtime();
116107
- console.log(`[${formatTimestamp()}] \uD83D\uDCCB Starting task-monitor (incremental subscribe)`);
116108
- const cooldown = new NudgeCooldown;
116109
- let stopped = false;
116110
- let monitorPassInFlight = false;
116111
116411
  const sessionDeps = {
116112
116412
  sessionId: session2.sessionId,
116113
116413
  convexUrl: session2.convexUrl,
@@ -116118,6 +116418,14 @@ var startTaskMonitorEffect = (wsClient2) => exports_Effect.gen(function* () {
116118
116418
  query: (fn2, args2) => session2.backend.query(fn2, args2)
116119
116419
  }
116120
116420
  };
116421
+ console.log(`[${formatTimestamp()}] \uD83D\uDCEC Starting task-inbox (machine-scoped signals)`);
116422
+ const inboxStore = createInboxStateStore(resolveInboxDbPath(session2.machineId));
116423
+ const persisted = inboxStore.get({
116424
+ inboxType: "task",
116425
+ scopeKey: session2.machineId
116426
+ });
116427
+ const abort = new AbortController;
116428
+ let stopped = false;
116121
116429
  registerNativeDeliverySession({
116122
116430
  runtime: runtime4,
116123
116431
  effectContext: effectContext2,
@@ -116125,61 +116433,64 @@ var startTaskMonitorEffect = (wsClient2) => exports_Effect.gen(function* () {
116125
116433
  sessionDeps,
116126
116434
  machineId: session2.machineId
116127
116435
  });
116128
- const unsubscribeSnapshotStore = subscribeAssignedTaskSnapshotStore(wsClient2, { sessionId: session2.sessionId, machineId: session2.machineId }, () => stopped);
116129
- const runMonitorPass = (tasks, pass) => {
116130
- if (stopped || monitorPassInFlight || tasks.length === 0)
116131
- return;
116132
- monitorPassInFlight = true;
116133
- processTasksUpdate(tasks, runtime4, effectContext2, cooldown, agentMgr, sessionDeps, session2.machineId, pass).finally(() => {
116134
- monitorPassInFlight = false;
116135
- });
116436
+ const cooldown = new RecoveryCooldown;
116437
+ const inboxOptions = {
116438
+ client: wsClient2,
116439
+ sessionId: session2.sessionId,
116440
+ machineId: session2.machineId,
116441
+ serviceStartedAt: Date.now(),
116442
+ initialAfterSignalKey: persisted?.state.afterSignalKey,
116443
+ signal: abort.signal
116136
116444
  };
116137
- registerAssignedTaskMonitorHandler(async (event) => {
116138
- handleInboundAssignedTaskEvent(event, runMonitorPass);
116139
- });
116140
- const reconcileTimer = setInterval(() => {
116141
- runLocalStoreReconcilePass({
116142
- stopped,
116143
- monitorPassInFlight,
116144
- agentMgr,
116445
+ const inboxHandler = async (update6) => {
116446
+ await handleTaskInboxUpdate(update6, {
116145
116447
  runtime: runtime4,
116146
116448
  effectContext: effectContext2,
116449
+ cooldown,
116450
+ agentMgr,
116147
116451
  sessionDeps,
116148
116452
  machineId: session2.machineId
116149
116453
  });
116454
+ inboxStore.save({ inboxType: "task", scopeKey: session2.machineId }, { afterSignalKey: update6.throughSignalKey });
116455
+ };
116456
+ const reconcileTimer = setInterval(() => {
116457
+ if (stopped)
116458
+ return;
116459
+ processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, session2.machineId, "periodic-reconcile");
116150
116460
  }, NATIVE_DELIVERY_RECONCILE_MS);
116151
- yield* exports_Effect.tryPromise(() => session2.backend.mutation(api.machines.syncMachineAssignedTaskSnapshotsMutation, {
116152
- sessionId: session2.sessionId,
116461
+ yield* exports_Effect.tryPromise(() => bootstrapMachineAssignedTaskSnapshots({
116462
+ sessionDeps,
116463
+ runtime: runtime4,
116464
+ effectContext: effectContext2,
116465
+ cooldown,
116466
+ agentMgr,
116153
116467
  machineId: session2.machineId
116154
- })).pipe(exports_Effect.catchAll(() => exports_Effect.void));
116468
+ })).pipe(exports_Effect.catchAll((error51) => {
116469
+ console.warn("[TaskInbox] bootstrap failed:", error51);
116470
+ return exports_Effect.void;
116471
+ }));
116472
+ runInboxLoopWithRestart(inboxOptions, inboxHandler, () => stopped);
116155
116473
  return {
116156
116474
  stop() {
116157
116475
  stopped = true;
116158
- unregisterAssignedTaskMonitorHandler();
116159
- unsubscribeSnapshotStore();
116160
- clearAssignedTaskSnapshots();
116161
- unregisterNativeDeliverySession();
116476
+ abort.abort();
116162
116477
  clearInterval(reconcileTimer);
116163
- console.log(`[${formatTimestamp()}] \uD83D\uDCCB Task-monitor stopped`);
116478
+ unregisterNativeDeliverySession();
116479
+ inboxStore.close();
116164
116480
  }
116165
116481
  };
116166
116482
  });
116167
- var init_task_monitor_runtime = __esm(() => {
116483
+ var init_task_inbox_runtime = __esm(() => {
116168
116484
  init_reliability();
116169
- init_participant();
116170
- init_parse_session_augmentation();
116171
- init_assigned_task_monitor_contract();
116172
116485
  init_esm();
116173
116486
  init_daemon_services();
116174
- init_native_ready_invariant();
116175
- init_native_task_delivery_coordinator();
116176
- init_native_task_injector_logic();
116177
- init_restart_orchestrator_in_flight();
116178
- init_task_monitor_logic();
116179
116487
  init_api3();
116180
- init_assigned_task_snapshot_store();
116181
- init_convex_error();
116182
- init_execution_kind();
116488
+ init_task_delivery_processor();
116489
+ init_task_delivery_logic();
116490
+ init_fetch_machine_assigned_task_snapshots();
116491
+ init_inbox();
116492
+ init_task_inbox_delivery();
116493
+ init_task();
116183
116494
  });
116184
116495
 
116185
116496
  // src/daemon/entry/workspace-git/git-subscription.ts
@@ -116529,16 +116840,16 @@ var init_workspace_list_subscription = __esm(() => {
116529
116840
 
116530
116841
  // src/daemon/entry/workspace-git-inbound-registry.ts
116531
116842
  function registerWorkspaceGitInboundHandler(h) {
116532
- handler7 = h;
116843
+ handler6 = h;
116533
116844
  }
116534
116845
  function unregisterWorkspaceGitInboundHandler() {
116535
- handler7 = undefined;
116846
+ handler6 = undefined;
116536
116847
  }
116537
116848
  async function dispatchWorkspaceGitInboundEvent(event) {
116538
- if (handler7)
116539
- await handler7(event);
116849
+ if (handler6)
116850
+ await handler6(event);
116540
116851
  }
116541
- var handler7;
116852
+ var handler6;
116542
116853
 
116543
116854
  // src/events/lifecycle/on-daemon-shutdown.ts
116544
116855
  var onDaemonShutdownEffect;
@@ -116579,7 +116890,7 @@ function createDaemonRuntime(deps) {
116579
116890
  let directHarnessWorkerHandle = null;
116580
116891
  let agenticQueryWorkerHandle = null;
116581
116892
  let enhancerWorkerHandle = null;
116582
- let taskMonitorHandle = null;
116893
+ let taskInboxHandle = null;
116583
116894
  const activeSessions = new Map;
116584
116895
  const harnesses = new Map;
116585
116896
  let signalCount = 0;
@@ -116614,7 +116925,7 @@ function createDaemonRuntime(deps) {
116614
116925
  gitSubscriptionHandle?.stop();
116615
116926
  fileTreeSubscriptionHandle?.stop();
116616
116927
  workspaceListSubscriptionHandle?.stop();
116617
- taskMonitorHandle?.stop();
116928
+ taskInboxHandle?.stop();
116618
116929
  logObserverSubscriptionHandle?.stop();
116619
116930
  directHarnessWorkerHandle?.stop();
116620
116931
  agenticQueryWorkerHandle?.stop();
@@ -116720,7 +117031,7 @@ function createDaemonRuntime(deps) {
116720
117031
  break;
116721
117032
  }
116722
117033
  });
116723
- taskMonitorHandle = yield* startTaskMonitorEffect(deps.wsClient);
117034
+ taskInboxHandle = yield* startTaskInboxEffect(deps.wsClient);
116724
117035
  logObserverSubscriptionHandle = startLogObserverSubscription({ sessionId: session2.sessionId, machineId: session2.machineId }, deps.wsClient);
116725
117036
  const commandRunRuntime = yield* exports_Effect.runtime();
116726
117037
  if (featureFlags.directHarnessWorkers) {
@@ -116780,7 +117091,7 @@ var init_daemon_runtime = __esm(() => {
116780
117091
  init_command_run_subscription();
116781
117092
  init_log_observer_sync();
116782
117093
  init_init_daemon();
116783
- init_task_monitor_runtime();
117094
+ init_task_inbox_runtime();
116784
117095
  init_git_heartbeat();
116785
117096
  init_git_subscription();
116786
117097
  init_api3();
@@ -116808,24 +117119,6 @@ var init_agentic_query_bridge = __esm(() => {
116808
117119
  init_process_agentic_query_prompt();
116809
117120
  });
116810
117121
 
116811
- // src/daemon/domain/usecase/deliver-assigned-task.ts
116812
- async function deliverAssignedTaskInbound(deps, event) {
116813
- await deps.dispatchInbound(event);
116814
- }
116815
-
116816
- // src/daemon/entry/bridge/assigned-task-bridge.ts
116817
- function createDeliverAssignedTaskDeps() {
116818
- return { dispatchInbound: dispatchAssignedTaskMonitorEvent };
116819
- }
116820
- function createAssignedTaskRouterDeps() {
116821
- return {
116822
- deliverInbound: async (event) => {
116823
- await deliverAssignedTaskInbound(createDeliverAssignedTaskDeps(), event);
116824
- }
116825
- };
116826
- }
116827
- var init_assigned_task_bridge = () => {};
116828
-
116829
117122
  // src/daemon/domain/usecase/handle-command-event.ts
116830
117123
  async function handleCommandEvent(deps, event) {
116831
117124
  await deps.dispatchInbound(event);
@@ -116943,7 +117236,6 @@ var init_workspace_git_bridge = () => {};
116943
117236
  // src/daemon/entry/default-router-deps.ts
116944
117237
  function createDefaultEventRouterDeps() {
116945
117238
  return {
116946
- assignedTask: createAssignedTaskRouterDeps(),
116947
117239
  directHarness: createDirectHarnessRouterDeps(),
116948
117240
  command: createCommandRouterDeps(),
116949
117241
  workspaceGit: createWorkspaceGitRouterDeps(),
@@ -116954,7 +117246,6 @@ function createDefaultEventRouterDeps() {
116954
117246
  }
116955
117247
  var init_default_router_deps = __esm(() => {
116956
117248
  init_agentic_query_bridge();
116957
- init_assigned_task_bridge();
116958
117249
  init_command_bridge();
116959
117250
  init_direct_harness_bridge();
116960
117251
  init_enhancer_bridge();
@@ -117335,10 +117626,10 @@ var init_deps = __esm(() => {
117335
117626
  });
117336
117627
 
117337
117628
  // src/daemon/entry/persistence-path.ts
117338
- import { homedir as homedir10 } from "node:os";
117339
- import { join as join26 } from "node:path";
117629
+ import { homedir as homedir11 } from "node:os";
117630
+ import { join as join27 } from "node:path";
117340
117631
  function resolvePersistenceDbPath(machineId) {
117341
- return join26(homedir10(), ".chatroom", "daemon", machineId, "events.sqlite");
117632
+ return join27(homedir11(), ".chatroom", "daemon", machineId, "events.sqlite");
117342
117633
  }
117343
117634
  var init_persistence_path = () => {};
117344
117635
 
@@ -117349,13 +117640,6 @@ async function handleAgenticQueryInbound(deps, event) {
117349
117640
  }
117350
117641
  }
117351
117642
 
117352
- // src/daemon/domain/usecase/handle-assigned-task-inbound.ts
117353
- async function handleAssignedTaskInbound(deps, event) {
117354
- if (deps.deliverInbound) {
117355
- await deps.deliverInbound(event);
117356
- }
117357
- }
117358
-
117359
117643
  // src/daemon/domain/usecase/handle-command-inbound.ts
117360
117644
  async function handleCommandInbound(deps, event) {
117361
117645
  if (deps.deliverInbound) {
@@ -117394,10 +117678,6 @@ async function handleWorkspaceGitInbound(deps, event) {
117394
117678
  // src/daemon/entry/event-router.ts
117395
117679
  async function routeInboundEvent(deps, event) {
117396
117680
  switch (event.type) {
117397
- case "assigned-task.signal":
117398
- case "assigned-task.presence":
117399
- await handleAssignedTaskInbound(deps.assignedTask, event);
117400
- break;
117401
117681
  case "direct-harness.session-opened":
117402
117682
  case "direct-harness.prompt":
117403
117683
  case "direct-harness.command":
@@ -117496,403 +117776,6 @@ var init_agentic_query_session = __esm(() => {
117496
117776
  init_api3();
117497
117777
  });
117498
117778
 
117499
- // src/infrastructure/incremental-sync/layers.ts
117500
- var IntervalClock, IntervalClockLive;
117501
- var init_layers = __esm(() => {
117502
- init_esm();
117503
- IntervalClock = class IntervalClock extends exports_Context.Tag("IntervalClock")() {
117504
- };
117505
- IntervalClockLive = exports_Layer.succeed(IntervalClock, {
117506
- sleep: (ms) => exports_Effect.promise(() => new Promise((resolve8) => setTimeout(resolve8, ms)))
117507
- });
117508
- });
117509
-
117510
- // src/infrastructure/incremental-sync/message-buffer.ts
117511
- class MessageBuffer {
117512
- keyOf;
117513
- queue = [];
117514
- inBuffer = new Set;
117515
- inFlight = new Map;
117516
- recentlyAcked = new Map;
117517
- dedupe;
117518
- dedupeTtlMs;
117519
- maxSize;
117520
- constructor(config4, keyOf) {
117521
- this.keyOf = keyOf;
117522
- this.dedupe = config4.dedupe ?? true;
117523
- this.dedupeTtlMs = config4.dedupeTtlMs ?? 0;
117524
- this.maxSize = config4.maxSize;
117525
- }
117526
- enqueue(items) {
117527
- this.pruneRecentlyAcked();
117528
- let enqueued = 0;
117529
- for (const item of items) {
117530
- const key = this.keyOf(item);
117531
- if (this.dedupe && this.shouldSkip(key)) {
117532
- continue;
117533
- }
117534
- this.queue.push({ key, item });
117535
- this.inBuffer.add(key);
117536
- enqueued++;
117537
- }
117538
- if (enqueued > 0) {
117539
- this.queue.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
117540
- }
117541
- this.enforceMaxSize();
117542
- return enqueued;
117543
- }
117544
- dequeue() {
117545
- this.pruneRecentlyAcked();
117546
- const next4 = this.queue.shift();
117547
- if (!next4)
117548
- return;
117549
- this.inBuffer.delete(next4.key);
117550
- this.inFlight.set(next4.key, next4.item);
117551
- return next4.item;
117552
- }
117553
- ack(key) {
117554
- this.inFlight.delete(key);
117555
- if (this.dedupe) {
117556
- this.recentlyAcked.set(key, Date.now());
117557
- }
117558
- }
117559
- nack(key, requeue = false) {
117560
- const item = this.inFlight.get(key);
117561
- this.inFlight.delete(key);
117562
- if (requeue && item !== undefined) {
117563
- this.enqueue([item]);
117564
- }
117565
- }
117566
- size() {
117567
- return this.queue.length;
117568
- }
117569
- highKeyOf(items) {
117570
- if (items.length === 0)
117571
- return null;
117572
- let high = null;
117573
- for (const item of items) {
117574
- const key = this.keyOf(item);
117575
- if (high === null || key > high) {
117576
- high = key;
117577
- }
117578
- }
117579
- return high;
117580
- }
117581
- shouldSkip(key) {
117582
- if (this.inBuffer.has(key) || this.inFlight.has(key)) {
117583
- return true;
117584
- }
117585
- if (this.dedupeTtlMs > 0) {
117586
- const ackedAt = this.recentlyAcked.get(key);
117587
- if (ackedAt !== undefined && Date.now() - ackedAt < this.dedupeTtlMs) {
117588
- return true;
117589
- }
117590
- } else if (this.recentlyAcked.has(key)) {
117591
- return true;
117592
- }
117593
- return false;
117594
- }
117595
- pruneRecentlyAcked() {
117596
- if (this.dedupeTtlMs <= 0)
117597
- return;
117598
- const now = Date.now();
117599
- for (const [key, ackedAt] of this.recentlyAcked) {
117600
- if (now - ackedAt >= this.dedupeTtlMs) {
117601
- this.recentlyAcked.delete(key);
117602
- }
117603
- }
117604
- }
117605
- enforceMaxSize() {
117606
- while (this.queue.length > this.maxSize) {
117607
- const dropped = this.queue.shift();
117608
- if (dropped) {
117609
- this.inBuffer.delete(dropped.key);
117610
- console.warn(`[incremental-sync] Buffer full — dropped oldest unacked item (key=${dropped.key})`);
117611
- }
117612
- }
117613
- }
117614
- }
117615
- // src/infrastructure/incremental-sync/resolve-high-key.ts
117616
- function resolveHighKey(def, buffer, page) {
117617
- if (page.highKey !== null)
117618
- return page.highKey;
117619
- const fromItems = buffer.highKeyOf(page.items);
117620
- if (fromItems !== null)
117621
- return fromItems;
117622
- if (def.itemToKey && page.items.length > 0) {
117623
- let high = null;
117624
- for (const item of page.items) {
117625
- const key = def.itemToKey(item);
117626
- if (high === null || key > high)
117627
- high = key;
117628
- }
117629
- return high;
117630
- }
117631
- return null;
117632
- }
117633
-
117634
- // src/infrastructure/incremental-sync/subscribe-loop.ts
117635
- function parseFeedItems(def, items, onError3) {
117636
- if (!def.parseItem) {
117637
- return items;
117638
- }
117639
- const parsed = [];
117640
- for (const raw of items) {
117641
- try {
117642
- parsed.push(def.parseItem(raw));
117643
- } catch (err) {
117644
- onError3?.(err);
117645
- }
117646
- }
117647
- return parsed;
117648
- }
117649
- function startSubscribeLoop(opts) {
117650
- let afterKey = opts.initialAfterKey ?? null;
117651
- let stopped = false;
117652
- let unsubscribe;
117653
- let drainInFlight = false;
117654
- const subscribe = () => {
117655
- if (stopped)
117656
- return;
117657
- unsubscribe?.();
117658
- unsubscribe = opts.wsClient.onUpdate(opts.target.query, opts.target.buildArgs(opts.args, afterKey, opts.config.limit), (result) => {
117659
- if (stopped)
117660
- return;
117661
- const page = opts.target.parsePage(result);
117662
- drainPages(page);
117663
- }, (err) => {
117664
- opts.onError?.(err);
117665
- });
117666
- };
117667
- const fetchPage = async (cursor) => {
117668
- const result = await opts.wsClient.query(opts.target.query, opts.target.buildArgs(opts.args, cursor, opts.config.limit));
117669
- return opts.target.parsePage(result);
117670
- };
117671
- const drainPages = async (initialPage) => {
117672
- if (stopped || drainInFlight)
117673
- return;
117674
- drainInFlight = true;
117675
- try {
117676
- const cursorAtStart = afterKey;
117677
- let page = initialPage;
117678
- while (!stopped && page.items.length > 0) {
117679
- const items = parseFeedItems(opts.def, page.items, opts.onError);
117680
- if (items.length > 0) {
117681
- opts.buffer.enqueue(items);
117682
- }
117683
- const nextKey = resolveHighKey(opts.def, opts.buffer, page);
117684
- if (nextKey === null) {
117685
- break;
117686
- }
117687
- afterKey = nextKey;
117688
- if (!page.hasMore) {
117689
- break;
117690
- }
117691
- page = await fetchPage(afterKey);
117692
- }
117693
- if (!stopped && afterKey !== cursorAtStart) {
117694
- subscribe();
117695
- }
117696
- } catch (err) {
117697
- opts.onError?.(err);
117698
- } finally {
117699
- drainInFlight = false;
117700
- }
117701
- };
117702
- subscribe();
117703
- return {
117704
- stop: () => {
117705
- stopped = true;
117706
- unsubscribe?.();
117707
- unsubscribe = undefined;
117708
- },
117709
- getAfterKey: () => afterKey
117710
- };
117711
- }
117712
- var init_subscribe_loop = () => {};
117713
-
117714
- // src/infrastructure/incremental-sync/feed-runtime.ts
117715
- function runWorkerLoop(feedName, buffer, keyOf, onItem) {
117716
- return exports_Effect.gen(function* () {
117717
- while (true) {
117718
- const item = buffer.dequeue();
117719
- if (item === undefined) {
117720
- yield* exports_Effect.sleep("10 millis");
117721
- continue;
117722
- }
117723
- const key = keyOf(item);
117724
- const ctx = {
117725
- item,
117726
- feedName,
117727
- ack: () => buffer.ack(key),
117728
- nack: (opts) => buffer.nack(key, opts?.requeue ?? false)
117729
- };
117730
- yield* onItem(ctx).pipe(exports_Effect.catchAll(() => exports_Effect.void));
117731
- }
117732
- });
117733
- }
117734
- var runIncrementalSubscribeLive = (opts) => exports_Effect.gen(function* () {
117735
- const buffer = new MessageBuffer(opts.buffer, opts.def.itemKey);
117736
- const subscribeHandle = startSubscribeLoop({
117737
- wsClient: opts.wsClient,
117738
- target: opts.target,
117739
- args: opts.args,
117740
- buffer,
117741
- def: opts.def,
117742
- config: opts.subscribe,
117743
- initialAfterKey: opts.initialAfterKey ?? null,
117744
- onError: opts.onError
117745
- });
117746
- const workerFiber = yield* exports_Effect.forkDaemon(runWorkerLoop(opts.def.name, buffer, opts.def.itemKey, opts.onItem));
117747
- return {
117748
- buffer,
117749
- stop: () => exports_Effect.gen(function* () {
117750
- subscribeHandle.stop();
117751
- yield* exports_Fiber.interrupt(workerFiber);
117752
- })
117753
- };
117754
- });
117755
- var init_feed_runtime = __esm(() => {
117756
- init_esm();
117757
- init_layers();
117758
- init_subscribe_loop();
117759
- });
117760
-
117761
- // src/infrastructure/incremental-sync/feeds/assigned-task-presence.ts
117762
- var assignedTaskPresenceFeedDef, assignedTaskPresenceSubscribeTarget, ASSIGNED_TASK_PRESENCE_FEED_LIMIT = 50, ASSIGNED_TASK_PRESENCE_FEED_BUFFER;
117763
- var init_assigned_task_presence = __esm(() => {
117764
- init_assigned_task_monitor_contract();
117765
- init_api3();
117766
- assignedTaskPresenceFeedDef = {
117767
- name: "assigned-task-presence",
117768
- itemKey: (item) => item.presenceKey,
117769
- parseItem: parseAssignedTaskPresenceSignal
117770
- };
117771
- assignedTaskPresenceSubscribeTarget = {
117772
- query: api.machines.subscribeAssignedTaskPresenceSince,
117773
- buildArgs: (args2, afterKey, limit) => ({
117774
- sessionId: args2.sessionId,
117775
- machineId: args2.machineId,
117776
- afterPresenceKey: afterKey ?? undefined,
117777
- limit
117778
- }),
117779
- parsePage: (result) => {
117780
- const page = result;
117781
- return {
117782
- items: page.items,
117783
- highKey: page.highPresenceKey,
117784
- hasMore: page.hasMore
117785
- };
117786
- }
117787
- };
117788
- ASSIGNED_TASK_PRESENCE_FEED_BUFFER = {
117789
- maxSize: 200,
117790
- dedupe: true
117791
- };
117792
- });
117793
-
117794
- // src/daemon/infrastructure/convex/subscribers/assigned-task-presence.ts
117795
- function startAssignedTaskPresenceSubscriber(deps, onEvent) {
117796
- let stopped = false;
117797
- const startPromise = exports_Effect.runPromise(runIncrementalSubscribeLive({
117798
- wsClient: deps.wsClient,
117799
- def: assignedTaskPresenceFeedDef,
117800
- target: assignedTaskPresenceSubscribeTarget,
117801
- args: { sessionId: deps.sessionId, machineId: deps.machineId },
117802
- buffer: ASSIGNED_TASK_PRESENCE_FEED_BUFFER,
117803
- subscribe: { limit: ASSIGNED_TASK_PRESENCE_FEED_LIMIT },
117804
- onItem: ({ item, ack }) => exports_Effect.sync(() => {
117805
- if (stopped)
117806
- return;
117807
- ack();
117808
- onEvent({ type: "assigned-task.presence", taskId: item.taskId, role: item.role });
117809
- }),
117810
- onError: (err) => {
117811
- console.warn(`[daemon] assigned-task-presence subscriber error: ${String(err)}`);
117812
- }
117813
- }));
117814
- let feedHandle;
117815
- startPromise.then((handle) => {
117816
- feedHandle = handle;
117817
- });
117818
- return {
117819
- async stop() {
117820
- stopped = true;
117821
- const handle = feedHandle ?? await startPromise;
117822
- await exports_Effect.runPromise(handle.stop());
117823
- }
117824
- };
117825
- }
117826
- var init_assigned_task_presence2 = __esm(() => {
117827
- init_esm();
117828
- init_feed_runtime();
117829
- init_assigned_task_presence();
117830
- });
117831
-
117832
- // src/infrastructure/incremental-sync/feeds/assigned-task-signals.ts
117833
- var assignedTaskSignalsFeedDef, assignedTaskSignalsSubscribeTarget, ASSIGNED_TASK_SIGNAL_FEED_LIMIT = 50, ASSIGNED_TASK_SIGNAL_FEED_BUFFER;
117834
- var init_assigned_task_signals = __esm(() => {
117835
- init_assigned_task_monitor_contract();
117836
- init_api3();
117837
- assignedTaskSignalsFeedDef = {
117838
- name: "assigned-task-signals",
117839
- itemKey: (item) => item.revisionKey,
117840
- parseItem: parseAssignedTaskSignal
117841
- };
117842
- assignedTaskSignalsSubscribeTarget = {
117843
- query: api.machines.subscribeAssignedTaskSignalsSince,
117844
- buildArgs: (args2, afterKey, limit) => ({
117845
- sessionId: args2.sessionId,
117846
- machineId: args2.machineId,
117847
- afterKey: afterKey ?? undefined,
117848
- limit
117849
- }),
117850
- parsePage: (result) => result
117851
- };
117852
- ASSIGNED_TASK_SIGNAL_FEED_BUFFER = {
117853
- maxSize: 200,
117854
- dedupe: true
117855
- };
117856
- });
117857
-
117858
- // src/daemon/infrastructure/convex/subscribers/assigned-task-signals.ts
117859
- function startAssignedTaskSignalsSubscriber(deps, onEvent) {
117860
- let stopped = false;
117861
- const startPromise = exports_Effect.runPromise(runIncrementalSubscribeLive({
117862
- wsClient: deps.wsClient,
117863
- def: assignedTaskSignalsFeedDef,
117864
- target: assignedTaskSignalsSubscribeTarget,
117865
- args: { sessionId: deps.sessionId, machineId: deps.machineId },
117866
- buffer: ASSIGNED_TASK_SIGNAL_FEED_BUFFER,
117867
- subscribe: { limit: ASSIGNED_TASK_SIGNAL_FEED_LIMIT },
117868
- onItem: ({ item, ack }) => exports_Effect.sync(() => {
117869
- if (stopped)
117870
- return;
117871
- ack();
117872
- onEvent({ type: "assigned-task.signal", taskId: item.taskId, role: item.role });
117873
- }),
117874
- onError: (err) => {
117875
- console.warn(`[daemon] assigned-task-signals subscriber error: ${String(err)}`);
117876
- }
117877
- }));
117878
- let feedHandle;
117879
- startPromise.then((handle) => {
117880
- feedHandle = handle;
117881
- });
117882
- return {
117883
- async stop() {
117884
- stopped = true;
117885
- const handle = feedHandle ?? await startPromise;
117886
- await exports_Effect.runPromise(handle.stop());
117887
- }
117888
- };
117889
- }
117890
- var init_assigned_task_signals2 = __esm(() => {
117891
- init_esm();
117892
- init_feed_runtime();
117893
- init_assigned_task_signals();
117894
- });
117895
-
117896
117779
  // src/daemon/infrastructure/convex/subscribers/command-events.ts
117897
117780
  function startCommandEventsSubscriber(deps, onEvent) {
117898
117781
  const seen = new Set;
@@ -118304,8 +118187,6 @@ function startAllSubscribers(deps) {
118304
118187
  const onEvent = (event) => {
118305
118188
  routeInboundEvent(deps.router, event);
118306
118189
  };
118307
- const signals = startAssignedTaskSignalsSubscriber(deps, onEvent);
118308
- const presence = startAssignedTaskPresenceSubscriber(deps, onEvent);
118309
118190
  const session2 = startDirectHarnessSessionSubscriber(deps, onEvent);
118310
118191
  const prompt = startDirectHarnessPromptSubscriber(deps, onEvent);
118311
118192
  const directHarnessCommand = startDirectHarnessCommandSubscriber(deps, onEvent);
@@ -118323,8 +118204,6 @@ function startAllSubscribers(deps) {
118323
118204
  return {
118324
118205
  async stopAll() {
118325
118206
  await Promise.all([
118326
- signals.stop(),
118327
- presence.stop(),
118328
118207
  session2.stop(),
118329
118208
  prompt.stop(),
118330
118209
  directHarnessCommand.stop(),
@@ -118347,8 +118226,6 @@ var init_subscriber_registry = __esm(() => {
118347
118226
  init_event_router();
118348
118227
  init_agentic_query_prompt();
118349
118228
  init_agentic_query_session();
118350
- init_assigned_task_presence2();
118351
- init_assigned_task_signals2();
118352
118229
  init_command_events();
118353
118230
  init_command_run();
118354
118231
  init_direct_harness_command();
@@ -118378,19 +118255,19 @@ function resolveEnvSlug(convexUrl) {
118378
118255
  }
118379
118256
 
118380
118257
  // src/infrastructure/log-server/resolve-logs-db-path.ts
118381
- import { homedir as homedir11 } from "node:os";
118382
- import { join as join27 } from "node:path";
118258
+ import { homedir as homedir12 } from "node:os";
118259
+ import { join as join28 } from "node:path";
118383
118260
  function resolveLogsDbPath(convexUrl) {
118384
- return join27(homedir11(), ".chatroom", resolveEnvSlug(convexUrl ?? getConvexUrl()), "logs.sqlite");
118261
+ return join28(homedir12(), ".chatroom", resolveEnvSlug(convexUrl ?? getConvexUrl()), "logs.sqlite");
118385
118262
  }
118386
118263
  var init_resolve_logs_db_path = __esm(() => {
118387
118264
  init_client2();
118388
118265
  });
118389
118266
 
118390
118267
  // src/infrastructure/log-server/log-schema.ts
118391
- var SCHEMA_VERSION = 2, MIGRATIONS;
118268
+ var SCHEMA_VERSION2 = 2, MIGRATIONS2;
118392
118269
  var init_log_schema = __esm(() => {
118393
- MIGRATIONS = [
118270
+ MIGRATIONS2 = [
118394
118271
  `CREATE TABLE IF NOT EXISTS schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`,
118395
118272
  `CREATE TABLE IF NOT EXISTS log_entries (
118396
118273
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -118414,18 +118291,18 @@ var init_log_schema = __esm(() => {
118414
118291
  });
118415
118292
 
118416
118293
  // src/infrastructure/log-server/open-log-database.ts
118417
- import { mkdirSync as mkdirSync8 } from "node:fs";
118418
- import { dirname as dirname15 } from "node:path";
118419
- import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
118294
+ import { mkdirSync as mkdirSync9 } from "node:fs";
118295
+ import { dirname as dirname16 } from "node:path";
118296
+ import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
118420
118297
  function openLogDatabase(dbPath) {
118421
- mkdirSync8(dirname15(dbPath), { recursive: true });
118422
- const db = new DatabaseSync3(dbPath);
118298
+ mkdirSync9(dirname16(dbPath), { recursive: true });
118299
+ const db = new DatabaseSync4(dbPath);
118423
118300
  db.exec("PRAGMA journal_mode = WAL");
118424
118301
  db.exec("PRAGMA busy_timeout = 5000");
118425
118302
  db.exec("PRAGMA synchronous = NORMAL");
118426
- for (const migration of MIGRATIONS)
118303
+ for (const migration of MIGRATIONS2)
118427
118304
  db.exec(migration);
118428
- db.prepare(`INSERT INTO schema_meta(key,value) VALUES('version',?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`).run(String(SCHEMA_VERSION));
118305
+ db.prepare(`INSERT INTO schema_meta(key,value) VALUES('version',?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`).run(String(SCHEMA_VERSION2));
118429
118306
  return db;
118430
118307
  }
118431
118308
  var init_open_log_database = __esm(() => {
@@ -118474,8 +118351,8 @@ function queryEventStream(db, input) {
118474
118351
  ...input.toTimestamp !== undefined ? [input.toTimestamp] : [],
118475
118352
  clamp4(input.limit)
118476
118353
  ];
118477
- const rows2 = db.prepare(`SELECT * FROM event_stream_entries WHERE 1=1 ${filters} ORDER BY id DESC LIMIT ?`).all(...values3);
118478
- return rows2.reverse().map((row) => ({
118354
+ const rows = db.prepare(`SELECT * FROM event_stream_entries WHERE 1=1 ${filters} ORDER BY id DESC LIMIT ?`).all(...values3);
118355
+ return rows.reverse().map((row) => ({
118479
118356
  id: Number(row.id),
118480
118357
  timestamp: Number(row.timestamp),
118481
118358
  type: row.type,
@@ -118501,8 +118378,8 @@ function queryAfterId(db, afterId = 0, limit = 100, source, chatroomId, role, ha
118501
118378
  ...toTimestamp !== undefined ? [toTimestamp] : [],
118502
118379
  clamp4(limit)
118503
118380
  ];
118504
- const rows2 = db.prepare(`SELECT * FROM log_entries WHERE id > ? ${filters} ORDER BY id ASC LIMIT ?`).all(...values3);
118505
- return rows2.map(map19);
118381
+ const rows = db.prepare(`SELECT * FROM log_entries WHERE id > ? ${filters} ORDER BY id ASC LIMIT ?`).all(...values3);
118382
+ return rows.map(map19);
118506
118383
  }
118507
118384
  function queryHistory(db, beforeId, limit = 100, source, chatroomId, role, harness, fromTimestamp, toTimestamp) {
118508
118385
  const filters = [
@@ -118524,8 +118401,8 @@ function queryHistory(db, beforeId, limit = 100, source, chatroomId, role, harne
118524
118401
  ...toTimestamp !== undefined ? [toTimestamp] : [],
118525
118402
  clamp4(limit)
118526
118403
  ];
118527
- const rows2 = db.prepare(`SELECT * FROM log_entries WHERE 1=1 ${filters} ORDER BY id DESC LIMIT ?`).all(...values3);
118528
- return rows2.map(map19).reverse();
118404
+ const rows = db.prepare(`SELECT * FROM log_entries WHERE 1=1 ${filters} ORDER BY id DESC LIMIT ?`).all(...values3);
118405
+ return rows.map(map19).reverse();
118529
118406
  }
118530
118407
  function listLogDimensions(db, chatroomId, limit = 100) {
118531
118408
  const clamped = clamp4(limit);
@@ -118614,9 +118491,9 @@ function appendOutboundEvent(db, event) {
118614
118491
  }
118615
118492
 
118616
118493
  // src/daemon/infrastructure/persistence/schema.ts
118617
- var SCHEMA_VERSION2 = 1, MIGRATIONS2;
118618
- var init_schema = __esm(() => {
118619
- MIGRATIONS2 = [
118494
+ var SCHEMA_VERSION3 = 1, MIGRATIONS3;
118495
+ var init_schema2 = __esm(() => {
118496
+ MIGRATIONS3 = [
118620
118497
  `CREATE TABLE IF NOT EXISTS schema_meta (
118621
118498
  key TEXT PRIMARY KEY,
118622
118499
  value TEXT NOT NULL
@@ -118645,21 +118522,21 @@ var init_schema = __esm(() => {
118645
118522
  });
118646
118523
 
118647
118524
  // src/daemon/infrastructure/persistence/open-database.ts
118648
- import { mkdirSync as mkdirSync9 } from "node:fs";
118649
- import { dirname as dirname16 } from "node:path";
118650
- import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
118651
- function openDatabase(dbPath) {
118652
- mkdirSync9(dirname16(dbPath), { recursive: true });
118653
- const db = new DatabaseSync4(dbPath);
118654
- for (const sql of MIGRATIONS2) {
118525
+ import { mkdirSync as mkdirSync10 } from "node:fs";
118526
+ import { dirname as dirname17 } from "node:path";
118527
+ import { DatabaseSync as DatabaseSync5 } from "node:sqlite";
118528
+ function openDatabase2(dbPath) {
118529
+ mkdirSync10(dirname17(dbPath), { recursive: true });
118530
+ const db = new DatabaseSync5(dbPath);
118531
+ for (const sql of MIGRATIONS3) {
118655
118532
  db.exec(sql);
118656
118533
  }
118657
118534
  db.prepare(`INSERT INTO schema_meta(key, value) VALUES('version', ?)
118658
- ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(String(SCHEMA_VERSION2));
118535
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(String(SCHEMA_VERSION3));
118659
118536
  return db;
118660
118537
  }
118661
- var init_open_database = __esm(() => {
118662
- init_schema();
118538
+ var init_open_database2 = __esm(() => {
118539
+ init_schema2();
118663
118540
  });
118664
118541
 
118665
118542
  // src/daemon/infrastructure/persistence/outbox.ts
@@ -118677,10 +118554,10 @@ function listPendingOutbox(db, limit = 100) {
118677
118554
  // src/daemon/infrastructure/persistence/read-model.ts
118678
118555
  function listHarnessStreamLines(db, opts = {}) {
118679
118556
  const limit = opts.limit ?? 500;
118680
- const rows2 = db.prepare(`SELECT payload_json FROM outbound_events
118557
+ const rows = db.prepare(`SELECT payload_json FROM outbound_events
118681
118558
  WHERE event_type = 'harness.stream'
118682
118559
  ORDER BY id DESC LIMIT ?`).all(limit);
118683
- const parsed = rows2.map((row) => JSON.parse(row.payload_json)).filter((event) => event.type === "harness.stream");
118560
+ const parsed = rows.map((row) => JSON.parse(row.payload_json)).filter((event) => event.type === "harness.stream");
118684
118561
  if (!opts.harness)
118685
118562
  return parsed.reverse();
118686
118563
  return parsed.filter((e) => e.harness === opts.harness).reverse();
@@ -118688,7 +118565,7 @@ function listHarnessStreamLines(db, opts = {}) {
118688
118565
 
118689
118566
  // src/daemon/infrastructure/persistence/persistence-store.ts
118690
118567
  function createPersistenceStore(dbPath) {
118691
- const db = openDatabase(dbPath);
118568
+ const db = openDatabase2(dbPath);
118692
118569
  return {
118693
118570
  append(event) {
118694
118571
  const eventId = appendOutboundEvent(db, event);
@@ -118702,7 +118579,7 @@ function createPersistenceStore(dbPath) {
118702
118579
  };
118703
118580
  }
118704
118581
  var init_persistence_store = __esm(() => {
118705
- init_open_database();
118582
+ init_open_database2();
118706
118583
  });
118707
118584
 
118708
118585
  // src/daemon/infrastructure/persistence/index.ts
@@ -121435,9 +121312,9 @@ var require_event_target2 = __commonJS((exports, module) => {
121435
121312
  }
121436
121313
  Object.defineProperty(MessageEvent.prototype, "data", { enumerable: true });
121437
121314
  var EventTarget = {
121438
- addEventListener(type, handler8, options = {}) {
121315
+ addEventListener(type, handler7, options = {}) {
121439
121316
  for (const listener of this.listeners(type)) {
121440
- if (!options[kForOnEventAttribute] && listener[kListener] === handler8 && !listener[kForOnEventAttribute]) {
121317
+ if (!options[kForOnEventAttribute] && listener[kListener] === handler7 && !listener[kForOnEventAttribute]) {
121441
121318
  return;
121442
121319
  }
121443
121320
  }
@@ -121448,7 +121325,7 @@ var require_event_target2 = __commonJS((exports, module) => {
121448
121325
  data: isBinary ? data : data.toString()
121449
121326
  });
121450
121327
  event[kTarget] = this;
121451
- callListener(handler8, this, event);
121328
+ callListener(handler7, this, event);
121452
121329
  };
121453
121330
  } else if (type === "close") {
121454
121331
  wrapper = function onClose(code2, message) {
@@ -121458,7 +121335,7 @@ var require_event_target2 = __commonJS((exports, module) => {
121458
121335
  wasClean: this._closeFrameReceived && this._closeFrameSent
121459
121336
  });
121460
121337
  event[kTarget] = this;
121461
- callListener(handler8, this, event);
121338
+ callListener(handler7, this, event);
121462
121339
  };
121463
121340
  } else if (type === "error") {
121464
121341
  wrapper = function onError3(error51) {
@@ -121467,28 +121344,28 @@ var require_event_target2 = __commonJS((exports, module) => {
121467
121344
  message: error51.message
121468
121345
  });
121469
121346
  event[kTarget] = this;
121470
- callListener(handler8, this, event);
121347
+ callListener(handler7, this, event);
121471
121348
  };
121472
121349
  } else if (type === "open") {
121473
121350
  wrapper = function onOpen() {
121474
121351
  const event = new Event2("open");
121475
121352
  event[kTarget] = this;
121476
- callListener(handler8, this, event);
121353
+ callListener(handler7, this, event);
121477
121354
  };
121478
121355
  } else {
121479
121356
  return;
121480
121357
  }
121481
121358
  wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];
121482
- wrapper[kListener] = handler8;
121359
+ wrapper[kListener] = handler7;
121483
121360
  if (options.once) {
121484
121361
  this.once(type, wrapper);
121485
121362
  } else {
121486
121363
  this.on(type, wrapper);
121487
121364
  }
121488
121365
  },
121489
- removeEventListener(type, handler8) {
121366
+ removeEventListener(type, handler7) {
121490
121367
  for (const listener of this.listeners(type)) {
121491
- if (listener[kListener] === handler8 && !listener[kForOnEventAttribute]) {
121368
+ if (listener[kListener] === handler7 && !listener[kForOnEventAttribute]) {
121492
121369
  this.removeListener(type, listener);
121493
121370
  break;
121494
121371
  }
@@ -122017,16 +121894,16 @@ var require_websocket2 = __commonJS((exports, module) => {
122017
121894
  }
122018
121895
  return null;
122019
121896
  },
122020
- set(handler8) {
121897
+ set(handler7) {
122021
121898
  for (const listener of this.listeners(method)) {
122022
121899
  if (listener[kForOnEventAttribute]) {
122023
121900
  this.removeListener(method, listener);
122024
121901
  break;
122025
121902
  }
122026
121903
  }
122027
- if (typeof handler8 !== "function")
121904
+ if (typeof handler7 !== "function")
122028
121905
  return;
122029
- this.addEventListener(method, handler8, {
121906
+ this.addEventListener(method, handler7, {
122030
121907
  [kForOnEventAttribute]: true
122031
121908
  });
122032
121909
  }
@@ -132360,19 +132237,19 @@ function routeRequest(req, res, deps) {
132360
132237
 
132361
132238
  // src/daemon/local-web/server/serve-static.ts
132362
132239
  import { existsSync as existsSync10, readFileSync as readFileSync11 } from "node:fs";
132363
- import { dirname as dirname17, join as join28 } from "node:path";
132240
+ import { dirname as dirname18, join as join29 } from "node:path";
132364
132241
  import { fileURLToPath as fileURLToPath7 } from "node:url";
132365
132242
  function clientDistCandidates(here) {
132366
132243
  return [
132367
- join28(here, "client/build"),
132368
- join28(here, "../client/build"),
132369
- join28(here, "../src/daemon/local-web/client/build")
132244
+ join29(here, "client/build"),
132245
+ join29(here, "../client/build"),
132246
+ join29(here, "../src/daemon/local-web/client/build")
132370
132247
  ];
132371
132248
  }
132372
- function resolveClientDistDir(here = dirname17(fileURLToPath7(import.meta.url))) {
132249
+ function resolveClientDistDir(here = dirname18(fileURLToPath7(import.meta.url))) {
132373
132250
  const candidates = clientDistCandidates(here);
132374
132251
  for (const dir of candidates) {
132375
- if (existsSync10(join28(dir, "index.html")))
132252
+ if (existsSync10(join29(dir, "index.html")))
132376
132253
  return dir;
132377
132254
  }
132378
132255
  return candidates[0];
@@ -132385,7 +132262,7 @@ function tryServeStatic(req, res, distDir) {
132385
132262
  return false;
132386
132263
  }
132387
132264
  const safePath = pathname === "/" ? "/index.html" : pathname;
132388
- const filePath = join28(distDir, safePath);
132265
+ const filePath = join29(distDir, safePath);
132389
132266
  if (!filePath.startsWith(distDir)) {
132390
132267
  res.writeHead(403);
132391
132268
  res.end();
@@ -132402,7 +132279,7 @@ function tryServeStatic(req, res, distDir) {
132402
132279
  }
132403
132280
  return true;
132404
132281
  }
132405
- const indexPath = join28(distDir, "index.html");
132282
+ const indexPath = join29(distDir, "index.html");
132406
132283
  if (existsSync10(indexPath)) {
132407
132284
  res.writeHead(200, { "Content-Type": "text/html" });
132408
132285
  if (req.method === "HEAD") {
@@ -132984,7 +132861,7 @@ async function harnessStatus() {
132984
132861
  };
132985
132862
  const program2 = exports_Effect.forEach(services, detectOne, { concurrency: "unbounded" });
132986
132863
  const results = await exports_Effect.runPromise(program2);
132987
- const rows2 = results.map(({ id: id3, displayName, result }) => {
132864
+ const rows = results.map(({ id: id3, displayName, result }) => {
132988
132865
  if (isInstalled(result)) {
132989
132866
  return { id: id3, displayName, status: "installed" };
132990
132867
  }
@@ -132996,13 +132873,13 @@ async function harnessStatus() {
132996
132873
  }
132997
132874
  return { id: id3, displayName, status: "not-installed" };
132998
132875
  });
132999
- const idWidth = Math.max(4, ...rows2.map((r) => r.id.length));
133000
- const nameWidth = Math.max(11, ...rows2.map((r) => r.displayName.length));
132876
+ const idWidth = Math.max(4, ...rows.map((r) => r.id.length));
132877
+ const nameWidth = Math.max(11, ...rows.map((r) => r.displayName.length));
133001
132878
  const header = `${"ID".padEnd(idWidth)} ${"DISPLAY NAME".padEnd(nameWidth)} STATUS`;
133002
132879
  const divider = `${"-".repeat(idWidth)} ${"-".repeat(nameWidth)} ------`;
133003
132880
  console.log(header);
133004
132881
  console.log(divider);
133005
- for (const row of rows2) {
132882
+ for (const row of rows) {
133006
132883
  const statusIcon = row.status === "installed" ? "✅ installed" : row.status === "error" ? "⚠️ error" : "❌ not installed";
133007
132884
  const line = `${row.id.padEnd(idWidth)} ${row.displayName.padEnd(nameWidth)} ${statusIcon}`;
133008
132885
  console.log(line);
@@ -133011,8 +132888,8 @@ async function harnessStatus() {
133011
132888
  }
133012
132889
  }
133013
132890
  console.log("");
133014
- const installedCount = rows2.filter((r) => r.status === "installed").length;
133015
- const totalCount = rows2.length;
132891
+ const installedCount = rows.filter((r) => r.status === "installed").length;
132892
+ const totalCount = rows.length;
133016
132893
  console.log(`${installedCount}/${totalCount} harnesses available on this machine.`);
133017
132894
  }
133018
132895
  var init_harness_status = __esm(() => {
@@ -134133,4 +134010,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
134133
134010
  });
134134
134011
  program2.parse();
134135
134012
 
134136
- //# debugId=D41963016C23E20F64756E2164756E21
134013
+ //# debugId=654C294BE572C9D764756E2164756E21