chatroom-cli 1.110.1 → 1.111.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");
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,197 +117993,6 @@ 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";
117630
- }
117631
- function isOperationalStopIntentActive2(row) {
117632
- return row?.stopState === "stopped" || row?.stopState === "stopping" || row?.stopState === "pending";
117633
- }
117634
-
117635
- class AgentOperationalReadModel {
117636
- rows = new Map;
117637
- replace(rows) {
117638
- const changed = [];
117639
- const nextKeys = new Set;
117640
- for (const row of rows) {
117641
- const key = roleKey3(row.chatroomId, row.role);
117642
- nextKeys.add(key);
117643
- const prev = this.rows.get(key);
117644
- if (!prev || prev.revisionKey !== row.revisionKey)
117645
- changed.push({ chatroomId: row.chatroomId, role: row.role });
117646
- this.rows.set(key, row);
117647
- }
117648
- for (const [key, prev] of this.rows) {
117649
- if (!nextKeys.has(key)) {
117650
- changed.push({ chatroomId: prev.chatroomId, role: prev.role });
117651
- this.rows.delete(key);
117652
- }
117653
- }
117654
- return changed;
117655
- }
117656
- applySignalPage(rows, removed) {
117657
- const changed = [];
117658
- for (const row of rows) {
117659
- const key = roleKey3(row.chatroomId, row.role);
117660
- const prev = this.rows.get(key);
117661
- if (!prev || prev.revisionKey !== row.revisionKey) {
117662
- changed.push({ chatroomId: row.chatroomId, role: row.role });
117663
- }
117664
- this.rows.set(key, row);
117665
- }
117666
- for (const item of removed) {
117667
- const key = roleKey3(item.chatroomId, item.role);
117668
- if (this.rows.has(key))
117669
- changed.push(item);
117670
- this.rows.delete(key);
117671
- }
117672
- return changed;
117673
- }
117674
- get(chatroomId, role) {
117675
- return this.rows.get(roleKey3(chatroomId, role));
117676
- }
117677
- }
117678
- var roleKey3 = (chatroomId, role) => `${chatroomId}:${role.toLowerCase()}`;
117679
-
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
117740
- });
117741
- }
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
117996
  // src/daemon/entry/task-inbox-membership-registry.ts
