chatroom-cli 1.98.6 → 1.98.7

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
@@ -84014,8 +84014,76 @@ async function logDaemonAuditEvent(logEvent, event) {
84014
84014
  });
84015
84015
  }
84016
84016
 
84017
+ // src/daemon/infrastructure/inbox/task-snapshot-state.ts
84018
+ function snapshotKey(taskId, role) {
84019
+ return `${taskId}:${role.toLowerCase()}`;
84020
+ }
84021
+
84022
+ class MachineTaskSnapshotState {
84023
+ snapshots = new Map;
84024
+ replace(snapshots) {
84025
+ this.snapshots.clear();
84026
+ this.upsert(snapshots);
84027
+ }
84028
+ applySignalPage(signals, snapshots) {
84029
+ const snapshotsByKey = new Map(snapshots.map((snapshot) => [
84030
+ snapshotKey(snapshot.taskId, snapshot.agentConfig.role),
84031
+ snapshot
84032
+ ]));
84033
+ for (const signal of signals) {
84034
+ const key = snapshotKey(signal.taskId, signal.targetRole);
84035
+ const snapshot = snapshotsByKey.get(key);
84036
+ if (snapshot) {
84037
+ this.snapshots.set(key, snapshot);
84038
+ } else {
84039
+ this.snapshots.delete(key);
84040
+ }
84041
+ }
84042
+ }
84043
+ listForRole(chatroomId, role) {
84044
+ const roleLower = role.toLowerCase();
84045
+ return [...this.snapshots.values()].filter((snapshot) => snapshot.chatroomId === chatroomId && snapshot.agentConfig.role.toLowerCase() === roleLower);
84046
+ }
84047
+ listAll() {
84048
+ return [...this.snapshots.values()];
84049
+ }
84050
+ setDesiredState(chatroomId, role, desiredState) {
84051
+ const roleLower = role.toLowerCase();
84052
+ for (const [key, snapshot] of this.snapshots) {
84053
+ if (snapshot.chatroomId !== chatroomId || snapshot.agentConfig.role.toLowerCase() !== roleLower) {
84054
+ continue;
84055
+ }
84056
+ this.snapshots.set(key, {
84057
+ ...snapshot,
84058
+ agentConfig: { ...snapshot.agentConfig, desiredState }
84059
+ });
84060
+ }
84061
+ }
84062
+ upsert(snapshots) {
84063
+ for (const snapshot of snapshots) {
84064
+ this.snapshots.set(snapshotKey(snapshot.taskId, snapshot.agentConfig.role), snapshot);
84065
+ }
84066
+ }
84067
+ }
84068
+
84069
+ // src/daemon/entry/native-delivery/native-delivery-session-registry.ts
84070
+ function registerNativeDeliverySession(ctx) {
84071
+ registered = {
84072
+ ...ctx,
84073
+ taskSnapshotState: ctx.taskSnapshotState ?? new MachineTaskSnapshotState
84074
+ };
84075
+ }
84076
+ function unregisterNativeDeliverySession() {
84077
+ registered = null;
84078
+ }
84079
+ function getNativeDeliverySession() {
84080
+ return registered;
84081
+ }
84082
+ var registered = null;
84083
+ var init_native_delivery_session_registry = () => {};
84084
+
84017
84085
  // ../../services/backend/config/reliability.ts
