chatroom-cli 1.110.1 → 1.112.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -28278,6 +28278,64 @@ var init_agent_process_service = __esm(() => {
28278
28278
  init_service();
28279
28279
  });
28280
28280
 
28281
+ // src/daemon/services/agent-process-service/infrastructure/components/agent-task-state/infra/in-memory-active-task-state-store.ts
28282
+ function keyOf(key) {
28283
+ return `${key.chatroomId}:${key.role.toLowerCase()}`;
28284
+ }
28285
+
28286
+ class InMemoryActiveTaskStateStore {
28287
+ states = new Map;
28288
+ get(key) {
28289
+ const state = this.states.get(keyOf(key));
28290
+ return state ? { ...state } : undefined;
28291
+ }
28292
+ start(input) {
28293
+ const state = {
28294
+ chatroomId: input.chatroomId,
28295
+ role: input.role,
28296
+ taskId: input.taskId
28297
+ };
28298
+ this.states.set(keyOf(input), state);
28299
+ return { ...state };
28300
+ }
28301
+ clear(key) {
28302
+ return this.states.delete(keyOf(key));
28303
+ }
28304
+ clearAll() {
28305
+ const count3 = this.states.size;
28306
+ this.states.clear();
28307
+ return count3;
28308
+ }
28309
+ }
28310
+
28311
+ // src/daemon/services/agent-process-service/infrastructure/components/agent-task-state/usecase/agent-task-state-service.ts
28312
+ class DefaultAgentTaskStateService {
28313
+ deps;
28314
+ constructor(deps) {
28315
+ this.deps = deps;
28316
+ }
28317
+ get(key) {
28318
+ return this.deps.taskState.get(key);
28319
+ }
28320
+ start(input) {
28321
+ return this.deps.taskState.start(input);
28322
+ }
28323
+ clear(key) {
28324
+ return this.deps.taskState.clear(key);
28325
+ }
28326
+ clearAll() {
28327
+ return this.deps.taskState.clearAll();
28328
+ }
28329
+ }
28330
+
28331
+ // src/daemon/services/agent-process-service/infrastructure/components/agent-task-state/index.ts
28332
+ function createAgentTaskStateService() {
28333
+ return new DefaultAgentTaskStateService({
28334
+ taskState: new InMemoryActiveTaskStateStore
28335
+ });
28336
+ }
28337
+ var init_agent_task_state = () => {};
28338
+
28281
28339
  // src/daemon/services/agent-process-service/domain/usecase/native-turn-phase.ts