117819
117997
  function registerTaskInboxRoomMembershipRefresh(refresh) {
117820
117998
  refreshRoomMembership = refresh;
@@ -117879,6 +118057,64 @@ var init_ack_machine_operational_signals = __esm(() => {
117879
118057
  init_api3();
117880
118058
  });
117881
118059
 
118060
+ // src/daemon/infrastructure/agent-operational/agent-operational-read-model.ts
118061
+ class AgentOperationalReadModel {
118062
+ rows = new Map;
118063
+ replace(rows) {
118064
+ const changed = [];
118065
+ const nextKeys = new Set;
118066
+ for (const row of rows) {
118067
+ const key = roleKey3(row.chatroomId, row.role);
118068
+ nextKeys.add(key);
118069
+ const prev = this.rows.get(key);
118070
+ if (!prev || prev.revisionKey !== row.revisionKey)
118071
+ changed.push({ chatroomId: row.chatroomId, role: row.role });
118072
+ this.rows.set(key, row);
118073
+ }
118074
+ for (const [key, prev] of this.rows) {
118075
+ if (!nextKeys.has(key)) {
118076
+ changed.push({ chatroomId: prev.chatroomId, role: prev.role });
118077
+ this.rows.delete(key);
118078
+ }
118079
+ }
118080
+ return changed;
118081
+ }
118082
+ applySignalPage(rows, removed) {
118083
+ const changed = [];
118084
+ for (const row of rows) {
118085
+ const key = roleKey3(row.chatroomId, row.role);
118086
+ const prev = this.rows.get(key);
118087
+ if (!prev || prev.revisionKey !== row.revisionKey) {
118088
+ changed.push({ chatroomId: row.chatroomId, role: row.role });
118089
+ }
118090
+ this.rows.set(key, row);
118091
+ }
118092
+ for (const item of removed) {
118093
+ const key = roleKey3(item.chatroomId, item.role);
118094
+ if (this.rows.has(key))
118095
+ changed.push(item);
118096
+ this.rows.delete(key);
118097
+ }
118098
+ return changed;
118099
+ }
118100
+ get(chatroomId, role) {
118101
+ return this.rows.get(roleKey3(chatroomId, role));
118102
+ }
118103
+ }
118104
+ var roleKey3 = (chatroomId, role) => `${chatroomId}:${role.toLowerCase()}`;
118105
+
118106
+ // src/daemon/infrastructure/agent-operational/fetch-machine-agent-operational-status.ts
118107
+ async function fetchMachineAgentOperationalStatus(sessionDeps, machineId) {
118108
+ const result = await sessionDeps.backend.query(api.machines.listMachineAgentOperationalStatus, {
118109
+ sessionId: sessionDeps.sessionId,
118110
+ machineId
118111
+ });
118112
+ return result;
118113
+ }
118114
+ var init_fetch_machine_agent_operational_status = __esm(() => {
118115
+ init_api3();
118116
+ });
118117
+
117882
118118
  // src/daemon/infrastructure/agent-operational/operational-inbox.ts
117883
118119
  function operationalSignalCursorAt(timestamp) {
117884
118120
  return `${String(Math.max(0, Math.floor(timestamp))).padStart(16, "0")}:`;
@@ -118012,7 +118248,7 @@ async function runOperationalInboxLoopWithRestart(options, onUpdate, isStopped)
118012
118248
  }
118013
118249
  }
118014
118250
  }