84018
- var HARNESS_SESSION_READY_TIMEOUT_MS = 5000, NATIVE_DELIVERY_RECONCILE_MS = 1e4, DAEMON_HEARTBEAT_INTERVAL_MS, DAEMON_HEARTBEAT_TTL_MS, AGENT_REQUEST_DEADLINE_MS = 120000, OBSERVED_FULL_PUSH_INTERVAL_MS, OBSERVED_SYNC_RECONCILE_MS, WORKSPACE_RECENCY_WINDOW_MS, WORKSPACE_LIST_RECONCILE_MS, CONNECTION_CLOSE_REQUEST_TTL_MS, ENHANCER_TERMINAL_JOB_RETENTION_MS;
84086
+ var HARNESS_SESSION_READY_TIMEOUT_MS = 5000, DAEMON_HEARTBEAT_INTERVAL_MS, DAEMON_HEARTBEAT_TTL_MS, AGENT_REQUEST_DEADLINE_MS = 120000, OBSERVED_FULL_PUSH_INTERVAL_MS, OBSERVED_SYNC_RECONCILE_MS, WORKSPACE_RECENCY_WINDOW_MS, WORKSPACE_LIST_RECONCILE_MS, CONNECTION_CLOSE_REQUEST_TTL_MS, ENHANCER_TERMINAL_JOB_RETENTION_MS;
84019
84087
  var init_reliability = __esm(() => {
84020
84088
  DAEMON_HEARTBEAT_INTERVAL_MS = 5 * 60000;
84021
84089
  DAEMON_HEARTBEAT_TTL_MS = 6 * DAEMON_HEARTBEAT_INTERVAL_MS;
@@ -98860,16 +98928,16 @@ function explainAgentReadyForNativeDeliveryBlock(task, slot) {
98860
98928
  if (!isAgentDesiredRunning(agentConfig.desiredState)) {
98861
98929
  return `desired_state_not_running (desiredState=${agentConfig.desiredState})`;
98862
98930
  }
98863
- if (agentConfig.spawnedAgentPid == null) {
98864
- return "spawned_pid_missing";
98865
- }
98866
98931
  if (!slot) {
98867
- return `slot_missing (expectedPid=${agentConfig.spawnedAgentPid})`;
98932
+ return agentConfig.spawnedAgentPid == null ? "spawned_pid_missing" : `slot_missing (expectedPid=${agentConfig.spawnedAgentPid})`;
98868
98933
  }
98869
98934
  if (!isSlotRunning(slot.state)) {
98870
- return `slot_not_running (slotState=${slot.state}, expectedPid=${agentConfig.spawnedAgentPid})`;
98935
+ return `slot_not_running (slotState=${slot.state}, expectedPid=${agentConfig.spawnedAgentPid ?? "none"})`;
98936
+ }
98937
+ if (slot.pid == null) {
98938
+ return "slot_pid_missing";
98871
98939
  }
98872
- if (slot.pid !== agentConfig.spawnedAgentPid) {
98940
+ if (agentConfig.spawnedAgentPid != null && slot.pid !== agentConfig.spawnedAgentPid) {
98873
98941
  return `pid_mismatch (slotPid=${slot.pid ?? "none"}, snapshotPid=${agentConfig.spawnedAgentPid})`;
98874
98942
  }
98875
98943
  if (typeof slot.harnessSessionId !== "string" || slot.harnessSessionId.length === 0) {
@@ -98911,18 +98979,6 @@ function logNativeDeliveryNoTasks(role, chatroomId) {
98911
98979
  console.log(`[NativeDelivery:skip] ${role}@${chatroomId} — no pending tasks for role`);
98912
98980
  }
98913
98981
 
98914
- // src/daemon/entry/native-delivery/native-delivery-session-registry.ts
98915
- function registerNativeDeliverySession(ctx) {
98916
- registered = ctx;
98917
- }
98918
- function unregisterNativeDeliverySession() {
98919
- registered = null;
98920
- }
98921
- function getNativeDeliverySession() {
98922
- return registered;
98923
- }
98924
- var registered = null;
98925
-
98926
98982
  // src/daemon/entry/native-delivery/native-stale-turn-phase.ts
98927
98983
  function isStaleTurnInFlightWhileWaiting(task, slot) {
98928
98984
  if (!slot || isTurnPhaseIdle(slot.nativeTurnPhase ?? "idle"))
@@ -99409,23 +99465,6 @@ function mapAssignedTaskSnapshotList(rows) {
99409
99465
  return rows.map(mapAssignedTaskSnapshot);
99410
99466
  }
99411
99467
 
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 ?? []));
99419
- }
99420
- function filterSnapshotsForRole(snapshots, chatroomId, role) {
99421
- const roleLower = role.toLowerCase();
99422
- return snapshots.filter((row) => row.chatroomId === chatroomId && row.agentConfig.role.toLowerCase() === roleLower);
99423
- }
99424
- var init_fetch_machine_assigned_task_snapshots = __esm(() => {
99425
- init_assigned_task_snapshot_contract();
99426
- init_api3();
99427
- });
99428
-
99429
99468
  // src/daemon/entry/restart-orchestrator-in-flight.ts
99430
99469
  function roleKey(chatroomId, role) {
99431
99470
  return `${chatroomId}:${role.toLowerCase()}`;
@@ -99517,22 +99556,18 @@ class NativeTaskDeliveryCoordinator {
99517
99556
  if (!session2)
99518
99557
  return;
99519
99558
  const { runtime: runtime4, effectContext: effectContext2, agentMgr, sessionDeps, machineId } = session2;
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)}`);
99559
+ const tasks = session2.taskSnapshotState?.listForRole(chatroomId, role) ?? [];
99560
+ if (tasks.length === 0) {
99561
+ logNativeDeliveryNoTasks(role, chatroomId);
99562
+ return;
99563
+ }
99564
+ this.reconcileAssignedTasks({
99565
+ tasks,
99566
+ runtime: runtime4,
99567
+ effectContext: effectContext2,
99568
+ agentMgr,
99569
+ sessionDeps,
99570
+ machineId
99536
99571
  });
99537
99572
  }
99538
99573
  reconcileAssignedTasks(params) {
@@ -99652,13 +99687,13 @@ function notifyNativeTurnIdle(params) {
99652
99687
  var coordinator;
99653
99688
  var init_native_task_delivery_coordinator = __esm(() => {
99654
99689
  init_esm();
99690
+ init_native_delivery_session_registry();
99655
99691
  init_native_stale_turn_phase();
99656
99692
  init_native_task_injector_logic();
99657
99693
  init_native_task_injector();
99658
99694
  init_api3();
99659
99695
  init_assigned_task();
99660
99696
  init_convex_error();
99661
- init_fetch_machine_assigned_task_snapshots();
99662
99697
  init_restart_orchestrator_in_flight();
99663
99698
  });
99664
99699
 
@@ -99880,15 +99915,23 @@ var init_restart_orchestrator = __esm(() => {
99880
99915
  function createStartAgentDeps(agentMgr, session2) {
99881
99916
  return {
99882
99917
  agentProcessManager: {
99883
- ensureRunning: async (args2) => exports_Effect.runPromise(agentMgr.ensureRunning({
99884
- chatroomId: args2.chatroomId,
99885
- role: args2.role,
99886
- agentHarness: args2.agentHarness,
99887
- model: args2.model,
99888
- workingDir: args2.workingDir,
99889
- reason: args2.reason,
99890
- wantResume: args2.wantResume
99891
- }))
99918
+ ensureRunning: async (args2) => {
99919
+ const taskSnapshotState = getNativeDeliverySession()?.taskSnapshotState;
99920
+ taskSnapshotState?.setDesiredState(args2.chatroomId, args2.role, "running");
99921
+ const result = await exports_Effect.runPromise(agentMgr.ensureRunning({
99922
+ chatroomId: args2.chatroomId,
99923
+ role: args2.role,
99924
+ agentHarness: args2.agentHarness,
99925
+ model: args2.model,
99926
+ workingDir: args2.workingDir,
99927
+ reason: args2.reason,
99928
+ wantResume: args2.wantResume
99929
+ }));
99930
+ if (!result.success) {
99931
+ taskSnapshotState?.setDesiredState(args2.chatroomId, args2.role, "stopped");
99932
+ }
99933
+ return result;
99934
+ }
99892
99935
  },
99893
99936
  session: {
99894
99937
  sessionId: session2.sessionId,
@@ -100009,6 +100052,7 @@ function createRecoverAgentStateDeps(agentMgr, session2) {
100009
100052
  var init_agent_control_bridge = __esm(() => {
100010
100053
  init_esm();
100011
100054
  init_api3();
100055
+ init_native_delivery_session_registry();
100012
100056
  init_restart_orchestrator();
100013
100057
  });
100014
100058
 
@@ -115783,7 +115827,7 @@ function isSlotUnavailableForPid(slot, pid, isPidAlive, now = Date.now()) {
115783
115827
  function isNativeRevivableTaskStatus(task) {
115784
115828
  const { status: status3 } = task;
115785
115829
  if (status3 === "pending") {
115786
- return task.agentConfig.spawnedAgentPid != null;
115830
+ return true;
115787
115831
  }
115788
115832
  if (status3 === "acknowledged") {
115789
115833
  return task.assignedTo?.toLowerCase() === task.agentConfig.role.toLowerCase();
@@ -116072,7 +116116,7 @@ async function wakeStoppedAgentsForPendingTasks(tasks, now, cooldown, runtime4,
116072
116116
  }
116073
116117
  }
116074
116118
  async function processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, machineId, _pass, options) {
116075
- const tasks = options?.snapshots ? [...options.snapshots] : await fetchMachineAssignedTaskSnapshots(sessionDeps, machineId);
116119
+ const tasks = [...options.snapshots];
116076
116120
  const filteredTasks = filterSnapshotsExcludingRestartInFlight(tasks);
116077
116121
  if (filteredTasks.length === 0)
116078
116122
  return;
@@ -116104,11 +116148,23 @@ var init_task_delivery_processor = __esm(() => {
116104
116148
  init_native_task_injector_logic();
116105
116149
  init_api3();
116106
116150
  init_convex_error();
116107
- init_fetch_machine_assigned_task_snapshots();
116108
116151
  init_restart_orchestrator_in_flight();
116109
116152
  init_task_delivery_logic();
116110
116153
  });
116111
116154
 
116155
+ // src/daemon/infrastructure/inbox/fetch-machine-assigned-task-snapshots.ts
116156
+ async function fetchMachineAssignedTaskSnapshots(sessionDeps, machineId) {
116157
+ const result = await sessionDeps.backend.query(api.machines.listMachineAssignedTaskSnapshots, {
116158
+ sessionId: sessionDeps.sessionId,
116159
+ machineId
116160
+ });
116161
+ return mapAssignedTaskSnapshotList(parseAssignedTaskSnapshotRows(result?.tasks ?? []));
116162
+ }
116163
+ var init_fetch_machine_assigned_task_snapshots = __esm(() => {
116164
+ init_assigned_task_snapshot_contract();
116165
+ init_api3();
116166
+ });
116167
+
116112
116168
  // src/daemon/infrastructure/inbox/store/schema.ts
116113
116169
  var SCHEMA_VERSION = 1, MIGRATIONS;
116114
116170
  var init_schema = __esm(() => {
@@ -116261,11 +116317,14 @@ var init_inbox = __esm(() => {
116261
116317
 
116262
116318
  // src/daemon/infrastructure/inbox/task-inbox-delivery.ts
116263
116319
  async function handleTaskInboxUpdate(update6, deps) {
116320
+ const taskSnapshotState = deps.taskSnapshotState ?? getNativeDeliverySession()?.taskSnapshotState;
116321
+ taskSnapshotState?.applySignalPage(update6.signals, update6.snapshots);
116264
116322
  if (update6.snapshots.length === 0)
116265
116323
  return;
116266
- await processTasksUpdate(deps.runtime, deps.effectContext, deps.cooldown, deps.agentMgr, deps.sessionDeps, deps.machineId, "inbox-signal");
116324
+ await processTasksUpdate(deps.runtime, deps.effectContext, deps.cooldown, deps.agentMgr, deps.sessionDeps, deps.machineId, "inbox-signal", { snapshots: update6.snapshots });
116267
116325
  }
116268
116326
  var init_task_inbox_delivery = __esm(() => {
116327
+ init_native_delivery_session_registry();
116269
116328
  init_task_delivery_processor();
116270
116329
  });
116271
116330
 
@@ -116381,6 +116440,7 @@ async function bootstrapMachineAssignedTaskSnapshots(deps) {
116381
116440
  machineId: deps.machineId
116382
116441
  });
116383
116442
  const tasks = await fetchMachineAssignedTaskSnapshots(deps.sessionDeps, deps.machineId);
116443
+ deps.taskSnapshotState?.replace(tasks);
116384
116444
  if (!tasks.length)
116385
116445
  return;
116386
116446
  await processTasksUpdate(deps.runtime, deps.effectContext, deps.cooldown, deps.agentMgr, deps.sessionDeps, deps.machineId, "bootstrap", { snapshots: tasks });
@@ -116403,7 +116463,7 @@ async function runInboxLoopWithRestart(options, onUpdate, isStopped) {
116403
116463
  }
116404
116464
  }
116405
116465
  }
116406
- var INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInboxEffect = (wsClient2) => exports_Effect.gen(function* () {
116466
+ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInboxEffect = (wsClient2) => exports_Effect.gen(function* () {
116407
116467
  const session2 = yield* DaemonSessionService;
116408
116468
  const agentMgr = yield* DaemonAgentProcessManagerService;
116409
116469
  const effectContext2 = yield* exports_Effect.context();
@@ -116426,14 +116486,18 @@ var INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInbo
116426
116486
  });
116427
116487
  const abort = new AbortController;
116428
116488
  let stopped = false;
116489
+ const taskSnapshotState = new MachineTaskSnapshotState;
116429
116490
  registerNativeDeliverySession({
116430
116491
  runtime: runtime4,
116431
116492
  effectContext: effectContext2,
116432
116493
  agentMgr,
116433
116494
  sessionDeps,
116434
- machineId: session2.machineId
116495
+ machineId: session2.machineId,
116496
+ taskSnapshotState
116435
116497
  });
116436
116498
  const cooldown = new RecoveryCooldown;
116499
+ let inboxUpdateInFlight = false;
116500
+ let reconcileInFlight = false;
116437
116501
  const inboxOptions = {
116438
116502
  client: wsClient2,
116439
116503
  sessionId: session2.sessionId,
@@ -116443,32 +116507,44 @@ var INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInbo
116443
116507
  signal: abort.signal
116444
116508
  };
116445
116509
  const inboxHandler = async (update6) => {
116446
- await handleTaskInboxUpdate(update6, {
116447
- runtime: runtime4,
116448
- effectContext: effectContext2,
116449
- cooldown,
116450
- agentMgr,
116451
- sessionDeps,
116452
- machineId: session2.machineId
116453
- });
116454
- inboxStore.save({ inboxType: "task", scopeKey: session2.machineId }, { afterSignalKey: update6.throughSignalKey });
116510
+ inboxUpdateInFlight = true;
116511
+ try {
116512
+ await handleTaskInboxUpdate(update6, {
116513
+ runtime: runtime4,
116514
+ effectContext: effectContext2,
116515
+ cooldown,
116516
+ agentMgr,
116517
+ sessionDeps,
116518
+ machineId: session2.machineId,
116519
+ taskSnapshotState
116520
+ });
116521
+ inboxStore.save({ inboxType: "task", scopeKey: session2.machineId }, { afterSignalKey: update6.throughSignalKey });
116522
+ } finally {
116523
+ inboxUpdateInFlight = false;
116524
+ }
116455
116525
  };
116456
- const reconcileTimer = setInterval(() => {
116457
- if (stopped)
116458
- return;
116459
- processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, session2.machineId, "periodic-reconcile");
116460
- }, NATIVE_DELIVERY_RECONCILE_MS);
116461
116526
  yield* exports_Effect.tryPromise(() => bootstrapMachineAssignedTaskSnapshots({
116462
116527
  sessionDeps,
116463
116528
  runtime: runtime4,
116464
116529
  effectContext: effectContext2,
116465
116530
  cooldown,
116466
116531
  agentMgr,
116467
- machineId: session2.machineId
116532
+ machineId: session2.machineId,
116533
+ taskSnapshotState
116468
116534
  })).pipe(exports_Effect.catchAll((error51) => {
116469
116535
  console.warn("[TaskInbox] bootstrap failed:", error51);
116470
116536
  return exports_Effect.void;
116471
116537
  }));
116538
+ const reconcileTimer = setInterval(() => {
116539
+ if (stopped || inboxUpdateInFlight || reconcileInFlight)
116540
+ return;
116541
+ reconcileInFlight = true;
116542
+ processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, session2.machineId, "periodic-reconcile", { snapshots: taskSnapshotState.listAll() }).catch((error51) => {
116543
+ console.warn("[TaskInbox] local delivery reconciliation failed:", error51);
116544
+ }).finally(() => {
116545
+ reconcileInFlight = false;
116546
+ });
116547
+ }, NATIVE_DELIVERY_RECONCILE_MS);
116472
116548
  runInboxLoopWithRestart(inboxOptions, inboxHandler, () => stopped);
116473
116549
  return {
116474
116550
  stop() {
@@ -116481,10 +116557,10 @@ var INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInbo
116481
116557
  };
116482
116558
  });
116483
116559
  var init_task_inbox_runtime = __esm(() => {
116484
- init_reliability();
116485
116560
  init_esm();
116486
116561
  init_daemon_services();
116487
116562
  init_api3();
116563
+ init_native_delivery_session_registry();
116488
116564
  init_task_delivery_processor();
116489
116565
  init_task_delivery_logic();
116490
116566
  init_fetch_machine_assigned_task_snapshots();
@@ -118163,10 +118239,10 @@ function startWorkspaceListSubscriber(deps, onEvent) {
118163
118239
  const unsub = deps.wsClient.onUpdate(api.workspaces.listRecentlyObservedWorkspacesForMachine, queryArgs, (workspaces) => {
118164
118240
  if (workspaces == null)
118165
118241
  return;
118166
- const snapshotKey = JSON.stringify(workspaces);
118167
- if (snapshotKey === lastSnapshotKey)
118242
+ const snapshotKey2 = JSON.stringify(workspaces);
118243
+ if (snapshotKey2 === lastSnapshotKey)
118168
118244
  return;
118169
- lastSnapshotKey = snapshotKey;
118245
+ lastSnapshotKey = snapshotKey2;
118170
118246
  onEvent({ type: "workspace.list-changed", machineId: deps.machineId });
118171
118247
  }, (err) => {
118172
118248
  console.warn(`[daemon] workspace-list subscriber error: ${err instanceof Error ? err.message : String(err)}`);
@@ -134010,4 +134086,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
134010
134086
  });
134011
134087
  program2.parse();
134012
134088
 
134013
- //# debugId=654C294BE572C9D764756E2164756E21
134089
+ //# debugId=D3E73C85EB221DCE64756E2164756E21