28282
28340
  function defaultNativeTurnPhase() {
28283
28341
  return "idle";
@@ -30996,6 +31054,7 @@ var init_harness_activity_emitter = __esm(() => {
30996
31054
  // src/daemon/services/agent-process-service/index.ts
30997
31055
  var init_agent_process_service2 = __esm(() => {
30998
31056
  init_agent_process_service();
31057
+ init_agent_task_state();
30999
31058
  init_agent_process_command_bus();
31000
31059
  init_service();
31001
31060
  init_agent_process_manager();
@@ -31005,64 +31064,6 @@ var init_agent_process_service2 = __esm(() => {
31005
31064
  init_orphan_process_tracker();
31006
31065
  });
31007
31066
 
31008
- // src/daemon/services/agent-process-service/infrastructure/components/agent-task-state/infra/in-memory-active-task-state-store.ts
31009
- function keyOf(key) {
31010
- return `${key.chatroomId}:${key.role.toLowerCase()}`;
31011
- }
31012
-
31013
- class InMemoryActiveTaskStateStore {
31014
- states = new Map;
31015
- get(key) {
31016
- const state = this.states.get(keyOf(key));
31017
- return state ? { ...state } : undefined;
31018
- }
31019
- start(input) {
31020
- const state = {
31021
- chatroomId: input.chatroomId,
31022
- role: input.role,
31023
- taskId: input.taskId
31024
- };
31025
- this.states.set(keyOf(input), state);
31026
- return { ...state };
31027
- }
31028
- clear(key) {
31029
- return this.states.delete(keyOf(key));
31030
- }
31031
- clearAll() {
31032
- const count3 = this.states.size;
31033
- this.states.clear();
31034
- return count3;
31035
- }
31036
- }
31037
-
31038
- // src/daemon/services/agent-process-service/infrastructure/components/agent-task-state/usecase/agent-task-state-service.ts
31039
- class DefaultAgentTaskStateService {
31040
- deps;
31041
- constructor(deps) {
31042
- this.deps = deps;
31043
- }
31044
- get(key) {
31045
- return this.deps.taskState.get(key);
31046
- }
31047
- start(input) {
31048
- return this.deps.taskState.start(input);
31049
- }
31050
- clear(key) {
31051
- return this.deps.taskState.clear(key);
31052
- }
31053
- clearAll() {
31054
- return this.deps.taskState.clearAll();
31055
- }
31056
- }
31057
-
31058
- // src/daemon/services/agent-process-service/infrastructure/components/agent-task-state/index.ts
31059
- function createAgentTaskStateService() {
31060
- return new DefaultAgentTaskStateService({
31061
- taskState: new InMemoryActiveTaskStateStore
31062
- });
31063
- }
31064
- var init_agent_task_state = () => {};
31065
-
31066
31067
  // src/daemon/services/agent-process-contracts.ts
31067
31068
  var init_agent_process_contracts = __esm(() => {
31068
31069
  init_agent_process_service2();
@@ -31786,6 +31787,595 @@ var init_native_task_injector = __esm(() => {
31786
31787
  init_native_task_injector_logic();
31787
31788
  });
31788
31789
 
31790
+ // src/daemon/services/task-service/service/native-delivery/native-delivery-log.ts
31791
+ function logNativeDeliveryDecision(source, role, chatroomId, decision, taskId, details) {
31792
+ const taskSuffix = taskId ? ` task=${taskId}` : "";
31793
+ const detailSuffix = details ? Object.entries(details).filter(([, value]) => value !== undefined).map(([key, value]) => `${key}=${value}`).join(" ") : "";
31794
+ console.log(`[NativeDelivery:decision] source=${source} role=${role} chatroom=${chatroomId}${taskSuffix} decision=${decision}${detailSuffix ? ` ${detailSuffix}` : ""}`);
31795
+ }
31796
+ function logNativeDeliveryTrigger(source, role, chatroomId, taskId) {
31797
+ const taskSuffix = taskId ? ` task ${taskId}` : "";
31798
+ console.log(`[NativeDelivery:trigger] source=${source} ${role}@${chatroomId}${taskSuffix}`);
31799
+ }
31800
+ function logNativeDeliverySkip(role, chatroomId, taskId, reason) {
31801
+ console.log(`[NativeDelivery:skip] ${role}@${chatroomId} task ${taskId} — ${reason}`);
31802
+ }
31803
+ function logNativeDeliveryMutexSkip(role, chatroomId, taskId) {
31804
+ console.log(`[NativeDelivery:skip] ${role}@${chatroomId} task ${taskId} — delivery_mutex_busy (another inject in flight)`);
31805
+ }
31806
+ function logNativeDeliveryInjecting(role, chatroomId, taskId) {
31807
+ console.log(`[NativeDelivery:inject] ${role}@${chatroomId} task ${taskId} — starting injection`);
31808
+ }
31809
+
31810
+ // src/daemon/services/task-service/service/native-delivery/delivery-decision.ts
31811
+ function taskSort(a, b) {
31812
+ const pendingOrder = Number(b.status === "pending") - Number(a.status === "pending");
31813
+ return pendingOrder || a.createdAt - b.createdAt;
31814
+ }
31815
+ function stableBlockReason(reason) {
31816
+ const reasons = [
31817
+ "not_native_harness",
31818
+ "task_status_not_deliverable",
31819
+ "acknowledged_wrong_role",
31820
+ "chatroom_stop_scope_active",
31821
+ "operational_stop_intent_active",
31822
+ "operational_circuit_open",
31823
+ "operational_state_not_running",
31824
+ "slot_missing",
31825
+ "slot_not_running",
31826
+ "slot_pid_missing",
31827
+ "spawned_pid_missing",
31828
+ "pid_mismatch",
31829
+ "harness_session_missing",
31830
+ "turn_not_idle",
31831
+ "working_dir_missing"
31832
+ ];
31833
+ return reasons.find((candidate) => reason.startsWith(candidate)) ?? "working_dir_missing";
31834
+ }
31835
+ function decideNextDelivery(tasks, context5) {
31836
+ const assignedTasks = [...tasks].filter((candidate) => candidate.agentConfig.role.toLowerCase() === context5.role.toLowerCase()).sort(taskSort);
31837
+ const task = assignedTasks.find((candidate) => isDeliverableTaskStatus(candidate.status));
31838
+ if (!task) {
31839
+ if (assignedTasks.length > 0) {
31840
+ return {
31841
+ kind: "blocked",
31842
+ taskId: assignedTasks[0].taskId,
31843
+ reason: "task_status_not_deliverable"
31844
+ };
31845
+ }
31846
+ return { kind: "idle", reason: tasks.length > 0 ? "not_assigned" : "no_deliverable_task" };
31847
+ }
31848
+ if (context5.activeTaskId === task.taskId) {
31849
+ return { kind: "deduplicated", taskId: task.taskId, reason: "task_state_active" };
31850
+ }
31851
+ if (context5.deliveryInFlight) {
31852
+ return { kind: "deduplicated", taskId: task.taskId, reason: "delivery_in_flight" };
31853
+ }
31854
+ if (!context5.isNativeHarness(task.agentConfig.agentHarness)) {
31855
+ return { kind: "blocked", taskId: task.taskId, reason: "not_native_harness" };
31856
+ }
31857
+ if (context5.agentLifecycleInFlight) {
31858
+ return { kind: "wait", taskId: task.taskId, reason: "agent_start_in_flight" };
31859
+ }
31860
+ const blockReason = context5.explainNativeDeliveryBlock(task, {
31861
+ slot: context5.slot,
31862
+ operational: context5.operational
31863
+ });
31864
+ if (blockReason === null) {
31865
+ return {
31866
+ kind: "inject",
31867
+ taskId: task.taskId,
31868
+ harnessSessionId: context5.slot?.harnessSessionId
31869
+ };
31870
+ }
31871
+ if (isSlotSpawning(context5.slot?.state ?? "idle")) {
31872
+ return { kind: "wait", taskId: task.taskId, reason: "slot_spawning" };
31873
+ }
31874
+ if (isSlotStopping(context5.slot?.state ?? "idle")) {
31875
+ return { kind: "wait", taskId: task.taskId, reason: "slot_stopping" };
31876
+ }
31877
+ const coldSession = context5.snapshotRequestsNativeColdSession(task);
31878
+ const startAllowed = blockReason.startsWith("slot_missing") || blockReason.startsWith("slot_not_running") || blockReason.startsWith("spawned_pid_missing");
31879
+ if (startAllowed && !coldSession && task.status === "pending" && isSlotIdle(context5.slot?.state ?? "idle") && task.agentConfig.workingDir) {
31880
+ return { kind: "start-agent", taskId: task.taskId };
31881
+ }
31882
+ if (blockReason.startsWith("harness_session_missing")) {
31883
+ return { kind: "wait", taskId: task.taskId, reason: "session_not_ready" };
31884
+ }
31885
+ return { kind: "blocked", taskId: task.taskId, reason: stableBlockReason(blockReason) };
31886
+ }
31887
+ var init_delivery_decision = __esm(() => {
31888
+ init_assigned_task();
31889
+ init_check_agent_slot();
31890
+ });
31891
+
31892
+ // src/infrastructure/mappers/map-assigned-task.ts
31893
+ function mapAssignedTaskSnapshot(row) {
31894
+ return {
31895
+ taskId: row.taskId,
31896
+ chatroomId: row.chatroomId,
31897
+ status: row.status,
31898
+ assignedTo: row.assignedTo,
31899
+ updatedAt: row.updatedAt,
31900
+ createdAt: row.createdAt,
31901
+ agentConfig: {
31902
+ role: row.agentConfig.role,
31903
+ machineId: row.agentConfig.machineId,
31904
+ agentHarness: row.agentConfig.agentHarness,
31905
+ model: row.agentConfig.model,
31906
+ workingDir: row.agentConfig.workingDir,
31907
+ spawnedAgentPid: row.agentConfig.spawnedAgentPid,
31908
+ desiredState: row.agentConfig.desiredState,
31909
+ circuitState: row.agentConfig.circuitState,
31910
+ configLifecycleRevision: row.agentConfig.configLifecycleRevision
31911
+ },
31912
+ participant: row.participant,
31913
+ requestsNativeColdSession: row.requestsNativeColdSession
31914
+ };
31915
+ }
31916
+ function mapAssignedTaskView(row) {
31917
+ return {
31918
+ ...mapAssignedTaskSnapshot(row),
31919
+ taskContent: row.taskContent,
31920
+ taskEnvelope: row.taskEnvelope,
31921
+ startInNewSession: row.startInNewSession
31922
+ };
31923
+ }
31924
+ function mapAssignedTaskSnapshotList(rows) {
31925
+ return rows.map(mapAssignedTaskSnapshot);
31926
+ }
31927
+
31928
+ // src/daemon/entry/restart-orchestrator-in-flight.ts
31929
+ function roleKey(chatroomId, role) {
31930
+ return `${chatroomId}:${role.toLowerCase()}`;
31931
+ }
31932
+ function markRestartOrchestratorInFlight(chatroomId, role, correlationId) {
31933
+ inFlight.set(roleKey(chatroomId, role), correlationId);
31934
+ }
31935
+ function clearRestartOrchestratorInFlight(chatroomId, role, correlationId) {
31936
+ const key = roleKey(chatroomId, role);
31937
+ if (correlationId !== undefined && inFlight.get(key) !== correlationId)
31938
+ return;
31939
+ inFlight.delete(key);
31940
+ }
31941
+ function isRestartOrchestratorInFlight(chatroomId, role) {
31942
+ return inFlight.has(roleKey(chatroomId, role));
31943
+ }
31944
+ var inFlight;
31945
+ var init_restart_orchestrator_in_flight = __esm(() => {
31946
+ inFlight = new Map;
31947
+ });
31948
+
31949
+ // src/daemon/entry/role-delivery-state.ts
31950
+ function roleKey2(chatroomId, role) {
31951
+ return `${chatroomId}:${role.toLowerCase()}`;
31952
+ }
31953
+
31954
+ class RoleDeliveryState {
31955
+ generation = new Map;
31956
+ inFlight = new Set;
31957
+ nativeNudgeFailures = new Map;
31958
+ getGeneration(chatroomId, role) {
31959
+ return this.generation.get(roleKey2(chatroomId, role)) ?? 0;
31960
+ }
31961
+ resetDeliveryState(chatroomId, role) {
31962
+ const key = roleKey2(chatroomId, role);
31963
+ const next4 = (this.generation.get(key) ?? 0) + 1;
31964
+ this.generation.set(key, next4);
31965
+ this.inFlight.delete(key);
31966
+ this.nativeNudgeFailures.delete(key);
31967
+ return next4;
31968
+ }
31969
+ tryAcquireDelivery(chatroomId, role) {
31970
+ const key = roleKey2(chatroomId, role);
31971
+ if (this.inFlight.has(key))
31972
+ return false;
31973
+ this.inFlight.add(key);
31974
+ return true;
31975
+ }
31976
+ releaseDelivery(chatroomId, role) {
31977
+ this.inFlight.delete(roleKey2(chatroomId, role));
31978
+ }
31979
+ recordNativeNudgeFailure(chatroomId, role) {
31980
+ const key = roleKey2(chatroomId, role);
31981
+ const count3 = (this.nativeNudgeFailures.get(key) ?? 0) + 1;
31982
+ this.nativeNudgeFailures.set(key, count3);
31983
+ return count3;
31984
+ }
31985
+ clearNativeNudgeFailures(chatroomId, role) {
31986
+ this.nativeNudgeFailures.delete(roleKey2(chatroomId, role));
31987
+ }
31988
+ getNativeNudgeFailures(chatroomId, role) {
31989
+ return this.nativeNudgeFailures.get(roleKey2(chatroomId, role)) ?? 0;
31990
+ }
31991
+ }
31992
+ function getRoleDeliveryState() {
31993
+ shared ??= new RoleDeliveryState;
31994
+ return shared;
31995
+ }
31996
+ var shared;
31997
+
31998
+ // src/daemon/services/task-service/service/native-delivery/native-task-delivery-coordinator.ts
31999
+ class NativeTaskDeliveryCoordinator {
32000
+ resetRoleDeliveryState(chatroomId, role) {
32001
+ getRoleDeliveryState().resetDeliveryState(chatroomId, role);
32002
+ }
32003
+ async reconcileRoleTasks(params) {
32004
+ const tasks = params.tasks;
32005
+ if (tasks.length === 0)
32006
+ return;
32007
+ const {
32008
+ runtime: runtime4,
32009
+ effectContext: effectContext2,
32010
+ agentMgr,
32011
+ sessionDeps,
32012
+ operationalModel,
32013
+ isTaskActive,
32014
+ machineId,
32015
+ onTaskDelivered,
32016
+ executors
32017
+ } = params;
32018
+ const deliveryState = getRoleDeliveryState();
32019
+ const taskService = params.taskService;
32020
+ const groups = new Map;
32021
+ for (const task of tasks) {
32022
+ const key = `${task.chatroomId}:${task.agentConfig.role.toLowerCase()}`;
32023
+ const group = groups.get(key) ?? [];
32024
+ group.push(task);
32025
+ groups.set(key, group);
32026
+ }
32027
+ for (const roleTasks of groups.values()) {
32028
+ const sortedTasks = [...roleTasks].sort((a, b) => {
32029
+ if (a.status === "pending" && b.status !== "pending")
32030
+ return -1;
32031
+ if (b.status === "pending" && a.status !== "pending")
32032
+ return 1;
32033
+ return a.createdAt - b.createdAt;
32034
+ });
32035
+ const firstTask = sortedTasks[0];
32036
+ if (!firstTask)
32037
+ continue;
32038
+ const { role } = firstTask.agentConfig;
32039
+ const slot = agentMgr.getSlot(firstTask.chatroomId, role);
32040
+ const operational = operationalModel.get(firstTask.chatroomId, role);
32041
+ const activeTaskId = roleTasks.find((candidate) => isTaskActive({ chatroomId: candidate.chatroomId, role, taskId: candidate.taskId }))?.taskId;
32042
+ const decision = decideNextDelivery(roleTasks, {
32043
+ role,
32044
+ slot,
32045
+ operational,
32046
+ activeTaskId,
32047
+ deliveryInFlight: false,
32048
+ agentLifecycleInFlight: isRestartOrchestratorInFlight(firstTask.chatroomId, role),
32049
+ isNativeHarness: taskService.isNativeHarness,
32050
+ snapshotRequestsNativeColdSession: taskService.snapshotRequestsNativeColdSession,
32051
+ explainNativeDeliveryBlock: taskService.explainNativeDeliveryBlock
32052
+ });
32053
+ const attemptId = `${Date.now()}-${firstTask.taskId}`;
32054
+ const decisionReason = "reason" in decision ? decision.reason : undefined;
32055
+ logNativeDeliveryDecision(params.pass ?? "inbox-signal", role, firstTask.chatroomId, decision.kind === "blocked" || decision.kind === "wait" ? `${decision.kind}:${decision.reason}` : decision.kind, "taskId" in decision ? decision.taskId : undefined, {
32056
+ ...decisionReason ? { reason: decisionReason } : {},
32057
+ attemptId,
32058
+ slotState: slot?.state ?? "missing",
32059
+ nativeTurnPhase: slot?.nativeTurnPhase ?? "unknown",
32060
+ harnessSessionPresent: Boolean(slot?.harnessSessionId),
32061
+ operationalState: operational?.operationalState ?? "missing"
32062
+ });
32063
+ const row = ("taskId" in decision ? sortedTasks.find((candidate) => candidate.taskId === decision.taskId) : firstTask) ?? firstTask;
32064
+ if (decision.kind === "idle" || decision.kind === "blocked" || decision.kind === "wait") {
32065
+ if (decision.kind === "blocked") {
32066
+ logNativeDeliverySkip(role, row.chatroomId, decision.taskId, decision.reason);
32067
+ }
32068
+ continue;
32069
+ }
32070
+ if (decision.kind === "deduplicated") {
32071
+ logNativeDeliverySkip(role, row.chatroomId, decision.taskId, decision.reason);
32072
+ continue;
32073
+ }
32074
+ if (decision.kind === "start-agent") {
32075
+ if (!row.agentConfig.workingDir || slot && !isSlotIdle(slot.state))
32076
+ continue;
32077
+ try {
32078
+ if (executors) {
32079
+ const startResult2 = await executors.startAgent(row, operational?.operationalState);
32080
+ console.log(`[NativeDelivery:execution] attempt=${attemptId} role=${role} chatroom=${row.chatroomId} task=${row.taskId} operation=start-agent result=${startResult2 && typeof startResult2 === "object" && "success" in startResult2 ? startResult2.success : "completed"}`);
32081
+ continue;
32082
+ }
32083
+ const startResult = await params.runSerializedForAgent({ chatroomId: row.chatroomId, role }, { timeoutMs: 120000 }, (ops, context5) => ops.startAgent({
32084
+ chatroomId: row.chatroomId,
32085
+ role,
32086
+ agentHarness: row.agentConfig.agentHarness,
32087
+ model: row.agentConfig.model ?? "",
32088
+ workingDir: row.agentConfig.workingDir,
32089
+ reason: operational?.operationalState === "running" ? AgentStartReasonEnum["platform.task_monitor_nudge"] : AgentStartReasonEnum["platform.pending_task_wake"],
32090
+ wantResume: false,
32091
+ lifecycleRevision: row.agentConfig.configLifecycleRevision,
32092
+ taskId: row.taskId
32093
+ }, context5.signal));
32094
+ console.log(`[NativeDelivery:execution] attempt=${attemptId} role=${role} chatroom=${row.chatroomId} task=${row.taskId} operation=start-agent result=${startResult && typeof startResult === "object" && "success" in startResult ? startResult.success : "completed"}`);
32095
+ } catch (error) {
32096
+ console.warn(`[NativeDelivery:failure] role=${role} chatroom=${row.chatroomId} task=${row.taskId} operation=start-agent error=${getErrorMessage(error)}`);
32097
+ }
32098
+ continue;
32099
+ }
32100
+ if (!deliveryState.tryAcquireDelivery(row.chatroomId, role)) {
32101
+ logNativeDeliveryMutexSkip(role, row.chatroomId, row.taskId);
32102
+ continue;
32103
+ }
32104
+ const harnessSessionId = decision.harnessSessionId;
32105
+ logNativeDeliveryInjecting(role, row.chatroomId, row.taskId);
32106
+ if (executors) {
32107
+ try {
32108
+ const result = await executors.injectTask(row, harnessSessionId);
32109
+ if (result.kind === "task-unavailable") {
32110
+ console.warn(`[NativeDelivery:execution] attempt=${attemptId} role=${role} chatroom=${row.chatroomId} task=${row.taskId} operation=inject result=task_hydration_missing`);
32111
+ } else if (result.delivered) {
32112
+ onTaskDelivered?.(result.delivered);
32113
+ deliveryState.clearNativeNudgeFailures(row.chatroomId, role);
32114
+ console.log(`[NativeDelivery:execution] attempt=${attemptId} role=${role} chatroom=${row.chatroomId} task=${row.taskId} operation=inject result=success`);
32115
+ }
32116
+ } catch (error) {
32117
+ console.warn(`[NativeDelivery:failure] role=${role} chatroom=${row.chatroomId} task=${row.taskId} operation=inject error=${getErrorMessage(error)}`);
32118
+ } finally {
32119
+ deliveryState.releaseDelivery(row.chatroomId, role);
32120
+ }
32121
+ continue;
32122
+ }
32123
+ await exports_Runtime.runPromise(runtime4)(exports_Effect.gen(function* () {
32124
+ const backend2 = yield* exports_Effect.tryPromise(() => sessionDeps.backend.query(api.machines.getAssignedTaskForAction, {
32125
+ sessionId: sessionDeps.sessionId,
32126
+ machineId,
32127
+ taskId: row.taskId,
32128
+ role: row.agentConfig.role
32129
+ }));
32130
+ if (!backend2) {
32131
+ console.warn(`[NativeDelivery:execution] attempt=${attemptId} role=${role} chatroom=${row.chatroomId} task=${row.taskId} operation=inject result=task_hydration_missing`);
32132
+ return;
32133
+ }
32134
+ const full = mapAssignedTaskView(backend2);
32135
+ yield* exports_Effect.tryPromise(() => taskService.deliverNativeTask(full, harnessSessionId, (delivered) => {
32136
+ onTaskDelivered?.(delivered);
32137
+ deliveryState.clearNativeNudgeFailures(delivered.chatroomId, delivered.role);
32138
+ console.log(`[NativeDelivery:execution] attempt=${attemptId} role=${delivered.role} chatroom=${delivered.chatroomId} task=${delivered.taskId} operation=inject result=success`);
32139
+ }));
32140
+ }).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[NativeDelivery:failure] role=${row.agentConfig.role} chatroom=${row.chatroomId} task=${row.taskId} operation=inject error=${getErrorMessage(err)}`))), exports_Effect.ensuring(exports_Effect.sync(() => {
32141
+ deliveryState.releaseDelivery(row.chatroomId, row.agentConfig.role);
32142
+ }))));
32143
+ }
32144
+ }
32145
+ }
32146
+ function getNativeTaskDeliveryCoordinator() {
32147
+ coordinator ??= new NativeTaskDeliveryCoordinator;
32148
+ return coordinator;
32149
+ }
32150
+ function resetRoleDeliveryState(chatroomId, role) {
32151
+ getRoleDeliveryState().resetDeliveryState(chatroomId, role);
32152
+ }
32153
+ var coordinator;
32154
+ var init_native_task_delivery_coordinator = __esm(() => {
32155
+ init_agent();
32156
+ init_esm();
32157
+ init_delivery_decision();
32158
+ init_api3();
32159
+ init_convex_error();
32160
+ init_check_agent_slot();
32161
+ init_restart_orchestrator_in_flight();
32162
+ });
32163
+
32164
+ // src/daemon/services/task-service/service/native-delivery/task-delivery-processor.ts
32165
+ async function processTasksUpdate(runtime4, effectContext2, agentMgr, runSerializedForAgent, taskService, sessionDeps, machineId, pass, lifecycleOutbox, operationalModel, isTaskActive, options) {
32166
+ const first = options.snapshots[0];
32167
+ if (!first)
32168
+ return;
32169
+ logNativeDeliveryTrigger(pass, first.agentConfig.role, first.chatroomId, first.taskId);
32170
+ const executors = {
32171
+ startAgent: (task, operationalState) => runSerializedForAgent({ chatroomId: task.chatroomId, role: task.agentConfig.role }, { timeoutMs: 120000 }, (ops, context5) => ops.startAgent({
32172
+ chatroomId: task.chatroomId,
32173
+ role: task.agentConfig.role,
32174
+ agentHarness: task.agentConfig.agentHarness,
32175
+ model: task.agentConfig.model ?? "",
32176
+ workingDir: task.agentConfig.workingDir,
32177
+ reason: operationalState === "running" ? AgentStartReasonEnum["platform.task_monitor_nudge"] : AgentStartReasonEnum["platform.pending_task_wake"],
32178
+ wantResume: false,
32179
+ lifecycleRevision: task.agentConfig.configLifecycleRevision,
32180
+ taskId: task.taskId
32181
+ }, context5.signal)),
32182
+ injectTask: async (task, harnessSessionId) => {
32183
+ const backend2 = await sessionDeps.backend.query(api.machines.getAssignedTaskForAction, {
32184
+ sessionId: sessionDeps.sessionId,
32185
+ machineId,
32186
+ taskId: task.taskId,
32187
+ role: task.agentConfig.role
32188
+ });
32189
+ if (!backend2)
32190
+ return { kind: "task-unavailable" };
32191
+ const full = mapAssignedTaskView(backend2);
32192
+ let delivered;
32193
+ await taskService.deliverNativeTask(full, harnessSessionId, (result) => {
32194
+ delivered = result;
32195
+ });
32196
+ return { kind: "delivered", ...delivered ? { delivered } : {} };
32197
+ }
32198
+ };
32199
+ await getNativeTaskDeliveryCoordinator().reconcileRoleTasks({
32200
+ tasks: [...options.snapshots],
32201
+ pass,
32202
+ runtime: runtime4,
32203
+ effectContext: effectContext2,
32204
+ agentMgr,
32205
+ runSerializedForAgent,
32206
+ taskService,
32207
+ sessionDeps,
32208
+ lifecycleOutbox,
32209
+ operationalModel,
32210
+ isTaskActive,
32211
+ machineId,
32212
+ onTaskDelivered: options.onTaskDelivered,
32213
+ executors
32214
+ });
32215
+ }
32216
+ var init_task_delivery_processor = __esm(() => {
32217
+ init_agent();
32218
+ init_native_task_delivery_coordinator();
32219
+ init_api3();
32220
+ });
32221
+
32222
+ // src/daemon/services/task-service/service/native-delivery/native-delivery-service.ts
32223
+ class NativeDeliveryService {
32224
+ deps;
32225
+ unsubscribeAgentTurnEnded;
32226
+ unsubscribeAgentStarted;
32227
+ unsubscribeAgentSessionLost;
32228
+ reconcileStates = new Map;
32229
+ unsubscribeTaskService;
32230
+ periodicReconcileTimer;
32231
+ periodicReconcileInFlight = false;
32232
+ constructor(deps) {
32233
+ this.deps = deps;
32234
+ this.unsubscribeAgentTurnEnded = deps.agentMgr.subscribeAgentTurnEnded((event) => this.handleAgentTurnEnded(event));
32235
+ this.unsubscribeAgentStarted = deps.agentMgr.subscribeAgentStarted((event) => this.handleAgentStarted(event));
32236
+ this.unsubscribeAgentSessionLost = deps.agentMgr.subscribeAgentSessionLost((event) => this.handleAgentSessionLost(event));
32237
+ this.unsubscribeTaskService = deps.taskService.subscribe?.((notification) => this.handleTaskServiceNotification(notification));
32238
+ }
32239
+ async handleAgentStarted(event) {
32240
+ await this.requestReconcile({
32241
+ chatroomId: event.chatroomId,
32242
+ role: event.role,
32243
+ source: "agent-started"
32244
+ });
32245
+ }
32246
+ handleAgentSessionLost(event) {
32247
+ getRoleDeliveryState().resetDeliveryState(event.chatroomId, event.role);
32248
+ this.deps.agentTaskState.clear({ chatroomId: event.chatroomId, role: event.role });
32249
+ this.requestReconcile({
32250
+ chatroomId: event.chatroomId,
32251
+ role: event.role,
32252
+ source: "operational-signal"
32253
+ }).catch((error) => {
32254
+ console.warn(`[NativeDelivery:failure] role=${event.role} chatroom=${event.chatroomId} operation=session-loss-reconcile error=${error instanceof Error ? error.message : String(error)}`);
32255
+ });
32256
+ }
32257
+ async handleAgentTurnEnded(event) {
32258
+ this.scheduleRoleDelivery(event.chatroomId, event.role);
32259
+ }
32260
+ scheduleRoleDelivery(chatroomId, role) {
32261
+ setTimeout(() => {
32262
+ this.requestReconcile({ chatroomId, role, source: "turn-ended" }).catch((error) => {
32263
+ console.warn(`[NativeDelivery] post-turn delivery failed for ${role}@${chatroomId}: ${error instanceof Error ? error.message : String(error)}`);
32264
+ });
32265
+ }, 0);
32266
+ }
32267
+ dispose() {
32268
+ this.unsubscribeAgentTurnEnded();
32269
+ this.unsubscribeAgentStarted();
32270
+ this.unsubscribeAgentSessionLost();
32271
+ this.unsubscribeTaskService?.();
32272
+ this.unsubscribeTaskService = undefined;
32273
+ if (this.periodicReconcileTimer) {
32274
+ clearInterval(this.periodicReconcileTimer);
32275
+ this.periodicReconcileTimer = undefined;
32276
+ }
32277
+ }
32278
+ startPeriodicReconciliation(intervalMs = NATIVE_DELIVERY_RECONCILE_MS) {
32279
+ if (this.periodicReconcileTimer)
32280
+ return;
32281
+ this.periodicReconcileTimer = setInterval(() => {
32282
+ if (this.periodicReconcileInFlight)
32283
+ return;
32284
+ this.periodicReconcileInFlight = true;
32285
+ const roleKeys = new Set(this.deps.taskSnapshotState.listAll().map((snapshot) => `${snapshot.chatroomId}:${snapshot.agentConfig.role.toLowerCase()}`));
32286
+ Promise.all([...roleKeys].map((key) => {
32287
+ const separator = key.indexOf(":");
32288
+ return this.requestReconcile({
32289
+ chatroomId: key.slice(0, separator),
32290
+ role: key.slice(separator + 1),
32291
+ source: "periodic-reconcile"
32292
+ });
32293
+ })).catch((error) => {
32294
+ console.warn("[TaskService] local delivery reconciliation failed:", error);
32295
+ }).finally(() => {
32296
+ this.periodicReconcileInFlight = false;
32297
+ });
32298
+ }, intervalMs);
32299
+ this.periodicReconcileTimer.unref?.();
32300
+ }
32301
+ get agentTaskState() {
32302
+ return this.deps.agentTaskState;
32303
+ }
32304
+ async handleTaskInboxUpdate(update5) {
32305
+ await this.requestReconcileForSnapshots(update5.snapshots, "task-signal");
32306
+ }
32307
+ async handleTaskServiceNotification(notification) {
32308
+ if (notification.kind === "bootstrap") {
32309
+ await this.requestReconcileForSnapshots(notification.snapshots, "bootstrap");
32310
+ return;
32311
+ }
32312
+ await this.handleTaskInboxUpdate(notification.update);
32313
+ }
32314
+ async requestReconcile(params) {
32315
+ const key = `${params.chatroomId}:${params.role.toLowerCase()}`;
32316
+ const existing = this.reconcileStates.get(key);
32317
+ if (existing) {
32318
+ existing.pendingSource = params.source;
32319
+ await existing.promise;
32320
+ return;
32321
+ }
32322
+ const state = {
32323
+ pendingSource: undefined,
32324
+ promise: Promise.resolve()
32325
+ };
32326
+ state.promise = (async () => {
32327
+ try {
32328
+ do {
32329
+ const source = state.pendingSource ?? params.source;
32330
+ state.pendingSource = undefined;
32331
+ const snapshots = this.deps.taskSnapshotState.listForRole(params.chatroomId, params.role);
32332
+ if (snapshots.length === 0) {
32333
+ logNativeDeliveryDecision(source, params.role, params.chatroomId, "idle", undefined, {
32334
+ reason: "no_deliverable_task",
32335
+ attemptId: `${Date.now()}-${params.chatroomId}-${params.role}`
32336
+ });
32337
+ }
32338
+ await this.reconcileRole(source, snapshots, params.onTaskDelivered);
32339
+ } while (state.pendingSource !== undefined);
32340
+ } finally {
32341
+ if (this.reconcileStates.get(key) === state)
32342
+ this.reconcileStates.delete(key);
32343
+ }
32344
+ })();
32345
+ this.reconcileStates.set(key, state);
32346
+ await state.promise;
32347
+ }
32348
+ async requestReconcileForSnapshots(snapshots, source) {
32349
+ const roles = new Set(snapshots.map((snapshot) => `${snapshot.chatroomId}:${snapshot.agentConfig.role.toLowerCase()}`));
32350
+ await Promise.all([...roles].map((key) => {
32351
+ const separator = key.indexOf(":");
32352
+ return this.requestReconcile({
32353
+ chatroomId: key.slice(0, separator),
32354
+ role: key.slice(separator + 1),
32355
+ source
32356
+ });
32357
+ }));
32358
+ }
32359
+ async reconcileRole(pass, snapshots, onTaskDelivered) {
32360
+ if (snapshots.length === 0)
32361
+ return;
32362
+ await processTasksUpdate(this.deps.runtime, this.deps.effectContext, this.deps.agentMgr, this.deps.runSerializedForAgent, this.deps.taskService, this.deps.sessionDeps, this.deps.machineId, pass, this.deps.lifecycleOutbox, this.deps.agentOperationalReadModel, ({ chatroomId, role, taskId }) => this.deps.agentTaskState.get({ chatroomId, role })?.taskId === taskId, {
32363
+ snapshots,
32364
+ onTaskDelivered: (args2) => {
32365
+ this.recordTaskDelivered(args2);
32366
+ onTaskDelivered?.(args2);
32367
+ }
32368
+ });
32369
+ }
32370
+ recordTaskDelivered(args2) {
32371
+ this.deps.agentTaskState.start(args2);
32372
+ }
32373
+ }
32374
+ var NATIVE_DELIVERY_RECONCILE_MS = 1e4;
32375
+ var init_native_delivery_service = __esm(() => {
32376
+ init_task_delivery_processor();
32377
+ });
32378
+
31789
32379
  // src/daemon/services/task-service/service/task-outbox.ts
31790
32380
  class TaskOutbox {
31791
32381
  sender;
@@ -46535,42 +47125,6 @@ var init_assigned_task_snapshot_contract = __esm(() => {
46535
47125
  }));
46536
47126
  });
46537
47127
 
46538
- // src/infrastructure/mappers/map-assigned-task.ts
46539
- function mapAssignedTaskSnapshot(row) {
46540
- return {
46541
- taskId: row.taskId,
46542
- chatroomId: row.chatroomId,
46543
- status: row.status,
46544
- assignedTo: row.assignedTo,
46545
- updatedAt: row.updatedAt,
46546
- createdAt: row.createdAt,
46547
- agentConfig: {
46548
- role: row.agentConfig.role,
46549
- machineId: row.agentConfig.machineId,
46550
- agentHarness: row.agentConfig.agentHarness,
46551
- model: row.agentConfig.model,
46552
- workingDir: row.agentConfig.workingDir,
46553
- spawnedAgentPid: row.agentConfig.spawnedAgentPid,
46554
- desiredState: row.agentConfig.desiredState,
46555
- circuitState: row.agentConfig.circuitState,
46556
- configLifecycleRevision: row.agentConfig.configLifecycleRevision
46557
- },
46558
- participant: row.participant,
46559
- requestsNativeColdSession: row.requestsNativeColdSession
46560
- };
46561
- }
46562
- function mapAssignedTaskView(row) {
46563
- return {
46564
- ...mapAssignedTaskSnapshot(row),
46565
- taskContent: row.taskContent,
46566
- taskEnvelope: row.taskEnvelope,
46567
- startInNewSession: row.startInNewSession
46568
- };
46569
- }
46570
- function mapAssignedTaskSnapshotList(rows) {
46571
- return rows.map(mapAssignedTaskSnapshot);
46572
- }
46573
-
46574
47128
  // src/daemon/infrastructure/inbox/fetch-machine-assigned-task-snapshots.ts
46575
47129
  async function fetchMachineAssignedTaskSnapshots(sessionDeps, machineId) {
46576
47130
  const result = await sessionDeps.backend.query(api.machines.listMachineAssignedTaskSnapshots, {
@@ -47025,7 +47579,7 @@ function createTaskService(deps) {
47025
47579
  roomControllers.set(chatroomId, controller);
47026
47580
  runRoomInbox(chatroomId, cursor, controller);
47027
47581
  };
47028
- return {
47582
+ const service4 = {
47029
47583
  startTaskInbox: async (client2) => {
47030
47584
  if (inboxClient)
47031
47585
  return;
@@ -47075,11 +47629,22 @@ function createTaskService(deps) {
47075
47629
  deliverNativeTask: (task, harnessSessionId, onTaskDelivered) => taskOutbox.enqueue({ task, harnessSessionId, onTaskDelivered }),
47076
47630
  isNativeHarness,
47077
47631
  snapshotRequestsNativeColdSession,
47078
- explainNativeDeliveryBlock: (task, options) => explainNativeDeliveryBlock(task, options)
47632
+ explainNativeDeliveryBlock: (task, options) => explainNativeDeliveryBlock(task, options),
47633
+ createNativeDeliveryService: (deliveryDeps) => {
47634
+ const nativeDelivery = new NativeDeliveryService({
47635
+ ...deliveryDeps,
47636
+ taskSnapshotState,
47637
+ taskService: service4
47638
+ });
47639
+ nativeDelivery.startPeriodicReconciliation();
47640
+ return nativeDelivery;
47641
+ }
47079
47642
  };
47643
+ return service4;
47080
47644
  }
47081
47645
  var init_task_service = __esm(() => {
47082
47646
  init_esm();
47647
+ init_native_delivery_service();
47083
47648
  init_native_task_injector();
47084
47649
  init_api3();
47085
47650
  init_fetch_machine_assigned_task_snapshots();
@@ -47098,6 +47663,10 @@ var init_task_service2 = __esm(() => {
47098
47663
  init_native_ready_invariant();
47099
47664
  init_native_cold_session_delivery();
47100
47665
  init_task_service();
47666
+ init_convex_native_task_delivery_gateway();
47667
+ init_daemon_audit_port();
47668
+ init_native_delivery_service();
47669
+ init_native_task_delivery_coordinator();
47101
47670
  });
47102
47671
 
47103
47672
  // src/daemon/services/service-interfaces.ts
@@ -47109,8 +47678,10 @@ __export(exports_service_interfaces, {
47109
47678
  shouldDeliverNativeTask: () => shouldDeliverNativeTask,
47110
47679
  setNativeTurnPhase: () => setNativeTurnPhase,
47111
47680
  runRoleScopedStop: () => runRoleScopedStop,
47681
+ runNativeInjectionEffect: () => runNativeInjectionEffect,
47112
47682
  runExactTargetsStop: () => runExactTargetsStop,
47113
47683
  runConfirmedStop: () => runConfirmedStop,
47684
+ resetRoleDeliveryState: () => resetRoleDeliveryState,
47114
47685
  resetChatroomScopeBarrierForTests: () => resetChatroomScopeBarrierForTests,
47115
47686
  reapOrphanedProcessGroupsEffect: () => reapOrphanedProcessGroupsEffect,
47116
47687
  reapOrphanedProcessGroups: () => reapOrphanedProcessGroups,
@@ -47130,6 +47701,8 @@ __export(exports_service_interfaces, {
47130
47701
  createStopAgentTargetsDeps: () => createStopAgentTargetsDeps,
47131
47702
  createStopAgentConfirmedDeps: () => createStopAgentConfirmedDeps,
47132
47703
  createHarnessActivityEmitter: () => createHarnessActivityEmitter,
47704
+ createDaemonAuditPort: () => createDaemonAuditPort,
47705
+ createConvexNativeTaskDeliveryGateway: () => createConvexNativeTaskDeliveryGateway,
47133
47706
  createChatroomScopeBarrier: () => createChatroomScopeBarrier,
47134
47707
  createAgentTaskStateService: () => createAgentTaskStateService,
47135
47708
  createAgentProcessService: () => createAgentProcessService,
@@ -47140,6 +47713,7 @@ __export(exports_service_interfaces, {
47140
47713
  buildStopTargetDescriptor: () => buildStopTargetDescriptor,
47141
47714
  buildNativeInjectionPrompt: () => buildNativeInjectionPrompt,
47142
47715
  STOPPING_TIMEOUT_MS: () => STOPPING_TIMEOUT_MS,
47716
+ NativeDeliveryService: () => NativeDeliveryService,
47143
47717
  InMemoryActiveTaskStateStore: () => InMemoryActiveTaskStateStore,
47144
47718
  HARNESS_ACTIVITY_KINDS: () => HARNESS_ACTIVITY_KINDS,
47145
47719
  DefaultAgentTaskStateService: () => DefaultAgentTaskStateService,
@@ -110113,6 +110687,346 @@ var init_command_sync_heartbeat = __esm(() => {
110113
110687
  });
110114
110688
  });
110115
110689
 
110690
+ // src/daemon/entry/refresh-models-outcome.ts
110691
+ function capabilitiesOutcomeToStatus(outcome) {
110692
+ switch (outcome.kind) {
110693
+ case "pushed":
110694
+ return { status: "completed" };
110695
+ case "skipped_no_changes":
110696
+ return { status: "skipped_no_changes" };
110697
+ case "failed":
110698
+ return { status: "failed", errorMessage: outcome.message };
110699
+ case "noop":
110700
+ return { status: "failed", errorMessage: "Daemon configuration unavailable" };
110701
+ default: {
110702
+ const _exhaustive = outcome;
110703
+ return _exhaustive;
110704
+ }
110705
+ }
110706
+ }
110707
+ var init_refresh_models_outcome = () => {};
110708
+
110709
+ // src/daemon/entry/resolve-local-web-port.ts
110710
+ function resolveDefaultLocalWebPort(convexUrl = getConvexUrl()) {
110711
+ return isProductionConvexUrl(convexUrl) ? PRODUCTION_LOCAL_WEB_PORT : NON_PRODUCTION_LOCAL_WEB_PORT;
110712
+ }
110713
+ function resolveLocalWebPort(env2 = process.env, convexUrl = getConvexUrl()) {
110714
+ const override = env2.CHATROOM_LOCAL_WEB_PORT;
110715
+ if (override !== undefined && override !== "") {
110716
+ return Number(override);
110717
+ }
110718
+ return resolveDefaultLocalWebPort(convexUrl);
110719
+ }
110720
+ var PRODUCTION_LOCAL_WEB_PORT = 18765, NON_PRODUCTION_LOCAL_WEB_PORT = 28765;
110721
+ var init_resolve_local_web_port = __esm(() => {
110722
+ init_env();
110723
+ init_client2();
110724
+ });
110725
+
110726
+ // src/daemon/infrastructure/git/git-writer.ts
110727
+ function classifyError2(errMessage) {
110728
+ return { status: "error", message: errMessage.trim() };
110729
+ }
110730
+ async function discardFile(workingDir, filePath) {
110731
+ const result = await runGit(["checkout", "--", filePath], workingDir);
110732
+ if ("error" in result) {
110733
+ return classifyError2(result.error.message);
110734
+ }
110735
+ return { status: "available" };
110736
+ }
110737
+ async function discardAllChanges(workingDir) {
110738
+ const checkoutResult = await runGit(["checkout", "--", "."], workingDir);
110739
+ if ("error" in checkoutResult) {
110740
+ return classifyError2(checkoutResult.error.message);
110741
+ }
110742
+ const cleanResult = await runGit(["clean", "-fd"], workingDir);
110743
+ if ("error" in cleanResult) {
110744
+ return classifyError2(cleanResult.error.message);
110745
+ }
110746
+ return { status: "available" };
110747
+ }
110748
+ async function gitPull(workingDir) {
110749
+ const result = await runGit(["pull"], workingDir);
110750
+ if ("error" in result) {
110751
+ const message = result.error.message;
110752
+ if (message.includes("no tracking branch")) {
110753
+ return {
110754
+ status: "error",
110755
+ message: "No tracking branch configured. Set upstream with `git push -u`."
110756
+ };
110757
+ }
110758
+ if (message.includes("conflict")) {
110759
+ return { status: "error", message: "Merge conflict detected. Resolve conflicts manually." };
110760
+ }
110761
+ if (message.includes("Authentication failed") || message.includes("could not read")) {
110762
+ return {
110763
+ status: "error",
110764
+ message: "Authentication failed. Run `gh auth status` to check your GitHub credentials."
110765
+ };
110766
+ }
110767
+ return classifyError2(message);
110768
+ }
110769
+ const stderr = result.stderr.trim();
110770
+ if (stderr && !stderr.includes("Already up to date")) {
110771
+ return { status: "available", message: stderr };
110772
+ }
110773
+ return { status: "available" };
110774
+ }
110775
+ async function gitPush(workingDir) {
110776
+ const result = await runGit(["push"], workingDir);
110777
+ if ("error" in result) {
110778
+ const message = result.error.message;
110779
+ if (message.includes("no upstream branch")) {
110780
+ return {
110781
+ status: "error",
110782
+ message: "No upstream branch configured. Set upstream with `git push -u`."
110783
+ };
110784
+ }
110785
+ if (message.includes("Authentication failed") || message.includes("could not read")) {
110786
+ return {
110787
+ status: "error",
110788
+ message: "Authentication failed. Run `gh auth status` to check your GitHub credentials."
110789
+ };
110790
+ }
110791
+ return classifyError2(message);
110792
+ }
110793
+ const stderr = result.stderr.trim();
110794
+ if (stderr && !stderr.includes("Everything up-to-date")) {
110795
+ return { status: "available", message: stderr };
110796
+ }
110797
+ return { status: "available" };
110798
+ }
110799
+ async function gitSync(workingDir) {
110800
+ const pullResult = await gitPull(workingDir);
110801
+ if (pullResult.status === "error") {
110802
+ return pullResult;
110803
+ }
110804
+ return gitPush(workingDir);
110805
+ }
110806
+ var init_git_writer = __esm(() => {
110807
+ init_run_command();
110808
+ });
110809
+
110810
+ // src/daemon/infrastructure/git/index.ts
110811
+ var init_git = __esm(() => {
110812
+ init_git_reader();
110813
+ init_git_writer();
110814
+ });
110815
+
110816
+ // src/infrastructure/local-actions/execute-local-action.ts
110817
+ import { spawn as spawn5 } from "node:child_process";
110818
+ import { access as access3 } from "node:fs/promises";
110819
+ function escapeShellArg(arg) {
110820
+ return `"${arg.replace(/"/g, "\\\"")}"`;
110821
+ }
110822
+ function resolveWhichCommand(name) {
110823
+ return process.platform === "win32" ? `where ${name}` : `which ${name}`;
110824
+ }
110825
+ function isCliAvailable(cliName) {
110826
+ return new Promise((resolve5) => {
110827
+ const child = spawn5(resolveWhichCommand(cliName), [], DETACHED_SHELL_SPAWN_OPTIONS);
110828
+ child.on("error", () => resolve5(false));
110829
+ child.on("close", (code2) => resolve5(code2 === 0));
110830
+ child.unref();
110831
+ });
110832
+ }
110833
+ function execFireAndForget(command, logTag) {
110834
+ const child = spawn5(command, [], DETACHED_SHELL_SPAWN_OPTIONS);
110835
+ child.on("error", (err) => {
110836
+ console.warn(`[${logTag}] spawn failed: ${err.message}`);
110837
+ });
110838
+ child.unref();
110839
+ }
110840
+ function resolveOpenCommand(platform) {
110841
+ switch (platform) {
110842
+ case "darwin":
110843
+ return "open";
110844
+ case "win32":
110845
+ return "explorer";
110846
+ default:
110847
+ return "xdg-open";
110848
+ }
110849
+ }
110850
+ function resolveOpenUrlCommand(platform) {
110851
+ return platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
110852
+ }
110853
+ async function openVscode(workingDir) {
110854
+ const available = await isCliAvailable("code");
110855
+ if (!available) {
110856
+ return {
110857
+ success: false,
110858
+ error: "VS Code CLI (code) not found. Install via: VS Code → Cmd+Shift+P → 'Shell Command: Install code in PATH'"
110859
+ };
110860
+ }
110861
+ execFireAndForget(`code ${escapeShellArg(workingDir)}`, "open-vscode");
110862
+ return { success: true };
110863
+ }
110864
+ async function openFinder(workingDir) {
110865
+ const cmd = resolveOpenCommand(process.platform);
110866
+ execFireAndForget(`${cmd} ${escapeShellArg(workingDir)}`, "open-finder");
110867
+ return { success: true };
110868
+ }
110869
+ async function openCursor(workingDir) {
110870
+ const available = await isCliAvailable("cursor");
110871
+ if (!available) {
110872
+ return {
110873
+ success: false,
110874
+ error: "Cursor CLI (cursor) not found. Install via: Cursor → Cmd+Shift+P → 'Shell Command: Install cursor in PATH'"
110875
+ };
110876
+ }
110877
+ execFireAndForget(`cursor ${escapeShellArg(workingDir)}`, "open-cursor");
110878
+ return { success: true };
110879
+ }
110880
+ async function openGithubDesktop(workingDir) {
110881
+ const available = await isCliAvailable("github");
110882
+ if (!available) {
110883
+ return { success: false, error: "GitHub Desktop CLI not found" };
110884
+ }
110885
+ execFireAndForget(`github ${escapeShellArg(workingDir)}`, "open-github-desktop");
110886
+ return { success: true };
110887
+ }
110888
+ async function openDaemonLogs(_workingDir, options) {
110889
+ const params = new URLSearchParams;
110890
+ if (options?.chatroomId)
110891
+ params.set("chatroomId", options.chatroomId);
110892
+ const qs = params.toString();
110893
+ const url3 = `http://127.0.0.1:${resolveLocalWebPort()}/${qs ? `?${qs}` : ""}`;
110894
+ execFireAndForget(`${resolveOpenUrlCommand(process.platform)} ${escapeShellArg(url3)}`, "open-daemon-logs");
110895
+ return { success: true };
110896
+ }
110897
+ async function gitDiscardFileAction(workingDir) {
110898
+ const separatorIndex = workingDir.indexOf("::");
110899
+ if (separatorIndex === -1) {
110900
+ return {
110901
+ success: false,
110902
+ error: 'Invalid file path. Expected format: "/path/to/dir::/path/to/file"'
110903
+ };
110904
+ }
110905
+ const dir = workingDir.slice(0, separatorIndex);
110906
+ const filePath = workingDir.slice(separatorIndex + 2);
110907
+ const result = await discardFile(dir, filePath);
110908
+ if (result.status === "error") {
110909
+ return { success: false, error: result.message };
110910
+ }
110911
+ return { success: true };
110912
+ }
110913
+ async function gitDiscardAllAction(workingDir) {
110914
+ const result = await discardAllChanges(workingDir);
110915
+ if (result.status === "error") {
110916
+ return { success: false, error: result.message };
110917
+ }
110918
+ return { success: true };
110919
+ }
110920
+ async function gitPullAction(workingDir) {
110921
+ const result = await gitPull(workingDir);
110922
+ if (result.status === "error") {
110923
+ return { success: false, error: result.message };
110924
+ }
110925
+ return { success: true, message: result.message ?? "Pull successful" };
110926
+ }
110927
+ async function gitPushAction(workingDir) {
110928
+ const result = await gitPush(workingDir);
110929
+ if (result.status === "error") {
110930
+ return { success: false, error: result.message };
110931
+ }
110932
+ return { success: true, message: result.message ?? "Push successful" };
110933
+ }
110934
+ async function gitSyncAction(workingDir) {
110935
+ const result = await gitSync(workingDir);
110936
+ if (result.status === "error") {
110937
+ return { success: false, error: result.message };
110938
+ }
110939
+ return { success: true, message: result.message ?? "Sync successful" };
110940
+ }
110941
+ async function executeLocalAction(action, workingDir, options) {
110942
+ if (action === "open-daemon-logs")
110943
+ return openDaemonLogs(workingDir, options);
110944
+ try {
110945
+ await access3(workingDir);
110946
+ } catch {
110947
+ return { success: false, error: `Directory not found: ${workingDir}` };
110948
+ }
110949
+ const handler2 = actionHandlers[action];
110950
+ if (handler2)
110951
+ return handler2(workingDir);
110952
+ return { success: false, error: `Unknown action: ${action}` };
110953
+ }
110954
+ var DETACHED_SHELL_SPAWN_OPTIONS, actionHandlers;
110955
+ var init_execute_local_action = __esm(() => {
110956
+ init_resolve_local_web_port();
110957
+ init_git();
110958
+ DETACHED_SHELL_SPAWN_OPTIONS = {
110959
+ stdio: "ignore",
110960
+ detached: true,
110961
+ shell: true
110962
+ };
110963
+ actionHandlers = {
110964
+ "open-vscode": openVscode,
110965
+ "open-finder": openFinder,
110966
+ "open-cursor": openCursor,
110967
+ "open-github-desktop": openGithubDesktop,
110968
+ "open-daemon-logs": openDaemonLogs,
110969
+ "git-discard-file": gitDiscardFileAction,
110970
+ "git-discard-all": gitDiscardAllAction,
110971
+ "git-pull": gitPullAction,
110972
+ "git-push": gitPushAction,
110973
+ "git-sync": gitSyncAction
110974
+ };
110975
+ });
110976
+
110977
+ // src/infrastructure/local-actions/index.ts
110978
+ var init_local_actions = __esm(() => {
110979
+ init_execute_local_action();
110980
+ });
110981
+
110982
+ // src/infrastructure/local-actions/pick-folder.ts
110983
+ import { execFileSync as execFileSync2 } from "node:child_process";
110984
+ function runPicker(command, args2) {
110985
+ try {
110986
+ const path3 = execFileSync2(command, args2, { encoding: "utf8", timeout: 300000 }).trim();
110987
+ if (!path3)
110988
+ return { success: false, error: "No folder selected" };
110989
+ return { success: true, path: path3 };
110990
+ } catch (error51) {
110991
+ const exitCode = typeof error51 === "object" && error51 !== null && "status" in error51 ? error51.status : null;
110992
+ if (exitCode === 1)
110993
+ return { success: false, error: "Cancelled", cancelled: true };
110994
+ const message = error51 instanceof Error ? error51.message : String(error51);
110995
+ return { success: false, error: message };
110996
+ }
110997
+ }
110998
+ function pickFolderDialog() {
110999
+ switch (process.platform) {
111000
+ case "darwin":
111001
+ return runPicker("osascript", [
111002
+ "-e",
111003
+ 'POSIX path of (choose folder with prompt "Select workspace folder")'
111004
+ ]);
111005
+ case "win32":
111006
+ return runPicker("powershell", [
111007
+ "-NoProfile",
111008
+ "-Command",
111009
+ [
111010
+ "Add-Type -AssemblyName System.Windows.Forms",
111011
+ "$dialog = New-Object System.Windows.Forms.FolderBrowserDialog",
111012
+ '$dialog.Description = "Select workspace folder"',
111013
+ "if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {",
111014
+ " Write-Output $dialog.SelectedPath",
111015
+ " exit 0",
111016
+ "}",
111017
+ "exit 1"
111018
+ ].join("; ")
111019
+ ]);
111020
+ default:
111021
+ return runPicker("zenity", [
111022
+ "--file-selection",
111023
+ "--directory",
111024
+ "--title=Select workspace folder"
111025
+ ]);
111026
+ }
111027
+ }
111028
+ var init_pick_folder = () => {};
111029
+
110116
111030
  // src/daemon/domain/usecase/restart-agent.ts
110117
111031
  async function restartAgent(deps, input) {
110118
111032
  const now = deps.now?.() ?? Date.now();
@@ -110134,7 +111048,9 @@ async function restartAgent(deps, input) {
110134
111048
  wantResume: input.wantResume,
110135
111049
  ...input.lifecycleRevision !== undefined ? { lifecycleRevision: input.lifecycleRevision } : {}
110136
111050
  });
110137
- } catch {}
111051
+ } catch (error51) {
111052
+ log4(`[daemon] agent.restart failed (correlationId=${input.correlationId}) for role=${input.role}: ${error51 instanceof Error ? error51.message : String(error51)}`);
111053
+ }
110138
111054
  }
110139
111055
 
110140
111056
  // ../../services/backend/src/domain/usecase/agent/build-agent-restart-event.ts
@@ -110165,200 +111081,6 @@ var init_build_agent_restart_event = __esm(() => {
110165
111081
  init_reliability();
110166
111082
  });
110167
111083
 
110168
- // src/daemon/infrastructure/agent-operational/fetch-machine-agent-operational-status.ts
110169
- async function fetchMachineAgentOperationalStatus(sessionDeps, machineId) {
110170
- const result = await sessionDeps.backend.query(api.machines.listMachineAgentOperationalStatus, {
110171
- sessionId: sessionDeps.sessionId,
110172
- machineId
110173
- });
110174
- return result;
110175
- }
110176
- var init_fetch_machine_agent_operational_status = __esm(() => {
110177
- init_api3();
110178
- });
110179
-
110180
- // src/daemon/entry/native-delivery/native-delivery-log.ts
110181
- function logNativeDeliveryTrigger(source, role, chatroomId, taskId) {
110182
- const taskSuffix = taskId ? ` task ${taskId}` : "";
110183
- console.log(`[NativeDelivery:trigger] source=${source} ${role}@${chatroomId}${taskSuffix}`);
110184
- }
110185
- function logNativeDeliveryFallback(reason, role, chatroomId, taskId) {
110186
- const taskSuffix = taskId ? ` task ${taskId}` : "";
110187
- console.log(`[NativeDelivery:fallback] source=${reason} ${role}@${chatroomId}${taskSuffix} — periodic recovery pass`);
110188
- }
110189
- function logNativeDeliverySkip(role, chatroomId, taskId, reason) {
110190
- console.log(`[NativeDelivery:skip] ${role}@${chatroomId} task ${taskId} — ${reason}`);
110191
- }
110192
- function logNativeDeliveryMutexSkip(role, chatroomId, taskId) {
110193
- console.log(`[NativeDelivery:skip] ${role}@${chatroomId} task ${taskId} — delivery_mutex_busy (another inject in flight)`);
110194
- }
110195
- function logNativeDeliveryInjecting(role, chatroomId, taskId) {
110196
- console.log(`[NativeDelivery:inject] ${role}@${chatroomId} task ${taskId} — starting injection`);
110197
- }
110198
-
110199
- // src/daemon/entry/restart-orchestrator-in-flight.ts
110200
- function roleKey(chatroomId, role) {
110201
- return `${chatroomId}:${role.toLowerCase()}`;
110202
- }
110203
- function markRestartOrchestratorInFlight(chatroomId, role, correlationId) {
110204
- inFlight.set(roleKey(chatroomId, role), correlationId);
110205
- }
110206
- function clearRestartOrchestratorInFlight(chatroomId, role, correlationId) {
110207
- const key = roleKey(chatroomId, role);
110208
- if (correlationId !== undefined && inFlight.get(key) !== correlationId)
110209
- return;
110210
- inFlight.delete(key);
110211
- }
110212
- function isRestartOrchestratorInFlight(chatroomId, role) {
110213
- return inFlight.has(roleKey(chatroomId, role));
110214
- }
110215
- function filterSnapshotsExcludingRestartInFlight(snapshots) {
110216
- return snapshots.filter((row) => !isRestartOrchestratorInFlight(row.chatroomId, row.agentConfig.role));
110217
- }
110218
- var inFlight;
110219
- var init_restart_orchestrator_in_flight = __esm(() => {
110220
- inFlight = new Map;
110221
- });
110222
-
110223
- // src/daemon/entry/role-delivery-state.ts
110224
- function roleKey2(chatroomId, role) {
110225
- return `${chatroomId}:${role.toLowerCase()}`;
110226
- }
110227
-
110228
- class RoleDeliveryState {
110229
- generation = new Map;
110230
- inFlight = new Set;
110231
- nativeNudgeFailures = new Map;
110232
- getGeneration(chatroomId, role) {
110233
- return this.generation.get(roleKey2(chatroomId, role)) ?? 0;
110234
- }
110235
- resetDeliveryState(chatroomId, role) {
110236
- const key = roleKey2(chatroomId, role);
110237
- const next4 = (this.generation.get(key) ?? 0) + 1;
110238
- this.generation.set(key, next4);
110239
- this.inFlight.delete(key);
110240
- this.nativeNudgeFailures.delete(key);
110241
- return next4;
110242
- }
110243
- tryAcquireDelivery(chatroomId, role) {
110244
- const key = roleKey2(chatroomId, role);
110245
- if (this.inFlight.has(key))
110246
- return false;
110247
- this.inFlight.add(key);
110248
- return true;
110249
- }
110250
- releaseDelivery(chatroomId, role) {
110251
- this.inFlight.delete(roleKey2(chatroomId, role));
110252
- }
110253
- recordNativeNudgeFailure(chatroomId, role) {
110254
- const key = roleKey2(chatroomId, role);
110255
- const count3 = (this.nativeNudgeFailures.get(key) ?? 0) + 1;
110256
- this.nativeNudgeFailures.set(key, count3);
110257
- return count3;
110258
- }
110259
- clearNativeNudgeFailures(chatroomId, role) {
110260
- this.nativeNudgeFailures.delete(roleKey2(chatroomId, role));
110261
- }
110262
- getNativeNudgeFailures(chatroomId, role) {
110263
- return this.nativeNudgeFailures.get(roleKey2(chatroomId, role)) ?? 0;
110264
- }
110265
- }
110266
- function getRoleDeliveryState() {
110267
- shared ??= new RoleDeliveryState;
110268
- return shared;
110269
- }
110270
- var shared;
110271
-
110272
- // src/daemon/entry/native-delivery/native-task-delivery-coordinator.ts
110273
- class NativeTaskDeliveryCoordinator {
110274
- resetRoleDeliveryState(chatroomId, role) {
110275
- getRoleDeliveryState().resetDeliveryState(chatroomId, role);
110276
- }
110277
- async reconcileAssignedTasks(params) {
110278
- const tasks = filterSnapshotsExcludingRestartInFlight(params.tasks);
110279
- if (tasks.length === 0)
110280
- return;
110281
- const {
110282
- runtime: runtime4,
110283
- effectContext: effectContext2,
110284
- agentMgr,
110285
- sessionDeps,
110286
- operationalModel,
110287
- isTaskActive,
110288
- machineId,
110289
- onTaskDelivered
110290
- } = params;
110291
- const deliveryState = getRoleDeliveryState();
110292
- const taskService = params.taskService;
110293
- const pendingFirst = [...tasks].sort((a, b) => {
110294
- if (a.status === "pending" && b.status !== "pending")
110295
- return -1;
110296
- if (b.status === "pending" && a.status !== "pending")
110297
- return 1;
110298
- return a.createdAt - b.createdAt;
110299
- });
110300
- for (const row of pendingFirst) {
110301
- const { role } = row.agentConfig;
110302
- const slot = agentMgr.getSlot(row.chatroomId, role);
110303
- const blockReason = taskService.explainNativeDeliveryBlock(row, {
110304
- slot,
110305
- operational: operationalModel.get(row.chatroomId, role)
110306
- });
110307
- if (blockReason) {
110308
- if (isDeliverableTaskStatus(row.status)) {
110309
- logNativeDeliverySkip(role, row.chatroomId, row.taskId, blockReason);
110310
- }
110311
- continue;
110312
- }
110313
- if (isTaskActive({ chatroomId: row.chatroomId, role, taskId: row.taskId })) {
110314
- logNativeDeliverySkip(role, row.chatroomId, row.taskId, "task_state_active");
110315
- continue;
110316
- }
110317
- const harnessSessionId = slot?.harnessSessionId;
110318
- if (!deliveryState.tryAcquireDelivery(row.chatroomId, role)) {
110319
- logNativeDeliveryMutexSkip(role, row.chatroomId, row.taskId);
110320
- continue;
110321
- }
110322
- logNativeDeliveryInjecting(role, row.chatroomId, row.taskId);
110323
- await exports_Runtime.runPromise(runtime4)(exports_Effect.gen(function* () {
110324
- const backend2 = yield* exports_Effect.tryPromise(() => sessionDeps.backend.query(api.machines.getAssignedTaskForAction, {
110325
- sessionId: sessionDeps.sessionId,
110326
- machineId,
110327
- taskId: row.taskId,
110328
- role: row.agentConfig.role
110329
- }));
110330
- if (!backend2) {
110331
- console.warn(`[NativeDelivery:skip] ${role}@${row.chatroomId} task ${row.taskId} — task_hydrate_missing (deleted or not assigned)`);
110332
- return;
110333
- }
110334
- const full = mapAssignedTaskView(backend2);
110335
- yield* exports_Effect.tryPromise(() => taskService.deliverNativeTask(full, harnessSessionId, (delivered) => {
110336
- onTaskDelivered?.(delivered);
110337
- deliveryState.clearNativeNudgeFailures(delivered.chatroomId, delivered.role);
110338
- }));
110339
- }).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[NativeTaskDelivery] delivery failed for ${row.agentConfig.role}@${row.chatroomId}: ${getErrorMessage(err)}`))), exports_Effect.ensuring(exports_Effect.sync(() => {
110340
- deliveryState.releaseDelivery(row.chatroomId, row.agentConfig.role);
110341
- }))));
110342
- break;
110343
- }
110344
- }
110345
- }
110346
- function getNativeTaskDeliveryCoordinator() {
110347
- coordinator ??= new NativeTaskDeliveryCoordinator;
110348
- return coordinator;
110349
- }
110350
- function resetRoleDeliveryState(chatroomId, role) {
110351
- getRoleDeliveryState().resetDeliveryState(chatroomId, role);
110352
- }
110353
- var coordinator;
110354
- var init_native_task_delivery_coordinator = __esm(() => {
110355
- init_esm();
110356
- init_api3();
110357
- init_assigned_task();
110358
- init_convex_error();
110359
- init_restart_orchestrator_in_flight();
110360
- });
110361
-
110362
111084
  // src/daemon/entry/restart-orchestrator.ts
110363
111085
  async function emitPhase(deps, event, phase, detail) {
110364
111086
  const now = Date.now();
@@ -110399,31 +111121,22 @@ async function forceNativeWaiting(deps, event) {
110399
111121
  action: NATIVE_WAITING_ACTION
110400
111122
  });
110401
111123
  }
110402
- async function listDeliverableSnapshots(deps, event) {
111124
+ async function syncAssignedTaskSnapshots(deps) {
110403
111125
  await deps.session.backend.mutation(api.machines.syncMachineAssignedTaskSnapshotsMutation, {
110404
111126
  sessionId: deps.session.sessionId,
110405
111127
  machineId: deps.session.machineId
110406
111128
  });
110407
- const result = await deps.session.backend.query(api.machines.listMachineAssignedTaskSnapshots, {
110408
- sessionId: deps.session.sessionId,
110409
- machineId: deps.session.machineId
110410
- });
110411
- const operationalRows = await fetchMachineAgentOperationalStatus({
110412
- sessionId: deps.session.sessionId,
110413
- machineId: deps.session.machineId,
110414
- convexUrl: deps.session.convexUrl,
110415
- logEvent: deps.session.logEvent,
110416
- backend: deps.session.backend
110417
- }, deps.session.machineId);
110418
- const slot = deps.agentMgr.getSlot(event.chatroomId, event.role);
110419
- const operational = operationalRows.find((row) => row.chatroomId === event.chatroomId && row.role.toLowerCase() === event.role.toLowerCase());
110420
- return mapAssignedTaskSnapshotList(parseAssignedTaskSnapshotRows(result.tasks ?? [])).filter((t) => t.chatroomId === event.chatroomId && t.agentConfig.role.toLowerCase() === event.role.toLowerCase() && isDeliverableTaskStatus(t.status) && isAgentReadyForNativeDelivery(t, slot, operational)).sort((a, b) => a.createdAt - b.createdAt);
110421
111129
  }
110422
111130
  async function deliverPendingTasks(deps, event) {
110423
111131
  const delivered = [];
110424
- const snapshots = await listDeliverableSnapshots(deps, event);
110425
- await deps.nativeDelivery.processSnapshots("restart", snapshots, ({ taskId }) => {
110426
- delivered.push(taskId);
111132
+ await syncAssignedTaskSnapshots(deps);
111133
+ await deps.nativeDelivery.requestReconcile({
111134
+ chatroomId: event.chatroomId,
111135
+ role: event.role,
111136
+ source: "restart-completed",
111137
+ onTaskDelivered: ({ taskId }) => {
111138
+ delivered.push(taskId);
111139
+ }
110427
111140
  });
110428
111141
  return delivered;
110429
111142
  }
@@ -110479,15 +111192,11 @@ async function runRestartOrchestrator(deps, event) {
110479
111192
  var init_restart_orchestrator = __esm(() => {
110480
111193
  init_reliability();
110481
111194
  init_build_agent_restart_event();
110482
- init_assigned_task_snapshot_contract();
110483
- init_fetch_machine_agent_operational_status();
110484
- init_api3();
110485
- init_service_interfaces();
110486
- init_native_task_delivery_coordinator();
110487
111195
  init_restart_orchestrator_in_flight();
111196
+ init_api3();
110488
111197
  init_convex_error();
110489
- init_assigned_task();
110490
111198
  init_execution_kind();
111199
+ init_service_interfaces();
110491
111200
  });
110492
111201
 
110493
111202
  // src/daemon/entry/bridge/agent-control-bridge.ts
@@ -110814,346 +111523,6 @@ var init_manager = __esm(() => {
110814
111523
  processManager = new ProcessManager;
110815
111524
  });
110816
111525
 
110817
- // src/daemon/entry/refresh-models-outcome.ts
110818
- function capabilitiesOutcomeToStatus(outcome) {
110819
- switch (outcome.kind) {
110820
- case "pushed":
110821
- return { status: "completed" };
110822
- case "skipped_no_changes":
110823
- return { status: "skipped_no_changes" };
110824
- case "failed":
110825
- return { status: "failed", errorMessage: outcome.message };
110826
- case "noop":
110827
- return { status: "failed", errorMessage: "Daemon configuration unavailable" };
110828
- default: {
110829
- const _exhaustive = outcome;
110830
- return _exhaustive;
110831
- }
110832
- }
110833
- }
110834
- var init_refresh_models_outcome = () => {};
110835
-
110836
- // src/daemon/entry/resolve-local-web-port.ts
110837
- function resolveDefaultLocalWebPort(convexUrl = getConvexUrl()) {
110838
- return isProductionConvexUrl(convexUrl) ? PRODUCTION_LOCAL_WEB_PORT : NON_PRODUCTION_LOCAL_WEB_PORT;
110839
- }
110840
- function resolveLocalWebPort(env2 = process.env, convexUrl = getConvexUrl()) {
110841
- const override = env2.CHATROOM_LOCAL_WEB_PORT;
110842
- if (override !== undefined && override !== "") {
110843
- return Number(override);
110844
- }
110845
- return resolveDefaultLocalWebPort(convexUrl);
110846
- }
110847
- var PRODUCTION_LOCAL_WEB_PORT = 18765, NON_PRODUCTION_LOCAL_WEB_PORT = 28765;
110848
- var init_resolve_local_web_port = __esm(() => {
110849
- init_env();
110850
- init_client2();
110851
- });
110852
-
110853
- // src/daemon/infrastructure/git/git-writer.ts
110854
- function classifyError2(errMessage) {
110855
- return { status: "error", message: errMessage.trim() };
110856
- }
110857
- async function discardFile(workingDir, filePath) {
110858
- const result = await runGit(["checkout", "--", filePath], workingDir);
110859
- if ("error" in result) {
110860
- return classifyError2(result.error.message);
110861
- }
110862
- return { status: "available" };
110863
- }
110864
- async function discardAllChanges(workingDir) {
110865
- const checkoutResult = await runGit(["checkout", "--", "."], workingDir);
110866
- if ("error" in checkoutResult) {
110867
- return classifyError2(checkoutResult.error.message);
110868
- }
110869
- const cleanResult = await runGit(["clean", "-fd"], workingDir);
110870
- if ("error" in cleanResult) {
110871
- return classifyError2(cleanResult.error.message);
110872
- }
110873
- return { status: "available" };
110874
- }
110875
- async function gitPull(workingDir) {
110876
- const result = await runGit(["pull"], workingDir);
110877
- if ("error" in result) {
110878
- const message = result.error.message;
110879
- if (message.includes("no tracking branch")) {
110880
- return {
110881
- status: "error",
110882
- message: "No tracking branch configured. Set upstream with `git push -u`."
110883
- };
110884
- }
110885
- if (message.includes("conflict")) {
110886
- return { status: "error", message: "Merge conflict detected. Resolve conflicts manually." };
110887
- }
110888
- if (message.includes("Authentication failed") || message.includes("could not read")) {
110889
- return {
110890
- status: "error",
110891
- message: "Authentication failed. Run `gh auth status` to check your GitHub credentials."
110892
- };
110893
- }
110894
- return classifyError2(message);
110895
- }
110896
- const stderr = result.stderr.trim();
110897
- if (stderr && !stderr.includes("Already up to date")) {
110898
- return { status: "available", message: stderr };
110899
- }
110900
- return { status: "available" };
110901
- }
110902
- async function gitPush(workingDir) {
110903
- const result = await runGit(["push"], workingDir);
110904
- if ("error" in result) {
110905
- const message = result.error.message;
110906
- if (message.includes("no upstream branch")) {
110907
- return {
110908
- status: "error",
110909
- message: "No upstream branch configured. Set upstream with `git push -u`."
110910
- };
110911
- }
110912
- if (message.includes("Authentication failed") || message.includes("could not read")) {
110913
- return {
110914
- status: "error",
110915
- message: "Authentication failed. Run `gh auth status` to check your GitHub credentials."
110916
- };
110917
- }
110918
- return classifyError2(message);
110919
- }
110920
- const stderr = result.stderr.trim();
110921
- if (stderr && !stderr.includes("Everything up-to-date")) {
110922
- return { status: "available", message: stderr };
110923
- }
110924
- return { status: "available" };
110925
- }
110926
- async function gitSync(workingDir) {
110927
- const pullResult = await gitPull(workingDir);
110928
- if (pullResult.status === "error") {
110929
- return pullResult;
110930
- }
110931
- return gitPush(workingDir);
110932
- }
110933
- var init_git_writer = __esm(() => {
110934
- init_run_command();
110935
- });
110936
-
110937
- // src/daemon/infrastructure/git/index.ts
110938
- var init_git = __esm(() => {
110939
- init_git_reader();
110940
- init_git_writer();
110941
- });
110942
-
110943
- // src/infrastructure/local-actions/execute-local-action.ts
110944
- import { spawn as spawn5 } from "node:child_process";
110945
- import { access as access3 } from "node:fs/promises";
110946
- function escapeShellArg(arg) {
110947
- return `"${arg.replace(/"/g, "\\\"")}"`;
110948
- }
110949
- function resolveWhichCommand(name) {
110950
- return process.platform === "win32" ? `where ${name}` : `which ${name}`;
110951
- }
110952
- function isCliAvailable(cliName) {
110953
- return new Promise((resolve5) => {
110954
- const child = spawn5(resolveWhichCommand(cliName), [], DETACHED_SHELL_SPAWN_OPTIONS);
110955
- child.on("error", () => resolve5(false));
110956
- child.on("close", (code2) => resolve5(code2 === 0));
110957
- child.unref();
110958
- });
110959
- }
110960
- function execFireAndForget(command, logTag) {
110961
- const child = spawn5(command, [], DETACHED_SHELL_SPAWN_OPTIONS);
110962
- child.on("error", (err) => {
110963
- console.warn(`[${logTag}] spawn failed: ${err.message}`);
110964
- });
110965
- child.unref();
110966
- }
110967
- function resolveOpenCommand(platform) {
110968
- switch (platform) {
110969
- case "darwin":
110970
- return "open";
110971
- case "win32":
110972
- return "explorer";
110973
- default:
110974
- return "xdg-open";
110975
- }
110976
- }
110977
- function resolveOpenUrlCommand(platform) {
110978
- return platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
110979
- }
110980
- async function openVscode(workingDir) {
110981
- const available = await isCliAvailable("code");
110982
- if (!available) {
110983
- return {
110984
- success: false,
110985
- error: "VS Code CLI (code) not found. Install via: VS Code → Cmd+Shift+P → 'Shell Command: Install code in PATH'"
110986
- };
110987
- }
110988
- execFireAndForget(`code ${escapeShellArg(workingDir)}`, "open-vscode");
110989
- return { success: true };
110990
- }
110991
- async function openFinder(workingDir) {
110992
- const cmd = resolveOpenCommand(process.platform);
110993
- execFireAndForget(`${cmd} ${escapeShellArg(workingDir)}`, "open-finder");
110994
- return { success: true };
110995
- }
110996
- async function openCursor(workingDir) {
110997
- const available = await isCliAvailable("cursor");
110998
- if (!available) {
110999
- return {
111000
- success: false,
111001
- error: "Cursor CLI (cursor) not found. Install via: Cursor → Cmd+Shift+P → 'Shell Command: Install cursor in PATH'"
111002
- };
111003
- }
111004
- execFireAndForget(`cursor ${escapeShellArg(workingDir)}`, "open-cursor");
111005
- return { success: true };
111006
- }
111007
- async function openGithubDesktop(workingDir) {
111008
- const available = await isCliAvailable("github");
111009
- if (!available) {
111010
- return { success: false, error: "GitHub Desktop CLI not found" };
111011
- }
111012
- execFireAndForget(`github ${escapeShellArg(workingDir)}`, "open-github-desktop");
111013
- return { success: true };
111014
- }
111015
- async function openDaemonLogs(_workingDir, options) {
111016
- const params = new URLSearchParams;
111017
- if (options?.chatroomId)
111018
- params.set("chatroomId", options.chatroomId);
111019
- const qs = params.toString();
111020
- const url3 = `http://127.0.0.1:${resolveLocalWebPort()}/${qs ? `?${qs}` : ""}`;
111021
- execFireAndForget(`${resolveOpenUrlCommand(process.platform)} ${escapeShellArg(url3)}`, "open-daemon-logs");
111022
- return { success: true };
111023
- }
111024
- async function gitDiscardFileAction(workingDir) {
111025
- const separatorIndex = workingDir.indexOf("::");
111026
- if (separatorIndex === -1) {
111027
- return {
111028
- success: false,
111029
- error: 'Invalid file path. Expected format: "/path/to/dir::/path/to/file"'
111030
- };
111031
- }
111032
- const dir = workingDir.slice(0, separatorIndex);
111033
- const filePath = workingDir.slice(separatorIndex + 2);
111034
- const result = await discardFile(dir, filePath);
111035
- if (result.status === "error") {
111036
- return { success: false, error: result.message };
111037
- }
111038
- return { success: true };
111039
- }
111040
- async function gitDiscardAllAction(workingDir) {
111041
- const result = await discardAllChanges(workingDir);
111042
- if (result.status === "error") {
111043
- return { success: false, error: result.message };
111044
- }
111045
- return { success: true };
111046
- }
111047
- async function gitPullAction(workingDir) {
111048
- const result = await gitPull(workingDir);
111049
- if (result.status === "error") {
111050
- return { success: false, error: result.message };
111051
- }
111052
- return { success: true, message: result.message ?? "Pull successful" };
111053
- }
111054
- async function gitPushAction(workingDir) {
111055
- const result = await gitPush(workingDir);
111056
- if (result.status === "error") {
111057
- return { success: false, error: result.message };
111058
- }
111059
- return { success: true, message: result.message ?? "Push successful" };
111060
- }
111061
- async function gitSyncAction(workingDir) {
111062
- const result = await gitSync(workingDir);
111063
- if (result.status === "error") {
111064
- return { success: false, error: result.message };
111065
- }
111066
- return { success: true, message: result.message ?? "Sync successful" };
111067
- }
111068
- async function executeLocalAction(action, workingDir, options) {
111069
- if (action === "open-daemon-logs")
111070
- return openDaemonLogs(workingDir, options);
111071
- try {
111072
- await access3(workingDir);
111073
- } catch {
111074
- return { success: false, error: `Directory not found: ${workingDir}` };
111075
- }
111076
- const handler2 = actionHandlers[action];
111077
- if (handler2)
111078
- return handler2(workingDir);
111079
- return { success: false, error: `Unknown action: ${action}` };
111080
- }
111081
- var DETACHED_SHELL_SPAWN_OPTIONS, actionHandlers;
111082
- var init_execute_local_action = __esm(() => {
111083
- init_resolve_local_web_port();
111084
- init_git();
111085
- DETACHED_SHELL_SPAWN_OPTIONS = {
111086
- stdio: "ignore",
111087
- detached: true,
111088
- shell: true
111089
- };
111090
- actionHandlers = {
111091
- "open-vscode": openVscode,
111092
- "open-finder": openFinder,
111093
- "open-cursor": openCursor,
111094
- "open-github-desktop": openGithubDesktop,
111095
- "open-daemon-logs": openDaemonLogs,
111096
- "git-discard-file": gitDiscardFileAction,
111097
- "git-discard-all": gitDiscardAllAction,
111098
- "git-pull": gitPullAction,
111099
- "git-push": gitPushAction,
111100
- "git-sync": gitSyncAction
111101
- };
111102
- });
111103
-
111104
- // src/infrastructure/local-actions/index.ts
111105
- var init_local_actions = __esm(() => {
111106
- init_execute_local_action();
111107
- });
111108
-
111109
- // src/infrastructure/local-actions/pick-folder.ts
111110
- import { execFileSync as execFileSync2 } from "node:child_process";
111111
- function runPicker(command, args2) {
111112
- try {
111113
- const path3 = execFileSync2(command, args2, { encoding: "utf8", timeout: 300000 }).trim();
111114
- if (!path3)
111115
- return { success: false, error: "No folder selected" };
111116
- return { success: true, path: path3 };
111117
- } catch (error51) {
111118
- const exitCode = typeof error51 === "object" && error51 !== null && "status" in error51 ? error51.status : null;
111119
- if (exitCode === 1)
111120
- return { success: false, error: "Cancelled", cancelled: true };
111121
- const message = error51 instanceof Error ? error51.message : String(error51);
111122
- return { success: false, error: message };
111123
- }
111124
- }
111125
- function pickFolderDialog() {
111126
- switch (process.platform) {
111127
- case "darwin":
111128
- return runPicker("osascript", [
111129
- "-e",
111130
- 'POSIX path of (choose folder with prompt "Select workspace folder")'
111131
- ]);
111132
- case "win32":
111133
- return runPicker("powershell", [
111134
- "-NoProfile",
111135
- "-Command",
111136
- [
111137
- "Add-Type -AssemblyName System.Windows.Forms",
111138
- "$dialog = New-Object System.Windows.Forms.FolderBrowserDialog",
111139
- '$dialog.Description = "Select workspace folder"',
111140
- "if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {",
111141
- " Write-Output $dialog.SelectedPath",
111142
- " exit 0",
111143
- "}",
111144
- "exit 1"
111145
- ].join("; ")
111146
- ]);
111147
- default:
111148
- return runPicker("zenity", [
111149
- "--file-selection",
111150
- "--directory",
111151
- "--title=Select workspace folder"
111152
- ]);
111153
- }
111154
- }
111155
- var init_pick_folder = () => {};
111156
-
111157
111526
  // src/daemon/domain/usecase/refresh-machine-capabilities.ts
111158
111527
  async function refreshMachineCapabilities(deps) {
111159
111528
  return deps.refresh.refresh();
@@ -111378,15 +111747,15 @@ var init_command_dispatch = __esm(() => {
111378
111747
  init_command_event_types();
111379
111748
  init_command_sync_heartbeat();
111380
111749
  init_daemon_services();
111750
+ init_refresh_models_outcome();
111751
+ init_local_actions();
111752
+ init_pick_folder();
111381
111753
  init_on_request_restart_agent();
111382
111754
  init_on_request_start_agent();
111383
111755
  init_on_request_stop_agent();
111384
111756
  init_on_stop_scope_agent();
111385
111757
  init_ping();
111386
111758
  init_manager();
111387
- init_refresh_models_outcome();
111388
- init_local_actions();
111389
- init_pick_folder();
111390
111759
  init_convex_error();
111391
111760
  GIT_PUSH_ACTIONS = new Set(["git-pull", "git-push", "git-sync", "git-discard-all"]);
111392
111761
  commandEventHandlers = {
@@ -117624,14 +117993,127 @@ var init_command_run_subscription = __esm(() => {
117624
117993
  dispatchedStop = new Set;
117625
117994
  });
117626
117995
 
117627
- // src/daemon/infrastructure/agent-operational/agent-operational-read-model.ts
117628
- function isOperationalCircuitOpen2(row) {
117629
- return row?.operationalState === "circuit_open";
117996
+ // src/daemon/entry/task-inbox-membership-registry.ts
117997
+ function registerTaskInboxRoomMembershipRefresh(refresh) {
117998
+ refreshRoomMembership = refresh;
117630
117999
  }
117631
- function isOperationalStopIntentActive2(row) {
117632
- return row?.stopState === "stopped" || row?.stopState === "stopping" || row?.stopState === "pending";
118000
+ function unregisterTaskInboxRoomMembershipRefresh() {
118001
+ refreshRoomMembership = null;
117633
118002
  }
118003
+ async function refreshTaskInboxRoomMembership() {
118004
+ await refreshRoomMembership?.();
118005
+ }
118006
+ var refreshRoomMembership = null;
117634
118007
 
118008
+ // src/daemon/infrastructure/agent-operational/operational-signal-feeds.ts
118009
+ function chatroomId(value) {
118010
+ return value;
118011
+ }
118012
+ function signalPage(result) {
118013
+ if (!result || typeof result !== "object")
118014
+ return null;
118015
+ const page = result;
118016
+ if (!page.items?.length || !page.highKey)
118017
+ return null;
118018
+ return {
118019
+ items: page.items,
118020
+ afterSignalKey: "",
118021
+ highSignalKey: page.highKey
118022
+ };
118023
+ }
118024
+ function createFeed(input) {
118025
+ return input;
118026
+ }
118027
+ function subscribeArgs(input) {
118028
+ return {
118029
+ sessionId: input.sessionId,
118030
+ machineId: input.machineId,
118031
+ chatroomId: chatroomId(input.chatroomId),
118032
+ afterKey: input.afterKey,
118033
+ limit: input.limit
118034
+ };
118035
+ }
118036
+ function rangeArgs(input) {
118037
+ return {
118038
+ sessionId: input.sessionId,
118039
+ machineId: input.machineId,
118040
+ chatroomId: chatroomId(input.chatroomId),
118041
+ afterSignalKey: input.afterSignalKey,
118042
+ throughSignalKey: input.throughSignalKey,
118043
+ limit: input.limit
118044
+ };
118045
+ }
118046
+ function ackArgs(input) {
118047
+ return {
118048
+ sessionId: input.sessionId,
118049
+ machineId: input.machineId,
118050
+ chatroomId: chatroomId(input.chatroomId),
118051
+ throughSignalKey: input.throughSignalKey
118052
+ };
118053
+ }
118054
+ var createMachineFeed = (config4) => createFeed({
118055
+ kind: config4.kind,
118056
+ subscribe: (client4, input, onResult, onError3) => client4.onUpdate(config4.subscribe, subscribeArgs(input), (result) => {
118057
+ const page = signalPage(result);
118058
+ onResult(page ? { ...page, afterSignalKey: input.afterKey } : result);
118059
+ }, onError3),
118060
+ hydrate: async (client4, input) => await client4.query(config4.hydrate, rangeArgs(input)),
118061
+ acknowledge: async (sessionDeps, input) => await sessionDeps.backend.mutation(config4.acknowledge, ackArgs({
118062
+ ...input,
118063
+ sessionId: sessionDeps.sessionId
118064
+ }))
118065
+ }), operationalSignalFeeds;
118066
+ var init_operational_signal_feeds = __esm(() => {
118067
+ init_api3();
118068
+ operationalSignalFeeds = {
118069
+ "agent-operational": createMachineFeed({
118070
+ kind: "agent-operational",
118071
+ subscribe: api.machines.subscribeMachineAgentOperationalSignalsSince,
118072
+ hydrate: api.machines.listMachineAgentOperationalStatusForSignalRange,
118073
+ acknowledge: api.machines.ackMachineAgentOperationalSignals
118074
+ }),
118075
+ connectivity: createMachineFeed({
118076
+ kind: "connectivity",
118077
+ subscribe: api.machines.subscribeMachineConnectivitySignalsSince,
118078
+ hydrate: api.machines.listMachineConnectivityStatusForSignalRange,
118079
+ acknowledge: api.machines.ackMachineConnectivitySignals
118080
+ }),
118081
+ "agent-stop": createMachineFeed({
118082
+ kind: "agent-stop",
118083
+ subscribe: api.machines.subscribeMachineAgentStopSignalsSince,
118084
+ hydrate: api.machines.listMachineAgentStopStatusForSignalRange,
118085
+ acknowledge: api.machines.ackMachineAgentStopSignals
118086
+ }),
118087
+ "agent-removal": createMachineFeed({
118088
+ kind: "agent-removal",
118089
+ subscribe: api.machines.subscribeMachineAgentRemovalSignalsSince,
118090
+ hydrate: api.machines.listMachineAgentRemovalStatusForSignalRange,
118091
+ acknowledge: api.machines.ackMachineAgentRemovalSignals
118092
+ })
118093
+ };
118094
+ });
118095
+
118096
+ // src/daemon/infrastructure/agent-operational/ack-machine-operational-signals.ts
118097
+ async function ackMachineSignal(sessionDeps, machineId, chatroomId2, throughSignalKey, kind) {
118098
+ const feed = operationalSignalFeeds[kind];
118099
+ while (true) {
118100
+ const result = await feed.acknowledge(sessionDeps, {
118101
+ machineId,
118102
+ chatroomId: chatroomId2,
118103
+ throughSignalKey
118104
+ });
118105
+ if (!result.hasMore)
118106
+ return;
118107
+ if (result.deletedCount === 0) {
118108
+ throw new Error(`${kind} signal ack reported more work without progress`);
118109
+ }
118110
+ }
118111
+ }
118112
+ var init_ack_machine_operational_signals = __esm(() => {
118113
+ init_operational_signal_feeds();
118114
+ });
118115
+
118116
+ // src/daemon/infrastructure/agent-operational/agent-operational-read-model.ts
117635
118117
  class AgentOperationalReadModel {
117636
118118
  rows = new Map;
117637
118119
  replace(rows) {
@@ -117671,211 +118153,21 @@ class AgentOperationalReadModel {
117671
118153
  }
117672
118154
  return changed;
117673
118155
  }
117674
- get(chatroomId, role) {
117675
- return this.rows.get(roleKey3(chatroomId, role));
118156
+ get(chatroomId2, role) {
118157
+ return this.rows.get(roleKey3(chatroomId2, role));
117676
118158
  }
117677
118159
  }
117678
- var roleKey3 = (chatroomId, role) => `${chatroomId}:${role.toLowerCase()}`;
118160
+ var roleKey3 = (chatroomId2, role) => `${chatroomId2}:${role.toLowerCase()}`;
117679
118161
 
117680
- // src/daemon/entry/native-delivery/task-delivery-processor.ts
117681
- async function startPendingNativeAgents(tasks, agentMgr, runSerializedForAgent, taskService, operationalModel) {
117682
- const started = new Set;
117683
- await Promise.all(tasks.map(async (task) => {
117684
- if (task.status !== "pending" || !taskService.isNativeHarness(task.agentConfig.agentHarness) || taskService.snapshotRequestsNativeColdSession(task) || !task.agentConfig.workingDir) {
117685
- return;
117686
- }
117687
- const key = `${task.chatroomId}:${task.agentConfig.role.toLowerCase()}`;
117688
- if (started.has(key))
117689
- return;
117690
- const slot = agentMgr.getSlot(task.chatroomId, task.agentConfig.role);
117691
- if (slot && !isSlotIdle(slot.state))
117692
- return;
117693
- const operational = operationalModel?.get(task.chatroomId, task.agentConfig.role);
117694
- if (isChatroomStopScopeActive(task.chatroomId))
117695
- return;
117696
- if (isOperationalCircuitOpen2(operational) || isOperationalStopIntentActive2(operational))
117697
- return;
117698
- started.add(key);
117699
- try {
117700
- await runSerializedForAgent({ chatroomId: task.chatroomId, role: task.agentConfig.role }, { timeoutMs: 120000 }, (ops, context5) => ops.startAgent({
117701
- chatroomId: task.chatroomId,
117702
- role: task.agentConfig.role,
117703
- agentHarness: task.agentConfig.agentHarness,
117704
- model: task.agentConfig.model,
117705
- workingDir: task.agentConfig.workingDir,
117706
- reason: operational?.operationalState === "running" ? AgentStartReasonEnum["platform.task_monitor_nudge"] : AgentStartReasonEnum["platform.pending_task_wake"],
117707
- wantResume: false,
117708
- lifecycleRevision: task.agentConfig.configLifecycleRevision,
117709
- taskId: task.taskId
117710
- }, context5.signal));
117711
- } catch (error51) {
117712
- console.warn(`[NativeDelivery] pending agent activation failed for ${task.agentConfig.role}@${task.chatroomId}: ${error51 instanceof Error ? error51.message : String(error51)}`);
117713
- }
117714
- }));
117715
- }
117716
- async function processTasksUpdate(runtime4, effectContext2, agentMgr, runSerializedForAgent, taskService, sessionDeps, machineId, pass, lifecycleOutbox, operationalModel, isTaskActive, options) {
117717
- const filteredTasks = filterSnapshotsExcludingRestartInFlight([...options.snapshots]);
117718
- if (filteredTasks.length === 0)
117719
- return;
117720
- await startPendingNativeAgents(filteredTasks, agentMgr, runSerializedForAgent, taskService, operationalModel);
117721
- const first = filteredTasks[0];
117722
- if (pass === "periodic-reconcile") {
117723
- logNativeDeliveryFallback(pass, first.agentConfig.role, first.chatroomId, first.taskId);
117724
- } else {
117725
- logNativeDeliveryTrigger(pass, first.agentConfig.role, first.chatroomId, first.taskId);
117726
- }
117727
- await getNativeTaskDeliveryCoordinator().reconcileAssignedTasks({
117728
- tasks: filteredTasks,
117729
- runtime: runtime4,
117730
- effectContext: effectContext2,
117731
- agentMgr,
117732
- runSerializedForAgent,
117733
- taskService,
117734
- sessionDeps,
117735
- lifecycleOutbox,
117736
- operationalModel,
117737
- isTaskActive,
117738
- machineId,
117739
- onTaskDelivered: options.onTaskDelivered
118162
+ // src/daemon/infrastructure/agent-operational/fetch-machine-agent-operational-status.ts
118163
+ async function fetchMachineAgentOperationalStatus(sessionDeps, machineId) {
118164
+ const result = await sessionDeps.backend.query(api.machines.listMachineAgentOperationalStatus, {
118165
+ sessionId: sessionDeps.sessionId,
118166
+ machineId
117740
118167
  });
118168
+ return result;
117741
118169
  }
117742
- var init_task_delivery_processor = __esm(() => {
117743
- init_agent();
117744
- init_native_task_delivery_coordinator();
117745
- init_check_agent_slot();
117746
- init_service_interfaces();
117747
- init_restart_orchestrator_in_flight();
117748
- });
117749
-
117750
- // src/daemon/entry/native-delivery/native-delivery-service.ts
117751
- class NativeDeliveryService {
117752
- deps;
117753
- unsubscribeAgentTurnEnded;
117754
- unsubscribeAgentStarted;
117755
- unsubscribeAgentSessionLost;
117756
- constructor(deps) {
117757
- this.deps = deps;
117758
- this.unsubscribeAgentTurnEnded = deps.agentMgr.subscribeAgentTurnEnded((event) => this.handleAgentTurnEnded(event));
117759
- this.unsubscribeAgentStarted = deps.agentMgr.subscribeAgentStarted((event) => this.handleAgentStarted(event));
117760
- this.unsubscribeAgentSessionLost = deps.agentMgr.subscribeAgentSessionLost((event) => this.handleAgentSessionLost(event));
117761
- }
117762
- async handleAgentStarted(event) {
117763
- const tasks = this.deps.taskSnapshotState.listForRole(event.chatroomId, event.role);
117764
- await this.processSnapshots("operational-status", tasks);
117765
- }
117766
- handleAgentSessionLost(event) {
117767
- getRoleDeliveryState().resetDeliveryState(event.chatroomId, event.role);
117768
- this.deps.agentTaskState.clear({ chatroomId: event.chatroomId, role: event.role });
117769
- }
117770
- async handleAgentTurnEnded(event) {
117771
- this.scheduleRoleDelivery(event.chatroomId, event.role);
117772
- }
117773
- scheduleRoleDelivery(chatroomId, role) {
117774
- setTimeout(() => {
117775
- const snapshots = this.deps.taskSnapshotState.listForRole(chatroomId, role);
117776
- this.processSnapshots("operational-status", snapshots).catch((error51) => {
117777
- console.warn(`[NativeDelivery] post-turn delivery failed for ${role}@${chatroomId}: ${error51 instanceof Error ? error51.message : String(error51)}`);
117778
- });
117779
- }, 0);
117780
- }
117781
- dispose() {
117782
- this.unsubscribeAgentTurnEnded();
117783
- this.unsubscribeAgentStarted();
117784
- this.unsubscribeAgentSessionLost();
117785
- }
117786
- get agentTaskState() {
117787
- return this.deps.agentTaskState;
117788
- }
117789
- async handleTaskInboxUpdate(update6) {
117790
- await this.processSnapshots("inbox-signal", update6.snapshots);
117791
- }
117792
- async handleTaskServiceNotification(notification) {
117793
- if (notification.kind === "bootstrap") {
117794
- await this.processSnapshots("bootstrap", notification.snapshots);
117795
- return;
117796
- }
117797
- await this.handleTaskInboxUpdate(notification.update);
117798
- }
117799
- async processSnapshots(pass, snapshots, onTaskDelivered) {
117800
- if (snapshots.length === 0)
117801
- return;
117802
- await processTasksUpdate(this.deps.runtime, this.deps.effectContext, this.deps.agentMgr, this.deps.runSerializedForAgent, this.deps.taskService, this.deps.sessionDeps, this.deps.machineId, pass, this.deps.lifecycleOutbox, this.deps.agentOperationalReadModel, ({ chatroomId, role, taskId }) => this.deps.agentTaskState.get({ chatroomId, role })?.taskId === taskId, {
117803
- snapshots,
117804
- onTaskDelivered: (args2) => {
117805
- this.recordTaskDelivered(args2);
117806
- onTaskDelivered?.(args2);
117807
- }
117808
- });
117809
- }
117810
- recordTaskDelivered(args2) {
117811
- this.deps.agentTaskState.start(args2);
117812
- }
117813
- }
117814
- var init_native_delivery_service = __esm(() => {
117815
- init_task_delivery_processor();
117816
- });
117817
-
117818
- // src/daemon/entry/task-inbox-membership-registry.ts
117819
- function registerTaskInboxRoomMembershipRefresh(refresh) {
117820
- refreshRoomMembership = refresh;
117821
- }
117822
- function unregisterTaskInboxRoomMembershipRefresh() {
117823
- refreshRoomMembership = null;
117824
- }
117825
- async function refreshTaskInboxRoomMembership() {
117826
- await refreshRoomMembership?.();
117827
- }
117828
- var refreshRoomMembership = null;
117829
-
117830
- // src/daemon/infrastructure/agent-operational/operational-signal-contract.ts
117831
- function asChatroomId2(chatroomId) {
117832
- return chatroomId;
117833
- }
117834
- function buildSubscribeMachineOperationalSignalsSinceArgs(input) {
117835
- return {
117836
- sessionId: input.sessionId,
117837
- machineId: input.machineId,
117838
- chatroomId: asChatroomId2(input.chatroomId),
117839
- afterKey: input.afterKey,
117840
- ...input.limit === undefined ? {} : { limit: input.limit }
117841
- };
117842
- }
117843
- function buildListOperationalStatusForMachineSignalRangeArgs(input) {
117844
- return {
117845
- sessionId: input.sessionId,
117846
- machineId: input.machineId,
117847
- chatroomId: asChatroomId2(input.chatroomId),
117848
- afterSignalKey: input.afterSignalKey,
117849
- throughSignalKey: input.throughSignalKey,
117850
- ...input.limit === undefined ? {} : { limit: input.limit }
117851
- };
117852
- }
117853
- function buildAckMachineOperationalSignalsArgs(input) {
117854
- return {
117855
- sessionId: input.sessionId,
117856
- machineId: input.machineId,
117857
- chatroomId: asChatroomId2(input.chatroomId),
117858
- throughSignalKey: input.throughSignalKey
117859
- };
117860
- }
117861
-
117862
- // src/daemon/infrastructure/agent-operational/ack-machine-operational-signals.ts
117863
- async function ackMachineOperationalSignals(sessionDeps, machineId, chatroomId, throughSignalKey) {
117864
- while (true) {
117865
- const result = await sessionDeps.backend.mutation(api.machines.ackMachineOperationalSignals, buildAckMachineOperationalSignalsArgs({
117866
- sessionId: sessionDeps.sessionId,
117867
- machineId,
117868
- chatroomId,
117869
- throughSignalKey
117870
- }));
117871
- if (!result.hasMore)
117872
- return;
117873
- if (result.deletedCount === 0) {
117874
- throw new Error("Operational signal ack reported more work without progress");
117875
- }
117876
- }
117877
- }
117878
- var init_ack_machine_operational_signals = __esm(() => {
118170
+ var init_fetch_machine_agent_operational_status = __esm(() => {
117879
118171
  init_api3();
117880
118172
  });
117881
118173
 
@@ -117892,6 +118184,9 @@ function throwIfAborted2(signal) {
117892
118184
  if (signal?.aborted)
117893
118185
  throw abortError2();
117894
118186
  }
118187
+ function feedFor(options) {
118188
+ return options.feed ?? operationalSignalFeeds["agent-operational"];
118189
+ }
117895
118190
  function waitForOperationalSignalPage(options, afterSignalKey) {
117896
118191
  return new Promise((resolve8, reject) => {
117897
118192
  let unsubscribe;
@@ -117918,25 +118213,17 @@ function waitForOperationalSignalPage(options, afterSignalKey) {
117918
118213
  settle2(() => reject(error51));
117919
118214
  return;
117920
118215
  }
117921
- unsubscribe = options.client.onUpdate(api.machines.subscribeMachineOperationalSignalsSince, buildSubscribeMachineOperationalSignalsSinceArgs({
118216
+ unsubscribe = feedFor(options).subscribe(options.client, {
117922
118217
  sessionId: options.sessionId,
117923
118218
  machineId: options.machineId,
117924
118219
  chatroomId: options.chatroomId,
117925
118220
  afterKey: afterSignalKey,
117926
118221
  limit: options.signalPageLimit ?? DEFAULT_SIGNAL_PAGE_LIMIT2
117927
- }), (result) => {
117928
- if (!result || typeof result !== "object")
117929
- return;
118222
+ }, (result) => {
117930
118223
  const page = result;
117931
- const items = page.items;
117932
- const highKey = page.highKey;
117933
- if (!items?.length || !highKey)
118224
+ if (!page)
117934
118225
  return;
117935
- settle2(() => resolve8({
117936
- items,
117937
- afterSignalKey,
117938
- highSignalKey: highKey
117939
- }));
118226
+ settle2(() => resolve8(page));
117940
118227
  }, (error51) => {
117941
118228
  settle2(() => reject(error51));
117942
118229
  });
@@ -117956,14 +118243,14 @@ async function fetchRowsForSignalPage(options, page) {
117956
118243
  let afterSignalKey = page.afterSignalKey;
117957
118244
  while (true) {
117958
118245
  throwIfAborted2(options.signal);
117959
- const result = await options.client.query(api.machines.listOperationalStatusForMachineSignalRange, buildListOperationalStatusForMachineSignalRangeArgs({
118246
+ const result = await feedFor(options).hydrate(options.client, {
117960
118247
  sessionId: options.sessionId,
117961
118248
  machineId: options.machineId,
117962
118249
  chatroomId: options.chatroomId,
117963
118250
  afterSignalKey,
117964
118251
  throughSignalKey: page.highSignalKey,
117965
118252
  limit: options.operationalPageLimit ?? DEFAULT_OPERATIONAL_PAGE_LIMIT
117966
- }));
118253
+ });
117967
118254
  rows.push(...result.rows);
117968
118255
  removed.push(...result.removed);
117969
118256
  if (!result.hasMore || !result.nextSignalKey)
@@ -117987,15 +118274,15 @@ async function runOperationalInbox(options, onUpdate) {
117987
118274
  }
117988
118275
  var DEFAULT_SIGNAL_PAGE_LIMIT2 = 100, DEFAULT_OPERATIONAL_PAGE_LIMIT = 500;
117989
118276
  var init_operational_inbox = __esm(() => {
117990
- init_api3();
118277
+ init_operational_signal_feeds();
117991
118278
  });
117992
118279
 
117993
118280
  // src/daemon/entry/task-inbox-runtime.ts
117994
118281
  function isAbortError2(error51) {
117995
118282
  return error51 instanceof Error && error51.name === "AbortError";
117996
118283
  }
117997
- function roomScopeKey(machineId, chatroomId) {
117998
- return JSON.stringify([machineId, chatroomId]);
118284
+ function roomScopeKey(machineId, chatroomId2) {
118285
+ return JSON.stringify([machineId, chatroomId2]);
117999
118286
  }
118000
118287
  async function runOperationalInboxLoopWithRestart(options, onUpdate, isStopped) {
118001
118288
  let backoffMs = INBOX_RESTART_INITIAL_MS;
@@ -118012,7 +118299,7 @@ async function runOperationalInboxLoopWithRestart(options, onUpdate, isStopped)
118012
118299
  }
118013
118300
  }
118014
118301
  }
118015
- var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInboxEffect = (wsClient2) => exports_Effect.gen(function* () {
118302
+ var INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInboxEffect = (wsClient2) => exports_Effect.gen(function* () {
118016
118303
  const session2 = yield* DaemonSessionService;
118017
118304
  const agentMgr = yield* DaemonAgentProcessManagerService;
118018
118305
  const commandService = yield* DaemonAgentProcessManagerCommandService;
@@ -118037,31 +118324,25 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
118037
118324
  const serviceStartedAt = Date.now();
118038
118325
  const abort = new AbortController;
118039
118326
  let stopped = false;
118040
- const taskSnapshotState = session2.taskService.taskSnapshotState;
118041
118327
  const agentOperationalReadModel = new AgentOperationalReadModel;
118042
118328
  const agentTaskState = createAgentTaskStateService();
118043
- const nativeDelivery = new NativeDeliveryService({
118329
+ const nativeDelivery = session2.taskService.createNativeDeliveryService({
118044
118330
  runtime: runtime4,
118045
118331
  effectContext: effectContext2,
118046
118332
  agentMgr,
118047
118333
  runSerializedForAgent: commandService.runSerializedForAgent,
118048
118334
  sessionDeps,
118049
118335
  machineId: session2.machineId,
118050
- taskSnapshotState,
118051
118336
  agentTaskState,
118052
118337
  agentOperationalReadModel,
118053
- lifecycleOutbox,
118054
- taskService: session2.taskService
118338
+ lifecycleOutbox
118055
118339
  });
118056
- const unsubscribeTaskService = session2.taskService.subscribe((notification) => nativeDelivery.handleTaskServiceNotification(notification));
118057
118340
  yield* exports_Effect.tryPromise(() => session2.taskService.startTaskInbox(wsClient2)).pipe(exports_Effect.catchAll((error51) => {
118058
118341
  console.warn("[TaskInbox] service bootstrap failed:", error51);
118059
118342
  return exports_Effect.void;
118060
118343
  }));
118061
118344
  const knownRoomIds = new Set;
118062
118345
  const roomWatchers = new Map;
118063
- let inboxUpdatesInFlight = 0;
118064
- let reconcileInFlight = false;
118065
118346
  const bootstrapSucceeded = yield* exports_Effect.tryPromise(async () => {
118066
118347
  const rows = await fetchMachineAgentOperationalStatus(sessionDeps, session2.machineId);
118067
118348
  agentOperationalReadModel.replace(rows);
@@ -118072,30 +118353,26 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
118072
118353
  console.warn("[OperationalInbox] bootstrap failed:", error51);
118073
118354
  return exports_Effect.succeed(false);
118074
118355
  }));
118075
- const operationalHandler = async (update6) => {
118076
- const chatroomId = update6.chatroomId;
118077
- inboxUpdatesInFlight += 1;
118356
+ const operationalHandler = async (kind, update6) => {
118357
+ const chatroomId2 = update6.chatroomId;
118358
+ const changed = agentOperationalReadModel.applySignalPage(update6.rows, update6.removed);
118359
+ await Promise.all(changed.map(({ chatroomId: roomId, role }) => nativeDelivery.requestReconcile({
118360
+ chatroomId: roomId,
118361
+ role,
118362
+ source: "operational-signal"
118363
+ })));
118364
+ inboxStore.save({
118365
+ inboxType: `operational:${kind}`,
118366
+ scopeKey: roomScopeKey(session2.machineId, chatroomId2)
118367
+ }, { afterSignalKey: update6.throughSignalKey });
118078
118368
  try {
118079
- const changed = agentOperationalReadModel.applySignalPage(update6.rows, update6.removed);
118080
- const snapshots = changed.flatMap(({ chatroomId: roomId, role }) => taskSnapshotState.listForRole(roomId, role));
118081
- if (snapshots.length > 0) {
118082
- await nativeDelivery.processSnapshots("operational-status", snapshots);
118083
- }
118084
- inboxStore.save({
118085
- inboxType: "operational",
118086
- scopeKey: roomScopeKey(session2.machineId, chatroomId)
118087
- }, { afterSignalKey: update6.throughSignalKey });
118088
- try {
118089
- await ackMachineOperationalSignals(sessionDeps, session2.machineId, chatroomId, update6.throughSignalKey);
118090
- } catch (error51) {
118091
- console.warn(`[OperationalInbox room=${chatroomId}] signal cleanup failed:`, error51);
118092
- }
118093
- } finally {
118094
- inboxUpdatesInFlight -= 1;
118369
+ await ackMachineSignal(sessionDeps, session2.machineId, chatroomId2, update6.throughSignalKey, kind);
118370
+ } catch (error51) {
118371
+ console.warn(`[OperationalInbox kind=${kind} room=${chatroomId2}] signal cleanup failed:`, error51);
118095
118372
  }
118096
118373
  };
118097
- const ensureRoomInboxes = (chatroomId) => {
118098
- const existing = roomWatchers.get(chatroomId);
118374
+ const ensureRoomInboxes = (chatroomId2) => {
118375
+ const existing = roomWatchers.get(chatroomId2);
118099
118376
  if (existing)
118100
118377
  return existing.startPromise;
118101
118378
  const controller = new AbortController;
@@ -118103,48 +118380,48 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
118103
118380
  controller,
118104
118381
  startPromise: Promise.resolve()
118105
118382
  };
118106
- roomWatchers.set(chatroomId, entry);
118383
+ roomWatchers.set(chatroomId2, entry);
118107
118384
  entry.startPromise = (async () => {
118108
- if (!knownRoomIds.has(chatroomId)) {
118385
+ if (!knownRoomIds.has(chatroomId2)) {
118109
118386
  try {
118110
118387
  const current = await fetchMachineAgentOperationalStatus(sessionDeps, session2.machineId);
118111
118388
  agentOperationalReadModel.replace(current);
118112
118389
  for (const row of current)
118113
118390
  knownRoomIds.add(row.chatroomId);
118114
118391
  } catch (error51) {
118115
- console.warn(`[OperationalInbox room=${chatroomId}] operational hydration failed:`, error51);
118392
+ console.warn(`[OperationalInbox room=${chatroomId2}] operational hydration failed:`, error51);
118116
118393
  }
118117
118394
  }
118118
- const operationalRoomKey = {
118119
- inboxType: "operational",
118120
- scopeKey: roomScopeKey(session2.machineId, chatroomId)
118121
- };
118122
- const persistedOperationalRoom = inboxStore.get(operationalRoomKey);
118123
- let operationalCursor;
118124
- if (persistedOperationalRoom) {
118125
- operationalCursor = persistedOperationalRoom.state.afterSignalKey;
118126
- ackMachineOperationalSignals(sessionDeps, session2.machineId, chatroomId, operationalCursor).catch((error51) => console.warn(`[OperationalInbox room=${chatroomId}] startup signal cleanup failed:`, error51));
118127
- } else if (bootstrapSucceeded) {
118128
- operationalCursor = operationalSignalCursorAt(serviceStartedAt);
118129
- try {
118130
- inboxStore.save(operationalRoomKey, { afterSignalKey: operationalCursor });
118131
- ackMachineOperationalSignals(sessionDeps, session2.machineId, chatroomId, operationalCursor).catch((error51) => console.warn(`[OperationalInbox room=${chatroomId}] startup signal cleanup failed:`, error51));
118132
- } catch (error51) {
118133
- console.warn(`[OperationalInbox room=${chatroomId}] failed to persist bootstrap baseline:`, error51);
118395
+ await Promise.all(["agent-operational", "connectivity", "agent-stop", "agent-removal"].map(async (kind) => {
118396
+ const operationalRoomKey = {
118397
+ inboxType: `operational:${kind}`,
118398
+ scopeKey: roomScopeKey(session2.machineId, chatroomId2)
118399
+ };
118400
+ const persistedRoom = inboxStore.get(operationalRoomKey);
118401
+ let cursor = persistedRoom?.state.afterSignalKey;
118402
+ if (!cursor) {
118403
+ cursor = operationalSignalCursorAt(serviceStartedAt);
118404
+ try {
118405
+ inboxStore.save(operationalRoomKey, { afterSignalKey: cursor });
118406
+ } catch (error51) {
118407
+ console.warn(`[OperationalInbox kind=${kind} room=${chatroomId2}] failed to persist bootstrap baseline:`, error51);
118408
+ }
118134
118409
  }
118135
- } else {
118136
- operationalCursor = operationalSignalCursorAt(serviceStartedAt);
118137
- }
118138
- runOperationalInboxLoopWithRestart({
118139
- client: wsClient2,
118140
- sessionId: session2.sessionId,
118141
- machineId: session2.machineId,
118142
- chatroomId,
118143
- serviceStartedAt,
118144
- initialAfterSignalKey: operationalCursor,
118145
- signal: controller.signal
118146
- }, operationalHandler, () => stopped);
118147
- await session2.taskService.registerTaskChatroom(chatroomId);
118410
+ if (persistedRoom || bootstrapSucceeded) {
118411
+ ackMachineSignal(sessionDeps, session2.machineId, chatroomId2, cursor, kind).catch((error51) => console.warn(`[OperationalInbox kind=${kind} room=${chatroomId2}] startup signal cleanup failed:`, error51));
118412
+ }
118413
+ runOperationalInboxLoopWithRestart({
118414
+ client: wsClient2,
118415
+ sessionId: session2.sessionId,
118416
+ machineId: session2.machineId,
118417
+ chatroomId: chatroomId2,
118418
+ feed: operationalSignalFeeds[kind],
118419
+ serviceStartedAt,
118420
+ initialAfterSignalKey: cursor,
118421
+ signal: controller.signal
118422
+ }, (update6) => operationalHandler(kind, update6), () => stopped);
118423
+ }));
118424
+ await session2.taskService.registerTaskChatroom(chatroomId2);
118148
118425
  })();
118149
118426
  return entry.startPromise;
118150
118427
  };
@@ -118160,35 +118437,25 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
118160
118437
  ...new Set((workspaces ?? []).map((workspace) => workspace.chatroomId))
118161
118438
  ];
118162
118439
  const activeChatroomIds = new Set(chatroomIds);
118163
- for (const [chatroomId, watcher] of roomWatchers) {
118164
- if (activeChatroomIds.has(chatroomId))
118440
+ for (const [chatroomId2, watcher] of roomWatchers) {
118441
+ if (activeChatroomIds.has(chatroomId2))
118165
118442
  continue;
118166
118443
  watcher.controller.abort();
118167
- session2.taskService.unregisterTaskChatroom(chatroomId);
118168
- roomWatchers.delete(chatroomId);
118169
- knownRoomIds.delete(chatroomId);
118444
+ session2.taskService.unregisterTaskChatroom(chatroomId2);
118445
+ roomWatchers.delete(chatroomId2);
118446
+ knownRoomIds.delete(chatroomId2);
118170
118447
  }
118171
- await Promise.all(chatroomIds.map((chatroomId) => ensureRoomInboxes(chatroomId)));
118448
+ await Promise.all(chatroomIds.map((chatroomId2) => ensureRoomInboxes(chatroomId2)));
118172
118449
  } catch (error51) {
118173
118450
  console.warn("[TaskInbox] room membership refresh failed:", error51);
118174
118451
  }
118175
118452
  };
118176
118453
  registerTaskInboxRoomMembershipRefresh(refreshRoomMembership2);
118177
118454
  yield* exports_Effect.promise(refreshRoomMembership2);
118178
- yield* exports_Effect.tryPromise(() => Promise.all([...knownRoomIds].map((chatroomId) => ensureRoomInboxes(chatroomId)))).pipe(exports_Effect.catchAll((error51) => {
118455
+ yield* exports_Effect.tryPromise(() => Promise.all([...knownRoomIds].map((chatroomId2) => ensureRoomInboxes(chatroomId2)))).pipe(exports_Effect.catchAll((error51) => {
118179
118456
  console.warn("[OperationalInbox] initial watcher start failed:", error51);
118180
118457
  return exports_Effect.void;
118181
118458
  }));
118182
- const reconcileTimer = setInterval(() => {
118183
- if (stopped || inboxUpdatesInFlight > 0 || reconcileInFlight)
118184
- return;
118185
- reconcileInFlight = true;
118186
- nativeDelivery.processSnapshots("periodic-reconcile", taskSnapshotState.listAll()).catch((error51) => {
118187
- console.warn("[TaskInbox] local delivery reconciliation failed:", error51);
118188
- }).finally(() => {
118189
- reconcileInFlight = false;
118190
- });
118191
- }, NATIVE_DELIVERY_RECONCILE_MS);
118192
118459
  return {
118193
118460
  nativeDelivery,
118194
118461
  stop() {
@@ -118197,9 +118464,7 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
118197
118464
  for (const watcher of roomWatchers.values()) {
118198
118465
  watcher.controller.abort();
118199
118466
  }
118200
- clearInterval(reconcileTimer);
118201
118467
  unregisterTaskInboxRoomMembershipRefresh();
118202
- unsubscribeTaskService();
118203
118468
  session2.taskService.stopTaskInbox();
118204
118469
  nativeDelivery.dispose();
118205
118470
  nativeDelivery.agentTaskState.clearAll();
@@ -118211,10 +118476,10 @@ var init_task_inbox_runtime = __esm(() => {
118211
118476
  init_esm();
118212
118477
  init_daemon_services();
118213
118478
  init_api3();
118214
- init_native_delivery_service();
118215
118479
  init_ack_machine_operational_signals();
118216
118480
  init_fetch_machine_agent_operational_status();
118217
118481
  init_operational_inbox();
118482
+ init_operational_signal_feeds();
118218
118483
  init_inbox();
118219
118484
  init_service_interfaces();
118220
118485
  });
@@ -118560,11 +118825,11 @@ var init_on_daemon_shutdown = __esm(() => {
118560
118825
  console.log(`[${formatTimestamp()}] Stopping ${activeAgents.length} agent(s) locally...`);
118561
118826
  let totalStopped = 0;
118562
118827
  let totalFailed = 0;
118563
- yield* exports_Effect.all(activeAgents.map(({ chatroomId, role }) => exports_Effect.promise(() => agentPm.stopAgent({ chatroomId, role, reason: "daemon.shutdown" })).pipe(exports_Effect.tap(() => exports_Effect.sync(() => {
118828
+ yield* exports_Effect.all(activeAgents.map(({ chatroomId: chatroomId2, role }) => exports_Effect.promise(() => agentPm.stopAgent({ chatroomId: chatroomId2, role, reason: "daemon.shutdown" })).pipe(exports_Effect.tap(() => exports_Effect.sync(() => {
118564
118829
  totalStopped += 1;
118565
118830
  })), exports_Effect.catchAll((e) => exports_Effect.sync(() => {
118566
118831
  totalFailed += 1;
118567
- console.log(` ⚠️ Failed to stop ${role}@${chatroomId}: ${e.message}`);
118832
+ console.log(` ⚠️ Failed to stop ${role}@${chatroomId2}: ${e.message}`);
118568
118833
  })))), { concurrency: "unbounded" });
118569
118834
  if (totalFailed > 0) {
118570
118835
  console.log(`[${formatTimestamp()}] Shutdown stops: ${totalStopped} stopped, ${totalFailed} failed`);
@@ -118746,7 +119011,12 @@ Listening for commands...`);
118746
119011
  registerCommandInboundHandler(async (event) => {
118747
119012
  evictStaleDedupEntries(dedupTracker);
118748
119013
  if (event.type === "command.received") {
118749
- await handleInboundCommandEvent(event.commandId, dedupTracker, effectContext2, session2, event.claimedCommand, taskInboxHandle.nativeDelivery);
119014
+ const nativeDelivery = taskInboxHandle?.nativeDelivery;
119015
+ if (!nativeDelivery) {
119016
+ console.warn("[Daemon] command received before task inbox started");
119017
+ return;
119018
+ }
119019
+ await handleInboundCommandEvent(event.commandId, dedupTracker, effectContext2, session2, event.claimedCommand, nativeDelivery);
118750
119020
  } else {
118751
119021
  await drainActionableCommandRuns(session2, commandRunRuntime);
118752
119022
  }
@@ -119381,15 +119651,15 @@ function startEnhancerJobSubscriber2(deps, onEvent) {
119381
119651
  const onError3 = (err) => {
119382
119652
  console.warn(`[daemon] enhancer-job subscriber error: ${err instanceof Error ? err.message : String(err)}`);
119383
119653
  };
119384
- const watchChatroom = (chatroomId) => {
119385
- if (watchers.has(chatroomId) || stopped)
119654
+ const watchChatroom = (chatroomId2) => {
119655
+ if (watchers.has(chatroomId2) || stopped)
119386
119656
  return;
119387
119657
  const unsub = deps.wsClient.onUpdate(api.daemon.enhancer.index.pendingForChatroom, {
119388
119658
  sessionId: deps.sessionId,
119389
119659
  machineId: deps.machineId,
119390
- chatroomId
119660
+ chatroomId: chatroomId2
119391
119661
  }, onPendingJobs, onError3);
119392
- watchers.set(chatroomId, unsub);
119662
+ watchers.set(chatroomId2, unsub);
119393
119663
  };
119394
119664
  const refreshChatrooms = async () => {
119395
119665
  if (refreshInFlight)
@@ -119874,10 +120144,10 @@ function queryEventStream(db, input) {
119874
120144
  payload: JSON.parse(row.payload_json)
119875
120145
  }));
119876
120146
  }
119877
- function queryAfterId(db, afterId = 0, limit = 100, source, chatroomId, role, harness, fromTimestamp, toTimestamp) {
120147
+ function queryAfterId(db, afterId = 0, limit = 100, source, chatroomId2, role, harness, fromTimestamp, toTimestamp) {
119878
120148
  const filters = [
119879
120149
  source ? "AND source = ?" : "",
119880
- chatroomId ? "AND json_extract(metadata_json, '$.chatroomId') = ?" : "",
120150
+ chatroomId2 ? "AND json_extract(metadata_json, '$.chatroomId') = ?" : "",
119881
120151
  role ? "AND json_extract(metadata_json, '$.role') = ?" : "",
119882
120152
  harness ? "AND (json_extract(metadata_json, '$.harness') = ? OR source = ?)" : "",
119883
120153
  fromTimestamp !== undefined ? "AND timestamp >= ?" : "",
@@ -119886,7 +120156,7 @@ function queryAfterId(db, afterId = 0, limit = 100, source, chatroomId, role, ha
119886
120156
  const values3 = [
119887
120157
  afterId,
119888
120158
  ...source ? [source] : [],
119889
- ...chatroomId ? [chatroomId] : [],
120159
+ ...chatroomId2 ? [chatroomId2] : [],
119890
120160
  ...role ? [role] : [],
119891
120161
  ...harness ? [harness, `harness:${harness}`] : [],
119892
120162
  ...fromTimestamp !== undefined ? [fromTimestamp] : [],
@@ -119896,11 +120166,11 @@ function queryAfterId(db, afterId = 0, limit = 100, source, chatroomId, role, ha
119896
120166
  const rows = db.prepare(`SELECT * FROM log_entries WHERE id > ? ${filters} ORDER BY id ASC LIMIT ?`).all(...values3);
119897
120167
  return rows.map(map19);
119898
120168
  }
119899
- function queryHistory(db, beforeId, limit = 100, source, chatroomId, role, harness, fromTimestamp, toTimestamp) {
120169
+ function queryHistory(db, beforeId, limit = 100, source, chatroomId2, role, harness, fromTimestamp, toTimestamp) {
119900
120170
  const filters = [
119901
120171
  beforeId ? "AND id < ?" : "",
119902
120172
  source ? "AND source = ?" : "",
119903
- chatroomId ? "AND json_extract(metadata_json, '$.chatroomId') = ?" : "",
120173
+ chatroomId2 ? "AND json_extract(metadata_json, '$.chatroomId') = ?" : "",
119904
120174
  role ? "AND json_extract(metadata_json, '$.role') = ?" : "",
119905
120175
  harness ? "AND (json_extract(metadata_json, '$.harness') = ? OR source = ?)" : "",
119906
120176
  fromTimestamp !== undefined ? "AND timestamp >= ?" : "",
@@ -119909,7 +120179,7 @@ function queryHistory(db, beforeId, limit = 100, source, chatroomId, role, harne
119909
120179
  const values3 = [
119910
120180
  ...beforeId ? [beforeId] : [],
119911
120181
  ...source ? [source] : [],
119912
- ...chatroomId ? [chatroomId] : [],
120182
+ ...chatroomId2 ? [chatroomId2] : [],
119913
120183
  ...role ? [role] : [],
119914
120184
  ...harness ? [harness, `harness:${harness}`] : [],
119915
120185
  ...fromTimestamp !== undefined ? [fromTimestamp] : [],
@@ -119919,9 +120189,9 @@ function queryHistory(db, beforeId, limit = 100, source, chatroomId, role, harne
119919
120189
  const rows = db.prepare(`SELECT * FROM log_entries WHERE 1=1 ${filters} ORDER BY id DESC LIMIT ?`).all(...values3);
119920
120190
  return rows.map(map19).reverse();
119921
120191
  }
119922
- function listLogDimensions(db, chatroomId, limit = 100) {
120192
+ function listLogDimensions(db, chatroomId2, limit = 100) {
119923
120193
  const clamped = clamp4(limit);
119924
- const values3 = (sql) => db.prepare(sql).all(chatroomId, clamped).map((r) => r.v);
120194
+ const values3 = (sql) => db.prepare(sql).all(chatroomId2, clamped).map((r) => r.v);
119925
120195
  const roles = values3("SELECT DISTINCT json_extract(metadata_json, '$.role') AS v FROM log_entries WHERE json_extract(metadata_json, '$.chatroomId') = ? AND json_extract(metadata_json, '$.role') IS NOT NULL ORDER BY v LIMIT ?");
119926
120196
  const meta3 = values3("SELECT DISTINCT json_extract(metadata_json, '$.harness') AS v FROM log_entries WHERE json_extract(metadata_json, '$.chatroomId') = ? AND json_extract(metadata_json, '$.harness') IS NOT NULL ORDER BY v LIMIT ?");
119927
120197
  const source = values3("SELECT DISTINCT substr(source, 9) AS v FROM log_entries WHERE json_extract(metadata_json, '$.chatroomId') = ? AND source LIKE 'harness:%' ORDER BY v LIMIT ?");
@@ -120105,17 +120375,17 @@ var init_persistence = __esm(() => {
120105
120375
  // src/daemon/infrastructure/repository/log-repository.ts
120106
120376
  function createLogRepository(db) {
120107
120377
  return {
120108
- queryAfterId(afterId = 0, limit = 100, source, chatroomId, role, harness, fromTimestamp, toTimestamp) {
120109
- return queryAfterId(db, afterId, limit, source, chatroomId, role, harness, fromTimestamp, toTimestamp);
120378
+ queryAfterId(afterId = 0, limit = 100, source, chatroomId2, role, harness, fromTimestamp, toTimestamp) {
120379
+ return queryAfterId(db, afterId, limit, source, chatroomId2, role, harness, fromTimestamp, toTimestamp);
120110
120380
  },
120111
- queryHistory(beforeId, limit = 100, source, chatroomId, role, harness, fromTimestamp, toTimestamp) {
120112
- return queryHistory(db, beforeId, limit, source, chatroomId, role, harness, fromTimestamp, toTimestamp);
120381
+ queryHistory(beforeId, limit = 100, source, chatroomId2, role, harness, fromTimestamp, toTimestamp) {
120382
+ return queryHistory(db, beforeId, limit, source, chatroomId2, role, harness, fromTimestamp, toTimestamp);
120113
120383
  },
120114
120384
  listSources(limit = 100) {
120115
120385
  return listDistinctSources(db, limit);
120116
120386
  },
120117
- listDimensions(chatroomId, limit = 100) {
120118
- return listLogDimensions(db, chatroomId, limit);
120387
+ listDimensions(chatroomId2, limit = 100) {
120388
+ return listLogDimensions(db, chatroomId2, limit);
120119
120389
  },
120120
120390
  writeChatroomEvent(event) {
120121
120391
  return appendChatroomEvent(db, event);
@@ -133927,8 +134197,8 @@ function listLogHistory(reader, input) {
133927
134197
  const entries2 = input.afterId !== undefined ? reader.queryAfterId(input.afterId, limit, input.source, input.chatroomId, input.role, input.harness, input.fromTimestamp, input.toTimestamp) : reader.queryHistory(input.beforeId, limit, input.source, input.chatroomId, input.role, input.harness, input.fromTimestamp, input.toTimestamp);
133928
134198
  return { entries: entries2 };
133929
134199
  }
133930
- function listLogDimensions2(reader, chatroomId, limit = 100) {
133931
- return reader.listDimensions ? reader.listDimensions(chatroomId, limit) : { roles: [], harnesses: [] };
134200
+ function listLogDimensions2(reader, chatroomId2, limit = 100) {
134201
+ return reader.listDimensions ? reader.listDimensions(chatroomId2, limit) : { roles: [], harnesses: [] };
133932
134202
  }
133933
134203
  function listLogSources(reader, limit = 100) {
133934
134204
  return { sources: reader.listSources(limit) };
@@ -135146,7 +135416,7 @@ handoffCommandGroup.option("--chatroom-id <id>", "Chatroom identifier").option("
135146
135416
  console.error(`error: required option '${flag} <...>' not specified`);
135147
135417
  process.exit(1);
135148
135418
  }
135149
- const { chatroomId, role, nextRole } = options;
135419
+ const { chatroomId: chatroomId2, role, nextRole } = options;
135150
135420
  await maybeRequireAuth();
135151
135421
  const { decode: decode6 } = await Promise.resolve().then(() => exports_decode);
135152
135422
  const stdinContent = await readStdin();
@@ -135165,7 +135435,7 @@ handoffCommandGroup.option("--chatroom-id <id>", "Chatroom identifier").option("
135165
135435
  process.exit(1);
135166
135436
  }
135167
135437
  const { handoff: handoff2 } = await Promise.resolve().then(() => (init_handoff(), exports_handoff));
135168
- await handoff2(chatroomId, {
135438
+ await handoff2(chatroomId2, {
135169
135439
  role,
135170
135440
  message,
135171
135441
  nextRole
@@ -135489,18 +135759,18 @@ registerChatroomRoleCommand(program2, {
135489
135759
  name: "get-system-prompt",
135490
135760
  description: "Fetch the system prompt for your role in a chatroom",
135491
135761
  maybeRequireAuth,
135492
- run: async (chatroomId, { role }) => {
135762
+ run: async (chatroomId2, { role }) => {
135493
135763
  const { getSystemPrompt: getSystemPrompt2 } = await Promise.resolve().then(() => (init_get_system_prompt(), exports_get_system_prompt));
135494
- await getSystemPrompt2(chatroomId, { role });
135764
+ await getSystemPrompt2(chatroomId2, { role });
135495
135765
  }
135496
135766
  });
135497
135767
  registerChatroomRoleCommand(program2, {
135498
135768
  name: "get-role-guidance",
135499
135769
  description: "Fetch role-specific operating-model guidance for your role in a chatroom",
135500
135770
  maybeRequireAuth,
135501
- run: async (chatroomId, { role }) => {
135771
+ run: async (chatroomId2, { role }) => {
135502
135772
  const { getRoleGuidance: getRoleGuidance2 } = await Promise.resolve().then(() => (init_get_role_guidance(), exports_get_role_guidance));
135503
- await getRoleGuidance2(chatroomId, { role });
135773
+ await getRoleGuidance2(chatroomId2, { role });
135504
135774
  }
135505
135775
  });
135506
135776
  var telegramCommand = program2.command("telegram").description("Telegram integration commands");
@@ -135535,9 +135805,9 @@ opencodeCommand.command("install").description("Install chatroom as an OpenCode
135535
135805
  });
135536
135806
  program2.hook("preAction", async (_thisCommand, actionCommand) => {
135537
135807
  const opts = actionCommand.opts();
135538
- const chatroomId = opts["chatroomId"];
135808
+ const chatroomId2 = opts["chatroomId"];
135539
135809
  const role = opts["role"];
135540
- if (!chatroomId || !role)
135810
+ if (!chatroomId2 || !role)
135541
135811
  return;
135542
135812
  const { getSessionId: getSessionId2 } = await Promise.resolve().then(() => (init_storage(), exports_storage));
135543
135813
  const { getConvexClient: getConvexClient2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
@@ -135546,8 +135816,8 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
135546
135816
  if (!sessionId)
135547
135817
  return;
135548
135818
  const client4 = await getConvexClient2();
135549
- sendLifecycleHeartbeat2(client4, { sessionId, chatroomId, role });
135819
+ sendLifecycleHeartbeat2(client4, { sessionId, chatroomId: chatroomId2, role });
135550
135820
  });
135551
135821
  program2.parse();
135552
135822
 
135553
- //# debugId=1B70D63A805E79F864756E2164756E21
135823
+ //# debugId=B512277D42B2480364756E2164756E21