118015
- var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInboxEffect = (wsClient2) => exports_Effect.gen(function* () {
118251
+ var INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInboxEffect = (wsClient2) => exports_Effect.gen(function* () {
118016
118252
  const session2 = yield* DaemonSessionService;
118017
118253
  const agentMgr = yield* DaemonAgentProcessManagerService;
118018
118254
  const commandService = yield* DaemonAgentProcessManagerCommandService;
@@ -118037,31 +118273,25 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
118037
118273
  const serviceStartedAt = Date.now();
118038
118274
  const abort = new AbortController;
118039
118275
  let stopped = false;
118040
- const taskSnapshotState = session2.taskService.taskSnapshotState;
118041
118276
  const agentOperationalReadModel = new AgentOperationalReadModel;
118042
118277
  const agentTaskState = createAgentTaskStateService();
118043
- const nativeDelivery = new NativeDeliveryService({
118278
+ const nativeDelivery = session2.taskService.createNativeDeliveryService({
118044
118279
  runtime: runtime4,
118045
118280
  effectContext: effectContext2,
118046
118281
  agentMgr,
118047
118282
  runSerializedForAgent: commandService.runSerializedForAgent,
118048
118283
  sessionDeps,
118049
118284
  machineId: session2.machineId,
118050
- taskSnapshotState,
118051
118285
  agentTaskState,
118052
118286
  agentOperationalReadModel,
118053
- lifecycleOutbox,
118054
- taskService: session2.taskService
118287
+ lifecycleOutbox
118055
118288
  });
118056
- const unsubscribeTaskService = session2.taskService.subscribe((notification) => nativeDelivery.handleTaskServiceNotification(notification));
118057
118289
  yield* exports_Effect.tryPromise(() => session2.taskService.startTaskInbox(wsClient2)).pipe(exports_Effect.catchAll((error51) => {
118058
118290
  console.warn("[TaskInbox] service bootstrap failed:", error51);
118059
118291
  return exports_Effect.void;
118060
118292
  }));
118061
118293
  const knownRoomIds = new Set;
118062
118294
  const roomWatchers = new Map;
118063
- let inboxUpdatesInFlight = 0;
118064
- let reconcileInFlight = false;
118065
118295
  const bootstrapSucceeded = yield* exports_Effect.tryPromise(async () => {
118066
118296
  const rows = await fetchMachineAgentOperationalStatus(sessionDeps, session2.machineId);
118067
118297
  agentOperationalReadModel.replace(rows);
@@ -118074,24 +118304,20 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
118074
118304
  }));
118075
118305
  const operationalHandler = async (update6) => {
118076
118306
  const chatroomId = update6.chatroomId;
118077
- inboxUpdatesInFlight += 1;
118307
+ const changed = agentOperationalReadModel.applySignalPage(update6.rows, update6.removed);
118308
+ await Promise.all(changed.map(({ chatroomId: roomId, role }) => nativeDelivery.requestReconcile({
118309
+ chatroomId: roomId,
118310
+ role,
118311
+ source: "operational-signal"
118312
+ })));
118313
+ inboxStore.save({
118314
+ inboxType: "operational",
118315
+ scopeKey: roomScopeKey(session2.machineId, chatroomId)
118316
+ }, { afterSignalKey: update6.throughSignalKey });
118078
118317
  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;
118318
+ await ackMachineOperationalSignals(sessionDeps, session2.machineId, chatroomId, update6.throughSignalKey);
118319
+ } catch (error51) {
118320
+ console.warn(`[OperationalInbox room=${chatroomId}] signal cleanup failed:`, error51);
118095
118321
  }
118096
118322
  };
118097
118323
  const ensureRoomInboxes = (chatroomId) => {
@@ -118179,16 +118405,6 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
118179
118405
  console.warn("[OperationalInbox] initial watcher start failed:", error51);
118180
118406
  return exports_Effect.void;
118181
118407
  }));
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
118408
  return {
118193
118409
  nativeDelivery,
118194
118410
  stop() {
@@ -118197,9 +118413,7 @@ var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_R
118197
118413
  for (const watcher of roomWatchers.values()) {
118198
118414
  watcher.controller.abort();
118199
118415
  }
118200
- clearInterval(reconcileTimer);
118201
118416
  unregisterTaskInboxRoomMembershipRefresh();
118202
- unsubscribeTaskService();
118203
118417
  session2.taskService.stopTaskInbox();
118204
118418
  nativeDelivery.dispose();
118205
118419
  nativeDelivery.agentTaskState.clearAll();
@@ -118211,7 +118425,6 @@ var init_task_inbox_runtime = __esm(() => {
118211
118425
  init_esm();
118212
118426
  init_daemon_services();
118213
118427
  init_api3();
118214
- init_native_delivery_service();
118215
118428
  init_ack_machine_operational_signals();
118216
118429
  init_fetch_machine_agent_operational_status();
118217
118430
  init_operational_inbox();
@@ -118746,7 +118959,12 @@ Listening for commands...`);
118746
118959
  registerCommandInboundHandler(async (event) => {
118747
118960
  evictStaleDedupEntries(dedupTracker);
118748
118961
  if (event.type === "command.received") {
118749
- await handleInboundCommandEvent(event.commandId, dedupTracker, effectContext2, session2, event.claimedCommand, taskInboxHandle.nativeDelivery);
118962
+ const nativeDelivery = taskInboxHandle?.nativeDelivery;
118963
+ if (!nativeDelivery) {
118964
+ console.warn("[Daemon] command received before task inbox started");
118965
+ return;
118966
+ }
118967
+ await handleInboundCommandEvent(event.commandId, dedupTracker, effectContext2, session2, event.claimedCommand, nativeDelivery);
118750
118968
  } else {
118751
118969
  await drainActionableCommandRuns(session2, commandRunRuntime);
118752
118970
  }
@@ -135550,4 +135768,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
135550
135768
  });
135551
135769
  program2.parse();
135552
135770
 
135553
- //# debugId=1B70D63A805E79F864756E2164756E21
135771
+ //# debugId=F48EA5F0861EF1C964756E2164756E21