chatroom-cli 1.65.7 → 1.65.9
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 +1056 -460
- package/dist/index.js.map +31 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -36196,6 +36196,21 @@ var init_terminal_provider_error = __esm(() => {
|
|
|
36196
36196
|
PROVIDER_ERROR_NAMES = ["ai_apicallerror", "ai_retryerror"];
|
|
36197
36197
|
});
|
|
36198
36198
|
|
|
36199
|
+
// src/infrastructure/services/remote-agents/opencode-sdk/opencode-session-status.ts
|
|
36200
|
+
function isOpenCodeSessionStatus(value) {
|
|
36201
|
+
return typeof value === "string" && OPENCODE_SESSION_STATUSES.includes(value);
|
|
36202
|
+
}
|
|
36203
|
+
function parseOpenCodeSessionStatus(raw) {
|
|
36204
|
+
return isOpenCodeSessionStatus(raw) ? raw : null;
|
|
36205
|
+
}
|
|
36206
|
+
function assertNeverOpenCodeSessionStatus(value, context5) {
|
|
36207
|
+
throw new Error(`Unhandled OpenCode session status in ${context5}: ${String(value)}`);
|
|
36208
|
+
}
|
|
36209
|
+
var OPENCODE_SESSION_STATUSES;
|
|
36210
|
+
var init_opencode_session_status = __esm(() => {
|
|
36211
|
+
OPENCODE_SESSION_STATUSES = ["idle", "busy", "retry"];
|
|
36212
|
+
});
|
|
36213
|
+
|
|
36199
36214
|
// src/infrastructure/services/remote-agents/opencode-sdk/session-event-forwarder.ts
|
|
36200
36215
|
function formatLogLine(options, kind, payload) {
|
|
36201
36216
|
return formatTimestampedLogLine(options.role, kind, payload, options.now);
|
|
@@ -36304,6 +36319,15 @@ function startSessionEventForwarder(client4, options) {
|
|
|
36304
36319
|
cancelled = true;
|
|
36305
36320
|
emitAgentEnd("provider_rate_limit");
|
|
36306
36321
|
}
|
|
36322
|
+
function armTurnEnd() {
|
|
36323
|
+
if (terminalAbortRequested) {
|
|
36324
|
+
logLine(target, "status", "turn_arm_blocked_terminal");
|
|
36325
|
+
return;
|
|
36326
|
+
}
|
|
36327
|
+
clearRetryIdleTimeout();
|
|
36328
|
+
agentEndEmitted = false;
|
|
36329
|
+
lastStatus = undefined;
|
|
36330
|
+
}
|
|
36307
36331
|
function resolvePartContent(delta, text) {
|
|
36308
36332
|
return delta !== undefined && delta !== "" ? delta : text;
|
|
36309
36333
|
}
|
|
@@ -36386,11 +36410,22 @@ function startSessionEventForwarder(client4, options) {
|
|
|
36386
36410
|
logLine(target, "compacted");
|
|
36387
36411
|
}
|
|
36388
36412
|
async function handleSessionStatus(props) {
|
|
36389
|
-
const
|
|
36390
|
-
|
|
36391
|
-
|
|
36392
|
-
|
|
36393
|
-
if (
|
|
36413
|
+
const raw = props?.status?.type;
|
|
36414
|
+
const parsed = parseOpenCodeSessionStatus(raw);
|
|
36415
|
+
if (parsed === null) {
|
|
36416
|
+
const unknownKey = raw === undefined ? "undefined" : String(raw);
|
|
36417
|
+
if (unknownKey !== lastStatus) {
|
|
36418
|
+
lastStatus = unknownKey;
|
|
36419
|
+
logLine(target, "status", `unknown_session_status:${unknownKey}`);
|
|
36420
|
+
}
|
|
36421
|
+
return;
|
|
36422
|
+
}
|
|
36423
|
+
if (parsed === lastStatus)
|
|
36424
|
+
return;
|
|
36425
|
+
lastStatus = parsed;
|
|
36426
|
+
logLine(target, "status", parsed);
|
|
36427
|
+
switch (parsed) {
|
|
36428
|
+
case "retry": {
|
|
36394
36429
|
if (terminalAbortRequested) {
|
|
36395
36430
|
abortTerminalProviderError();
|
|
36396
36431
|
return;
|
|
@@ -36398,7 +36433,18 @@ function startSessionEventForwarder(client4, options) {
|
|
|
36398
36433
|
scheduleRetryIdleTimeout();
|
|
36399
36434
|
return;
|
|
36400
36435
|
}
|
|
36401
|
-
|
|
36436
|
+
case "idle": {
|
|
36437
|
+
clearRetryIdleTimeout();
|
|
36438
|
+
await handleSessionIdle();
|
|
36439
|
+
return;
|
|
36440
|
+
}
|
|
36441
|
+
case "busy": {
|
|
36442
|
+
clearRetryIdleTimeout();
|
|
36443
|
+
return;
|
|
36444
|
+
}
|
|
36445
|
+
default: {
|
|
36446
|
+
assertNeverOpenCodeSessionStatus(parsed, "handleSessionStatus");
|
|
36447
|
+
}
|
|
36402
36448
|
}
|
|
36403
36449
|
}
|
|
36404
36450
|
async function handleSessionError(props) {
|
|
@@ -36489,12 +36535,14 @@ function startSessionEventForwarder(client4, options) {
|
|
|
36489
36535
|
onAgentEnd: (cb) => {
|
|
36490
36536
|
agentEndCallbacks.push(cb);
|
|
36491
36537
|
},
|
|
36492
|
-
abortTerminalProviderError
|
|
36538
|
+
abortTerminalProviderError,
|
|
36539
|
+
armTurnEnd
|
|
36493
36540
|
};
|
|
36494
36541
|
}
|
|
36495
36542
|
var RECENT_LOG_LINE_CAP = 20, DEFAULT_SESSION_RETRY_IDLE_TIMEOUT_MS;
|
|
36496
36543
|
var init_session_event_forwarder = __esm(() => {
|
|
36497
36544
|
init_terminal_provider_error();
|
|
36545
|
+
init_opencode_session_status();
|
|
36498
36546
|
DEFAULT_SESSION_RETRY_IDLE_TIMEOUT_MS = 5 * 60 * 1000;
|
|
36499
36547
|
});
|
|
36500
36548
|
|
|
@@ -37010,6 +37058,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
37010
37058
|
`);
|
|
37011
37059
|
return;
|
|
37012
37060
|
}
|
|
37061
|
+
this.forwarders.get(pid)?.armTurnEnd();
|
|
37013
37062
|
const client4 = createOpencodeClient({ baseUrl: meta.baseUrl });
|
|
37014
37063
|
const deferredSystem = meta.deferredSystemPrompt;
|
|
37015
37064
|
const context5 = {
|
|
@@ -84676,7 +84725,7 @@ var init_featureFlags = __esm(() => {
|
|
|
84676
84725
|
});
|
|
84677
84726
|
|
|
84678
84727
|
// ../../services/backend/config/reliability.ts
|
|
84679
|
-
var DAEMON_HEARTBEAT_INTERVAL_MS, DAEMON_HEARTBEAT_TTL_MS, AGENT_REQUEST_DEADLINE_MS = 120000, OBSERVATION_TTL_MS = 60000, OBSERVED_FULL_PUSH_INTERVAL_MS, OBSERVED_SAFETY_POLL_MS = 30000, WORKSPACE_RECENCY_WINDOW_MS, WORKSPACE_LIST_RECONCILE_MS, CONNECTION_CLOSE_REQUEST_TTL_MS;
|
|
84728
|
+
var HARNESS_SESSION_READY_TIMEOUT_MS = 5000, NATIVE_DELIVERY_RECONCILE_MS = 1e4, DAEMON_HEARTBEAT_INTERVAL_MS, DAEMON_HEARTBEAT_TTL_MS, AGENT_REQUEST_DEADLINE_MS = 120000, OBSERVATION_TTL_MS = 60000, OBSERVED_FULL_PUSH_INTERVAL_MS, OBSERVED_SAFETY_POLL_MS = 30000, WORKSPACE_RECENCY_WINDOW_MS, WORKSPACE_LIST_RECONCILE_MS, CONNECTION_CLOSE_REQUEST_TTL_MS;
|
|
84680
84729
|
var init_reliability = __esm(() => {
|
|
84681
84730
|
DAEMON_HEARTBEAT_INTERVAL_MS = 5 * 60000;
|
|
84682
84731
|
DAEMON_HEARTBEAT_TTL_MS = 6 * DAEMON_HEARTBEAT_INTERVAL_MS;
|
|
@@ -84731,6 +84780,780 @@ var init_daemon_services = __esm(() => {
|
|
|
84731
84780
|
};
|
|
84732
84781
|
});
|
|
84733
84782
|
|
|
84783
|
+
// ../../services/backend/src/domain/entities/participant.ts
|
|
84784
|
+
var NATIVE_WAITING_ACTION = "native:waiting", NATIVE_TASK_INJECTED_ACTION = "native:task-injected", NATIVE_HANDOFF_REMINDER = "Reminder: Use the handoff command to send your response to the team.", ONLINE_OR_STARTING_STATUSES;
|
|
84785
|
+
var init_participant = __esm(() => {
|
|
84786
|
+
ONLINE_OR_STARTING_STATUSES = new Set([
|
|
84787
|
+
"agent.waiting",
|
|
84788
|
+
"agent.requestStart",
|
|
84789
|
+
"agent.started",
|
|
84790
|
+
"task.acknowledged",
|
|
84791
|
+
"task.inProgress",
|
|
84792
|
+
"task.completed",
|
|
84793
|
+
"agent.requestStop",
|
|
84794
|
+
"agent.awaitingHandoff"
|
|
84795
|
+
]);
|
|
84796
|
+
});
|
|
84797
|
+
|
|
84798
|
+
// src/commands/machine/daemon-start/native-ready-invariant.ts
|
|
84799
|
+
function isAgentReadyForNativeDelivery(task, slot) {
|
|
84800
|
+
return explainAgentReadyForNativeDeliveryBlock(task, slot) === null;
|
|
84801
|
+
}
|
|
84802
|
+
function explainAgentReadyForNativeDeliveryBlock(task, slot) {
|
|
84803
|
+
const { agentConfig } = task;
|
|
84804
|
+
if (!isNativeHarness(agentConfig.agentHarness)) {
|
|
84805
|
+
return `not_native_harness (harness=${agentConfig.agentHarness})`;
|
|
84806
|
+
}
|
|
84807
|
+
if (agentConfig.desiredState !== "running") {
|
|
84808
|
+
return `desired_state_not_running (desiredState=${agentConfig.desiredState})`;
|
|
84809
|
+
}
|
|
84810
|
+
if (agentConfig.spawnedAgentPid == null) {
|
|
84811
|
+
return "spawned_pid_missing";
|
|
84812
|
+
}
|
|
84813
|
+
if (!slot) {
|
|
84814
|
+
return `slot_missing (expectedPid=${agentConfig.spawnedAgentPid})`;
|
|
84815
|
+
}
|
|
84816
|
+
if (slot.state !== "running") {
|
|
84817
|
+
return `slot_not_running (slotState=${slot.state}, expectedPid=${agentConfig.spawnedAgentPid})`;
|
|
84818
|
+
}
|
|
84819
|
+
if (slot.pid !== agentConfig.spawnedAgentPid) {
|
|
84820
|
+
return `pid_mismatch (slotPid=${slot.pid ?? "none"}, snapshotPid=${agentConfig.spawnedAgentPid})`;
|
|
84821
|
+
}
|
|
84822
|
+
if (typeof slot.harnessSessionId !== "string" || slot.harnessSessionId.length === 0) {
|
|
84823
|
+
return "harness_session_missing";
|
|
84824
|
+
}
|
|
84825
|
+
const turnPhase = slot.nativeTurnPhase ?? "idle";
|
|
84826
|
+
if (turnPhase !== "idle") {
|
|
84827
|
+
return `turn_not_idle (nativeTurnPhase=${turnPhase})`;
|
|
84828
|
+
}
|
|
84829
|
+
return null;
|
|
84830
|
+
}
|
|
84831
|
+
function isDeliverableNativeTaskStatus(status3) {
|
|
84832
|
+
return status3 === "pending" || status3 === "acknowledged";
|
|
84833
|
+
}
|
|
84834
|
+
var init_native_ready_invariant = __esm(() => {
|
|
84835
|
+
init_types();
|
|
84836
|
+
});
|
|
84837
|
+
|
|
84838
|
+
// src/commands/machine/daemon-start/assigned-task-snapshot-store.ts
|
|
84839
|
+
function replaceAssignedTaskSnapshots(next4) {
|
|
84840
|
+
rows = [...next4];
|
|
84841
|
+
hasSnapshot = true;
|
|
84842
|
+
}
|
|
84843
|
+
function clearAssignedTaskSnapshots() {
|
|
84844
|
+
rows = [];
|
|
84845
|
+
hasSnapshot = false;
|
|
84846
|
+
}
|
|
84847
|
+
function hasAssignedTaskSnapshot() {
|
|
84848
|
+
return hasSnapshot;
|
|
84849
|
+
}
|
|
84850
|
+
function listAssignedTaskSnapshots() {
|
|
84851
|
+
return [...rows];
|
|
84852
|
+
}
|
|
84853
|
+
function listAssignedTaskSnapshotsForRole(chatroomId, role) {
|
|
84854
|
+
const roleLower = role.toLowerCase();
|
|
84855
|
+
return rows.filter((row) => row.chatroomId === chatroomId && row.agentConfig.role.toLowerCase() === roleLower);
|
|
84856
|
+
}
|
|
84857
|
+
var rows, hasSnapshot = false;
|
|
84858
|
+
var init_assigned_task_snapshot_store = __esm(() => {
|
|
84859
|
+
rows = [];
|
|
84860
|
+
});
|
|
84861
|
+
|
|
84862
|
+
// src/commands/machine/daemon-start/native-delivery-log.ts
|
|
84863
|
+
function logNativeDeliveryPrimary(role, chatroomId) {
|
|
84864
|
+
console.log(`[NativeDelivery:primary] turn idle ${role}@${chatroomId} — trying inject`);
|
|
84865
|
+
}
|
|
84866
|
+
function logNativeDeliveryFallback(reason, role, chatroomId, taskId) {
|
|
84867
|
+
const taskSuffix = taskId ? ` task ${taskId}` : "";
|
|
84868
|
+
console.log(`[NativeDelivery:fallback] ${reason} ${role}@${chatroomId}${taskSuffix} — reconcile`);
|
|
84869
|
+
}
|
|
84870
|
+
function logNativeDeliverySkip(role, chatroomId, taskId, reason) {
|
|
84871
|
+
console.log(`[NativeDelivery:skip] ${role}@${chatroomId} task ${taskId} — ${reason}`);
|
|
84872
|
+
}
|
|
84873
|
+
function logNativeDeliveryMutexSkip(role, chatroomId, taskId) {
|
|
84874
|
+
console.log(`[NativeDelivery:skip] ${role}@${chatroomId} task ${taskId} — delivery_mutex_busy (another inject in flight)`);
|
|
84875
|
+
}
|
|
84876
|
+
function logNativeDeliveryInjecting(role, chatroomId, taskId) {
|
|
84877
|
+
console.log(`[NativeDelivery:inject] ${role}@${chatroomId} task ${taskId} — starting injection`);
|
|
84878
|
+
}
|
|
84879
|
+
function logNativeDeliveryNoTasks(role, chatroomId) {
|
|
84880
|
+
console.log(`[NativeDelivery:skip] ${role}@${chatroomId} — no pending tasks for role`);
|
|
84881
|
+
}
|
|
84882
|
+
|
|
84883
|
+
// src/commands/machine/daemon-start/native-delivery-session-registry.ts
|
|
84884
|
+
function registerNativeDeliverySession(ctx) {
|
|
84885
|
+
registered = ctx;
|
|
84886
|
+
}
|
|
84887
|
+
function unregisterNativeDeliverySession() {
|
|
84888
|
+
registered = null;
|
|
84889
|
+
}
|
|
84890
|
+
function getNativeDeliverySession() {
|
|
84891
|
+
return registered;
|
|
84892
|
+
}
|
|
84893
|
+
var registered = null;
|
|
84894
|
+
|
|
84895
|
+
// src/domain/native-integration/predicates.ts
|
|
84896
|
+
function isStaleCliGetNextTaskWaiting(task) {
|
|
84897
|
+
const lastSeenAt = task.participant?.lastSeenAt ?? 0;
|
|
84898
|
+
return task.participant?.lastSeenAction === "get-next-task:started" && task.createdAt > lastSeenAt;
|
|
84899
|
+
}
|
|
84900
|
+
function isCliIdleNotListening(task, now, thresholdMs) {
|
|
84901
|
+
const lastSeenAt = task.participant?.lastSeenAt ?? 0;
|
|
84902
|
+
if (lastSeenAt === 0)
|
|
84903
|
+
return now - task.createdAt > thresholdMs;
|
|
84904
|
+
return now - lastSeenAt > thresholdMs;
|
|
84905
|
+
}
|
|
84906
|
+
|
|
84907
|
+
// src/infrastructure/services/remote-agents/spawn-prompt.ts
|
|
84908
|
+
function createSpawnPrompt(raw, opts) {
|
|
84909
|
+
if (opts?.nativeBootstrap) {
|
|
84910
|
+
return NATIVE_BOOTSTRAP_PROMPT;
|
|
84911
|
+
}
|
|
84912
|
+
const trimmed = raw?.trim();
|
|
84913
|
+
return trimmed && trimmed.length > 0 ? trimmed : DEFAULT_TRIGGER_PROMPT;
|
|
84914
|
+
}
|
|
84915
|
+
var DEFAULT_TRIGGER_PROMPT = "Please read your system prompt carefully and follow the Getting Started instructions.", NATIVE_BOOTSTRAP_PROMPT = "Focus on your role responsibilities. Complete each task via handoff.";
|
|
84916
|
+
|
|
84917
|
+
// src/domain/native-integration/spawn-policy.ts
|
|
84918
|
+
function shouldDeferInitialTurn(harness) {
|
|
84919
|
+
return isNativeHarness(harness);
|
|
84920
|
+
}
|
|
84921
|
+
function resolveNativeSpawnPolicy(harness, initMessage) {
|
|
84922
|
+
const deferInitialTurn = shouldDeferInitialTurn(harness);
|
|
84923
|
+
return {
|
|
84924
|
+
deferInitialTurn,
|
|
84925
|
+
prompt: createSpawnPrompt(initMessage, { nativeBootstrap: deferInitialTurn })
|
|
84926
|
+
};
|
|
84927
|
+
}
|
|
84928
|
+
var init_spawn_policy = __esm(() => {
|
|
84929
|
+
init_types();
|
|
84930
|
+
});
|
|
84931
|
+
|
|
84932
|
+
// src/domain/native-integration/index.ts
|
|
84933
|
+
var init_native_integration = __esm(() => {
|
|
84934
|
+
init_types();
|
|
84935
|
+
init_spawn_policy();
|
|
84936
|
+
});
|
|
84937
|
+
|
|
84938
|
+
// src/commands/machine/daemon-start/native-task-injector-logic.ts
|
|
84939
|
+
function explainNativeDeliveryBlock(task, opts) {
|
|
84940
|
+
if (!isDeliverableNativeTaskStatus(task.status)) {
|
|
84941
|
+
return `task_status_not_deliverable (status=${task.status})`;
|
|
84942
|
+
}
|
|
84943
|
+
if (task.status === "acknowledged") {
|
|
84944
|
+
const assignedTo = task.assignedTo?.toLowerCase();
|
|
84945
|
+
const role = task.agentConfig.role.toLowerCase();
|
|
84946
|
+
if (assignedTo !== role) {
|
|
84947
|
+
return `acknowledged_wrong_role (assignedTo=${assignedTo ?? "none"}, role=${role})`;
|
|
84948
|
+
}
|
|
84949
|
+
}
|
|
84950
|
+
return explainAgentReadyForNativeDeliveryBlock(task, opts.slot);
|
|
84951
|
+
}
|
|
84952
|
+
function buildNativeInjectionPrompt(params) {
|
|
84953
|
+
const { taskDeliveryOutput, augmentationMode } = params;
|
|
84954
|
+
if (augmentationMode === "compact") {
|
|
84955
|
+
return [
|
|
84956
|
+
"⚠️ Context was compacted. Run `chatroom get-system-prompt` only if role instructions are missing.",
|
|
84957
|
+
"",
|
|
84958
|
+
taskDeliveryOutput
|
|
84959
|
+
].join(`
|
|
84960
|
+
`);
|
|
84961
|
+
}
|
|
84962
|
+
if (augmentationMode === "new_session") {
|
|
84963
|
+
return [
|
|
84964
|
+
"⚠️ Starting a new agent session. Run `chatroom get-system-prompt` to reload role instructions if needed.",
|
|
84965
|
+
"",
|
|
84966
|
+
taskDeliveryOutput
|
|
84967
|
+
].join(`
|
|
84968
|
+
`);
|
|
84969
|
+
}
|
|
84970
|
+
return taskDeliveryOutput;
|
|
84971
|
+
}
|
|
84972
|
+
var init_native_task_injector_logic = __esm(() => {
|
|
84973
|
+
init_native_ready_invariant();
|
|
84974
|
+
init_native_integration();
|
|
84975
|
+
});
|
|
84976
|
+
|
|
84977
|
+
// ../../services/backend/src/domain/entities/team-agent-settings.ts
|
|
84978
|
+
function roleSupportsSessionAugmentation(role) {
|
|
84979
|
+
const normalized = role.toLowerCase();
|
|
84980
|
+
return SESSION_AUGMENTATION_ROLES.some((r) => r === normalized);
|
|
84981
|
+
}
|
|
84982
|
+
var SESSION_AUGMENTATION_ROLES;
|
|
84983
|
+
var init_team_agent_settings = __esm(() => {
|
|
84984
|
+
SESSION_AUGMENTATION_ROLES = ["builder"];
|
|
84985
|
+
});
|
|
84986
|
+
|
|
84987
|
+
// ../../services/backend/src/domain/handoff/parse-session-augmentation.ts
|
|
84988
|
+
function findSectionIndex(content, headings) {
|
|
84989
|
+
const indices = headings.map((heading) => content.indexOf(heading)).filter((idx) => idx !== -1);
|
|
84990
|
+
return indices.length === 0 ? -1 : Math.min(...indices);
|
|
84991
|
+
}
|
|
84992
|
+
function normalizeMode(raw) {
|
|
84993
|
+
return MODE_ALIASES[raw.toLowerCase()] ?? DEFAULT_MODE;
|
|
84994
|
+
}
|
|
84995
|
+
function extractSectionBody(content, sectionIdx) {
|
|
84996
|
+
const matchedHeading = SECTION_HEADINGS.find((h) => content.indexOf(h, sectionIdx) === sectionIdx) ?? SECTION_HEADINGS[0];
|
|
84997
|
+
const afterSection = content.slice(sectionIdx);
|
|
84998
|
+
const nextHeading = afterSection.slice(matchedHeading.length).search(/\n## /);
|
|
84999
|
+
return nextHeading === -1 ? afterSection : afterSection.slice(0, matchedHeading.length + nextHeading);
|
|
85000
|
+
}
|
|
85001
|
+
function parseSessionAugmentation(handoffContent) {
|
|
85002
|
+
const sectionIdx = findSectionIndex(handoffContent, SECTION_HEADINGS);
|
|
85003
|
+
if (sectionIdx === -1)
|
|
85004
|
+
return DEFAULT_MODE;
|
|
85005
|
+
const match17 = extractSectionBody(handoffContent, sectionIdx).match(DATA_TAG);
|
|
85006
|
+
if (!match17)
|
|
85007
|
+
return DEFAULT_MODE;
|
|
85008
|
+
return normalizeMode(match17[1]);
|
|
85009
|
+
}
|
|
85010
|
+
function resolveSessionAugmentationForRole(handoffContent, role) {
|
|
85011
|
+
if (!roleSupportsSessionAugmentation(role)) {
|
|
85012
|
+
return "none";
|
|
85013
|
+
}
|
|
85014
|
+
return parseSessionAugmentation(handoffContent);
|
|
85015
|
+
}
|
|
85016
|
+
function sessionAugmentationToWantResume(mode) {
|
|
85017
|
+
return mode === "none" || mode === "compact";
|
|
85018
|
+
}
|
|
85019
|
+
function sessionAugmentationNewSessionStarted(mode) {
|
|
85020
|
+
return mode === "new_session";
|
|
85021
|
+
}
|
|
85022
|
+
var SECTION_HEADINGS, DATA_TAG, DEFAULT_MODE = "new_session", MODE_ALIASES;
|
|
85023
|
+
var init_parse_session_augmentation = __esm(() => {
|
|
85024
|
+
init_team_agent_settings();
|
|
85025
|
+
SECTION_HEADINGS = [
|
|
85026
|
+
"## Session Augmentation",
|
|
85027
|
+
"## Session Management",
|
|
85028
|
+
"## Restart new context"
|
|
85029
|
+
];
|
|
85030
|
+
DATA_TAG = /\/\/\s*data:agent\.(?:session_augmentation|compress_context)=(none|compact|new_session|reset)\b/i;
|
|
85031
|
+
MODE_ALIASES = {
|
|
85032
|
+
reset: "new_session",
|
|
85033
|
+
none: "none",
|
|
85034
|
+
compact: "compact",
|
|
85035
|
+
new_session: "new_session"
|
|
85036
|
+
};
|
|
85037
|
+
});
|
|
85038
|
+
|
|
85039
|
+
// src/commands/machine/daemon-start/native-task-injector.ts
|
|
85040
|
+
async function emitTaskDeliveryFailed(deps, args2) {
|
|
85041
|
+
try {
|
|
85042
|
+
await deps.backend.mutation(api.machines.emitTaskDeliveryFailed, {
|
|
85043
|
+
sessionId: deps.sessionId,
|
|
85044
|
+
machineId: deps.machineId,
|
|
85045
|
+
chatroomId: args2.chatroomId,
|
|
85046
|
+
role: args2.role,
|
|
85047
|
+
taskId: args2.taskId,
|
|
85048
|
+
error: args2.error
|
|
85049
|
+
});
|
|
85050
|
+
} catch {}
|
|
85051
|
+
}
|
|
85052
|
+
function runNativeInjectionEffect(task, harnessSessionId, deps) {
|
|
85053
|
+
return exports_Effect.gen(function* () {
|
|
85054
|
+
const { chatroomId, taskId, taskContent, agentConfig, status: status3 } = task;
|
|
85055
|
+
const { role } = agentConfig;
|
|
85056
|
+
if (status3 === "pending") {
|
|
85057
|
+
const claimResult = yield* exports_Effect.tryPromise({
|
|
85058
|
+
try: () => deps.backend.mutation(api.tasks.claimTask, {
|
|
85059
|
+
sessionId: deps.sessionId,
|
|
85060
|
+
chatroomId,
|
|
85061
|
+
role,
|
|
85062
|
+
taskId
|
|
85063
|
+
}),
|
|
85064
|
+
catch: (err) => err
|
|
85065
|
+
}).pipe(exports_Effect.either);
|
|
85066
|
+
if (claimResult._tag === "Left") {
|
|
85067
|
+
yield* exports_Effect.tryPromise({
|
|
85068
|
+
try: () => emitTaskDeliveryFailed(deps, {
|
|
85069
|
+
chatroomId,
|
|
85070
|
+
role,
|
|
85071
|
+
taskId,
|
|
85072
|
+
error: getErrorMessage2(claimResult.left)
|
|
85073
|
+
}),
|
|
85074
|
+
catch: () => {
|
|
85075
|
+
return;
|
|
85076
|
+
}
|
|
85077
|
+
}).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
85078
|
+
return yield* exports_Effect.fail(claimResult.left);
|
|
85079
|
+
}
|
|
85080
|
+
}
|
|
85081
|
+
const deliveryResult = yield* exports_Effect.tryPromise({
|
|
85082
|
+
try: () => deps.backend.query(api.messages.getTaskDeliveryPrompt, {
|
|
85083
|
+
sessionId: deps.sessionId,
|
|
85084
|
+
chatroomId,
|
|
85085
|
+
role,
|
|
85086
|
+
taskId,
|
|
85087
|
+
convexUrl: deps.convexUrl
|
|
85088
|
+
}),
|
|
85089
|
+
catch: (err) => err
|
|
85090
|
+
}).pipe(exports_Effect.either);
|
|
85091
|
+
if (deliveryResult._tag === "Left") {
|
|
85092
|
+
yield* exports_Effect.tryPromise({
|
|
85093
|
+
try: () => emitTaskDeliveryFailed(deps, {
|
|
85094
|
+
chatroomId,
|
|
85095
|
+
role,
|
|
85096
|
+
taskId,
|
|
85097
|
+
error: getErrorMessage2(deliveryResult.left)
|
|
85098
|
+
}),
|
|
85099
|
+
catch: () => {
|
|
85100
|
+
return;
|
|
85101
|
+
}
|
|
85102
|
+
}).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
85103
|
+
return yield* exports_Effect.fail(deliveryResult.left);
|
|
85104
|
+
}
|
|
85105
|
+
const delivery = deliveryResult.right;
|
|
85106
|
+
const augmentationMode = resolveSessionAugmentationForRole(taskContent, role);
|
|
85107
|
+
const prompt = buildNativeInjectionPrompt({
|
|
85108
|
+
taskDeliveryOutput: delivery.fullCliOutput,
|
|
85109
|
+
augmentationMode
|
|
85110
|
+
});
|
|
85111
|
+
yield* exports_Effect.tryPromise({
|
|
85112
|
+
try: () => deps.backend.mutation(api.participants.join, {
|
|
85113
|
+
sessionId: deps.sessionId,
|
|
85114
|
+
chatroomId,
|
|
85115
|
+
role,
|
|
85116
|
+
action: NATIVE_TASK_INJECTED_ACTION,
|
|
85117
|
+
taskId
|
|
85118
|
+
}),
|
|
85119
|
+
catch: (err) => err
|
|
85120
|
+
});
|
|
85121
|
+
if (roleSupportsSessionAugmentation(role)) {
|
|
85122
|
+
yield* exports_Effect.tryPromise({
|
|
85123
|
+
try: () => deps.backend.mutation(api.machines.emitSessionAugmented, {
|
|
85124
|
+
sessionId: deps.sessionId,
|
|
85125
|
+
machineId: deps.machineId,
|
|
85126
|
+
chatroomId,
|
|
85127
|
+
role,
|
|
85128
|
+
taskId,
|
|
85129
|
+
mode: augmentationMode,
|
|
85130
|
+
newSessionStarted: sessionAugmentationNewSessionStarted(augmentationMode),
|
|
85131
|
+
harnessSessionId
|
|
85132
|
+
}),
|
|
85133
|
+
catch: (err) => err
|
|
85134
|
+
}).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
85135
|
+
}
|
|
85136
|
+
const resumeResult = yield* exports_Effect.tryPromise({
|
|
85137
|
+
try: () => deps.agentMgr.resumeTurnForSlot({ chatroomId, role, prompt }),
|
|
85138
|
+
catch: (err) => err
|
|
85139
|
+
}).pipe(exports_Effect.either);
|
|
85140
|
+
if (resumeResult._tag === "Left") {
|
|
85141
|
+
const error = getErrorMessage2(resumeResult.left);
|
|
85142
|
+
console.warn(`[NativeTaskInjector] resumeTurn failed for ${role}@${chatroomId}: ${error}`);
|
|
85143
|
+
yield* exports_Effect.tryPromise({
|
|
85144
|
+
try: () => emitTaskDeliveryFailed(deps, {
|
|
85145
|
+
chatroomId,
|
|
85146
|
+
role,
|
|
85147
|
+
taskId,
|
|
85148
|
+
error
|
|
85149
|
+
}),
|
|
85150
|
+
catch: () => {
|
|
85151
|
+
return;
|
|
85152
|
+
}
|
|
85153
|
+
}).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
85154
|
+
return;
|
|
85155
|
+
}
|
|
85156
|
+
yield* exports_Effect.tryPromise({
|
|
85157
|
+
try: () => deps.backend.mutation(api.machines.emitTaskDelivered, {
|
|
85158
|
+
sessionId: deps.sessionId,
|
|
85159
|
+
machineId: deps.machineId,
|
|
85160
|
+
chatroomId,
|
|
85161
|
+
role,
|
|
85162
|
+
taskId
|
|
85163
|
+
}),
|
|
85164
|
+
catch: (err) => err
|
|
85165
|
+
}).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
85166
|
+
deps.onTaskDelivered?.({ chatroomId, role, taskId });
|
|
85167
|
+
});
|
|
85168
|
+
}
|
|
85169
|
+
var init_native_task_injector = __esm(() => {
|
|
85170
|
+
init_participant();
|
|
85171
|
+
init_team_agent_settings();
|
|
85172
|
+
init_parse_session_augmentation();
|
|
85173
|
+
init_esm();
|
|
85174
|
+
init_native_task_injector_logic();
|
|
85175
|
+
init_api3();
|
|
85176
|
+
init_convex_error();
|
|
85177
|
+
});
|
|
85178
|
+
|
|
85179
|
+
// src/commands/machine/daemon-start/role-delivery-state.ts
|
|
85180
|
+
function roleKey(chatroomId, role) {
|
|
85181
|
+
return `${chatroomId}:${role.toLowerCase()}`;
|
|
85182
|
+
}
|
|
85183
|
+
|
|
85184
|
+
class RoleDeliveryState {
|
|
85185
|
+
generation = new Map;
|
|
85186
|
+
inFlight = new Set;
|
|
85187
|
+
nativeNudgeFailures = new Map;
|
|
85188
|
+
getGeneration(chatroomId, role) {
|
|
85189
|
+
return this.generation.get(roleKey(chatroomId, role)) ?? 0;
|
|
85190
|
+
}
|
|
85191
|
+
resetDeliveryState(chatroomId, role) {
|
|
85192
|
+
const key = roleKey(chatroomId, role);
|
|
85193
|
+
const next4 = (this.generation.get(key) ?? 0) + 1;
|
|
85194
|
+
this.generation.set(key, next4);
|
|
85195
|
+
this.inFlight.delete(key);
|
|
85196
|
+
this.nativeNudgeFailures.delete(key);
|
|
85197
|
+
return next4;
|
|
85198
|
+
}
|
|
85199
|
+
tryAcquireDelivery(chatroomId, role) {
|
|
85200
|
+
const key = roleKey(chatroomId, role);
|
|
85201
|
+
if (this.inFlight.has(key))
|
|
85202
|
+
return false;
|
|
85203
|
+
this.inFlight.add(key);
|
|
85204
|
+
return true;
|
|
85205
|
+
}
|
|
85206
|
+
releaseDelivery(chatroomId, role) {
|
|
85207
|
+
this.inFlight.delete(roleKey(chatroomId, role));
|
|
85208
|
+
}
|
|
85209
|
+
recordNativeNudgeFailure(chatroomId, role) {
|
|
85210
|
+
const key = roleKey(chatroomId, role);
|
|
85211
|
+
const count3 = (this.nativeNudgeFailures.get(key) ?? 0) + 1;
|
|
85212
|
+
this.nativeNudgeFailures.set(key, count3);
|
|
85213
|
+
return count3;
|
|
85214
|
+
}
|
|
85215
|
+
clearNativeNudgeFailures(chatroomId, role) {
|
|
85216
|
+
this.nativeNudgeFailures.delete(roleKey(chatroomId, role));
|
|
85217
|
+
}
|
|
85218
|
+
getNativeNudgeFailures(chatroomId, role) {
|
|
85219
|
+
return this.nativeNudgeFailures.get(roleKey(chatroomId, role)) ?? 0;
|
|
85220
|
+
}
|
|
85221
|
+
}
|
|
85222
|
+
function getRoleDeliveryState() {
|
|
85223
|
+
shared ??= new RoleDeliveryState;
|
|
85224
|
+
return shared;
|
|
85225
|
+
}
|
|
85226
|
+
var shared;
|
|
85227
|
+
|
|
85228
|
+
// src/commands/machine/daemon-start/native-task-delivery-coordinator.ts
|
|
85229
|
+
class NativeTaskDeliveryCoordinator {
|
|
85230
|
+
onSessionLost(params) {
|
|
85231
|
+
getRoleDeliveryState().resetDeliveryState(params.chatroomId, params.role);
|
|
85232
|
+
}
|
|
85233
|
+
resetRoleDeliveryState(chatroomId, role) {
|
|
85234
|
+
getRoleDeliveryState().resetDeliveryState(chatroomId, role);
|
|
85235
|
+
}
|
|
85236
|
+
tryInjectNextForRole(chatroomId, role) {
|
|
85237
|
+
const session2 = getNativeDeliverySession();
|
|
85238
|
+
if (!session2)
|
|
85239
|
+
return;
|
|
85240
|
+
const { runtime: runtime4, effectContext: effectContext2, agentMgr, sessionDeps, machineId } = session2;
|
|
85241
|
+
const tasks = listAssignedTaskSnapshotsForRole(chatroomId, role);
|
|
85242
|
+
if (tasks.length === 0) {
|
|
85243
|
+
logNativeDeliveryNoTasks(role, chatroomId);
|
|
85244
|
+
return;
|
|
85245
|
+
}
|
|
85246
|
+
this.reconcileAssignedTasks({
|
|
85247
|
+
tasks,
|
|
85248
|
+
runtime: runtime4,
|
|
85249
|
+
effectContext: effectContext2,
|
|
85250
|
+
agentMgr,
|
|
85251
|
+
sessionDeps,
|
|
85252
|
+
machineId
|
|
85253
|
+
});
|
|
85254
|
+
}
|
|
85255
|
+
reconcileAssignedTasks(params) {
|
|
85256
|
+
const { tasks, runtime: runtime4, effectContext: effectContext2, agentMgr, sessionDeps, machineId } = params;
|
|
85257
|
+
const deliveryState = getRoleDeliveryState();
|
|
85258
|
+
const pendingFirst = [...tasks].sort((a, b) => {
|
|
85259
|
+
if (a.status === "pending" && b.status !== "pending")
|
|
85260
|
+
return -1;
|
|
85261
|
+
if (b.status === "pending" && a.status !== "pending")
|
|
85262
|
+
return 1;
|
|
85263
|
+
return a.createdAt - b.createdAt;
|
|
85264
|
+
});
|
|
85265
|
+
for (const row of pendingFirst) {
|
|
85266
|
+
const { role } = row.agentConfig;
|
|
85267
|
+
const slot = agentMgr.getSlot(row.chatroomId, role);
|
|
85268
|
+
const blockReason = explainNativeDeliveryBlock(row, { slot });
|
|
85269
|
+
if (blockReason) {
|
|
85270
|
+
if (row.status === "pending" || row.status === "acknowledged") {
|
|
85271
|
+
logNativeDeliverySkip(role, row.chatroomId, row.taskId, blockReason);
|
|
85272
|
+
}
|
|
85273
|
+
continue;
|
|
85274
|
+
}
|
|
85275
|
+
if (!deliveryState.tryAcquireDelivery(row.chatroomId, role)) {
|
|
85276
|
+
logNativeDeliveryMutexSkip(role, row.chatroomId, row.taskId);
|
|
85277
|
+
continue;
|
|
85278
|
+
}
|
|
85279
|
+
logNativeDeliveryInjecting(role, row.chatroomId, row.taskId);
|
|
85280
|
+
exports_Runtime.runFork(runtime4)(exports_Effect.gen(function* () {
|
|
85281
|
+
const full = yield* exports_Effect.tryPromise(() => sessionDeps.backend.query(api.machines.getAssignedTaskForAction, {
|
|
85282
|
+
sessionId: sessionDeps.sessionId,
|
|
85283
|
+
machineId,
|
|
85284
|
+
taskId: row.taskId,
|
|
85285
|
+
role: row.agentConfig.role
|
|
85286
|
+
}));
|
|
85287
|
+
if (!full) {
|
|
85288
|
+
console.warn(`[NativeDelivery:skip] ${role}@${row.chatroomId} task ${row.taskId} — task_hydrate_missing (deleted or not assigned)`);
|
|
85289
|
+
return;
|
|
85290
|
+
}
|
|
85291
|
+
const harnessSessionId = slot?.harnessSessionId;
|
|
85292
|
+
if (!harnessSessionId) {
|
|
85293
|
+
console.warn(`[NativeDelivery:skip] ${role}@${row.chatroomId} task ${row.taskId} — harness_session_missing (post-gate)`);
|
|
85294
|
+
return;
|
|
85295
|
+
}
|
|
85296
|
+
yield* runNativeInjectionEffect(full, harnessSessionId, {
|
|
85297
|
+
sessionId: sessionDeps.sessionId,
|
|
85298
|
+
machineId: sessionDeps.machineId,
|
|
85299
|
+
backend: sessionDeps.backend,
|
|
85300
|
+
agentMgr: {
|
|
85301
|
+
resumeTurnForSlot: (args2) => exports_Effect.runPromise(agentMgr.resumeTurnForSlot(args2))
|
|
85302
|
+
},
|
|
85303
|
+
convexUrl: sessionDeps.convexUrl,
|
|
85304
|
+
onTaskDelivered: ({ chatroomId, role: role2, taskId }) => {
|
|
85305
|
+
exports_Effect.runSync(agentMgr.setLastInFlightTask(chatroomId, role2, taskId));
|
|
85306
|
+
deliveryState.clearNativeNudgeFailures(chatroomId, role2);
|
|
85307
|
+
}
|
|
85308
|
+
});
|
|
85309
|
+
}).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[NativeTaskDelivery] delivery failed for ${row.agentConfig.role}@${row.chatroomId}: ${getErrorMessage2(err)}`))), exports_Effect.ensuring(exports_Effect.sync(() => deliveryState.releaseDelivery(row.chatroomId, row.agentConfig.role)))));
|
|
85310
|
+
break;
|
|
85311
|
+
}
|
|
85312
|
+
}
|
|
85313
|
+
}
|
|
85314
|
+
function getNativeTaskDeliveryCoordinator() {
|
|
85315
|
+
coordinator ??= new NativeTaskDeliveryCoordinator;
|
|
85316
|
+
return coordinator;
|
|
85317
|
+
}
|
|
85318
|
+
function notifyNativeSessionLost(params) {
|
|
85319
|
+
getNativeTaskDeliveryCoordinator().onSessionLost(params);
|
|
85320
|
+
}
|
|
85321
|
+
function resetRoleDeliveryState(chatroomId, role) {
|
|
85322
|
+
getRoleDeliveryState().resetDeliveryState(chatroomId, role);
|
|
85323
|
+
}
|
|
85324
|
+
function notifyNativeTurnIdle(params) {
|
|
85325
|
+
logNativeDeliveryPrimary(params.role, params.chatroomId);
|
|
85326
|
+
getNativeTaskDeliveryCoordinator().tryInjectNextForRole(params.chatroomId, params.role);
|
|
85327
|
+
}
|
|
85328
|
+
var coordinator;
|
|
85329
|
+
var init_native_task_delivery_coordinator = __esm(() => {
|
|
85330
|
+
init_esm();
|
|
85331
|
+
init_assigned_task_snapshot_store();
|
|
85332
|
+
init_native_task_injector_logic();
|
|
85333
|
+
init_native_task_injector();
|
|
85334
|
+
init_api3();
|
|
85335
|
+
init_convex_error();
|
|
85336
|
+
});
|
|
85337
|
+
|
|
85338
|
+
// src/commands/machine/daemon-start/restart-orchestrator.ts
|
|
85339
|
+
async function emitPhase(deps, event, phase, detail) {
|
|
85340
|
+
await deps.session.backend.mutation(api.machines.emitRestartPhase, {
|
|
85341
|
+
sessionId: deps.session.sessionId,
|
|
85342
|
+
machineId: deps.session.machineId,
|
|
85343
|
+
chatroomId: event.chatroomId,
|
|
85344
|
+
role: event.role,
|
|
85345
|
+
correlationId: event.correlationId,
|
|
85346
|
+
phase,
|
|
85347
|
+
detail
|
|
85348
|
+
});
|
|
85349
|
+
}
|
|
85350
|
+
function sleep5(ms) {
|
|
85351
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
85352
|
+
}
|
|
85353
|
+
async function waitForHarnessSessionId(deps, event, pid) {
|
|
85354
|
+
const initial = deps.agentMgr.getSlot(event.chatroomId, event.role);
|
|
85355
|
+
if (initial?.harnessSessionId) {
|
|
85356
|
+
return initial.harnessSessionId;
|
|
85357
|
+
}
|
|
85358
|
+
await deps.session.backend.mutation(api.machines.emitHarnessSessionAwaiting, {
|
|
85359
|
+
sessionId: deps.session.sessionId,
|
|
85360
|
+
machineId: deps.session.machineId,
|
|
85361
|
+
chatroomId: event.chatroomId,
|
|
85362
|
+
role: event.role,
|
|
85363
|
+
pid,
|
|
85364
|
+
timeoutMs: HARNESS_SESSION_READY_TIMEOUT_MS
|
|
85365
|
+
});
|
|
85366
|
+
const deadline = Date.now() + HARNESS_SESSION_READY_TIMEOUT_MS;
|
|
85367
|
+
while (Date.now() < deadline) {
|
|
85368
|
+
const slot = deps.agentMgr.getSlot(event.chatroomId, event.role);
|
|
85369
|
+
if (slot?.harnessSessionId) {
|
|
85370
|
+
return slot.harnessSessionId;
|
|
85371
|
+
}
|
|
85372
|
+
await sleep5(100);
|
|
85373
|
+
}
|
|
85374
|
+
await deps.session.backend.mutation(api.machines.emitHarnessSessionTimeout, {
|
|
85375
|
+
sessionId: deps.session.sessionId,
|
|
85376
|
+
machineId: deps.session.machineId,
|
|
85377
|
+
chatroomId: event.chatroomId,
|
|
85378
|
+
role: event.role,
|
|
85379
|
+
pid,
|
|
85380
|
+
timeoutMs: HARNESS_SESSION_READY_TIMEOUT_MS
|
|
85381
|
+
});
|
|
85382
|
+
await deps.agentMgr.stop({
|
|
85383
|
+
chatroomId: event.chatroomId,
|
|
85384
|
+
role: event.role,
|
|
85385
|
+
reason: "user.restart",
|
|
85386
|
+
pid
|
|
85387
|
+
});
|
|
85388
|
+
return null;
|
|
85389
|
+
}
|
|
85390
|
+
async function forceNativeWaiting(deps, event) {
|
|
85391
|
+
await deps.session.backend.mutation(api.participants.join, {
|
|
85392
|
+
sessionId: deps.session.sessionId,
|
|
85393
|
+
chatroomId: event.chatroomId,
|
|
85394
|
+
role: event.role,
|
|
85395
|
+
action: NATIVE_WAITING_ACTION
|
|
85396
|
+
});
|
|
85397
|
+
}
|
|
85398
|
+
async function listDeliverableSnapshots(deps, event) {
|
|
85399
|
+
await deps.session.backend.mutation(api.machines.syncMachineAssignedTaskSnapshotsMutation, {
|
|
85400
|
+
sessionId: deps.session.sessionId,
|
|
85401
|
+
machineId: deps.session.machineId
|
|
85402
|
+
});
|
|
85403
|
+
const result = await deps.session.backend.query(api.machines.listMachineAssignedTaskSnapshots, {
|
|
85404
|
+
sessionId: deps.session.sessionId,
|
|
85405
|
+
machineId: deps.session.machineId
|
|
85406
|
+
});
|
|
85407
|
+
const slot = deps.agentMgr.getSlot(event.chatroomId, event.role);
|
|
85408
|
+
return (result.tasks ?? []).filter((t) => t.chatroomId === event.chatroomId && t.agentConfig.role.toLowerCase() === event.role.toLowerCase() && (t.status === "pending" || t.status === "acknowledged") && isAgentReadyForNativeDelivery(t, slot)).sort((a, b) => a.createdAt - b.createdAt);
|
|
85409
|
+
}
|
|
85410
|
+
async function deliverOneTask(deps, event, snapshot) {
|
|
85411
|
+
const slot = deps.agentMgr.getSlot(event.chatroomId, event.role);
|
|
85412
|
+
const harnessSessionId = slot?.harnessSessionId;
|
|
85413
|
+
if (!harnessSessionId)
|
|
85414
|
+
return false;
|
|
85415
|
+
const full = await deps.session.backend.query(api.machines.getAssignedTaskForAction, {
|
|
85416
|
+
sessionId: deps.session.sessionId,
|
|
85417
|
+
machineId: deps.session.machineId,
|
|
85418
|
+
taskId: snapshot.taskId,
|
|
85419
|
+
role: event.role
|
|
85420
|
+
});
|
|
85421
|
+
if (!full)
|
|
85422
|
+
return false;
|
|
85423
|
+
try {
|
|
85424
|
+
await exports_Effect.runPromise(runNativeInjectionEffect(full, harnessSessionId, {
|
|
85425
|
+
sessionId: deps.session.sessionId,
|
|
85426
|
+
machineId: deps.session.machineId,
|
|
85427
|
+
backend: deps.session.backend,
|
|
85428
|
+
convexUrl: deps.session.convexUrl,
|
|
85429
|
+
agentMgr: {
|
|
85430
|
+
resumeTurnForSlot: async (args2) => {
|
|
85431
|
+
await exports_Effect.runPromise(deps.agentMgr.resumeTurnForSlot(args2));
|
|
85432
|
+
}
|
|
85433
|
+
},
|
|
85434
|
+
onTaskDelivered: ({ chatroomId, role, taskId }) => {
|
|
85435
|
+
deps.agentMgr.setLastInFlightTask(chatroomId, role, taskId);
|
|
85436
|
+
}
|
|
85437
|
+
}));
|
|
85438
|
+
return true;
|
|
85439
|
+
} catch (err) {
|
|
85440
|
+
console.warn(`[RestartOrchestrator] deliver failed for task ${snapshot.taskId}: ${getErrorMessage2(err)}`);
|
|
85441
|
+
return false;
|
|
85442
|
+
}
|
|
85443
|
+
}
|
|
85444
|
+
async function deliverPendingTasks(deps, event) {
|
|
85445
|
+
const delivered = [];
|
|
85446
|
+
const snapshots = await listDeliverableSnapshots(deps, event);
|
|
85447
|
+
for (const snapshot of snapshots) {
|
|
85448
|
+
if (snapshot.status !== "pending")
|
|
85449
|
+
continue;
|
|
85450
|
+
const ok = await deliverOneTask(deps, event, snapshot);
|
|
85451
|
+
if (ok) {
|
|
85452
|
+
delivered.push(snapshot.taskId);
|
|
85453
|
+
}
|
|
85454
|
+
}
|
|
85455
|
+
return delivered;
|
|
85456
|
+
}
|
|
85457
|
+
async function runRestartOrchestrator(deps, event) {
|
|
85458
|
+
const { chatroomId, role } = event;
|
|
85459
|
+
try {
|
|
85460
|
+
await emitPhase(deps, event, "reset");
|
|
85461
|
+
resetRoleDeliveryState(chatroomId, role);
|
|
85462
|
+
await deps.agentMgr.stop({
|
|
85463
|
+
chatroomId,
|
|
85464
|
+
role,
|
|
85465
|
+
reason: "user.restart"
|
|
85466
|
+
});
|
|
85467
|
+
await emitPhase(deps, event, "spawn");
|
|
85468
|
+
const spawnResult = await exports_Effect.runPromise(deps.agentMgr.ensureRunning({
|
|
85469
|
+
chatroomId,
|
|
85470
|
+
role,
|
|
85471
|
+
agentHarness: event.agentHarness,
|
|
85472
|
+
model: event.model,
|
|
85473
|
+
workingDir: event.workingDir,
|
|
85474
|
+
reason: "user.restart",
|
|
85475
|
+
wantResume: event.wantResume ?? true
|
|
85476
|
+
}));
|
|
85477
|
+
if (!spawnResult.success || !spawnResult.pid) {
|
|
85478
|
+
await emitPhase(deps, event, "failed", spawnResult.error ?? "spawn failed");
|
|
85479
|
+
return;
|
|
85480
|
+
}
|
|
85481
|
+
await emitPhase(deps, event, "await_session");
|
|
85482
|
+
const harnessSessionId = await waitForHarnessSessionId(deps, event, spawnResult.pid);
|
|
85483
|
+
if (!harnessSessionId) {
|
|
85484
|
+
await emitPhase(deps, event, "failed", "harnessSessionId timeout");
|
|
85485
|
+
return;
|
|
85486
|
+
}
|
|
85487
|
+
await deps.session.backend.mutation(api.machines.emitHarnessSessionReady, {
|
|
85488
|
+
sessionId: deps.session.sessionId,
|
|
85489
|
+
machineId: deps.session.machineId,
|
|
85490
|
+
chatroomId,
|
|
85491
|
+
role,
|
|
85492
|
+
harnessSessionId,
|
|
85493
|
+
pid: spawnResult.pid
|
|
85494
|
+
});
|
|
85495
|
+
await forceNativeWaiting(deps, event);
|
|
85496
|
+
await emitPhase(deps, event, "ready");
|
|
85497
|
+
await emitPhase(deps, event, "deliver");
|
|
85498
|
+
const deliveredTaskIds = await deliverPendingTasks(deps, event);
|
|
85499
|
+
await deps.session.backend.mutation(api.machines.emitRestartCompleted, {
|
|
85500
|
+
sessionId: deps.session.sessionId,
|
|
85501
|
+
machineId: deps.session.machineId,
|
|
85502
|
+
chatroomId,
|
|
85503
|
+
role,
|
|
85504
|
+
correlationId: event.correlationId,
|
|
85505
|
+
deliveredTaskIds
|
|
85506
|
+
});
|
|
85507
|
+
await emitPhase(deps, event, "completed");
|
|
85508
|
+
} catch (err) {
|
|
85509
|
+
console.warn(`[RestartOrchestrator] failed for ${role}@${chatroomId}: ${getErrorMessage2(err)}`);
|
|
85510
|
+
await emitPhase(deps, event, "failed", getErrorMessage2(err));
|
|
85511
|
+
}
|
|
85512
|
+
}
|
|
85513
|
+
var init_restart_orchestrator = __esm(() => {
|
|
85514
|
+
init_reliability();
|
|
85515
|
+
init_participant();
|
|
85516
|
+
init_esm();
|
|
85517
|
+
init_native_ready_invariant();
|
|
85518
|
+
init_native_task_delivery_coordinator();
|
|
85519
|
+
init_native_task_injector();
|
|
85520
|
+
init_api3();
|
|
85521
|
+
init_convex_error();
|
|
85522
|
+
});
|
|
85523
|
+
|
|
85524
|
+
// src/events/daemon/agent/on-request-restart-agent.ts
|
|
85525
|
+
var onRequestRestartAgentEffect = (event) => exports_Effect.gen(function* () {
|
|
85526
|
+
if (Date.now() > event.deadline) {
|
|
85527
|
+
console.log(`[daemon] ⏰ Skipping expired agent.restart for role=${event.role} (deadline passed)`);
|
|
85528
|
+
return;
|
|
85529
|
+
}
|
|
85530
|
+
console.log(`[daemon] Processing agent.restart (correlationId=${event.correlationId}) for role=${event.role}`);
|
|
85531
|
+
const agentMgr = yield* DaemonAgentProcessManagerService;
|
|
85532
|
+
const session2 = yield* DaemonSessionService;
|
|
85533
|
+
yield* exports_Effect.tryPromise(() => runRestartOrchestrator({
|
|
85534
|
+
session: {
|
|
85535
|
+
sessionId: session2.sessionId,
|
|
85536
|
+
machineId: session2.machineId,
|
|
85537
|
+
convexUrl: session2.convexUrl,
|
|
85538
|
+
backend: session2.backend
|
|
85539
|
+
},
|
|
85540
|
+
agentMgr
|
|
85541
|
+
}, {
|
|
85542
|
+
chatroomId: event.chatroomId,
|
|
85543
|
+
role: event.role,
|
|
85544
|
+
agentHarness: event.agentHarness,
|
|
85545
|
+
model: event.model,
|
|
85546
|
+
workingDir: event.workingDir,
|
|
85547
|
+
correlationId: event.correlationId,
|
|
85548
|
+
wantResume: event.wantResume
|
|
85549
|
+
})).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
85550
|
+
});
|
|
85551
|
+
var init_on_request_restart_agent = __esm(() => {
|
|
85552
|
+
init_esm();
|
|
85553
|
+
init_daemon_services();
|
|
85554
|
+
init_restart_orchestrator();
|
|
85555
|
+
});
|
|
85556
|
+
|
|
84734
85557
|
// src/events/daemon/agent/on-request-start-agent.ts
|
|
84735
85558
|
function notifyAgentStartFailed(backend2, opts) {
|
|
84736
85559
|
backend2.mutation(api.machines.emitAgentStartFailed, opts).catch((err) => {
|
|
@@ -85758,7 +86581,7 @@ var init_git = __esm(() => {
|
|
|
85758
86581
|
});
|
|
85759
86582
|
|
|
85760
86583
|
// src/infrastructure/local-actions/execute-local-action.ts
|
|
85761
|
-
import {
|
|
86584
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
85762
86585
|
import { access as access3 } from "node:fs/promises";
|
|
85763
86586
|
function escapeShellArg(arg) {
|
|
85764
86587
|
return `"${arg.replace(/"/g, "\\\"")}"`;
|
|
@@ -85768,17 +86591,18 @@ function resolveWhichCommand(name) {
|
|
|
85768
86591
|
}
|
|
85769
86592
|
function isCliAvailable(cliName) {
|
|
85770
86593
|
return new Promise((resolve4) => {
|
|
85771
|
-
|
|
85772
|
-
|
|
85773
|
-
|
|
86594
|
+
const child = spawn5(resolveWhichCommand(cliName), [], DETACHED_SHELL_SPAWN_OPTIONS);
|
|
86595
|
+
child.on("error", () => resolve4(false));
|
|
86596
|
+
child.on("close", (code2) => resolve4(code2 === 0));
|
|
86597
|
+
child.unref();
|
|
85774
86598
|
});
|
|
85775
86599
|
}
|
|
85776
86600
|
function execFireAndForget(command, logTag) {
|
|
85777
|
-
|
|
85778
|
-
|
|
85779
|
-
|
|
85780
|
-
}
|
|
86601
|
+
const child = spawn5(command, [], DETACHED_SHELL_SPAWN_OPTIONS);
|
|
86602
|
+
child.on("error", (err) => {
|
|
86603
|
+
console.warn(`[${logTag}] spawn failed: ${err.message}`);
|
|
85781
86604
|
});
|
|
86605
|
+
child.unref();
|
|
85782
86606
|
}
|
|
85783
86607
|
function resolveOpenCommand(platform) {
|
|
85784
86608
|
switch (platform) {
|
|
@@ -85869,9 +86693,14 @@ async function executeLocalAction(action, workingDir) {
|
|
|
85869
86693
|
return handler(workingDir);
|
|
85870
86694
|
return { success: false, error: `Unknown action: ${action}` };
|
|
85871
86695
|
}
|
|
85872
|
-
var actionHandlers;
|
|
86696
|
+
var DETACHED_SHELL_SPAWN_OPTIONS, actionHandlers;
|
|
85873
86697
|
var init_execute_local_action = __esm(() => {
|
|
85874
86698
|
init_git();
|
|
86699
|
+
DETACHED_SHELL_SPAWN_OPTIONS = {
|
|
86700
|
+
stdio: "ignore",
|
|
86701
|
+
detached: true,
|
|
86702
|
+
shell: true
|
|
86703
|
+
};
|
|
85875
86704
|
actionHandlers = {
|
|
85876
86705
|
"open-vscode": openVscode,
|
|
85877
86706
|
"open-finder": openFinder,
|
|
@@ -86019,7 +86848,7 @@ function logWaitingForShutdown(pid) {
|
|
|
86019
86848
|
function logDaemonAlreadyRunning(pid) {
|
|
86020
86849
|
console.error(`❌ Daemon already running for ${getConvexUrl()} (PID: ${pid})`);
|
|
86021
86850
|
}
|
|
86022
|
-
async function waitForLockOrTimeout(deadline, intervalMs,
|
|
86851
|
+
async function waitForLockOrTimeout(deadline, intervalMs, sleep6) {
|
|
86023
86852
|
let loggedWait = false;
|
|
86024
86853
|
while (Date.now() < deadline) {
|
|
86025
86854
|
if (tryAcquireLock()) {
|
|
@@ -86030,16 +86859,16 @@ async function waitForLockOrTimeout(deadline, intervalMs, sleep5) {
|
|
|
86030
86859
|
logWaitingForShutdown(pid);
|
|
86031
86860
|
loggedWait = true;
|
|
86032
86861
|
}
|
|
86033
|
-
await
|
|
86862
|
+
await sleep6(intervalMs);
|
|
86034
86863
|
}
|
|
86035
86864
|
return false;
|
|
86036
86865
|
}
|
|
86037
86866
|
async function acquireLockWithRetry(options) {
|
|
86038
86867
|
const intervalMs = options?.intervalMs ?? LOCK_RETRY_INTERVAL_MS;
|
|
86039
86868
|
const maxWaitMs = options?.maxWaitMs ?? LOCK_RETRY_MAX_WAIT_MS;
|
|
86040
|
-
const
|
|
86869
|
+
const sleep6 = options?.sleep ?? ((ms) => new Promise((resolve4) => setTimeout(resolve4, ms)));
|
|
86041
86870
|
const deadline = Date.now() + maxWaitMs;
|
|
86042
|
-
if (await waitForLockOrTimeout(deadline, intervalMs,
|
|
86871
|
+
if (await waitForLockOrTimeout(deadline, intervalMs, sleep6)) {
|
|
86043
86872
|
return true;
|
|
86044
86873
|
}
|
|
86045
86874
|
const { pid } = isDaemonRunning();
|
|
@@ -86890,7 +87719,7 @@ var init_opencode_session = __esm(() => {
|
|
|
86890
87719
|
});
|
|
86891
87720
|
|
|
86892
87721
|
// src/infrastructure/harnesses/opencode-sdk/opencode-harness.ts
|
|
86893
|
-
import { spawn as
|
|
87722
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
86894
87723
|
function harnessEventSessionId(event) {
|
|
86895
87724
|
const p = event.properties;
|
|
86896
87725
|
if (!p)
|
|
@@ -87164,7 +87993,7 @@ class OpencodeSdkHarness {
|
|
|
87164
87993
|
}
|
|
87165
87994
|
}
|
|
87166
87995
|
var OPENCODE_COMMAND3 = "opencode", SERVE_STARTUP_TIMEOUT_MS2 = 1e4, startOpencodeSdkHarness = async (config3) => {
|
|
87167
|
-
const childProcess =
|
|
87996
|
+
const childProcess = spawn6(OPENCODE_COMMAND3, ["serve", "--print-logs", "--log-level", "WARN"], {
|
|
87168
87997
|
cwd: config3.workingDir,
|
|
87169
87998
|
stdio: ["pipe", "pipe", "pipe"],
|
|
87170
87999
|
shell: false,
|
|
@@ -88955,9 +89784,9 @@ var init_file_content_fulfillment = __esm(() => {
|
|
|
88955
89784
|
for (const request2 of requests) {
|
|
88956
89785
|
const startTime = Date.now();
|
|
88957
89786
|
const { workingDir, filePath } = request2;
|
|
88958
|
-
const
|
|
88959
|
-
if (!
|
|
88960
|
-
console.warn(`[${formatTimestamp()}] ⚠️ Rejected unregistered workspace: ${workingDir} (${
|
|
89787
|
+
const registered2 = yield* exports_Effect.catchAll(exports_Effect.tryPromise(() => assertRegisteredWorkingDir(session2, workingDir)), () => exports_Effect.succeed({ ok: false, error: "Workspace check failed" }));
|
|
89788
|
+
if (!registered2.ok) {
|
|
89789
|
+
console.warn(`[${formatTimestamp()}] ⚠️ Rejected unregistered workspace: ${workingDir} (${registered2.error})`);
|
|
88961
89790
|
yield* fulfillGzippedContentEffect(session2, workingDir, filePath, "[Error: workspace not registered]", false);
|
|
88962
89791
|
continue;
|
|
88963
89792
|
}
|
|
@@ -91795,17 +92624,17 @@ var startFileTreeSubscriptionEffect = (wsClient2) => exports_Effect.gen(function
|
|
|
91795
92624
|
});
|
|
91796
92625
|
coordinators.set(normalized, coordinatorPromise);
|
|
91797
92626
|
}
|
|
91798
|
-
return coordinatorPromise.then(async (
|
|
92627
|
+
return coordinatorPromise.then(async (coordinator2) => {
|
|
91799
92628
|
const checkpoint = await session2.backend.query(api.workspaceFiles.getFileTreeCheckpoint, {
|
|
91800
92629
|
sessionId: session2.sessionId,
|
|
91801
92630
|
machineId: session2.machineId,
|
|
91802
92631
|
workingDir: normalized
|
|
91803
92632
|
});
|
|
91804
92633
|
if (checkpoint === null)
|
|
91805
|
-
await
|
|
92634
|
+
await coordinator2.checkpoint();
|
|
91806
92635
|
if (forceReconcile)
|
|
91807
|
-
await
|
|
91808
|
-
return
|
|
92636
|
+
await coordinator2.reconcile();
|
|
92637
|
+
return coordinator2;
|
|
91809
92638
|
});
|
|
91810
92639
|
};
|
|
91811
92640
|
const unsubscribe = wsClient2.onUpdate(api.workspaceFiles.getPendingFileTreeRequests, { sessionId: session2.sessionId, machineId: session2.machineId }, (requests) => {
|
|
@@ -91835,7 +92664,7 @@ var startFileTreeSubscriptionEffect = (wsClient2) => exports_Effect.gen(function
|
|
|
91835
92664
|
return {
|
|
91836
92665
|
stop: () => {
|
|
91837
92666
|
unsubscribe();
|
|
91838
|
-
Promise.all([...coordinators.values()].map((
|
|
92667
|
+
Promise.all([...coordinators.values()].map((coordinator2) => coordinator2.then((handle) => handle.stop()).catch(() => {
|
|
91839
92668
|
return;
|
|
91840
92669
|
})));
|
|
91841
92670
|
coordinators.clear();
|
|
@@ -91920,11 +92749,11 @@ async function writePayloadToDisk(absolutePath, operation, content) {
|
|
|
91920
92749
|
async function fulfillOneFileWriteRequest(session2, request2) {
|
|
91921
92750
|
const startTime = Date.now();
|
|
91922
92751
|
const { workingDir, filePath, operation } = request2;
|
|
91923
|
-
const
|
|
91924
|
-
if (!
|
|
92752
|
+
const registered2 = await assertRegisteredWorkingDir(session2, workingDir);
|
|
92753
|
+
if (!registered2.ok) {
|
|
91925
92754
|
await completeWriteRequest(session2, request2._id, {
|
|
91926
92755
|
status: "error",
|
|
91927
|
-
errorMessage:
|
|
92756
|
+
errorMessage: registered2.error
|
|
91928
92757
|
});
|
|
91929
92758
|
return;
|
|
91930
92759
|
}
|
|
@@ -93095,21 +93924,6 @@ var init_crash_loop_tracker = __esm(() => {
|
|
|
93095
93924
|
];
|
|
93096
93925
|
});
|
|
93097
93926
|
|
|
93098
|
-
// ../../services/backend/src/domain/entities/participant.ts
|
|
93099
|
-
var PARTICIPANT_EXITED_ACTION = "exited", NATIVE_WAITING_ACTION = "native:waiting", NATIVE_TASK_INJECTED_ACTION = "native:task-injected", NATIVE_HANDOFF_REMINDER = "Reminder: Use the handoff command to send your response to the team.", ONLINE_OR_STARTING_STATUSES;
|
|
93100
|
-
var init_participant = __esm(() => {
|
|
93101
|
-
ONLINE_OR_STARTING_STATUSES = new Set([
|
|
93102
|
-
"agent.waiting",
|
|
93103
|
-
"agent.requestStart",
|
|
93104
|
-
"agent.started",
|
|
93105
|
-
"task.acknowledged",
|
|
93106
|
-
"task.inProgress",
|
|
93107
|
-
"task.completed",
|
|
93108
|
-
"agent.requestStop",
|
|
93109
|
-
"agent.awaitingHandoff"
|
|
93110
|
-
]);
|
|
93111
|
-
});
|
|
93112
|
-
|
|
93113
93927
|
// src/infrastructure/services/agent-process-manager/turn-completed-backend.ts
|
|
93114
93928
|
function createTurnCompletedBackend(deps) {
|
|
93115
93929
|
return {
|
|
@@ -93142,386 +93956,6 @@ class TurnEndQueue {
|
|
|
93142
93956
|
}
|
|
93143
93957
|
}
|
|
93144
93958
|
|
|
93145
|
-
// src/commands/machine/daemon-start/native-delivery-ledger.ts
|
|
93146
|
-
class NativeDeliveryLedger {
|
|
93147
|
-
delivered = new Set;
|
|
93148
|
-
inFlight = new Set;
|
|
93149
|
-
deliveryKey(taskId, harnessSessionId) {
|
|
93150
|
-
return `${taskId}\x00${harnessSessionId}`;
|
|
93151
|
-
}
|
|
93152
|
-
isDelivered(taskId, harnessSessionId) {
|
|
93153
|
-
return this.delivered.has(this.deliveryKey(taskId, harnessSessionId));
|
|
93154
|
-
}
|
|
93155
|
-
tryAcquire(taskId, harnessSessionId) {
|
|
93156
|
-
const key = this.deliveryKey(taskId, harnessSessionId);
|
|
93157
|
-
if (this.delivered.has(key) || this.inFlight.has(key)) {
|
|
93158
|
-
return false;
|
|
93159
|
-
}
|
|
93160
|
-
this.inFlight.add(key);
|
|
93161
|
-
return true;
|
|
93162
|
-
}
|
|
93163
|
-
markDelivered(taskId, harnessSessionId) {
|
|
93164
|
-
const key = this.deliveryKey(taskId, harnessSessionId);
|
|
93165
|
-
this.inFlight.delete(key);
|
|
93166
|
-
this.delivered.add(key);
|
|
93167
|
-
}
|
|
93168
|
-
clearDelivery(taskId, harnessSessionId) {
|
|
93169
|
-
const key = this.deliveryKey(taskId, harnessSessionId);
|
|
93170
|
-
this.inFlight.delete(key);
|
|
93171
|
-
this.delivered.delete(key);
|
|
93172
|
-
}
|
|
93173
|
-
clearSession(harnessSessionId) {
|
|
93174
|
-
const suffix = `\x00${harnessSessionId}`;
|
|
93175
|
-
for (const key of [...this.delivered, ...this.inFlight]) {
|
|
93176
|
-
if (key.endsWith(suffix)) {
|
|
93177
|
-
this.delivered.delete(key);
|
|
93178
|
-
this.inFlight.delete(key);
|
|
93179
|
-
}
|
|
93180
|
-
}
|
|
93181
|
-
}
|
|
93182
|
-
}
|
|
93183
|
-
|
|
93184
|
-
// src/domain/native-integration/predicates.ts
|
|
93185
|
-
function isNativeInjectableAliveRunning(task) {
|
|
93186
|
-
const { agentConfig, status: status3 } = task;
|
|
93187
|
-
if (!isNativeHarness(agentConfig.agentHarness))
|
|
93188
|
-
return false;
|
|
93189
|
-
if (agentConfig.spawnedAgentPid == null || agentConfig.desiredState !== "running") {
|
|
93190
|
-
return false;
|
|
93191
|
-
}
|
|
93192
|
-
if (status3 === "pending")
|
|
93193
|
-
return true;
|
|
93194
|
-
if (status3 === "acknowledged") {
|
|
93195
|
-
const assignedTo = task.assignedTo?.toLowerCase();
|
|
93196
|
-
return assignedTo === agentConfig.role.toLowerCase();
|
|
93197
|
-
}
|
|
93198
|
-
return false;
|
|
93199
|
-
}
|
|
93200
|
-
function isInjectableNativeAction(action) {
|
|
93201
|
-
if (action == null)
|
|
93202
|
-
return true;
|
|
93203
|
-
return action === NATIVE_WAITING_ACTION || action === PARTICIPANT_EXITED_ACTION;
|
|
93204
|
-
}
|
|
93205
|
-
function isNativePendingRedeliveryAfterRelease(task) {
|
|
93206
|
-
return task.status === "pending" && task.participant?.lastSeenAction === NATIVE_TASK_INJECTED_ACTION;
|
|
93207
|
-
}
|
|
93208
|
-
function isNativeIdleAfterTaskComplete(participant) {
|
|
93209
|
-
return participant.lastSeenAction === NATIVE_TASK_INJECTED_ACTION && participant.lastStatus === "task.completed";
|
|
93210
|
-
}
|
|
93211
|
-
function isNativeAcknowledgedInjectionRetry(task) {
|
|
93212
|
-
if (task.status !== "acknowledged")
|
|
93213
|
-
return false;
|
|
93214
|
-
const assignedTo = task.assignedTo?.toLowerCase();
|
|
93215
|
-
if (assignedTo !== task.agentConfig.role.toLowerCase())
|
|
93216
|
-
return false;
|
|
93217
|
-
return task.participant?.lastSeenAction === NATIVE_TASK_INJECTED_ACTION;
|
|
93218
|
-
}
|
|
93219
|
-
function isStaleCliGetNextTaskWaiting(task) {
|
|
93220
|
-
const lastSeenAt = task.participant?.lastSeenAt ?? 0;
|
|
93221
|
-
return task.participant?.lastSeenAction === "get-next-task:started" && task.createdAt > lastSeenAt;
|
|
93222
|
-
}
|
|
93223
|
-
function isCliIdleNotListening(task, now, thresholdMs) {
|
|
93224
|
-
const lastSeenAt = task.participant?.lastSeenAt ?? 0;
|
|
93225
|
-
if (lastSeenAt === 0)
|
|
93226
|
-
return now - task.createdAt > thresholdMs;
|
|
93227
|
-
return now - lastSeenAt > thresholdMs;
|
|
93228
|
-
}
|
|
93229
|
-
var init_predicates = __esm(() => {
|
|
93230
|
-
init_types();
|
|
93231
|
-
init_participant();
|
|
93232
|
-
});
|
|
93233
|
-
|
|
93234
|
-
// src/infrastructure/services/remote-agents/spawn-prompt.ts
|
|
93235
|
-
function createSpawnPrompt(raw, opts) {
|
|
93236
|
-
if (opts?.nativeBootstrap) {
|
|
93237
|
-
return NATIVE_BOOTSTRAP_PROMPT;
|
|
93238
|
-
}
|
|
93239
|
-
const trimmed = raw?.trim();
|
|
93240
|
-
return trimmed && trimmed.length > 0 ? trimmed : DEFAULT_TRIGGER_PROMPT;
|
|
93241
|
-
}
|
|
93242
|
-
var DEFAULT_TRIGGER_PROMPT = "Please read your system prompt carefully and follow the Getting Started instructions.", NATIVE_BOOTSTRAP_PROMPT = "Focus on your role responsibilities. Complete each task via handoff.";
|
|
93243
|
-
|
|
93244
|
-
// src/domain/native-integration/spawn-policy.ts
|
|
93245
|
-
function shouldDeferInitialTurn(harness) {
|
|
93246
|
-
return isNativeHarness(harness);
|
|
93247
|
-
}
|
|
93248
|
-
function resolveNativeSpawnPolicy(harness, initMessage) {
|
|
93249
|
-
const deferInitialTurn = shouldDeferInitialTurn(harness);
|
|
93250
|
-
return {
|
|
93251
|
-
deferInitialTurn,
|
|
93252
|
-
prompt: createSpawnPrompt(initMessage, { nativeBootstrap: deferInitialTurn })
|
|
93253
|
-
};
|
|
93254
|
-
}
|
|
93255
|
-
var init_spawn_policy = __esm(() => {
|
|
93256
|
-
init_types();
|
|
93257
|
-
});
|
|
93258
|
-
|
|
93259
|
-
// src/domain/native-integration/index.ts
|
|
93260
|
-
var init_native_integration = __esm(() => {
|
|
93261
|
-
init_types();
|
|
93262
|
-
init_predicates();
|
|
93263
|
-
init_spawn_policy();
|
|
93264
|
-
});
|
|
93265
|
-
|
|
93266
|
-
// src/commands/machine/daemon-start/native-task-injector-logic.ts
|
|
93267
|
-
function shouldDeliverNativeTask(task, opts) {
|
|
93268
|
-
if (!isNativeInjectableAliveRunning(task))
|
|
93269
|
-
return false;
|
|
93270
|
-
if (!opts.harnessSessionId)
|
|
93271
|
-
return false;
|
|
93272
|
-
if (opts.ledger.isDelivered(task.taskId, opts.harnessSessionId) && task.status !== "pending") {
|
|
93273
|
-
return false;
|
|
93274
|
-
}
|
|
93275
|
-
return isInjectableNativeAction(task.participant?.lastSeenAction) || isNativeIdleAfterTaskComplete(task.participant ?? {}) || isNativeAcknowledgedInjectionRetry(task) || isNativePendingRedeliveryAfterRelease(task);
|
|
93276
|
-
}
|
|
93277
|
-
function buildNativeInjectionPrompt(params) {
|
|
93278
|
-
const { taskDeliveryOutput, augmentationMode } = params;
|
|
93279
|
-
if (augmentationMode === "compact") {
|
|
93280
|
-
return [
|
|
93281
|
-
"⚠️ Context was compacted. Run `chatroom get-system-prompt` only if role instructions are missing.",
|
|
93282
|
-
"",
|
|
93283
|
-
taskDeliveryOutput
|
|
93284
|
-
].join(`
|
|
93285
|
-
`);
|
|
93286
|
-
}
|
|
93287
|
-
if (augmentationMode === "new_session") {
|
|
93288
|
-
return [
|
|
93289
|
-
"⚠️ Starting a new agent session. Run `chatroom get-system-prompt` to reload role instructions if needed.",
|
|
93290
|
-
"",
|
|
93291
|
-
taskDeliveryOutput
|
|
93292
|
-
].join(`
|
|
93293
|
-
`);
|
|
93294
|
-
}
|
|
93295
|
-
return taskDeliveryOutput;
|
|
93296
|
-
}
|
|
93297
|
-
var init_native_task_injector_logic = __esm(() => {
|
|
93298
|
-
init_predicates();
|
|
93299
|
-
init_native_integration();
|
|
93300
|
-
});
|
|
93301
|
-
|
|
93302
|
-
// ../../services/backend/src/domain/entities/team-agent-settings.ts
|
|
93303
|
-
function roleSupportsSessionAugmentation(role) {
|
|
93304
|
-
const normalized = role.toLowerCase();
|
|
93305
|
-
return SESSION_AUGMENTATION_ROLES.some((r) => r === normalized);
|
|
93306
|
-
}
|
|
93307
|
-
var SESSION_AUGMENTATION_ROLES;
|
|
93308
|
-
var init_team_agent_settings = __esm(() => {
|
|
93309
|
-
SESSION_AUGMENTATION_ROLES = ["builder"];
|
|
93310
|
-
});
|
|
93311
|
-
|
|
93312
|
-
// ../../services/backend/src/domain/handoff/parse-session-augmentation.ts
|
|
93313
|
-
function findSectionIndex(content, headings) {
|
|
93314
|
-
const indices = headings.map((heading) => content.indexOf(heading)).filter((idx) => idx !== -1);
|
|
93315
|
-
return indices.length === 0 ? -1 : Math.min(...indices);
|
|
93316
|
-
}
|
|
93317
|
-
function normalizeMode(raw) {
|
|
93318
|
-
return MODE_ALIASES[raw.toLowerCase()] ?? DEFAULT_MODE;
|
|
93319
|
-
}
|
|
93320
|
-
function extractSectionBody(content, sectionIdx) {
|
|
93321
|
-
const matchedHeading = SECTION_HEADINGS.find((h) => content.indexOf(h, sectionIdx) === sectionIdx) ?? SECTION_HEADINGS[0];
|
|
93322
|
-
const afterSection = content.slice(sectionIdx);
|
|
93323
|
-
const nextHeading = afterSection.slice(matchedHeading.length).search(/\n## /);
|
|
93324
|
-
return nextHeading === -1 ? afterSection : afterSection.slice(0, matchedHeading.length + nextHeading);
|
|
93325
|
-
}
|
|
93326
|
-
function parseSessionAugmentation(handoffContent) {
|
|
93327
|
-
const sectionIdx = findSectionIndex(handoffContent, SECTION_HEADINGS);
|
|
93328
|
-
if (sectionIdx === -1)
|
|
93329
|
-
return DEFAULT_MODE;
|
|
93330
|
-
const match17 = extractSectionBody(handoffContent, sectionIdx).match(DATA_TAG);
|
|
93331
|
-
if (!match17)
|
|
93332
|
-
return DEFAULT_MODE;
|
|
93333
|
-
return normalizeMode(match17[1]);
|
|
93334
|
-
}
|
|
93335
|
-
function resolveSessionAugmentationForRole(handoffContent, role) {
|
|
93336
|
-
if (!roleSupportsSessionAugmentation(role)) {
|
|
93337
|
-
return "none";
|
|
93338
|
-
}
|
|
93339
|
-
return parseSessionAugmentation(handoffContent);
|
|
93340
|
-
}
|
|
93341
|
-
function sessionAugmentationToWantResume(mode) {
|
|
93342
|
-
return mode === "none" || mode === "compact";
|
|
93343
|
-
}
|
|
93344
|
-
function sessionAugmentationNewSessionStarted(mode) {
|
|
93345
|
-
return mode === "new_session";
|
|
93346
|
-
}
|
|
93347
|
-
var SECTION_HEADINGS, DATA_TAG, DEFAULT_MODE = "new_session", MODE_ALIASES;
|
|
93348
|
-
var init_parse_session_augmentation = __esm(() => {
|
|
93349
|
-
init_team_agent_settings();
|
|
93350
|
-
SECTION_HEADINGS = [
|
|
93351
|
-
"## Session Augmentation",
|
|
93352
|
-
"## Session Management",
|
|
93353
|
-
"## Restart new context"
|
|
93354
|
-
];
|
|
93355
|
-
DATA_TAG = /\/\/\s*data:agent\.(?:session_augmentation|compress_context)=(none|compact|new_session|reset)\b/i;
|
|
93356
|
-
MODE_ALIASES = {
|
|
93357
|
-
reset: "new_session",
|
|
93358
|
-
none: "none",
|
|
93359
|
-
compact: "compact",
|
|
93360
|
-
new_session: "new_session"
|
|
93361
|
-
};
|
|
93362
|
-
});
|
|
93363
|
-
|
|
93364
|
-
// src/commands/machine/daemon-start/native-task-injector.ts
|
|
93365
|
-
function runNativeInjectionEffect(task, harnessSessionId, deps, ledger) {
|
|
93366
|
-
return exports_Effect.gen(function* () {
|
|
93367
|
-
if (!shouldDeliverNativeTask(task, { ledger, harnessSessionId })) {
|
|
93368
|
-
return;
|
|
93369
|
-
}
|
|
93370
|
-
const { chatroomId, taskId, taskContent, agentConfig, status: status3 } = task;
|
|
93371
|
-
const { role } = agentConfig;
|
|
93372
|
-
if (!ledger.tryAcquire(taskId, harnessSessionId)) {
|
|
93373
|
-
return;
|
|
93374
|
-
}
|
|
93375
|
-
if (status3 === "pending") {
|
|
93376
|
-
const claimResult = yield* exports_Effect.tryPromise({
|
|
93377
|
-
try: () => deps.backend.mutation(api.tasks.claimTask, {
|
|
93378
|
-
sessionId: deps.sessionId,
|
|
93379
|
-
chatroomId,
|
|
93380
|
-
role,
|
|
93381
|
-
taskId
|
|
93382
|
-
}),
|
|
93383
|
-
catch: (err) => err
|
|
93384
|
-
}).pipe(exports_Effect.either);
|
|
93385
|
-
if (claimResult._tag === "Left") {
|
|
93386
|
-
ledger.clearDelivery(taskId, harnessSessionId);
|
|
93387
|
-
return yield* exports_Effect.fail(claimResult.left);
|
|
93388
|
-
}
|
|
93389
|
-
}
|
|
93390
|
-
const deliveryResult = yield* exports_Effect.tryPromise({
|
|
93391
|
-
try: () => deps.backend.query(api.messages.getTaskDeliveryPrompt, {
|
|
93392
|
-
sessionId: deps.sessionId,
|
|
93393
|
-
chatroomId,
|
|
93394
|
-
role,
|
|
93395
|
-
taskId,
|
|
93396
|
-
convexUrl: deps.convexUrl
|
|
93397
|
-
}),
|
|
93398
|
-
catch: (err) => err
|
|
93399
|
-
}).pipe(exports_Effect.either);
|
|
93400
|
-
if (deliveryResult._tag === "Left") {
|
|
93401
|
-
ledger.clearDelivery(taskId, harnessSessionId);
|
|
93402
|
-
return yield* exports_Effect.fail(deliveryResult.left);
|
|
93403
|
-
}
|
|
93404
|
-
const delivery = deliveryResult.right;
|
|
93405
|
-
const augmentationMode = resolveSessionAugmentationForRole(taskContent, role);
|
|
93406
|
-
const prompt = buildNativeInjectionPrompt({
|
|
93407
|
-
taskDeliveryOutput: delivery.fullCliOutput,
|
|
93408
|
-
augmentationMode
|
|
93409
|
-
});
|
|
93410
|
-
yield* exports_Effect.tryPromise({
|
|
93411
|
-
try: () => deps.backend.mutation(api.participants.join, {
|
|
93412
|
-
sessionId: deps.sessionId,
|
|
93413
|
-
chatroomId,
|
|
93414
|
-
role,
|
|
93415
|
-
action: NATIVE_TASK_INJECTED_ACTION,
|
|
93416
|
-
taskId
|
|
93417
|
-
}),
|
|
93418
|
-
catch: (err) => err
|
|
93419
|
-
}).pipe(exports_Effect.tapError(() => exports_Effect.sync(() => ledger.clearDelivery(taskId, harnessSessionId))));
|
|
93420
|
-
if (roleSupportsSessionAugmentation(role)) {
|
|
93421
|
-
yield* exports_Effect.tryPromise({
|
|
93422
|
-
try: () => deps.backend.mutation(api.machines.emitSessionAugmented, {
|
|
93423
|
-
sessionId: deps.sessionId,
|
|
93424
|
-
machineId: deps.machineId,
|
|
93425
|
-
chatroomId,
|
|
93426
|
-
role,
|
|
93427
|
-
taskId,
|
|
93428
|
-
mode: augmentationMode,
|
|
93429
|
-
newSessionStarted: sessionAugmentationNewSessionStarted(augmentationMode),
|
|
93430
|
-
harnessSessionId
|
|
93431
|
-
}),
|
|
93432
|
-
catch: (err) => err
|
|
93433
|
-
}).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
93434
|
-
}
|
|
93435
|
-
const resumeResult = yield* exports_Effect.tryPromise({
|
|
93436
|
-
try: () => deps.agentMgr.resumeTurnForSlot({ chatroomId, role, prompt }),
|
|
93437
|
-
catch: (err) => err
|
|
93438
|
-
}).pipe(exports_Effect.either);
|
|
93439
|
-
if (resumeResult._tag === "Left") {
|
|
93440
|
-
ledger.clearDelivery(taskId, harnessSessionId);
|
|
93441
|
-
console.warn(`[NativeTaskInjector] resumeTurn failed for ${role}@${chatroomId}: ${getErrorMessage2(resumeResult.left)}`);
|
|
93442
|
-
return;
|
|
93443
|
-
}
|
|
93444
|
-
ledger.markDelivered(taskId, harnessSessionId);
|
|
93445
|
-
deps.onTaskDelivered?.({ chatroomId, role, taskId });
|
|
93446
|
-
});
|
|
93447
|
-
}
|
|
93448
|
-
var init_native_task_injector = __esm(() => {
|
|
93449
|
-
init_participant();
|
|
93450
|
-
init_team_agent_settings();
|
|
93451
|
-
init_parse_session_augmentation();
|
|
93452
|
-
init_esm();
|
|
93453
|
-
init_native_task_injector_logic();
|
|
93454
|
-
init_api3();
|
|
93455
|
-
init_convex_error();
|
|
93456
|
-
});
|
|
93457
|
-
|
|
93458
|
-
// src/commands/machine/daemon-start/native-task-delivery-coordinator.ts
|
|
93459
|
-
class NativeTaskDeliveryCoordinator {
|
|
93460
|
-
ledger;
|
|
93461
|
-
constructor(ledger = new NativeDeliveryLedger) {
|
|
93462
|
-
this.ledger = ledger;
|
|
93463
|
-
}
|
|
93464
|
-
onSessionLost(params) {
|
|
93465
|
-
if (params.harnessSessionId) {
|
|
93466
|
-
this.ledger.clearSession(params.harnessSessionId);
|
|
93467
|
-
}
|
|
93468
|
-
}
|
|
93469
|
-
reconcileAssignedTasks(params) {
|
|
93470
|
-
const { tasks, runtime: runtime4, effectContext: effectContext2, agentMgr, sessionDeps, machineId } = params;
|
|
93471
|
-
const ledger = this.ledger;
|
|
93472
|
-
for (const row of tasks) {
|
|
93473
|
-
const slot = agentMgr.getSlot(row.chatroomId, row.agentConfig.role);
|
|
93474
|
-
const harnessSessionId = slot?.harnessSessionId;
|
|
93475
|
-
if (!shouldDeliverNativeTask(row, {
|
|
93476
|
-
ledger,
|
|
93477
|
-
harnessSessionId
|
|
93478
|
-
})) {
|
|
93479
|
-
continue;
|
|
93480
|
-
}
|
|
93481
|
-
if (!harnessSessionId) {
|
|
93482
|
-
continue;
|
|
93483
|
-
}
|
|
93484
|
-
exports_Runtime.runFork(runtime4)(exports_Effect.gen(function* () {
|
|
93485
|
-
const full = yield* exports_Effect.tryPromise(() => sessionDeps.backend.query(api.machines.getAssignedTaskForAction, {
|
|
93486
|
-
sessionId: sessionDeps.sessionId,
|
|
93487
|
-
machineId,
|
|
93488
|
-
taskId: row.taskId,
|
|
93489
|
-
role: row.agentConfig.role
|
|
93490
|
-
}));
|
|
93491
|
-
if (!full)
|
|
93492
|
-
return;
|
|
93493
|
-
yield* runNativeInjectionEffect(full, harnessSessionId, {
|
|
93494
|
-
sessionId: sessionDeps.sessionId,
|
|
93495
|
-
machineId: sessionDeps.machineId,
|
|
93496
|
-
backend: sessionDeps.backend,
|
|
93497
|
-
agentMgr: {
|
|
93498
|
-
resumeTurnForSlot: (args2) => exports_Effect.runPromise(agentMgr.resumeTurnForSlot(args2))
|
|
93499
|
-
},
|
|
93500
|
-
convexUrl: sessionDeps.convexUrl,
|
|
93501
|
-
onTaskDelivered: ({ chatroomId, role, taskId }) => {
|
|
93502
|
-
exports_Effect.runSync(agentMgr.setLastInFlightTask(chatroomId, role, taskId));
|
|
93503
|
-
}
|
|
93504
|
-
}, ledger);
|
|
93505
|
-
}).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[NativeTaskDelivery] delivery failed for ${row.agentConfig.role}@${row.chatroomId}: ${getErrorMessage2(err)}`)))));
|
|
93506
|
-
}
|
|
93507
|
-
}
|
|
93508
|
-
}
|
|
93509
|
-
function getNativeTaskDeliveryCoordinator() {
|
|
93510
|
-
coordinator ??= new NativeTaskDeliveryCoordinator;
|
|
93511
|
-
return coordinator;
|
|
93512
|
-
}
|
|
93513
|
-
function notifyNativeSessionLost(params) {
|
|
93514
|
-
getNativeTaskDeliveryCoordinator().onSessionLost(params);
|
|
93515
|
-
}
|
|
93516
|
-
var coordinator;
|
|
93517
|
-
var init_native_task_delivery_coordinator = __esm(() => {
|
|
93518
|
-
init_esm();
|
|
93519
|
-
init_native_task_injector_logic();
|
|
93520
|
-
init_native_task_injector();
|
|
93521
|
-
init_api3();
|
|
93522
|
-
init_convex_error();
|
|
93523
|
-
});
|
|
93524
|
-
|
|
93525
93959
|
// src/domain/agent-lifecycle/resolve-resumable-harness-session-id.ts
|
|
93526
93960
|
function resolveResumableHarnessSessionId(snapshot) {
|
|
93527
93961
|
return snapshot.resumableHarnessSessionId ?? snapshot.harnessSessionId;
|
|
@@ -93726,6 +94160,14 @@ var init_native_harness_session_exit = __esm(() => {
|
|
|
93726
94160
|
init_agent_lifecycle();
|
|
93727
94161
|
});
|
|
93728
94162
|
|
|
94163
|
+
// src/commands/machine/daemon-start/native-turn-phase.ts
|
|
94164
|
+
function defaultNativeTurnPhase() {
|
|
94165
|
+
return "idle";
|
|
94166
|
+
}
|
|
94167
|
+
function setNativeTurnPhase(slot, phase) {
|
|
94168
|
+
slot.nativeTurnPhase = phase;
|
|
94169
|
+
}
|
|
94170
|
+
|
|
93729
94171
|
// src/domain/agent-lifecycle/policies/classify-resume-storm-reason.ts
|
|
93730
94172
|
function classifyResumeStormReason(logLines) {
|
|
93731
94173
|
const blob = logLines.join(`
|
|
@@ -94284,6 +94726,7 @@ class AgentProcessManager {
|
|
|
94284
94726
|
slot.startedAt = undefined;
|
|
94285
94727
|
slot.pendingOperation = undefined;
|
|
94286
94728
|
slot.stoppingSince = undefined;
|
|
94729
|
+
slot.nativeTurnPhase = undefined;
|
|
94287
94730
|
}
|
|
94288
94731
|
bumpStopGeneration(slot) {
|
|
94289
94732
|
slot.stopGeneration = (slot.stopGeneration ?? 0) + 1;
|
|
@@ -94319,7 +94762,14 @@ class AgentProcessManager {
|
|
|
94319
94762
|
if (!service3?.resumeTurn) {
|
|
94320
94763
|
throw new Error(`Harness ${slot.harness} does not support resumeTurn`);
|
|
94321
94764
|
}
|
|
94322
|
-
|
|
94765
|
+
setNativeTurnPhase(slot, "injecting");
|
|
94766
|
+
try {
|
|
94767
|
+
await service3.resumeTurn(slot.pid, args2.prompt);
|
|
94768
|
+
setNativeTurnPhase(slot, "turn_in_flight");
|
|
94769
|
+
} catch (err) {
|
|
94770
|
+
setNativeTurnPhase(slot, defaultNativeTurnPhase());
|
|
94771
|
+
throw err;
|
|
94772
|
+
}
|
|
94323
94773
|
}
|
|
94324
94774
|
async injectHarnessReminder(chatroomId, role, prompt) {
|
|
94325
94775
|
const key = agentKey3(chatroomId, role);
|
|
@@ -94329,7 +94779,13 @@ class AgentProcessManager {
|
|
|
94329
94779
|
const service3 = this.deps.agentServices.get(slot.harness);
|
|
94330
94780
|
if (!service3?.resumeTurn)
|
|
94331
94781
|
return;
|
|
94332
|
-
|
|
94782
|
+
setNativeTurnPhase(slot, "injecting");
|
|
94783
|
+
try {
|
|
94784
|
+
await service3.resumeTurn(slot.pid, prompt);
|
|
94785
|
+
setNativeTurnPhase(slot, "turn_in_flight");
|
|
94786
|
+
} catch {
|
|
94787
|
+
setNativeTurnPhase(slot, defaultNativeTurnPhase());
|
|
94788
|
+
}
|
|
94333
94789
|
}
|
|
94334
94790
|
async stop(opts) {
|
|
94335
94791
|
const key = agentKey3(opts.chatroomId, opts.role);
|
|
@@ -94457,6 +94913,10 @@ class AgentProcessManager {
|
|
|
94457
94913
|
console.log(`[AgentProcessManager] ⏩ Handoff reminder injected for ${opts.role}`);
|
|
94458
94914
|
return;
|
|
94459
94915
|
}
|
|
94916
|
+
if (slot) {
|
|
94917
|
+
setNativeTurnPhase(slot, defaultNativeTurnPhase());
|
|
94918
|
+
}
|
|
94919
|
+
notifyNativeTurnIdle({ chatroomId: opts.chatroomId, role: opts.role });
|
|
94460
94920
|
console.log(`[AgentProcessManager] ✅ Native agent_end handled for ${opts.role}`);
|
|
94461
94921
|
} catch (err) {
|
|
94462
94922
|
console.log(` ⚠️ Failed native agent_end for ${opts.role}: ${err.message}`);
|
|
@@ -94542,6 +95002,7 @@ class AgentProcessManager {
|
|
|
94542
95002
|
slot.pid = undefined;
|
|
94543
95003
|
slot.startedAt = undefined;
|
|
94544
95004
|
slot.pendingOperation = undefined;
|
|
95005
|
+
slot.nativeTurnPhase = undefined;
|
|
94545
95006
|
}
|
|
94546
95007
|
async emitExitEvent(slot, opts, ctx) {
|
|
94547
95008
|
const stopReason = ctx.stopReason;
|
|
@@ -95322,6 +95783,9 @@ class AgentProcessManager {
|
|
|
95322
95783
|
await this.deps.persistence.persistAgentPid(this.deps.machineId, opts.chatroomId, opts.role, pid, opts.agentHarness);
|
|
95323
95784
|
} catch {}
|
|
95324
95785
|
this.registerSpawnCallbacks(slot, opts, spawnResult, pid);
|
|
95786
|
+
if (getHarnessCapabilities(opts.agentHarness).supportsNativeIntegration) {
|
|
95787
|
+
setNativeTurnPhase(slot, defaultNativeTurnPhase());
|
|
95788
|
+
}
|
|
95325
95789
|
await this.emitNativeWaiting(opts.chatroomId, opts.role, opts.agentHarness);
|
|
95326
95790
|
}
|
|
95327
95791
|
async emitNativeWaiting(chatroomId, role, harness) {
|
|
@@ -95357,11 +95821,11 @@ class AgentProcessManager {
|
|
|
95357
95821
|
const initPrompt = await this.fetchInitPromptResult(opts, slot);
|
|
95358
95822
|
if (!initPrompt.ok)
|
|
95359
95823
|
return initPrompt.result;
|
|
95360
|
-
const
|
|
95361
|
-
if (!
|
|
95362
|
-
return
|
|
95363
|
-
await this.finalizeRunningSlot(key, slot, opts,
|
|
95364
|
-
return { success: true, pid:
|
|
95824
|
+
const spawn7 = await this.spawnAgentForEnsureRunning(key, slot, opts, initPrompt, wantResume);
|
|
95825
|
+
if (!spawn7.ok)
|
|
95826
|
+
return spawn7.result;
|
|
95827
|
+
await this.finalizeRunningSlot(key, slot, opts, spawn7.spawnResult, wantResume);
|
|
95828
|
+
return { success: true, pid: spawn7.spawnResult.pid };
|
|
95365
95829
|
} catch (e) {
|
|
95366
95830
|
this.resetSlotIdle(slot);
|
|
95367
95831
|
return { success: false, error: `Unexpected error: ${e.message}` };
|
|
@@ -109109,10 +109573,22 @@ function shouldNudgeCliPendingTask(task, now, pendingIdleThresholdMs) {
|
|
|
109109
109573
|
}
|
|
109110
109574
|
function shouldNudgePendingTask(task, now, pendingIdleThresholdMs = PENDING_IDLE_NUDGE_MS) {
|
|
109111
109575
|
if (isNativeHarness(task.agentConfig.agentHarness)) {
|
|
109112
|
-
return
|
|
109576
|
+
return shouldNudgeNativePendingTask(task, now, pendingIdleThresholdMs);
|
|
109113
109577
|
}
|
|
109114
109578
|
return shouldNudgeCliPendingTask(task, now, pendingIdleThresholdMs);
|
|
109115
109579
|
}
|
|
109580
|
+
function shouldNudgeNativePendingTask(task, now, pendingIdleThresholdMs, slot) {
|
|
109581
|
+
if (!isPendingAliveRunningTask(task))
|
|
109582
|
+
return false;
|
|
109583
|
+
if (!isAgentReadyForNativeDelivery(task, slot))
|
|
109584
|
+
return false;
|
|
109585
|
+
const lastSeenAt = task.participant?.lastSeenAt ?? 0;
|
|
109586
|
+
const idleSince = lastSeenAt > 0 ? now - lastSeenAt : now - task.createdAt;
|
|
109587
|
+
return idleSince > pendingIdleThresholdMs;
|
|
109588
|
+
}
|
|
109589
|
+
function shouldEscalateNativeNudgeToRestart(chatroomId, role, failures3) {
|
|
109590
|
+
return failures3 >= NATIVE_NUDGE_ESCALATION_THRESHOLD;
|
|
109591
|
+
}
|
|
109116
109592
|
|
|
109117
109593
|
class NudgeCooldown {
|
|
109118
109594
|
cooldownMs;
|
|
@@ -109129,9 +109605,14 @@ class NudgeCooldown {
|
|
|
109129
109605
|
this.lastNudgedAt.set(`${chatroomId}:${role}`, now);
|
|
109130
109606
|
}
|
|
109131
109607
|
}
|
|
109132
|
-
function isTaskReadyForNudge(task, now, cooldown) {
|
|
109133
|
-
if (
|
|
109608
|
+
function isTaskReadyForNudge(task, now, cooldown, getSlot) {
|
|
109609
|
+
if (isNativeHarness(task.agentConfig.agentHarness)) {
|
|
109610
|
+
const slot = getSlot?.(task.chatroomId, task.agentConfig.role);
|
|
109611
|
+
if (!shouldNudgeNativePendingTask(task, now, PENDING_IDLE_NUDGE_MS, slot))
|
|
109612
|
+
return false;
|
|
109613
|
+
} else if (!shouldNudgePendingTask(task, now)) {
|
|
109134
109614
|
return false;
|
|
109615
|
+
}
|
|
109135
109616
|
const { chatroomId, agentConfig } = task;
|
|
109136
109617
|
if (!cooldown.canNudge(chatroomId, agentConfig.role, now))
|
|
109137
109618
|
return false;
|
|
@@ -109139,18 +109620,18 @@ function isTaskReadyForNudge(task, now, cooldown) {
|
|
|
109139
109620
|
return false;
|
|
109140
109621
|
return true;
|
|
109141
109622
|
}
|
|
109142
|
-
function listTasksReadyForNudge(tasks, now, cooldown) {
|
|
109623
|
+
function listTasksReadyForNudge(tasks, now, cooldown, getSlot) {
|
|
109143
109624
|
return tasks.filter((task) => {
|
|
109144
|
-
if (!isTaskReadyForNudge(task, now, cooldown))
|
|
109625
|
+
if (!isTaskReadyForNudge(task, now, cooldown, getSlot))
|
|
109145
109626
|
return false;
|
|
109146
109627
|
cooldown.recordNudge(task.chatroomId, task.agentConfig.role, now);
|
|
109147
109628
|
return true;
|
|
109148
109629
|
});
|
|
109149
109630
|
}
|
|
109150
|
-
var PENDING_IDLE_NUDGE_MS = 15000, NUDGE_COOLDOWN_MS = 60000;
|
|
109631
|
+
var PENDING_IDLE_NUDGE_MS = 15000, NUDGE_COOLDOWN_MS = 60000, NATIVE_NUDGE_ESCALATION_THRESHOLD = 2;
|
|
109151
109632
|
var init_task_monitor_logic = __esm(() => {
|
|
109633
|
+
init_native_ready_invariant();
|
|
109152
109634
|
init_native_task_injector_logic();
|
|
109153
|
-
init_predicates();
|
|
109154
109635
|
init_agent_process_manager();
|
|
109155
109636
|
});
|
|
109156
109637
|
// ../../services/backend/src/domain/usecase/machine/assigned-task-monitor-row.ts
|
|
@@ -109220,9 +109701,9 @@ class WorkingSnapshot {
|
|
|
109220
109701
|
constructor(opts) {
|
|
109221
109702
|
this.opts = opts;
|
|
109222
109703
|
}
|
|
109223
|
-
replaceAll(
|
|
109704
|
+
replaceAll(rows2) {
|
|
109224
109705
|
this.rows.clear();
|
|
109225
|
-
for (const row of
|
|
109706
|
+
for (const row of rows2) {
|
|
109226
109707
|
this.rows.set(this.opts.rowKey(row), row);
|
|
109227
109708
|
}
|
|
109228
109709
|
}
|
|
@@ -109566,10 +110047,10 @@ var runIncrementalSubscribeLive = (opts) => exports_Effect.gen(function* () {
|
|
|
109566
110047
|
}), runReconcilePollLive = (opts) => runReconcilePoll(opts).pipe(exports_Effect.provide(IntervalClockLive)), runDualChannelFeedLive = (opts) => exports_Effect.gen(function* () {
|
|
109567
110048
|
const initial = yield* exports_Effect.tryPromise(() => opts.fetchReconcile()).pipe(exports_Effect.orElseSucceed(() => null));
|
|
109568
110049
|
if (initial !== null) {
|
|
109569
|
-
const
|
|
109570
|
-
opts.snapshot.replaceAll(
|
|
109571
|
-
if (
|
|
109572
|
-
yield* opts.onReconcileRows(
|
|
110050
|
+
const rows2 = opts.extractReconcileRows(initial);
|
|
110051
|
+
opts.snapshot.replaceAll(rows2);
|
|
110052
|
+
if (rows2.length > 0) {
|
|
110053
|
+
yield* opts.onReconcileRows(rows2).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
109573
110054
|
}
|
|
109574
110055
|
}
|
|
109575
110056
|
const seedKey = yield* exports_Effect.tryPromise(() => opts.seedCursor()).pipe(exports_Effect.orElseSucceed(() => null));
|
|
@@ -109602,9 +110083,9 @@ var runIncrementalSubscribeLive = (opts) => exports_Effect.gen(function* () {
|
|
|
109602
110083
|
args: undefined,
|
|
109603
110084
|
intervalMs: opts.reconcileIntervalMs,
|
|
109604
110085
|
onResult: (result) => exports_Effect.gen(function* () {
|
|
109605
|
-
const
|
|
109606
|
-
opts.snapshot.replaceAll(
|
|
109607
|
-
yield* opts.onReconcileRows(
|
|
110086
|
+
const rows2 = opts.extractReconcileRows(result);
|
|
110087
|
+
opts.snapshot.replaceAll(rows2);
|
|
110088
|
+
yield* opts.onReconcileRows(rows2).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
109608
110089
|
})
|
|
109609
110090
|
});
|
|
109610
110091
|
return {
|
|
@@ -109801,8 +110282,42 @@ async function clearStuckStoppingSlotIfNeeded(agentMgr, chatroomId, role) {
|
|
|
109801
110282
|
}
|
|
109802
110283
|
}
|
|
109803
110284
|
async function nudgeStuckTasks(tasks, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId) {
|
|
109804
|
-
|
|
110285
|
+
const getSlot = (chatroomId, role) => agentMgr.getSlot(chatroomId, role);
|
|
110286
|
+
for (const row of listTasksReadyForNudge(tasks, now, cooldown, getSlot)) {
|
|
109805
110287
|
await clearStuckStoppingSlotIfNeeded(agentMgr, row.chatroomId, row.agentConfig.role);
|
|
110288
|
+
if (isNativeHarness(row.agentConfig.agentHarness)) {
|
|
110289
|
+
const { chatroomId, agentConfig } = row;
|
|
110290
|
+
const { role } = agentConfig;
|
|
110291
|
+
const deliveryState = getRoleDeliveryState();
|
|
110292
|
+
const failures3 = deliveryState.recordNativeNudgeFailure(chatroomId, role);
|
|
110293
|
+
if (shouldEscalateNativeNudgeToRestart(chatroomId, role, failures3)) {
|
|
110294
|
+
const full2 = await fetchTaskForAction(sessionDeps, machineId, row);
|
|
110295
|
+
if (!full2)
|
|
110296
|
+
continue;
|
|
110297
|
+
console.log(`[TaskMonitor] native nudge escalate restart ${role}@${chatroomId} — pending task ${row.taskId}`);
|
|
110298
|
+
runCliNudgeEffect(full2, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
|
|
110299
|
+
deliveryState.clearNativeNudgeFailures(chatroomId, role);
|
|
110300
|
+
continue;
|
|
110301
|
+
}
|
|
110302
|
+
resetRoleDeliveryState(chatroomId, role);
|
|
110303
|
+
await sessionDeps.backend.mutation(api.participants.join, {
|
|
110304
|
+
sessionId: sessionDeps.sessionId,
|
|
110305
|
+
chatroomId,
|
|
110306
|
+
role,
|
|
110307
|
+
action: NATIVE_WAITING_ACTION
|
|
110308
|
+
});
|
|
110309
|
+
console.log(`[TaskMonitor] native light nudge ${role}@${chatroomId} — redeliver pending task ${row.taskId}`);
|
|
110310
|
+
logNativeDeliveryFallback("native-light-nudge", role, chatroomId, row.taskId);
|
|
110311
|
+
getNativeTaskDeliveryCoordinator().reconcileAssignedTasks({
|
|
110312
|
+
tasks: [row],
|
|
110313
|
+
runtime: runtime4,
|
|
110314
|
+
effectContext: effectContext2,
|
|
110315
|
+
agentMgr,
|
|
110316
|
+
sessionDeps,
|
|
110317
|
+
machineId
|
|
110318
|
+
});
|
|
110319
|
+
continue;
|
|
110320
|
+
}
|
|
109806
110321
|
const full = await fetchTaskForAction(sessionDeps, machineId, row);
|
|
109807
110322
|
if (!full)
|
|
109808
110323
|
continue;
|
|
@@ -109827,6 +110342,10 @@ async function processTasksUpdate(tasks, runtime4, effectContext2, cooldown, age
|
|
|
109827
110342
|
isPidAlive: (pid) => isProcessAlive((p) => process.kill(p, 0), pid)
|
|
109828
110343
|
};
|
|
109829
110344
|
await reviveNativeTasks(tasks, localHealth, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
|
|
110345
|
+
if (tasks.length > 0) {
|
|
110346
|
+
const first2 = tasks[0];
|
|
110347
|
+
logNativeDeliveryFallback("signal-presence", first2.agentConfig.role, first2.chatroomId, first2.taskId);
|
|
110348
|
+
}
|
|
109830
110349
|
getNativeTaskDeliveryCoordinator().reconcileAssignedTasks({
|
|
109831
110350
|
tasks,
|
|
109832
110351
|
runtime: runtime4,
|
|
@@ -109837,6 +110356,44 @@ async function processTasksUpdate(tasks, runtime4, effectContext2, cooldown, age
|
|
|
109837
110356
|
});
|
|
109838
110357
|
await nudgeStuckTasks(tasks, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
|
|
109839
110358
|
}
|
|
110359
|
+
function listDeliverablePendingFromStore(agentMgr) {
|
|
110360
|
+
if (!hasAssignedTaskSnapshot())
|
|
110361
|
+
return [];
|
|
110362
|
+
return listAssignedTaskSnapshots().filter((row) => {
|
|
110363
|
+
if (row.status !== "pending")
|
|
110364
|
+
return false;
|
|
110365
|
+
const slot = agentMgr.getSlot(row.chatroomId, row.agentConfig.role);
|
|
110366
|
+
return isAgentReadyForNativeDelivery(row, slot);
|
|
110367
|
+
});
|
|
110368
|
+
}
|
|
110369
|
+
function runLocalStoreReconcilePass(params) {
|
|
110370
|
+
const { stopped, monitorPassInFlight, agentMgr, runtime: runtime4, effectContext: effectContext2, sessionDeps, machineId } = params;
|
|
110371
|
+
if (stopped || monitorPassInFlight)
|
|
110372
|
+
return;
|
|
110373
|
+
const deliverable = listDeliverablePendingFromStore(agentMgr);
|
|
110374
|
+
if (deliverable.length === 0)
|
|
110375
|
+
return;
|
|
110376
|
+
const first2 = deliverable[0];
|
|
110377
|
+
logNativeDeliveryFallback("periodic-reconcile", first2.agentConfig.role, first2.chatroomId, first2.taskId);
|
|
110378
|
+
getNativeTaskDeliveryCoordinator().reconcileAssignedTasks({
|
|
110379
|
+
tasks: deliverable,
|
|
110380
|
+
runtime: runtime4,
|
|
110381
|
+
effectContext: effectContext2,
|
|
110382
|
+
agentMgr,
|
|
110383
|
+
sessionDeps,
|
|
110384
|
+
machineId
|
|
110385
|
+
});
|
|
110386
|
+
}
|
|
110387
|
+
function subscribeAssignedTaskSnapshotStore(wsClient2, args2, isStopped) {
|
|
110388
|
+
return wsClient2.onUpdate(api.machines.listMachineAssignedTaskSnapshots, args2, (result) => {
|
|
110389
|
+
if (isStopped())
|
|
110390
|
+
return;
|
|
110391
|
+
const tasks = parseAssignedTaskMonitorRows(result?.tasks ?? []);
|
|
110392
|
+
replaceAssignedTaskSnapshots(tasks);
|
|
110393
|
+
}, (err) => {
|
|
110394
|
+
console.warn(`[${formatTimestamp()}] ⚠️ Assigned-task snapshot subscription error: ${getErrorMessage2(err)}`);
|
|
110395
|
+
});
|
|
110396
|
+
}
|
|
109840
110397
|
var startTaskMonitorEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
109841
110398
|
const session2 = yield* DaemonSessionService;
|
|
109842
110399
|
const agentMgr = yield* DaemonAgentProcessManagerService;
|
|
@@ -109856,6 +110413,14 @@ var startTaskMonitorEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
|
109856
110413
|
query: (fn2, args2) => session2.backend.query(fn2, args2)
|
|
109857
110414
|
}
|
|
109858
110415
|
};
|
|
110416
|
+
registerNativeDeliverySession({
|
|
110417
|
+
runtime: runtime4,
|
|
110418
|
+
effectContext: effectContext2,
|
|
110419
|
+
agentMgr,
|
|
110420
|
+
sessionDeps,
|
|
110421
|
+
machineId: session2.machineId
|
|
110422
|
+
});
|
|
110423
|
+
const unsubscribeSnapshotStore = subscribeAssignedTaskSnapshotStore(wsClient2, { sessionId: session2.sessionId, machineId: session2.machineId }, () => stopped);
|
|
109859
110424
|
const runMonitorPass = (tasks, pass) => {
|
|
109860
110425
|
if (stopped || monitorPassInFlight || tasks.length === 0)
|
|
109861
110426
|
return;
|
|
@@ -109864,6 +110429,17 @@ var startTaskMonitorEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
|
109864
110429
|
monitorPassInFlight = false;
|
|
109865
110430
|
});
|
|
109866
110431
|
};
|
|
110432
|
+
const reconcileTimer = setInterval(() => {
|
|
110433
|
+
runLocalStoreReconcilePass({
|
|
110434
|
+
stopped,
|
|
110435
|
+
monitorPassInFlight,
|
|
110436
|
+
agentMgr,
|
|
110437
|
+
runtime: runtime4,
|
|
110438
|
+
effectContext: effectContext2,
|
|
110439
|
+
sessionDeps,
|
|
110440
|
+
machineId: session2.machineId
|
|
110441
|
+
});
|
|
110442
|
+
}, NATIVE_DELIVERY_RECONCILE_MS);
|
|
109867
110443
|
yield* exports_Effect.tryPromise(() => session2.backend.mutation(api.machines.syncMachineAssignedTaskSnapshotsMutation, {
|
|
109868
110444
|
sessionId: session2.sessionId,
|
|
109869
110445
|
machineId: session2.machineId
|
|
@@ -109918,6 +110494,10 @@ var startTaskMonitorEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
|
109918
110494
|
return {
|
|
109919
110495
|
stop() {
|
|
109920
110496
|
stopped = true;
|
|
110497
|
+
unsubscribeSnapshotStore();
|
|
110498
|
+
clearAssignedTaskSnapshots();
|
|
110499
|
+
unregisterNativeDeliverySession();
|
|
110500
|
+
clearInterval(reconcileTimer);
|
|
109921
110501
|
exports_Effect.runPromise(signalHandle.stop());
|
|
109922
110502
|
exports_Effect.runPromise(presenceHandle.stop());
|
|
109923
110503
|
console.log(`[${formatTimestamp()}] \uD83D\uDCCB Task-monitor stopped`);
|
|
@@ -109925,12 +110505,17 @@ var startTaskMonitorEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
|
109925
110505
|
};
|
|
109926
110506
|
});
|
|
109927
110507
|
var init_task_monitor = __esm(() => {
|
|
110508
|
+
init_reliability();
|
|
110509
|
+
init_participant();
|
|
109928
110510
|
init_team_agent_settings();
|
|
109929
110511
|
init_parse_session_augmentation();
|
|
109930
110512
|
init_assigned_task_monitor_contract();
|
|
109931
110513
|
init_esm();
|
|
110514
|
+
init_assigned_task_snapshot_store();
|
|
109932
110515
|
init_daemon_services();
|
|
110516
|
+
init_native_ready_invariant();
|
|
109933
110517
|
init_native_task_delivery_coordinator();
|
|
110518
|
+
init_native_task_injector_logic();
|
|
109934
110519
|
init_task_monitor_logic();
|
|
109935
110520
|
init_task_monitor_snapshot();
|
|
109936
110521
|
init_api3();
|
|
@@ -110027,6 +110612,15 @@ function handleRequestStartEffect(event, tracker) {
|
|
|
110027
110612
|
tracker.commandIds.set(eventId, Date.now());
|
|
110028
110613
|
});
|
|
110029
110614
|
}
|
|
110615
|
+
function handleRequestRestartEffect(event, tracker) {
|
|
110616
|
+
return exports_Effect.gen(function* () {
|
|
110617
|
+
const eventId = event._id.toString();
|
|
110618
|
+
if (tracker.commandIds.has(eventId))
|
|
110619
|
+
return;
|
|
110620
|
+
yield* onRequestRestartAgentEffect(event);
|
|
110621
|
+
tracker.commandIds.set(eventId, Date.now());
|
|
110622
|
+
});
|
|
110623
|
+
}
|
|
110030
110624
|
function handleRequestStopEffect(event, tracker) {
|
|
110031
110625
|
return exports_Effect.gen(function* () {
|
|
110032
110626
|
const eventId = event._id.toString();
|
|
@@ -110178,6 +110772,7 @@ var init_command_loop = __esm(() => {
|
|
|
110178
110772
|
init_reliability();
|
|
110179
110773
|
init_esm();
|
|
110180
110774
|
init_api3();
|
|
110775
|
+
init_on_request_restart_agent();
|
|
110181
110776
|
init_on_request_start_agent();
|
|
110182
110777
|
init_on_request_stop_agent();
|
|
110183
110778
|
init_on_daemon_shutdown();
|
|
@@ -110205,6 +110800,7 @@ var init_command_loop = __esm(() => {
|
|
|
110205
110800
|
GIT_PUSH_ACTIONS = new Set(["git-pull", "git-push", "git-sync", "git-discard-all"]);
|
|
110206
110801
|
commandEventHandlers = {
|
|
110207
110802
|
"agent.requestStart": handleRequestStartEffect,
|
|
110803
|
+
"agent.restart": handleRequestRestartEffect,
|
|
110208
110804
|
"agent.requestStop": handleRequestStopEffect,
|
|
110209
110805
|
"daemon.ping": handlePingCommandEffect,
|
|
110210
110806
|
"daemon.gitRefresh": handleGitRefreshCommandEffect,
|
|
@@ -110478,7 +111074,7 @@ async function harnessStatus() {
|
|
|
110478
111074
|
};
|
|
110479
111075
|
const program2 = exports_Effect.forEach(services, detectOne, { concurrency: "unbounded" });
|
|
110480
111076
|
const results = await exports_Effect.runPromise(program2);
|
|
110481
|
-
const
|
|
111077
|
+
const rows2 = results.map(({ id: id3, displayName, result }) => {
|
|
110482
111078
|
if (isInstalled(result)) {
|
|
110483
111079
|
return { id: id3, displayName, status: "installed" };
|
|
110484
111080
|
} else if (isNotInstalled(result)) {
|
|
@@ -110488,13 +111084,13 @@ async function harnessStatus() {
|
|
|
110488
111084
|
}
|
|
110489
111085
|
return { id: id3, displayName, status: "not-installed" };
|
|
110490
111086
|
});
|
|
110491
|
-
const idWidth = Math.max(4, ...
|
|
110492
|
-
const nameWidth = Math.max(11, ...
|
|
111087
|
+
const idWidth = Math.max(4, ...rows2.map((r) => r.id.length));
|
|
111088
|
+
const nameWidth = Math.max(11, ...rows2.map((r) => r.displayName.length));
|
|
110493
111089
|
const header = `${"ID".padEnd(idWidth)} ${"DISPLAY NAME".padEnd(nameWidth)} STATUS`;
|
|
110494
111090
|
const divider = `${"-".repeat(idWidth)} ${"-".repeat(nameWidth)} ------`;
|
|
110495
111091
|
console.log(header);
|
|
110496
111092
|
console.log(divider);
|
|
110497
|
-
for (const row of
|
|
111093
|
+
for (const row of rows2) {
|
|
110498
111094
|
const statusIcon = row.status === "installed" ? "✅ installed" : row.status === "error" ? "⚠️ error" : "❌ not installed";
|
|
110499
111095
|
const line = `${row.id.padEnd(idWidth)} ${row.displayName.padEnd(nameWidth)} ${statusIcon}`;
|
|
110500
111096
|
console.log(line);
|
|
@@ -110503,8 +111099,8 @@ async function harnessStatus() {
|
|
|
110503
111099
|
}
|
|
110504
111100
|
}
|
|
110505
111101
|
console.log("");
|
|
110506
|
-
const installedCount =
|
|
110507
|
-
const totalCount =
|
|
111102
|
+
const installedCount = rows2.filter((r) => r.status === "installed").length;
|
|
111103
|
+
const totalCount = rows2.length;
|
|
110508
111104
|
console.log(`${installedCount}/${totalCount} harnesses available on this machine.`);
|
|
110509
111105
|
}
|
|
110510
111106
|
var init_harness_status = __esm(() => {
|
|
@@ -111471,4 +112067,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
111471
112067
|
});
|
|
111472
112068
|
program2.parse();
|
|
111473
112069
|
|
|
111474
|
-
//# debugId=
|
|
112070
|
+
//# debugId=A68932632BD7E62C64756E2164756E21
|