chatroom-cli 1.57.0 → 1.57.2
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 +662 -401
- package/dist/index.js.map +25 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -29173,7 +29173,7 @@ function writeSpawnError(logPrefix, err, emitLogLine) {
|
|
|
29173
29173
|
emitLogLine?.(line);
|
|
29174
29174
|
console.error(`[${new Date().toISOString()}] ${logPrefix} spawn-error]`, err);
|
|
29175
29175
|
}
|
|
29176
|
-
var NO_SUBAGENT_DIRECTIVE2 = "NEVER spawn subagents. Follow the chatroom instructions strictly.", _sdkCache, _sdkLoadError, CURSOR_SDK_COMMAND = "cursor-sdk", DEFAULT_MODEL = "composer-2.5", AGENT_CREATE_TIMEOUT_MS = 60000, SEND_TIMEOUT_MS = 60000, RUN_WAIT_TIMEOUT_MS = 3600000, MODELS_LIST_TIMEOUT_MS =
|
|
29176
|
+
var NO_SUBAGENT_DIRECTIVE2 = "NEVER spawn subagents. Follow the chatroom instructions strictly.", _sdkCache, _sdkLoadError, CURSOR_SDK_COMMAND = "cursor-sdk", DEFAULT_MODEL = "composer-2.5", AGENT_CREATE_TIMEOUT_MS = 60000, SEND_TIMEOUT_MS = 60000, RUN_WAIT_TIMEOUT_MS = 3600000, MODELS_LIST_TIMEOUT_MS = 60000, RUN_CANCEL_TIMEOUT_MS = 5000, cachedSdkPackageVersion, CursorSdkAgentService;
|
|
29177
29177
|
var init_cursor_sdk_agent_service = __esm(() => {
|
|
29178
29178
|
init_esm();
|
|
29179
29179
|
init_base_cli_agent_service();
|
|
@@ -75589,9 +75589,18 @@ function getPlannerToBuilderHandoffTemplate(nativeIntegration = false) {
|
|
|
75589
75589
|
**Detail bar:** Specify down to **every file** the builder will create or modify (full repo paths). Include code snippets — types, signatures, stubs, or target implementations — until a competent builder **cannot misinterpret** what to write. Vague layers ("update the backend", "fix the component") are not acceptable.
|
|
75590
75590
|
|
|
75591
75591
|
\`\`\`markdown
|
|
75592
|
+
## Summary
|
|
75593
|
+
<brief context for this delegation slice — what problem it solves and where it fits in the larger task>
|
|
75594
|
+
|
|
75592
75595
|
## Goal
|
|
75593
75596
|
<one sentence: the outcome this slice delivers>
|
|
75594
75597
|
|
|
75598
|
+
## Key Knowledge for High Quality Bar
|
|
75599
|
+
<details that would move the implementation from good to excellent and delightful — domain context, user expectations, edge cases, naming, UX polish, invariants the builder must preserve>
|
|
75600
|
+
|
|
75601
|
+
## Force Multipliers
|
|
75602
|
+
<choices that greatly simplify the solution while preserving long-term maintainability — reuse existing abstractions, avoid unnecessary layers, leverage platform conventions>
|
|
75603
|
+
|
|
75595
75604
|
## Files to implement (exhaustive, file-level)
|
|
75596
75605
|
List **every** file in this slice. For each file, state the exact change and paste the code the builder should match (no guessing).
|
|
75597
75606
|
|
|
@@ -75661,9 +75670,19 @@ function getPlannerToUserReportTemplate() {
|
|
|
75661
75670
|
## Summary
|
|
75662
75671
|
<what was accomplished, in plain terms — no references to prior messages>
|
|
75663
75672
|
|
|
75664
|
-
##
|
|
75673
|
+
## Template Disclosure Confirmation
|
|
75674
|
+
- [ ] I confirm that I have seen this template at the start of any planning, before working on or delegating any task to the team
|
|
75675
|
+
|
|
75676
|
+
## Proof of Principle
|
|
75677
|
+
<!-- Demonstrate adherence to:
|
|
75678
|
+
- Organization & Maintainability: a small change in requirements should result in a small change in code in a small number of files and folders.
|
|
75679
|
+
- Static Evaluability and Provability: the system's behavior should be provably correct by looking at the source code, then automated tests, then manual tests, in this order.
|
|
75680
|
+
-->
|
|
75681
|
+
<how this work follows the principles above — localized changes, readable structure, correctness provable from source then tests>
|
|
75682
|
+
|
|
75683
|
+
## Proof of Completion
|
|
75665
75684
|
- \`path/to/file.ts\` — <what changed and why>
|
|
75666
|
-
<list every file you (or the builder) modified
|
|
75685
|
+
<evidence the goal was met — list every file you (or the builder) modified>
|
|
75667
75686
|
|
|
75668
75687
|
## Key Technical Decisions
|
|
75669
75688
|
- <schema design, modules, interfaces, domain entities — what you chose and why, or "Not Applicable">
|
|
@@ -80624,19 +80643,51 @@ function isDaemonRunning() {
|
|
|
80624
80643
|
removePid();
|
|
80625
80644
|
return { running: false, pid: null };
|
|
80626
80645
|
}
|
|
80627
|
-
function
|
|
80628
|
-
const { running: running3
|
|
80646
|
+
function tryAcquireLock() {
|
|
80647
|
+
const { running: running3 } = isDaemonRunning();
|
|
80629
80648
|
if (running3) {
|
|
80630
|
-
console.error(`❌ Daemon already running for ${getConvexUrl()} (PID: ${pid})`);
|
|
80631
80649
|
return false;
|
|
80632
80650
|
}
|
|
80633
80651
|
writePid();
|
|
80634
80652
|
return true;
|
|
80635
80653
|
}
|
|
80654
|
+
function logWaitingForShutdown(pid) {
|
|
80655
|
+
console.error(`⏳ Waiting for previous daemon to shut down for ${getConvexUrl()} (PID: ${pid})...`);
|
|
80656
|
+
}
|
|
80657
|
+
function logDaemonAlreadyRunning(pid) {
|
|
80658
|
+
console.error(`❌ Daemon already running for ${getConvexUrl()} (PID: ${pid})`);
|
|
80659
|
+
}
|
|
80660
|
+
async function waitForLockOrTimeout(deadline, intervalMs, sleep5) {
|
|
80661
|
+
let loggedWait = false;
|
|
80662
|
+
while (Date.now() < deadline) {
|
|
80663
|
+
if (tryAcquireLock()) {
|
|
80664
|
+
return true;
|
|
80665
|
+
}
|
|
80666
|
+
const { pid } = isDaemonRunning();
|
|
80667
|
+
if (pid !== null && !loggedWait) {
|
|
80668
|
+
logWaitingForShutdown(pid);
|
|
80669
|
+
loggedWait = true;
|
|
80670
|
+
}
|
|
80671
|
+
await sleep5(intervalMs);
|
|
80672
|
+
}
|
|
80673
|
+
return false;
|
|
80674
|
+
}
|
|
80675
|
+
async function acquireLockWithRetry(options) {
|
|
80676
|
+
const intervalMs = options?.intervalMs ?? LOCK_RETRY_INTERVAL_MS;
|
|
80677
|
+
const maxWaitMs = options?.maxWaitMs ?? LOCK_RETRY_MAX_WAIT_MS;
|
|
80678
|
+
const sleep5 = options?.sleep ?? ((ms) => new Promise((resolve3) => setTimeout(resolve3, ms)));
|
|
80679
|
+
const deadline = Date.now() + maxWaitMs;
|
|
80680
|
+
if (await waitForLockOrTimeout(deadline, intervalMs, sleep5)) {
|
|
80681
|
+
return true;
|
|
80682
|
+
}
|
|
80683
|
+
const { pid } = isDaemonRunning();
|
|
80684
|
+
logDaemonAlreadyRunning(pid);
|
|
80685
|
+
return false;
|
|
80686
|
+
}
|
|
80636
80687
|
function releaseLock() {
|
|
80637
80688
|
removePid();
|
|
80638
80689
|
}
|
|
80639
|
-
var CHATROOM_DIR4;
|
|
80690
|
+
var CHATROOM_DIR4, LOCK_RETRY_INTERVAL_MS = 500, LOCK_RETRY_MAX_WAIT_MS = 15000;
|
|
80640
80691
|
var init_pid = __esm(() => {
|
|
80641
80692
|
init_client2();
|
|
80642
80693
|
CHATROOM_DIR4 = join16(homedir6(), ".chatroom");
|
|
@@ -84918,6 +84969,315 @@ class TurnEndQueue {
|
|
|
84918
84969
|
}
|
|
84919
84970
|
}
|
|
84920
84971
|
|
|
84972
|
+
// src/commands/machine/daemon-start/native-delivery-ledger.ts
|
|
84973
|
+
class NativeDeliveryLedger {
|
|
84974
|
+
delivered = new Set;
|
|
84975
|
+
inFlight = new Set;
|
|
84976
|
+
deliveryKey(taskId, harnessSessionId) {
|
|
84977
|
+
return `${taskId}\x00${harnessSessionId}`;
|
|
84978
|
+
}
|
|
84979
|
+
isDelivered(taskId, harnessSessionId) {
|
|
84980
|
+
return this.delivered.has(this.deliveryKey(taskId, harnessSessionId));
|
|
84981
|
+
}
|
|
84982
|
+
tryAcquire(taskId, harnessSessionId) {
|
|
84983
|
+
const key = this.deliveryKey(taskId, harnessSessionId);
|
|
84984
|
+
if (this.delivered.has(key) || this.inFlight.has(key)) {
|
|
84985
|
+
return false;
|
|
84986
|
+
}
|
|
84987
|
+
this.inFlight.add(key);
|
|
84988
|
+
return true;
|
|
84989
|
+
}
|
|
84990
|
+
markDelivered(taskId, harnessSessionId) {
|
|
84991
|
+
const key = this.deliveryKey(taskId, harnessSessionId);
|
|
84992
|
+
this.inFlight.delete(key);
|
|
84993
|
+
this.delivered.add(key);
|
|
84994
|
+
}
|
|
84995
|
+
clearDelivery(taskId, harnessSessionId) {
|
|
84996
|
+
const key = this.deliveryKey(taskId, harnessSessionId);
|
|
84997
|
+
this.inFlight.delete(key);
|
|
84998
|
+
this.delivered.delete(key);
|
|
84999
|
+
}
|
|
85000
|
+
clearSession(harnessSessionId) {
|
|
85001
|
+
const suffix = `\x00${harnessSessionId}`;
|
|
85002
|
+
for (const key of [...this.delivered, ...this.inFlight]) {
|
|
85003
|
+
if (key.endsWith(suffix)) {
|
|
85004
|
+
this.delivered.delete(key);
|
|
85005
|
+
this.inFlight.delete(key);
|
|
85006
|
+
}
|
|
85007
|
+
}
|
|
85008
|
+
}
|
|
85009
|
+
}
|
|
85010
|
+
|
|
85011
|
+
// src/domain/native-integration/predicates.ts
|
|
85012
|
+
function isNativeInjectableAliveRunning(task) {
|
|
85013
|
+
const { agentConfig, status: status3 } = task;
|
|
85014
|
+
if (!isNativeHarness(agentConfig.agentHarness))
|
|
85015
|
+
return false;
|
|
85016
|
+
if (agentConfig.spawnedAgentPid == null || agentConfig.desiredState !== "running") {
|
|
85017
|
+
return false;
|
|
85018
|
+
}
|
|
85019
|
+
if (status3 === "pending")
|
|
85020
|
+
return true;
|
|
85021
|
+
if (status3 === "acknowledged") {
|
|
85022
|
+
const assignedTo = task.assignedTo?.toLowerCase();
|
|
85023
|
+
return assignedTo === agentConfig.role.toLowerCase();
|
|
85024
|
+
}
|
|
85025
|
+
return false;
|
|
85026
|
+
}
|
|
85027
|
+
function isInjectableNativeAction(action) {
|
|
85028
|
+
if (action == null)
|
|
85029
|
+
return true;
|
|
85030
|
+
return action === NATIVE_WAITING_ACTION;
|
|
85031
|
+
}
|
|
85032
|
+
function isNativeIdleAfterTaskComplete(participant) {
|
|
85033
|
+
return participant.lastSeenAction === NATIVE_TASK_INJECTED_ACTION && participant.lastStatus === "task.completed";
|
|
85034
|
+
}
|
|
85035
|
+
function isNativeAcknowledgedInjectionRetry(task) {
|
|
85036
|
+
if (task.status !== "acknowledged")
|
|
85037
|
+
return false;
|
|
85038
|
+
const assignedTo = task.assignedTo?.toLowerCase();
|
|
85039
|
+
if (assignedTo !== task.agentConfig.role.toLowerCase())
|
|
85040
|
+
return false;
|
|
85041
|
+
return task.participant?.lastSeenAction === NATIVE_TASK_INJECTED_ACTION;
|
|
85042
|
+
}
|
|
85043
|
+
function isStaleCliGetNextTaskWaiting(task) {
|
|
85044
|
+
const lastSeenAt = task.participant?.lastSeenAt ?? 0;
|
|
85045
|
+
return task.participant?.lastSeenAction === "get-next-task:started" && task.createdAt > lastSeenAt;
|
|
85046
|
+
}
|
|
85047
|
+
function isCliIdleNotListening(task, now, thresholdMs) {
|
|
85048
|
+
const lastSeenAt = task.participant?.lastSeenAt ?? 0;
|
|
85049
|
+
if (lastSeenAt === 0)
|
|
85050
|
+
return now - task.createdAt > thresholdMs;
|
|
85051
|
+
return now - lastSeenAt > thresholdMs;
|
|
85052
|
+
}
|
|
85053
|
+
var init_predicates = __esm(() => {
|
|
85054
|
+
init_types();
|
|
85055
|
+
init_participant();
|
|
85056
|
+
});
|
|
85057
|
+
|
|
85058
|
+
// src/infrastructure/services/remote-agents/spawn-prompt.ts
|
|
85059
|
+
function createSpawnPrompt(raw, opts) {
|
|
85060
|
+
if (opts?.nativeBootstrap) {
|
|
85061
|
+
return NATIVE_BOOTSTRAP_PROMPT;
|
|
85062
|
+
}
|
|
85063
|
+
const trimmed = raw?.trim();
|
|
85064
|
+
return trimmed && trimmed.length > 0 ? trimmed : DEFAULT_TRIGGER_PROMPT;
|
|
85065
|
+
}
|
|
85066
|
+
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.";
|
|
85067
|
+
|
|
85068
|
+
// src/domain/native-integration/spawn-policy.ts
|
|
85069
|
+
function shouldDeferInitialTurn(harness) {
|
|
85070
|
+
return isNativeHarness(harness);
|
|
85071
|
+
}
|
|
85072
|
+
function resolveNativeSpawnPolicy(harness, initMessage) {
|
|
85073
|
+
const deferInitialTurn = shouldDeferInitialTurn(harness);
|
|
85074
|
+
return {
|
|
85075
|
+
deferInitialTurn,
|
|
85076
|
+
prompt: createSpawnPrompt(initMessage, { nativeBootstrap: deferInitialTurn })
|
|
85077
|
+
};
|
|
85078
|
+
}
|
|
85079
|
+
var init_spawn_policy = __esm(() => {
|
|
85080
|
+
init_types();
|
|
85081
|
+
});
|
|
85082
|
+
|
|
85083
|
+
// src/domain/native-integration/index.ts
|
|
85084
|
+
var init_native_integration = __esm(() => {
|
|
85085
|
+
init_types();
|
|
85086
|
+
init_predicates();
|
|
85087
|
+
init_spawn_policy();
|
|
85088
|
+
});
|
|
85089
|
+
|
|
85090
|
+
// src/commands/machine/daemon-start/native-task-injector-logic.ts
|
|
85091
|
+
function shouldDeliverNativeTask(task, opts) {
|
|
85092
|
+
if (!isNativeInjectableAliveRunning(task))
|
|
85093
|
+
return false;
|
|
85094
|
+
if (!opts.harnessSessionId)
|
|
85095
|
+
return false;
|
|
85096
|
+
if (opts.ledger.isDelivered(task.taskId, opts.harnessSessionId))
|
|
85097
|
+
return false;
|
|
85098
|
+
return isInjectableNativeAction(task.participant?.lastSeenAction) || isNativeIdleAfterTaskComplete(task.participant ?? {}) || isNativeAcknowledgedInjectionRetry(task);
|
|
85099
|
+
}
|
|
85100
|
+
function buildNativeInjectionPrompt(params) {
|
|
85101
|
+
const { taskDeliveryOutput, compressMode } = params;
|
|
85102
|
+
if (compressMode === "new_session") {
|
|
85103
|
+
return [
|
|
85104
|
+
"⚠️ Context was compacted. Run `chatroom get-system-prompt` only if role instructions are missing.",
|
|
85105
|
+
"",
|
|
85106
|
+
taskDeliveryOutput
|
|
85107
|
+
].join(`
|
|
85108
|
+
`);
|
|
85109
|
+
}
|
|
85110
|
+
return taskDeliveryOutput;
|
|
85111
|
+
}
|
|
85112
|
+
var init_native_task_injector_logic = __esm(() => {
|
|
85113
|
+
init_predicates();
|
|
85114
|
+
init_native_integration();
|
|
85115
|
+
});
|
|
85116
|
+
|
|
85117
|
+
// ../../services/backend/src/domain/handoff/parse-compress-context.ts
|
|
85118
|
+
function findSectionIndex(content, headings) {
|
|
85119
|
+
const indices = headings.map((heading) => content.indexOf(heading)).filter((idx) => idx !== -1);
|
|
85120
|
+
return indices.length === 0 ? -1 : Math.min(...indices);
|
|
85121
|
+
}
|
|
85122
|
+
function normalizeMode(raw) {
|
|
85123
|
+
const value = raw.toLowerCase();
|
|
85124
|
+
if (value === "reset")
|
|
85125
|
+
return "new_session";
|
|
85126
|
+
if (value === "none")
|
|
85127
|
+
return value;
|
|
85128
|
+
return DEFAULT_MODE;
|
|
85129
|
+
}
|
|
85130
|
+
function extractSectionBody(content, sectionIdx) {
|
|
85131
|
+
const matchedHeading = SECTION_HEADINGS.find((h) => content.indexOf(h, sectionIdx) === sectionIdx) ?? SECTION_HEADINGS[0];
|
|
85132
|
+
const afterSection = content.slice(sectionIdx);
|
|
85133
|
+
const nextHeading = afterSection.slice(matchedHeading.length).search(/\n## /);
|
|
85134
|
+
return nextHeading === -1 ? afterSection : afterSection.slice(0, matchedHeading.length + nextHeading);
|
|
85135
|
+
}
|
|
85136
|
+
function parseCompressContext(handoffContent) {
|
|
85137
|
+
const sectionIdx = findSectionIndex(handoffContent, SECTION_HEADINGS);
|
|
85138
|
+
if (sectionIdx === -1)
|
|
85139
|
+
return DEFAULT_MODE;
|
|
85140
|
+
const match17 = extractSectionBody(handoffContent, sectionIdx).match(DATA_TAG);
|
|
85141
|
+
if (!match17)
|
|
85142
|
+
return DEFAULT_MODE;
|
|
85143
|
+
return normalizeMode(match17[1]);
|
|
85144
|
+
}
|
|
85145
|
+
function compressContextToWantResume(mode) {
|
|
85146
|
+
return mode === "none";
|
|
85147
|
+
}
|
|
85148
|
+
var SECTION_HEADINGS, DATA_TAG, DEFAULT_MODE = "new_session";
|
|
85149
|
+
var init_parse_compress_context = __esm(() => {
|
|
85150
|
+
SECTION_HEADINGS = ["## Session Management", "## Restart new context"];
|
|
85151
|
+
DATA_TAG = /\/\/\s*data:agent\.compress_context=(new_session|reset|none)\b/i;
|
|
85152
|
+
});
|
|
85153
|
+
|
|
85154
|
+
// src/commands/machine/daemon-start/native-task-injector.ts
|
|
85155
|
+
function runNativeInjectionEffect(task, harnessSessionId, deps, ledger) {
|
|
85156
|
+
return exports_Effect.gen(function* () {
|
|
85157
|
+
if (!shouldDeliverNativeTask(task, { ledger, harnessSessionId })) {
|
|
85158
|
+
return;
|
|
85159
|
+
}
|
|
85160
|
+
const { chatroomId, taskId, taskContent, agentConfig, status: status3 } = task;
|
|
85161
|
+
const { role } = agentConfig;
|
|
85162
|
+
if (!ledger.tryAcquire(taskId, harnessSessionId)) {
|
|
85163
|
+
return;
|
|
85164
|
+
}
|
|
85165
|
+
if (status3 === "pending") {
|
|
85166
|
+
const claimResult = yield* exports_Effect.tryPromise({
|
|
85167
|
+
try: () => deps.backend.mutation(api.tasks.claimTask, {
|
|
85168
|
+
sessionId: deps.sessionId,
|
|
85169
|
+
chatroomId,
|
|
85170
|
+
role,
|
|
85171
|
+
taskId
|
|
85172
|
+
}),
|
|
85173
|
+
catch: (err) => err
|
|
85174
|
+
}).pipe(exports_Effect.either);
|
|
85175
|
+
if (claimResult._tag === "Left") {
|
|
85176
|
+
ledger.clearDelivery(taskId, harnessSessionId);
|
|
85177
|
+
return yield* exports_Effect.fail(claimResult.left);
|
|
85178
|
+
}
|
|
85179
|
+
}
|
|
85180
|
+
const deliveryResult = yield* exports_Effect.tryPromise({
|
|
85181
|
+
try: () => deps.backend.query(api.messages.getTaskDeliveryPrompt, {
|
|
85182
|
+
sessionId: deps.sessionId,
|
|
85183
|
+
chatroomId,
|
|
85184
|
+
role,
|
|
85185
|
+
taskId,
|
|
85186
|
+
convexUrl: deps.convexUrl
|
|
85187
|
+
}),
|
|
85188
|
+
catch: (err) => err
|
|
85189
|
+
}).pipe(exports_Effect.either);
|
|
85190
|
+
if (deliveryResult._tag === "Left") {
|
|
85191
|
+
ledger.clearDelivery(taskId, harnessSessionId);
|
|
85192
|
+
return yield* exports_Effect.fail(deliveryResult.left);
|
|
85193
|
+
}
|
|
85194
|
+
const delivery = deliveryResult.right;
|
|
85195
|
+
const prompt = buildNativeInjectionPrompt({
|
|
85196
|
+
taskDeliveryOutput: delivery.fullCliOutput,
|
|
85197
|
+
compressMode: parseCompressContext(taskContent)
|
|
85198
|
+
});
|
|
85199
|
+
yield* exports_Effect.tryPromise({
|
|
85200
|
+
try: () => deps.backend.mutation(api.participants.join, {
|
|
85201
|
+
sessionId: deps.sessionId,
|
|
85202
|
+
chatroomId,
|
|
85203
|
+
role,
|
|
85204
|
+
action: NATIVE_TASK_INJECTED_ACTION,
|
|
85205
|
+
taskId
|
|
85206
|
+
}),
|
|
85207
|
+
catch: (err) => err
|
|
85208
|
+
}).pipe(exports_Effect.tapError(() => exports_Effect.sync(() => ledger.clearDelivery(taskId, harnessSessionId))));
|
|
85209
|
+
const resumeResult = yield* exports_Effect.tryPromise({
|
|
85210
|
+
try: () => deps.agentMgr.resumeTurnForSlot({ chatroomId, role, prompt }),
|
|
85211
|
+
catch: (err) => err
|
|
85212
|
+
}).pipe(exports_Effect.either);
|
|
85213
|
+
if (resumeResult._tag === "Left") {
|
|
85214
|
+
ledger.clearDelivery(taskId, harnessSessionId);
|
|
85215
|
+
console.warn(`[NativeTaskInjector] resumeTurn failed for ${role}@${chatroomId}: ${getErrorMessage(resumeResult.left)}`);
|
|
85216
|
+
return;
|
|
85217
|
+
}
|
|
85218
|
+
ledger.markDelivered(taskId, harnessSessionId);
|
|
85219
|
+
});
|
|
85220
|
+
}
|
|
85221
|
+
var init_native_task_injector = __esm(() => {
|
|
85222
|
+
init_participant();
|
|
85223
|
+
init_parse_compress_context();
|
|
85224
|
+
init_esm();
|
|
85225
|
+
init_native_task_injector_logic();
|
|
85226
|
+
init_api3();
|
|
85227
|
+
init_convex_error();
|
|
85228
|
+
});
|
|
85229
|
+
|
|
85230
|
+
// src/commands/machine/daemon-start/native-task-delivery-coordinator.ts
|
|
85231
|
+
class NativeTaskDeliveryCoordinator {
|
|
85232
|
+
ledger;
|
|
85233
|
+
constructor(ledger = new NativeDeliveryLedger) {
|
|
85234
|
+
this.ledger = ledger;
|
|
85235
|
+
}
|
|
85236
|
+
onSessionLost(params) {
|
|
85237
|
+
if (params.harnessSessionId) {
|
|
85238
|
+
this.ledger.clearSession(params.harnessSessionId);
|
|
85239
|
+
}
|
|
85240
|
+
}
|
|
85241
|
+
reconcileAssignedTasks(params) {
|
|
85242
|
+
const { tasks, runtime: runtime4, effectContext: effectContext2, agentMgr, sessionDeps } = params;
|
|
85243
|
+
for (const task of tasks) {
|
|
85244
|
+
const slot = agentMgr.getSlot(task.chatroomId, task.agentConfig.role);
|
|
85245
|
+
const harnessSessionId = slot?.harnessSessionId;
|
|
85246
|
+
if (!shouldDeliverNativeTask(task, {
|
|
85247
|
+
ledger: this.ledger,
|
|
85248
|
+
harnessSessionId
|
|
85249
|
+
})) {
|
|
85250
|
+
continue;
|
|
85251
|
+
}
|
|
85252
|
+
if (!harnessSessionId) {
|
|
85253
|
+
continue;
|
|
85254
|
+
}
|
|
85255
|
+
exports_Runtime.runFork(runtime4)(runNativeInjectionEffect(task, harnessSessionId, {
|
|
85256
|
+
sessionId: sessionDeps.sessionId,
|
|
85257
|
+
backend: sessionDeps.backend,
|
|
85258
|
+
agentMgr: {
|
|
85259
|
+
resumeTurnForSlot: (args2) => exports_Effect.runPromise(agentMgr.resumeTurnForSlot(args2))
|
|
85260
|
+
},
|
|
85261
|
+
convexUrl: sessionDeps.convexUrl
|
|
85262
|
+
}, this.ledger).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[NativeTaskDelivery] delivery failed for ${task.agentConfig.role}@${task.chatroomId}: ${getErrorMessage(err)}`)))));
|
|
85263
|
+
}
|
|
85264
|
+
}
|
|
85265
|
+
}
|
|
85266
|
+
function getNativeTaskDeliveryCoordinator() {
|
|
85267
|
+
coordinator ??= new NativeTaskDeliveryCoordinator;
|
|
85268
|
+
return coordinator;
|
|
85269
|
+
}
|
|
85270
|
+
function notifyNativeSessionLost(params) {
|
|
85271
|
+
getNativeTaskDeliveryCoordinator().onSessionLost(params);
|
|
85272
|
+
}
|
|
85273
|
+
var coordinator;
|
|
85274
|
+
var init_native_task_delivery_coordinator = __esm(() => {
|
|
85275
|
+
init_esm();
|
|
85276
|
+
init_native_task_injector_logic();
|
|
85277
|
+
init_native_task_injector();
|
|
85278
|
+
init_convex_error();
|
|
85279
|
+
});
|
|
85280
|
+
|
|
84921
85281
|
// src/domain/agent-lifecycle/entities/stop-reason.ts
|
|
84922
85282
|
function resolveStopReason(code2, signal) {
|
|
84923
85283
|
if (signal !== null)
|
|
@@ -85089,6 +85449,45 @@ var init_agent_lifecycle = __esm(() => {
|
|
|
85089
85449
|
init_restart_decision();
|
|
85090
85450
|
});
|
|
85091
85451
|
|
|
85452
|
+
// src/domain/agent-lifecycle/policies/cursor-sdk-run-error.ts
|
|
85453
|
+
function isCursorSdkRunErrorInLogs(logLines) {
|
|
85454
|
+
return logLines.some((line) => line.includes(" run-error]"));
|
|
85455
|
+
}
|
|
85456
|
+
function formatCursorSdkRunErrorMessage(logLines) {
|
|
85457
|
+
const line = [...logLines].reverse().find((l) => l.includes(" run-error]"));
|
|
85458
|
+
return line?.trim() ?? "Cursor SDK run failed";
|
|
85459
|
+
}
|
|
85460
|
+
|
|
85461
|
+
// src/commands/machine/daemon-start/native-harness-session-exit.ts
|
|
85462
|
+
function isNativeHarnessSessionDiscardedOnExit(ctx) {
|
|
85463
|
+
const { harness, harnessSessionId, stopReason, recentLogLines, supportsDaemonMemoryResume } = ctx;
|
|
85464
|
+
if (!harness || !harnessSessionId) {
|
|
85465
|
+
return false;
|
|
85466
|
+
}
|
|
85467
|
+
if (isCursorSdkRunErrorInLogs(recentLogLines ?? [])) {
|
|
85468
|
+
return true;
|
|
85469
|
+
}
|
|
85470
|
+
if (!supportsDaemonMemoryResume) {
|
|
85471
|
+
return true;
|
|
85472
|
+
}
|
|
85473
|
+
return !shouldRetainHarnessSessionForReconnect(stopReason);
|
|
85474
|
+
}
|
|
85475
|
+
function notifyNativeHarnessSessionLostOnExit(ctx) {
|
|
85476
|
+
if (!ctx.harness || !ctx.harnessSessionId || !getHarnessCapabilities(ctx.harness).supportsNativeIntegration || !isNativeHarnessSessionDiscardedOnExit(ctx)) {
|
|
85477
|
+
return;
|
|
85478
|
+
}
|
|
85479
|
+
notifyNativeSessionLost({
|
|
85480
|
+
chatroomId: ctx.chatroomId,
|
|
85481
|
+
role: ctx.role,
|
|
85482
|
+
harnessSessionId: ctx.harnessSessionId
|
|
85483
|
+
});
|
|
85484
|
+
}
|
|
85485
|
+
var init_native_harness_session_exit = __esm(() => {
|
|
85486
|
+
init_types();
|
|
85487
|
+
init_native_task_delivery_coordinator();
|
|
85488
|
+
init_agent_lifecycle();
|
|
85489
|
+
});
|
|
85490
|
+
|
|
85092
85491
|
// src/domain/agent-lifecycle/policies/classify-resume-storm-reason.ts
|
|
85093
85492
|
function classifyResumeStormReason(logLines) {
|
|
85094
85493
|
const blob = logLines.join(`
|
|
@@ -85209,15 +85608,6 @@ function appendRecentLogLine(slot, line) {
|
|
|
85209
85608
|
}
|
|
85210
85609
|
var RECENT_LOG_LINE_CAP2 = 100;
|
|
85211
85610
|
|
|
85212
|
-
// src/domain/agent-lifecycle/policies/cursor-sdk-run-error.ts
|
|
85213
|
-
function isCursorSdkRunErrorInLogs(logLines) {
|
|
85214
|
-
return logLines.some((line) => line.includes(" run-error]"));
|
|
85215
|
-
}
|
|
85216
|
-
function formatCursorSdkRunErrorMessage(logLines) {
|
|
85217
|
-
const line = [...logLines].reverse().find((l) => l.includes(" run-error]"));
|
|
85218
|
-
return line?.trim() ?? "Cursor SDK run failed";
|
|
85219
|
-
}
|
|
85220
|
-
|
|
85221
85611
|
// src/domain/agent-lifecycle/use-cases/handle-turn-completed.ts
|
|
85222
85612
|
async function handleTurnCompleted(deps, input, slot) {
|
|
85223
85613
|
if (slot?.resumeInFlight) {
|
|
@@ -85278,31 +85668,6 @@ var init_handle_turn_completed = __esm(() => {
|
|
|
85278
85668
|
init_terminal_provider_error();
|
|
85279
85669
|
});
|
|
85280
85670
|
|
|
85281
|
-
// src/infrastructure/services/remote-agents/spawn-prompt.ts
|
|
85282
|
-
function createSpawnPrompt(raw, opts) {
|
|
85283
|
-
if (opts?.nativeBootstrap) {
|
|
85284
|
-
return NATIVE_BOOTSTRAP_PROMPT;
|
|
85285
|
-
}
|
|
85286
|
-
const trimmed = raw?.trim();
|
|
85287
|
-
return trimmed && trimmed.length > 0 ? trimmed : DEFAULT_TRIGGER_PROMPT;
|
|
85288
|
-
}
|
|
85289
|
-
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.";
|
|
85290
|
-
|
|
85291
|
-
// src/domain/native-integration/spawn-policy.ts
|
|
85292
|
-
function shouldDeferInitialTurn(harness) {
|
|
85293
|
-
return isNativeHarness(harness);
|
|
85294
|
-
}
|
|
85295
|
-
function resolveNativeSpawnPolicy(harness, initMessage) {
|
|
85296
|
-
const deferInitialTurn = shouldDeferInitialTurn(harness);
|
|
85297
|
-
return {
|
|
85298
|
-
deferInitialTurn,
|
|
85299
|
-
prompt: createSpawnPrompt(initMessage, { nativeBootstrap: deferInitialTurn })
|
|
85300
|
-
};
|
|
85301
|
-
}
|
|
85302
|
-
var init_spawn_policy = __esm(() => {
|
|
85303
|
-
init_types();
|
|
85304
|
-
});
|
|
85305
|
-
|
|
85306
85671
|
// src/infrastructure/deps/process.ts
|
|
85307
85672
|
function isProcessAlive(kill, pid) {
|
|
85308
85673
|
try {
|
|
@@ -85921,6 +86286,15 @@ class AgentProcessManager {
|
|
|
85921
86286
|
}
|
|
85922
86287
|
const stopReason = resolveStopReason(opts.code, opts.signal);
|
|
85923
86288
|
const ctx = this.captureExitContext(slot, opts, stopReason);
|
|
86289
|
+
notifyNativeHarnessSessionLostOnExit({
|
|
86290
|
+
chatroomId: opts.chatroomId,
|
|
86291
|
+
role: opts.role,
|
|
86292
|
+
harness: ctx.harness,
|
|
86293
|
+
harnessSessionId: ctx.harnessSessionId,
|
|
86294
|
+
stopReason: ctx.stopReason,
|
|
86295
|
+
recentLogLines: ctx.recentLogLines,
|
|
86296
|
+
supportsDaemonMemoryResume: Boolean(ctx.harness && this.deps.agentServices.get(ctx.harness)?.resumeFromDaemonMemory)
|
|
86297
|
+
});
|
|
85924
86298
|
await this.preserveHarnessSessionOnExit(key, slot, ctx);
|
|
85925
86299
|
const lifecyclePromise = this.lifecycle.runPromise(exports_Effect.gen(function* () {
|
|
85926
86300
|
const svc = yield* AgentLifecycleService;
|
|
@@ -86021,11 +86395,11 @@ class AgentProcessManager {
|
|
|
86021
86395
|
}
|
|
86022
86396
|
this.maybeRestartAgent(opts, ctx);
|
|
86023
86397
|
}
|
|
86024
|
-
clearHarnessSessionAfterRunError(key,
|
|
86398
|
+
clearHarnessSessionAfterRunError(key, recentLogLines) {
|
|
86025
86399
|
if (!isCursorSdkRunErrorInLogs(recentLogLines)) {
|
|
86026
86400
|
return false;
|
|
86027
86401
|
}
|
|
86028
|
-
console.log(`[AgentProcessManager] cursor-sdk run-error — cold restarting ${
|
|
86402
|
+
console.log(`[AgentProcessManager] cursor-sdk run-error — cold restarting ${key}: ${formatCursorSdkRunErrorMessage(recentLogLines)}`);
|
|
86029
86403
|
this.clearLastHarnessSession(key);
|
|
86030
86404
|
return true;
|
|
86031
86405
|
}
|
|
@@ -86041,7 +86415,7 @@ class AgentProcessManager {
|
|
|
86041
86415
|
this.handlePermanentFailureForRestart(opts, recentLogLines, ctx.terminalProviderFailureHandled);
|
|
86042
86416
|
return;
|
|
86043
86417
|
}
|
|
86044
|
-
const coldRestartAfterRunError = this.clearHarnessSessionAfterRunError(key,
|
|
86418
|
+
const coldRestartAfterRunError = this.clearHarnessSessionAfterRunError(key, logs);
|
|
86045
86419
|
this.ensureRunning({
|
|
86046
86420
|
chatroomId: opts.chatroomId,
|
|
86047
86421
|
role: opts.role,
|
|
@@ -86050,6 +86424,10 @@ class AgentProcessManager {
|
|
|
86050
86424
|
workingDir,
|
|
86051
86425
|
reason: "platform.crash_recovery",
|
|
86052
86426
|
wantResume: coldRestartAfterRunError ? false : ctx.wantResume ?? true
|
|
86427
|
+
}).then((result) => {
|
|
86428
|
+
if (!result.success) {
|
|
86429
|
+
console.log(`[AgentProcessManager] ⚠️ Agent restart did not complete for ${opts.role}: ${result.error ?? "unknown"}`);
|
|
86430
|
+
}
|
|
86053
86431
|
}).catch((err) => {
|
|
86054
86432
|
console.log(` ⚠️ Failed to restart agent: ${err.message}`);
|
|
86055
86433
|
this.emitStartFailedEvent(opts.role, opts.chatroomId, err.message);
|
|
@@ -86739,6 +87117,7 @@ var init_agent_process_manager = __esm(() => {
|
|
|
86739
87117
|
init_turn_completed_backend();
|
|
86740
87118
|
init_api3();
|
|
86741
87119
|
init_orphan_tracker();
|
|
87120
|
+
init_native_harness_session_exit();
|
|
86742
87121
|
init_agent_lifecycle();
|
|
86743
87122
|
init_abort_resume_storm();
|
|
86744
87123
|
init_classify_resume_storm_reason();
|
|
@@ -86832,7 +87211,7 @@ var init_harness_spawning = __esm(() => {
|
|
|
86832
87211
|
});
|
|
86833
87212
|
|
|
86834
87213
|
// src/commands/machine/daemon-start/handlers/daemon-startup-log.ts
|
|
86835
|
-
var logStartupEffect = (
|
|
87214
|
+
var logStartupEffect = (cachedModels) => exports_Effect.gen(function* () {
|
|
86836
87215
|
const session2 = yield* DaemonSessionService;
|
|
86837
87216
|
yield* exports_Effect.sync(() => {
|
|
86838
87217
|
console.log(`[${formatTimestamp()}] \uD83D\uDE80 Daemon started`);
|
|
@@ -86840,7 +87219,7 @@ var logStartupEffect = (availableModels) => exports_Effect.gen(function* () {
|
|
|
86840
87219
|
console.log(` Machine ID: ${session2.machineId}`);
|
|
86841
87220
|
console.log(` Hostname: ${session2.config?.hostname ?? "unknown"}`);
|
|
86842
87221
|
console.log(` Available harnesses: ${session2.config?.availableHarnesses.join(", ") || "none"}`);
|
|
86843
|
-
console.log(` Available models: ${Object.keys(
|
|
87222
|
+
console.log(` Available models: ${Object.keys(cachedModels).length > 0 ? `${Object.values(cachedModels).flat().length} cached across ${Object.keys(cachedModels).join(", ")} (refreshing in background)` : "discovering in background"}`);
|
|
86844
87223
|
console.log(` PID: ${process.pid}`);
|
|
86845
87224
|
});
|
|
86846
87225
|
});
|
|
@@ -86852,6 +87231,23 @@ var init_daemon_startup_log = __esm(() => {
|
|
|
86852
87231
|
|
|
86853
87232
|
// src/commands/machine/daemon-start/init.ts
|
|
86854
87233
|
import { stat as stat3 } from "node:fs/promises";
|
|
87234
|
+
async function discoverModelsForHarness(harness, service3) {
|
|
87235
|
+
const installed2 = await service3.isInstalled();
|
|
87236
|
+
if (!installed2) {
|
|
87237
|
+
return { harness, models: [], installed: false };
|
|
87238
|
+
}
|
|
87239
|
+
try {
|
|
87240
|
+
const models = await service3.listModels();
|
|
87241
|
+
return { harness, models, installed: true };
|
|
87242
|
+
} catch (reason) {
|
|
87243
|
+
console.warn(JSON.stringify({
|
|
87244
|
+
event: "discover-models-error",
|
|
87245
|
+
harness,
|
|
87246
|
+
reason: getErrorMessage(reason)
|
|
87247
|
+
}));
|
|
87248
|
+
return { harness, models: [], installed: true };
|
|
87249
|
+
}
|
|
87250
|
+
}
|
|
86855
87251
|
async function discoverModels(agentServices) {
|
|
86856
87252
|
return exports_Effect.runPromise(discoverModelsEffect(agentServices));
|
|
86857
87253
|
}
|
|
@@ -86886,6 +87282,51 @@ function createDefaultDeps18() {
|
|
|
86886
87282
|
agentProcessManager: null
|
|
86887
87283
|
};
|
|
86888
87284
|
}
|
|
87285
|
+
function assembleDaemonSessionInit(args2) {
|
|
87286
|
+
const {
|
|
87287
|
+
client: client4,
|
|
87288
|
+
typedSessionId,
|
|
87289
|
+
machineId,
|
|
87290
|
+
config: config3,
|
|
87291
|
+
convexUrl,
|
|
87292
|
+
agentServices,
|
|
87293
|
+
cachedModels,
|
|
87294
|
+
deps
|
|
87295
|
+
} = args2;
|
|
87296
|
+
deps.backend.mutation = (endpoint, args3) => client4.mutation(endpoint, args3);
|
|
87297
|
+
deps.backend.query = (endpoint, args3) => client4.query(endpoint, args3);
|
|
87298
|
+
deps.agentProcessManager = new AgentProcessManager({
|
|
87299
|
+
agentServices,
|
|
87300
|
+
backend: deps.backend,
|
|
87301
|
+
sessionId: typedSessionId,
|
|
87302
|
+
machineId,
|
|
87303
|
+
processes: deps.processes,
|
|
87304
|
+
clock: deps.clock,
|
|
87305
|
+
fs: deps.fs,
|
|
87306
|
+
persistence: deps.machine,
|
|
87307
|
+
spawning: deps.spawning,
|
|
87308
|
+
crashLoop: new CrashLoopTracker,
|
|
87309
|
+
convexUrl
|
|
87310
|
+
});
|
|
87311
|
+
return {
|
|
87312
|
+
client: client4,
|
|
87313
|
+
sessionId: typedSessionId,
|
|
87314
|
+
machineId,
|
|
87315
|
+
config: config3,
|
|
87316
|
+
convexUrl,
|
|
87317
|
+
backend: deps.backend,
|
|
87318
|
+
fs: deps.fs,
|
|
87319
|
+
machine: deps.machine,
|
|
87320
|
+
spawning: deps.spawning,
|
|
87321
|
+
agentProcessManager: deps.agentProcessManager,
|
|
87322
|
+
events: new DaemonEventBus,
|
|
87323
|
+
agentServices,
|
|
87324
|
+
lastPushedGitState: new Map,
|
|
87325
|
+
lastPushedModels: Object.keys(cachedModels).length > 0 ? cachedModels : null,
|
|
87326
|
+
lastPushedHarnessFingerprint: harnessCapabilitiesFingerprint(config3.availableHarnesses, config3.harnessVersions),
|
|
87327
|
+
logger: console
|
|
87328
|
+
};
|
|
87329
|
+
}
|
|
86889
87330
|
|
|
86890
87331
|
class NetworkRetryError {
|
|
86891
87332
|
cause;
|
|
@@ -86900,21 +87341,11 @@ async function initDaemon() {
|
|
|
86900
87341
|
return exports_Effect.runPromise(initDaemonEffect);
|
|
86901
87342
|
}
|
|
86902
87343
|
var discoverModelsEffect = (agentServices) => exports_Effect.gen(function* () {
|
|
86903
|
-
const discoverOne = ([harness, service3]) => exports_Effect.promise(() => service3
|
|
86904
|
-
if (!
|
|
86905
|
-
return
|
|
87344
|
+
const discoverOne = ([harness, service3]) => exports_Effect.promise(() => discoverModelsForHarness(harness, service3)).pipe(exports_Effect.map((result) => {
|
|
87345
|
+
if (!result.installed) {
|
|
87346
|
+
return;
|
|
86906
87347
|
}
|
|
86907
|
-
return
|
|
86908
|
-
try: () => service3.listModels(),
|
|
86909
|
-
catch: (reason) => reason
|
|
86910
|
-
}).pipe(exports_Effect.map((models) => ({ harness, models })), exports_Effect.catchAll((reason) => {
|
|
86911
|
-
console.warn(JSON.stringify({
|
|
86912
|
-
event: "discover-models-error",
|
|
86913
|
-
harness,
|
|
86914
|
-
reason: getErrorMessage(reason)
|
|
86915
|
-
}));
|
|
86916
|
-
return exports_Effect.succeed({ harness, models: [] });
|
|
86917
|
-
}));
|
|
87348
|
+
return { harness: result.harness, models: result.models };
|
|
86918
87349
|
}));
|
|
86919
87350
|
const results = yield* exports_Effect.forEach(Array.from(agentServices.entries()), discoverOne, {
|
|
86920
87351
|
concurrency: "unbounded"
|
|
@@ -87011,21 +87442,28 @@ Run: chatroom auth login`);
|
|
|
87011
87442
|
return yield* exports_Effect.die(new Error("Machine config missing after ensureMachineRegistered — this should not happen"));
|
|
87012
87443
|
}
|
|
87013
87444
|
return config3;
|
|
87014
|
-
}),
|
|
87445
|
+
}), registerMachineEffect = (client4, sessionId, config3) => exports_Effect.catchAll(exports_Effect.tryPromise(() => client4.mutation(api.machines.register, {
|
|
87446
|
+
sessionId,
|
|
87447
|
+
machineId: config3.machineId,
|
|
87448
|
+
hostname: config3.hostname,
|
|
87449
|
+
os: config3.os,
|
|
87450
|
+
availableHarnesses: config3.availableHarnesses,
|
|
87451
|
+
harnessVersions: config3.harnessVersions
|
|
87452
|
+
})), (error) => exports_Effect.sync(() => {
|
|
87453
|
+
console.warn(`⚠️ Machine registration update failed: ${getErrorMessage(error)}`);
|
|
87454
|
+
})), fetchCachedMachineModelsEffect = (client4, sessionId, machineId) => exports_Effect.tryPromise({
|
|
87455
|
+
try: () => client4.query(api.machines.getMachineModels, { sessionId, machineId }),
|
|
87456
|
+
catch: (e) => e
|
|
87457
|
+
}).pipe(exports_Effect.map((result) => result?.availableModels ?? {}), exports_Effect.catchAll(() => exports_Effect.succeed({}))), connectOnceEffect = (client4, sessionId, convexUrl) => exports_Effect.gen(function* () {
|
|
87458
|
+
const typedSessionId = yield* validateSessionEffect(client4, sessionId, convexUrl);
|
|
87459
|
+
const config3 = yield* setupMachineEffect();
|
|
87015
87460
|
const { machineId } = config3;
|
|
87016
|
-
|
|
87017
|
-
|
|
87018
|
-
|
|
87019
|
-
|
|
87020
|
-
|
|
87021
|
-
|
|
87022
|
-
availableHarnesses: config3.availableHarnesses,
|
|
87023
|
-
harnessVersions: config3.harnessVersions,
|
|
87024
|
-
availableModels
|
|
87025
|
-
})), (error) => exports_Effect.sync(() => {
|
|
87026
|
-
console.warn(`⚠️ Machine registration update failed: ${getErrorMessage(error)}`);
|
|
87027
|
-
}));
|
|
87028
|
-
return availableModels;
|
|
87461
|
+
initHarnessRegistry();
|
|
87462
|
+
const agentServices = new Map(getAllHarnesses().map((s) => [s.id, s]));
|
|
87463
|
+
yield* registerMachineEffect(client4, typedSessionId, config3);
|
|
87464
|
+
const cachedModels = yield* fetchCachedMachineModelsEffect(client4, typedSessionId, machineId);
|
|
87465
|
+
yield* connectDaemonEffect(client4, typedSessionId, machineId);
|
|
87466
|
+
return { typedSessionId, config: config3, machineId, agentServices, cachedModels };
|
|
87029
87467
|
}), connectDaemonEffect = (client4, sessionId, machineId) => exports_Effect.tryPromise({
|
|
87030
87468
|
try: () => client4.mutation(api.machines.updateDaemonStatus, {
|
|
87031
87469
|
sessionId,
|
|
@@ -87070,14 +87508,7 @@ Run: chatroom auth login`);
|
|
|
87070
87508
|
const attemptRef = yield* exports_Ref.make(0);
|
|
87071
87509
|
const connectOnce = exports_Effect.gen(function* () {
|
|
87072
87510
|
yield* exports_Ref.update(attemptRef, (n) => n + 1);
|
|
87073
|
-
|
|
87074
|
-
const config3 = yield* setupMachineEffect();
|
|
87075
|
-
const { machineId } = config3;
|
|
87076
|
-
initHarnessRegistry();
|
|
87077
|
-
const agentServices = new Map(getAllHarnesses().map((s) => [s.id, s]));
|
|
87078
|
-
const availableModels = yield* registerCapabilitiesEffect(client4, typedSessionId, config3, agentServices);
|
|
87079
|
-
yield* connectDaemonEffect(client4, typedSessionId, machineId);
|
|
87080
|
-
return { typedSessionId, config: config3, machineId, agentServices, availableModels };
|
|
87511
|
+
return yield* connectOnceEffect(client4, sessionId, convexUrl);
|
|
87081
87512
|
}).pipe(exports_Effect.catchAll((error) => exports_Effect.flatMap(exports_Ref.get(attemptRef), (currentAttempt) => isNetworkError(error) ? exports_Effect.fail(new NetworkRetryError(error, currentAttempt)) : exports_Effect.die(error))));
|
|
87082
87513
|
const retrySchedule2 = exports_Schedule.fixed(exports_Duration.millis(CONNECTION_RETRY_INTERVAL_MS));
|
|
87083
87514
|
const connectWithRetry = connectOnce.pipe(exports_Effect.tapError((retryErr) => exports_Effect.gen(function* () {
|
|
@@ -87119,7 +87550,11 @@ var init_init2 = __esm(() => {
|
|
|
87119
87550
|
init_spawn_env();
|
|
87120
87551
|
AUTH_WAIT_TIMEOUT_MS = 5 * 60 * 1000;
|
|
87121
87552
|
initDaemonEffect = exports_Effect.gen(function* () {
|
|
87122
|
-
|
|
87553
|
+
const lockAcquired = yield* exports_Effect.tryPromise({
|
|
87554
|
+
try: () => acquireLockWithRetry(),
|
|
87555
|
+
catch: (e) => e
|
|
87556
|
+
});
|
|
87557
|
+
if (!lockAcquired) {
|
|
87123
87558
|
return yield* exports_Effect.sync(() => {
|
|
87124
87559
|
process.exit(1);
|
|
87125
87560
|
});
|
|
@@ -87142,44 +87577,19 @@ var init_init2 = __esm(() => {
|
|
|
87142
87577
|
try: () => getConvexClient(),
|
|
87143
87578
|
catch: (e) => e
|
|
87144
87579
|
});
|
|
87145
|
-
const { typedSessionId, config: config3, machineId, agentServices,
|
|
87146
|
-
const
|
|
87147
|
-
deps.backend.mutation = (endpoint, args2) => client4.mutation(endpoint, args2);
|
|
87148
|
-
deps.backend.query = (endpoint, args2) => client4.query(endpoint, args2);
|
|
87149
|
-
deps.agentProcessManager = new AgentProcessManager({
|
|
87150
|
-
agentServices,
|
|
87151
|
-
backend: deps.backend,
|
|
87152
|
-
sessionId: typedSessionId,
|
|
87153
|
-
machineId,
|
|
87154
|
-
processes: deps.processes,
|
|
87155
|
-
clock: deps.clock,
|
|
87156
|
-
fs: deps.fs,
|
|
87157
|
-
persistence: deps.machine,
|
|
87158
|
-
spawning: deps.spawning,
|
|
87159
|
-
crashLoop: new CrashLoopTracker,
|
|
87160
|
-
convexUrl
|
|
87161
|
-
});
|
|
87162
|
-
const events = new DaemonEventBus;
|
|
87163
|
-
const init2 = {
|
|
87580
|
+
const { typedSessionId, config: config3, machineId, agentServices, cachedModels } = yield* connectWithRetryEffect(client4, sessionId, convexUrl);
|
|
87581
|
+
const init2 = assembleDaemonSessionInit({
|
|
87164
87582
|
client: client4,
|
|
87165
|
-
|
|
87583
|
+
typedSessionId,
|
|
87166
87584
|
machineId,
|
|
87167
87585
|
config: config3,
|
|
87168
87586
|
convexUrl,
|
|
87169
|
-
backend: deps.backend,
|
|
87170
|
-
fs: deps.fs,
|
|
87171
|
-
machine: deps.machine,
|
|
87172
|
-
spawning: deps.spawning,
|
|
87173
|
-
agentProcessManager: deps.agentProcessManager,
|
|
87174
|
-
events,
|
|
87175
87587
|
agentServices,
|
|
87176
|
-
|
|
87177
|
-
|
|
87178
|
-
|
|
87179
|
-
logger: console
|
|
87180
|
-
};
|
|
87588
|
+
cachedModels,
|
|
87589
|
+
deps: createDefaultDeps18()
|
|
87590
|
+
});
|
|
87181
87591
|
yield* registerEventListenersEffect().pipe(exports_Effect.provide(daemonSessionToLayers(init2)));
|
|
87182
|
-
yield* logStartupEffect(
|
|
87592
|
+
yield* logStartupEffect(cachedModels).pipe(exports_Effect.provide(daemonSessionToLayers(init2)));
|
|
87183
87593
|
yield* recoverStateEffect(init2);
|
|
87184
87594
|
return init2;
|
|
87185
87595
|
});
|
|
@@ -87229,7 +87639,70 @@ function logRefreshOutcome(diff8, totalCount) {
|
|
|
87229
87639
|
const summary5 = totalCount > 0 ? `${totalCount} models` : "none discovered";
|
|
87230
87640
|
console.log(`[${formatTimestamp()}] \uD83D\uDD04 Model refresh pushed: ${summary5}`);
|
|
87231
87641
|
}
|
|
87232
|
-
|
|
87642
|
+
function logPushOutcome(modelDiff, totalCount, options) {
|
|
87643
|
+
if (options?.logPrefix) {
|
|
87644
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDD04 ${options.logPrefix}: ${totalCount > 0 ? `${totalCount} models` : "none discovered"}`);
|
|
87645
|
+
return;
|
|
87646
|
+
}
|
|
87647
|
+
logRefreshOutcome(modelDiff, totalCount);
|
|
87648
|
+
}
|
|
87649
|
+
var pushModelsSnapshotMutationEffect = (models, modelDiff, nextHarnessFingerprint, ctxConfig, options) => exports_Effect.gen(function* () {
|
|
87650
|
+
const session2 = yield* DaemonSessionService;
|
|
87651
|
+
yield* exports_Effect.tryPromise({
|
|
87652
|
+
try: async () => session2.backend.mutation(api.machines.refreshCapabilities, {
|
|
87653
|
+
sessionId: session2.sessionId,
|
|
87654
|
+
machineId: session2.machineId,
|
|
87655
|
+
availableHarnesses: ctxConfig.availableHarnesses,
|
|
87656
|
+
harnessVersions: ctxConfig.harnessVersions,
|
|
87657
|
+
availableModels: models
|
|
87658
|
+
}),
|
|
87659
|
+
catch: (e) => e
|
|
87660
|
+
});
|
|
87661
|
+
const totalCount = Object.values(models).flat().length;
|
|
87662
|
+
logPushOutcome(modelDiff, totalCount, options);
|
|
87663
|
+
return {
|
|
87664
|
+
kind: "pushed",
|
|
87665
|
+
snapshot: {
|
|
87666
|
+
lastPushedModels: models,
|
|
87667
|
+
lastPushedHarnessFingerprint: nextHarnessFingerprint
|
|
87668
|
+
}
|
|
87669
|
+
};
|
|
87670
|
+
}), pushModelsSnapshotIfChangedEffect = (models, options) => exports_Effect.gen(function* () {
|
|
87671
|
+
const session2 = yield* DaemonSessionService;
|
|
87672
|
+
const mutable = yield* DaemonMutableStateService;
|
|
87673
|
+
if (!session2.config) {
|
|
87674
|
+
return { kind: "skipped_no_changes" };
|
|
87675
|
+
}
|
|
87676
|
+
const lastPushedModels = yield* exports_Ref.get(mutable.lastPushedModels);
|
|
87677
|
+
const lastPushedHarnessFingerprint = yield* exports_Ref.get(mutable.lastPushedHarnessFingerprint);
|
|
87678
|
+
const modelDiff = diffModels(lastPushedModels, models);
|
|
87679
|
+
const nextHarnessFingerprint = harnessCapabilitiesFingerprint(session2.config.availableHarnesses, session2.config.harnessVersions);
|
|
87680
|
+
if (!modelDiff.hasChanges && !harnessFingerprintChanged(lastPushedHarnessFingerprint, nextHarnessFingerprint)) {
|
|
87681
|
+
return { kind: "skipped_no_changes" };
|
|
87682
|
+
}
|
|
87683
|
+
return yield* pushModelsSnapshotMutationEffect(models, modelDiff, nextHarnessFingerprint, session2.config, options);
|
|
87684
|
+
}).pipe(exports_Effect.catchAll((error) => exports_Effect.sync(() => {
|
|
87685
|
+
const message = getErrorMessage(error);
|
|
87686
|
+
console.warn(`[${formatTimestamp()}] ⚠️ Model refresh failed: ${message}`);
|
|
87687
|
+
return { kind: "failed", message };
|
|
87688
|
+
}))), refreshModelsEffect, discoverAndPushHarnessModelsEffect = (harness, service3) => exports_Effect.gen(function* () {
|
|
87689
|
+
const mutable = yield* DaemonMutableStateService;
|
|
87690
|
+
const result = yield* exports_Effect.promise(() => discoverModelsForHarness(harness, service3));
|
|
87691
|
+
const current = (yield* exports_Ref.get(mutable.lastPushedModels)) ?? {};
|
|
87692
|
+
const next4 = { ...current };
|
|
87693
|
+
if (result.installed) {
|
|
87694
|
+
next4[harness] = result.models;
|
|
87695
|
+
} else {
|
|
87696
|
+
delete next4[harness];
|
|
87697
|
+
}
|
|
87698
|
+
const pushOutcome = yield* pushModelsSnapshotIfChangedEffect(next4, {
|
|
87699
|
+
logPrefix: `${harness} models updated`
|
|
87700
|
+
});
|
|
87701
|
+
if (pushOutcome.kind === "pushed") {
|
|
87702
|
+
yield* exports_Ref.set(mutable.lastPushedModels, pushOutcome.snapshot.lastPushedModels);
|
|
87703
|
+
yield* exports_Ref.set(mutable.lastPushedHarnessFingerprint, pushOutcome.snapshot.lastPushedHarnessFingerprint);
|
|
87704
|
+
}
|
|
87705
|
+
}), startBackgroundModelDiscoveryEffect;
|
|
87233
87706
|
var init_models_refresh = __esm(() => {
|
|
87234
87707
|
init_esm();
|
|
87235
87708
|
init_daemon_services();
|
|
@@ -87244,8 +87717,6 @@ var init_models_refresh = __esm(() => {
|
|
|
87244
87717
|
return { kind: "noop" };
|
|
87245
87718
|
}
|
|
87246
87719
|
const ctxConfig = session2.config;
|
|
87247
|
-
const lastPushedModels = yield* exports_Ref.get(mutable.lastPushedModels);
|
|
87248
|
-
const lastPushedHarnessFingerprint = yield* exports_Ref.get(mutable.lastPushedHarnessFingerprint);
|
|
87249
87720
|
const outcome = yield* exports_Effect.gen(function* () {
|
|
87250
87721
|
const models = yield* exports_Effect.tryPromise({
|
|
87251
87722
|
try: async () => discoverModels(session2.agentServices),
|
|
@@ -87257,31 +87728,7 @@ var init_models_refresh = __esm(() => {
|
|
|
87257
87728
|
});
|
|
87258
87729
|
ctxConfig.availableHarnesses = freshConfig.availableHarnesses;
|
|
87259
87730
|
ctxConfig.harnessVersions = freshConfig.harnessVersions;
|
|
87260
|
-
|
|
87261
|
-
const nextHarnessFingerprint = harnessCapabilitiesFingerprint(ctxConfig.availableHarnesses, ctxConfig.harnessVersions);
|
|
87262
|
-
const fingerprintChanged = harnessFingerprintChanged(lastPushedHarnessFingerprint, nextHarnessFingerprint);
|
|
87263
|
-
if (!modelDiff.hasChanges && !fingerprintChanged) {
|
|
87264
|
-
return { kind: "skipped_no_changes" };
|
|
87265
|
-
}
|
|
87266
|
-
const totalCount = Object.values(models).flat().length;
|
|
87267
|
-
yield* exports_Effect.tryPromise({
|
|
87268
|
-
try: async () => session2.backend.mutation(api.machines.refreshCapabilities, {
|
|
87269
|
-
sessionId: session2.sessionId,
|
|
87270
|
-
machineId: session2.machineId,
|
|
87271
|
-
availableHarnesses: ctxConfig.availableHarnesses,
|
|
87272
|
-
harnessVersions: ctxConfig.harnessVersions,
|
|
87273
|
-
availableModels: models
|
|
87274
|
-
}),
|
|
87275
|
-
catch: (e) => e
|
|
87276
|
-
});
|
|
87277
|
-
logRefreshOutcome(modelDiff, totalCount);
|
|
87278
|
-
return {
|
|
87279
|
-
kind: "pushed",
|
|
87280
|
-
snapshot: {
|
|
87281
|
-
lastPushedModels: models,
|
|
87282
|
-
lastPushedHarnessFingerprint: nextHarnessFingerprint
|
|
87283
|
-
}
|
|
87284
|
-
};
|
|
87731
|
+
return yield* pushModelsSnapshotIfChangedEffect(models);
|
|
87285
87732
|
}).pipe(exports_Effect.catchAll((error) => exports_Effect.sync(() => {
|
|
87286
87733
|
const message = getErrorMessage(error);
|
|
87287
87734
|
console.warn(`[${formatTimestamp()}] ⚠️ Model refresh failed: ${message}`);
|
|
@@ -87290,9 +87737,22 @@ var init_models_refresh = __esm(() => {
|
|
|
87290
87737
|
if (outcome.kind === "pushed") {
|
|
87291
87738
|
yield* exports_Ref.set(mutable.lastPushedModels, outcome.snapshot.lastPushedModels);
|
|
87292
87739
|
yield* exports_Ref.set(mutable.lastPushedHarnessFingerprint, outcome.snapshot.lastPushedHarnessFingerprint);
|
|
87740
|
+
return {
|
|
87741
|
+
kind: "pushed",
|
|
87742
|
+
snapshot: outcome.snapshot
|
|
87743
|
+
};
|
|
87744
|
+
}
|
|
87745
|
+
if (outcome.kind === "skipped_no_changes") {
|
|
87746
|
+
return { kind: "skipped_no_changes" };
|
|
87293
87747
|
}
|
|
87294
87748
|
return outcome;
|
|
87295
87749
|
});
|
|
87750
|
+
startBackgroundModelDiscoveryEffect = exports_Effect.gen(function* () {
|
|
87751
|
+
const session2 = yield* DaemonSessionService;
|
|
87752
|
+
if (!session2.config)
|
|
87753
|
+
return;
|
|
87754
|
+
yield* exports_Effect.forEach(Array.from(session2.agentServices.entries()), ([harness, service3]) => discoverAndPushHarnessModelsEffect(harness, service3), { concurrency: "unbounded" });
|
|
87755
|
+
});
|
|
87296
87756
|
});
|
|
87297
87757
|
|
|
87298
87758
|
// src/commands/machine/daemon-start/observed-sync.ts
|
|
@@ -87489,225 +87949,6 @@ var init_observed_sync = __esm(() => {
|
|
|
87489
87949
|
init_convex_error();
|
|
87490
87950
|
});
|
|
87491
87951
|
|
|
87492
|
-
// ../../services/backend/src/domain/handoff/parse-compress-context.ts
|
|
87493
|
-
function findSectionIndex(content, headings) {
|
|
87494
|
-
const indices = headings.map((heading) => content.indexOf(heading)).filter((idx) => idx !== -1);
|
|
87495
|
-
return indices.length === 0 ? -1 : Math.min(...indices);
|
|
87496
|
-
}
|
|
87497
|
-
function normalizeMode(raw) {
|
|
87498
|
-
const value = raw.toLowerCase();
|
|
87499
|
-
if (value === "reset")
|
|
87500
|
-
return "new_session";
|
|
87501
|
-
if (value === "none")
|
|
87502
|
-
return value;
|
|
87503
|
-
return DEFAULT_MODE;
|
|
87504
|
-
}
|
|
87505
|
-
function extractSectionBody(content, sectionIdx) {
|
|
87506
|
-
const matchedHeading = SECTION_HEADINGS.find((h) => content.indexOf(h, sectionIdx) === sectionIdx) ?? SECTION_HEADINGS[0];
|
|
87507
|
-
const afterSection = content.slice(sectionIdx);
|
|
87508
|
-
const nextHeading = afterSection.slice(matchedHeading.length).search(/\n## /);
|
|
87509
|
-
return nextHeading === -1 ? afterSection : afterSection.slice(0, matchedHeading.length + nextHeading);
|
|
87510
|
-
}
|
|
87511
|
-
function parseCompressContext(handoffContent) {
|
|
87512
|
-
const sectionIdx = findSectionIndex(handoffContent, SECTION_HEADINGS);
|
|
87513
|
-
if (sectionIdx === -1)
|
|
87514
|
-
return DEFAULT_MODE;
|
|
87515
|
-
const match17 = extractSectionBody(handoffContent, sectionIdx).match(DATA_TAG);
|
|
87516
|
-
if (!match17)
|
|
87517
|
-
return DEFAULT_MODE;
|
|
87518
|
-
return normalizeMode(match17[1]);
|
|
87519
|
-
}
|
|
87520
|
-
function compressContextToWantResume(mode) {
|
|
87521
|
-
return mode === "none";
|
|
87522
|
-
}
|
|
87523
|
-
var SECTION_HEADINGS, DATA_TAG, DEFAULT_MODE = "new_session";
|
|
87524
|
-
var init_parse_compress_context = __esm(() => {
|
|
87525
|
-
SECTION_HEADINGS = ["## Session Management", "## Restart new context"];
|
|
87526
|
-
DATA_TAG = /\/\/\s*data:agent\.compress_context=(new_session|reset|none)\b/i;
|
|
87527
|
-
});
|
|
87528
|
-
|
|
87529
|
-
// src/domain/native-integration/predicates.ts
|
|
87530
|
-
function isNativePendingAliveRunning(task) {
|
|
87531
|
-
const { agentConfig, status: status3 } = task;
|
|
87532
|
-
return isNativeHarness(agentConfig.agentHarness) && status3 === "pending" && agentConfig.spawnedAgentPid != null && agentConfig.desiredState === "running";
|
|
87533
|
-
}
|
|
87534
|
-
function isNativeInjectableAliveRunning(task) {
|
|
87535
|
-
const { agentConfig, status: status3 } = task;
|
|
87536
|
-
if (!isNativeHarness(agentConfig.agentHarness))
|
|
87537
|
-
return false;
|
|
87538
|
-
if (agentConfig.spawnedAgentPid == null || agentConfig.desiredState !== "running") {
|
|
87539
|
-
return false;
|
|
87540
|
-
}
|
|
87541
|
-
if (status3 === "pending")
|
|
87542
|
-
return true;
|
|
87543
|
-
if (status3 === "acknowledged") {
|
|
87544
|
-
const assignedTo = task.assignedTo?.toLowerCase();
|
|
87545
|
-
return assignedTo === agentConfig.role.toLowerCase();
|
|
87546
|
-
}
|
|
87547
|
-
return false;
|
|
87548
|
-
}
|
|
87549
|
-
function isInjectableNativeAction(action) {
|
|
87550
|
-
if (action == null)
|
|
87551
|
-
return true;
|
|
87552
|
-
return action === NATIVE_WAITING_ACTION;
|
|
87553
|
-
}
|
|
87554
|
-
function isNativeIdleAfterTaskComplete(participant) {
|
|
87555
|
-
return participant.lastSeenAction === NATIVE_TASK_INJECTED_ACTION && participant.lastStatus === "task.completed";
|
|
87556
|
-
}
|
|
87557
|
-
function isNativeAcknowledgedInjectionRetry(task) {
|
|
87558
|
-
if (task.status !== "acknowledged")
|
|
87559
|
-
return false;
|
|
87560
|
-
const assignedTo = task.assignedTo?.toLowerCase();
|
|
87561
|
-
if (assignedTo !== task.agentConfig.role.toLowerCase())
|
|
87562
|
-
return false;
|
|
87563
|
-
return task.participant?.lastSeenAction === NATIVE_TASK_INJECTED_ACTION;
|
|
87564
|
-
}
|
|
87565
|
-
function isStaleCliGetNextTaskWaiting(task) {
|
|
87566
|
-
const lastSeenAt = task.participant?.lastSeenAt ?? 0;
|
|
87567
|
-
return task.participant?.lastSeenAction === "get-next-task:started" && task.createdAt > lastSeenAt;
|
|
87568
|
-
}
|
|
87569
|
-
function isCliIdleNotListening(task, now, thresholdMs) {
|
|
87570
|
-
const lastSeenAt = task.participant?.lastSeenAt ?? 0;
|
|
87571
|
-
if (lastSeenAt === 0)
|
|
87572
|
-
return now - task.createdAt > thresholdMs;
|
|
87573
|
-
return now - lastSeenAt > thresholdMs;
|
|
87574
|
-
}
|
|
87575
|
-
var init_predicates = __esm(() => {
|
|
87576
|
-
init_types();
|
|
87577
|
-
init_participant();
|
|
87578
|
-
});
|
|
87579
|
-
|
|
87580
|
-
// src/domain/native-integration/index.ts
|
|
87581
|
-
var init_native_integration = __esm(() => {
|
|
87582
|
-
init_types();
|
|
87583
|
-
init_predicates();
|
|
87584
|
-
init_spawn_policy();
|
|
87585
|
-
});
|
|
87586
|
-
|
|
87587
|
-
// src/commands/machine/daemon-start/native-task-injector-logic.ts
|
|
87588
|
-
function shouldInjectNativeTask(task, opts) {
|
|
87589
|
-
if (!isNativeInjectableAliveRunning(task))
|
|
87590
|
-
return false;
|
|
87591
|
-
if (opts?.alreadyInjectedTaskIds?.has(task.taskId))
|
|
87592
|
-
return false;
|
|
87593
|
-
return isInjectableNativeAction(task.participant?.lastSeenAction) || isNativeIdleAfterTaskComplete(task.participant ?? {}) || isNativeAcknowledgedInjectionRetry(task);
|
|
87594
|
-
}
|
|
87595
|
-
function buildNativeInjectionPrompt(params) {
|
|
87596
|
-
const { taskDeliveryOutput, compressMode } = params;
|
|
87597
|
-
if (compressMode === "new_session") {
|
|
87598
|
-
return [
|
|
87599
|
-
"⚠️ Context was compacted. Run `chatroom get-system-prompt` only if role instructions are missing.",
|
|
87600
|
-
"",
|
|
87601
|
-
taskDeliveryOutput
|
|
87602
|
-
].join(`
|
|
87603
|
-
`);
|
|
87604
|
-
}
|
|
87605
|
-
return taskDeliveryOutput;
|
|
87606
|
-
}
|
|
87607
|
-
|
|
87608
|
-
class NativeInjectionDedup {
|
|
87609
|
-
injected = new Set;
|
|
87610
|
-
inFlight = new Set;
|
|
87611
|
-
tryAcquire(taskId) {
|
|
87612
|
-
if (this.has(taskId) || this.inFlight.has(taskId)) {
|
|
87613
|
-
return false;
|
|
87614
|
-
}
|
|
87615
|
-
this.inFlight.add(taskId);
|
|
87616
|
-
return true;
|
|
87617
|
-
}
|
|
87618
|
-
markInjected(taskId) {
|
|
87619
|
-
this.inFlight.delete(taskId);
|
|
87620
|
-
this.injected.add(taskId);
|
|
87621
|
-
}
|
|
87622
|
-
has(taskId) {
|
|
87623
|
-
return this.injected.has(taskId);
|
|
87624
|
-
}
|
|
87625
|
-
clear(taskId) {
|
|
87626
|
-
this.inFlight.delete(taskId);
|
|
87627
|
-
this.injected.delete(taskId);
|
|
87628
|
-
}
|
|
87629
|
-
}
|
|
87630
|
-
var init_native_task_injector_logic = __esm(() => {
|
|
87631
|
-
init_predicates();
|
|
87632
|
-
init_native_integration();
|
|
87633
|
-
});
|
|
87634
|
-
|
|
87635
|
-
// src/commands/machine/daemon-start/native-task-injector.ts
|
|
87636
|
-
function runNativeInjectionEffect(task, deps, dedup) {
|
|
87637
|
-
return exports_Effect.gen(function* () {
|
|
87638
|
-
if (!shouldInjectNativeTask(task, { alreadyInjectedTaskIds: dedup })) {
|
|
87639
|
-
return;
|
|
87640
|
-
}
|
|
87641
|
-
const { chatroomId, taskId, taskContent, agentConfig, status: status3 } = task;
|
|
87642
|
-
const { role } = agentConfig;
|
|
87643
|
-
if (!dedup.tryAcquire(taskId)) {
|
|
87644
|
-
return;
|
|
87645
|
-
}
|
|
87646
|
-
if (status3 === "pending") {
|
|
87647
|
-
const claimResult = yield* exports_Effect.tryPromise({
|
|
87648
|
-
try: () => deps.backend.mutation(api.tasks.claimTask, {
|
|
87649
|
-
sessionId: deps.sessionId,
|
|
87650
|
-
chatroomId,
|
|
87651
|
-
role,
|
|
87652
|
-
taskId
|
|
87653
|
-
}),
|
|
87654
|
-
catch: (err) => err
|
|
87655
|
-
}).pipe(exports_Effect.either);
|
|
87656
|
-
if (claimResult._tag === "Left") {
|
|
87657
|
-
dedup.clear(taskId);
|
|
87658
|
-
return yield* exports_Effect.fail(claimResult.left);
|
|
87659
|
-
}
|
|
87660
|
-
}
|
|
87661
|
-
const deliveryResult = yield* exports_Effect.tryPromise({
|
|
87662
|
-
try: () => deps.backend.query(api.messages.getTaskDeliveryPrompt, {
|
|
87663
|
-
sessionId: deps.sessionId,
|
|
87664
|
-
chatroomId,
|
|
87665
|
-
role,
|
|
87666
|
-
taskId,
|
|
87667
|
-
convexUrl: deps.convexUrl
|
|
87668
|
-
}),
|
|
87669
|
-
catch: (err) => err
|
|
87670
|
-
}).pipe(exports_Effect.either);
|
|
87671
|
-
if (deliveryResult._tag === "Left") {
|
|
87672
|
-
dedup.clear(taskId);
|
|
87673
|
-
return yield* exports_Effect.fail(deliveryResult.left);
|
|
87674
|
-
}
|
|
87675
|
-
const delivery = deliveryResult.right;
|
|
87676
|
-
const prompt = buildNativeInjectionPrompt({
|
|
87677
|
-
taskDeliveryOutput: delivery.fullCliOutput,
|
|
87678
|
-
compressMode: parseCompressContext(taskContent)
|
|
87679
|
-
});
|
|
87680
|
-
yield* exports_Effect.tryPromise({
|
|
87681
|
-
try: () => deps.backend.mutation(api.participants.join, {
|
|
87682
|
-
sessionId: deps.sessionId,
|
|
87683
|
-
chatroomId,
|
|
87684
|
-
role,
|
|
87685
|
-
action: NATIVE_TASK_INJECTED_ACTION,
|
|
87686
|
-
taskId
|
|
87687
|
-
}),
|
|
87688
|
-
catch: (err) => err
|
|
87689
|
-
}).pipe(exports_Effect.tapError(() => exports_Effect.sync(() => dedup.clear(taskId))));
|
|
87690
|
-
const resumeResult = yield* exports_Effect.tryPromise({
|
|
87691
|
-
try: () => deps.agentMgr.resumeTurnForSlot({ chatroomId, role, prompt }),
|
|
87692
|
-
catch: (err) => err
|
|
87693
|
-
}).pipe(exports_Effect.either);
|
|
87694
|
-
if (resumeResult._tag === "Left") {
|
|
87695
|
-
dedup.clear(taskId);
|
|
87696
|
-
console.warn(`[NativeTaskInjector] resumeTurn failed for ${role}@${chatroomId}: ${getErrorMessage(resumeResult.left)}`);
|
|
87697
|
-
return;
|
|
87698
|
-
}
|
|
87699
|
-
dedup.markInjected(taskId);
|
|
87700
|
-
});
|
|
87701
|
-
}
|
|
87702
|
-
var init_native_task_injector = __esm(() => {
|
|
87703
|
-
init_participant();
|
|
87704
|
-
init_parse_compress_context();
|
|
87705
|
-
init_esm();
|
|
87706
|
-
init_native_task_injector_logic();
|
|
87707
|
-
init_api3();
|
|
87708
|
-
init_convex_error();
|
|
87709
|
-
});
|
|
87710
|
-
|
|
87711
87952
|
// src/commands/machine/daemon-start/task-monitor-logic.ts
|
|
87712
87953
|
function isPendingAliveRunningTask(task) {
|
|
87713
87954
|
const { agentConfig, status: status3 } = task;
|
|
@@ -87722,18 +87963,38 @@ function isSlotUnavailableForPid(slot, pid, isPidAlive) {
|
|
|
87722
87963
|
}
|
|
87723
87964
|
return !isPidAlive(pid);
|
|
87724
87965
|
}
|
|
87725
|
-
function
|
|
87726
|
-
|
|
87727
|
-
|
|
87728
|
-
|
|
87729
|
-
|
|
87730
|
-
|
|
87966
|
+
function isNativeRevivableTaskStatus(task) {
|
|
87967
|
+
const { status: status3 } = task;
|
|
87968
|
+
if (status3 === "pending") {
|
|
87969
|
+
return task.agentConfig.spawnedAgentPid != null;
|
|
87970
|
+
}
|
|
87971
|
+
if (status3 === "acknowledged") {
|
|
87972
|
+
return task.assignedTo?.toLowerCase() === task.agentConfig.role.toLowerCase();
|
|
87973
|
+
}
|
|
87974
|
+
return false;
|
|
87975
|
+
}
|
|
87976
|
+
function isNativeAgentSlotDown(task, health) {
|
|
87731
87977
|
const slot = health.getSlot(task.chatroomId, task.agentConfig.role);
|
|
87978
|
+
if (slot?.state === "spawning")
|
|
87979
|
+
return false;
|
|
87980
|
+
const pid = task.agentConfig.spawnedAgentPid ?? slot?.pid;
|
|
87981
|
+
if (pid == null) {
|
|
87982
|
+
return slot?.state !== "running";
|
|
87983
|
+
}
|
|
87732
87984
|
return isSlotUnavailableForPid(slot, pid, health.isPidAlive);
|
|
87733
87985
|
}
|
|
87986
|
+
function isNativeActiveTaskAgentDown(task, health) {
|
|
87987
|
+
if (!isNativeHarness(task.agentConfig.agentHarness))
|
|
87988
|
+
return false;
|
|
87989
|
+
if (task.agentConfig.desiredState !== "running")
|
|
87990
|
+
return false;
|
|
87991
|
+
if (!isNativeRevivableTaskStatus(task))
|
|
87992
|
+
return false;
|
|
87993
|
+
return isNativeAgentSlotDown(task, health);
|
|
87994
|
+
}
|
|
87734
87995
|
function listNativeTasksNeedingRevive(tasks, health, now, cooldown) {
|
|
87735
87996
|
return tasks.filter((task) => {
|
|
87736
|
-
if (!
|
|
87997
|
+
if (!isNativeActiveTaskAgentDown(task, health))
|
|
87737
87998
|
return false;
|
|
87738
87999
|
const { chatroomId, agentConfig } = task;
|
|
87739
88000
|
if (!agentConfig.workingDir)
|
|
@@ -87799,16 +88060,6 @@ var init_task_monitor_logic = __esm(() => {
|
|
|
87799
88060
|
function resolveTaskWantResume(task) {
|
|
87800
88061
|
return compressContextToWantResume(parseCompressContext(task.taskContent ?? ""));
|
|
87801
88062
|
}
|
|
87802
|
-
function runNativeInjectionFork(task, runtime4, effectContext2, dedup, agentMgr, session2) {
|
|
87803
|
-
exports_Runtime.runFork(runtime4)(runNativeInjectionEffect(task, {
|
|
87804
|
-
sessionId: session2.sessionId,
|
|
87805
|
-
backend: session2.backend,
|
|
87806
|
-
agentMgr: {
|
|
87807
|
-
resumeTurnForSlot: (args2) => exports_Effect.runPromise(agentMgr.resumeTurnForSlot(args2))
|
|
87808
|
-
},
|
|
87809
|
-
convexUrl: session2.convexUrl
|
|
87810
|
-
}, dedup).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[TaskMonitor] native injection failed for ${task.agentConfig.role}@${task.chatroomId}: ${getErrorMessage(err)}`)))));
|
|
87811
|
-
}
|
|
87812
88063
|
function buildCliNudgeLogLine(task) {
|
|
87813
88064
|
const { chatroomId, agentConfig } = task;
|
|
87814
88065
|
const { role } = agentConfig;
|
|
@@ -87817,13 +88068,25 @@ function buildCliNudgeLogLine(task) {
|
|
|
87817
88068
|
const wantResume = resolveTaskWantResume(task);
|
|
87818
88069
|
return `[TaskMonitor] nudging ${role}@${chatroomId} — pending task ${task.taskId}, lastSeenAction=${lastSeenAction}, compress_context=${compressMode}, wantResume=${wantResume}`;
|
|
87819
88070
|
}
|
|
87820
|
-
function
|
|
88071
|
+
function resolveTaskRunnerContext(task) {
|
|
87821
88072
|
const { chatroomId, agentConfig } = task;
|
|
87822
88073
|
const { role } = agentConfig;
|
|
87823
88074
|
const workingDir = agentConfig.workingDir;
|
|
87824
88075
|
if (!workingDir)
|
|
87825
88076
|
return;
|
|
87826
|
-
|
|
88077
|
+
return {
|
|
88078
|
+
chatroomId,
|
|
88079
|
+
agentConfig,
|
|
88080
|
+
role,
|
|
88081
|
+
workingDir,
|
|
88082
|
+
wantResume: resolveTaskWantResume(task)
|
|
88083
|
+
};
|
|
88084
|
+
}
|
|
88085
|
+
function executeCliNudge(task, runtime4, effectContext2, agentMgr) {
|
|
88086
|
+
const ctx = resolveTaskRunnerContext(task);
|
|
88087
|
+
if (!ctx)
|
|
88088
|
+
return;
|
|
88089
|
+
const { chatroomId, agentConfig, role, workingDir, wantResume } = ctx;
|
|
87827
88090
|
exports_Runtime.runFork(runtime4)(exports_Effect.gen(function* () {
|
|
87828
88091
|
yield* agentMgr.stop({ chatroomId, role, reason: "platform.task_monitor_nudge" });
|
|
87829
88092
|
yield* agentMgr.ensureRunning({
|
|
@@ -87838,12 +88101,10 @@ function executeCliNudge(task, runtime4, effectContext2, agentMgr) {
|
|
|
87838
88101
|
}).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[TaskMonitor] nudge failed for ${role}@${chatroomId}: ${getErrorMessage(err)}`)))));
|
|
87839
88102
|
}
|
|
87840
88103
|
function runNativeReviveEffect(task, runtime4, effectContext2, agentMgr) {
|
|
87841
|
-
const
|
|
87842
|
-
|
|
87843
|
-
const workingDir = agentConfig.workingDir;
|
|
87844
|
-
if (!workingDir)
|
|
88104
|
+
const ctx = resolveTaskRunnerContext(task);
|
|
88105
|
+
if (!ctx)
|
|
87845
88106
|
return;
|
|
87846
|
-
const wantResume =
|
|
88107
|
+
const { chatroomId, agentConfig, role, workingDir, wantResume } = ctx;
|
|
87847
88108
|
console.log(`[TaskMonitor] native revive ${role}@${chatroomId} — backend PID stale or missing locally for pending task ${task.taskId}`);
|
|
87848
88109
|
exports_Runtime.runFork(runtime4)(exports_Effect.gen(function* () {
|
|
87849
88110
|
yield* agentMgr.ensureRunning({
|
|
@@ -87871,21 +88132,20 @@ function reviveNativeTasks(tasks, localHealth, now, cooldown, runtime4, effectCo
|
|
|
87871
88132
|
runNativeReviveEffect(task, runtime4, effectContext2, agentMgr);
|
|
87872
88133
|
}
|
|
87873
88134
|
}
|
|
87874
|
-
function
|
|
87875
|
-
for (const task of tasks) {
|
|
87876
|
-
if (shouldInjectNativeTask(task, { alreadyInjectedTaskIds: dedup })) {
|
|
87877
|
-
runNativeInjectionFork(task, runtime4, effectContext2, dedup, agentMgr, sessionDeps);
|
|
87878
|
-
}
|
|
87879
|
-
}
|
|
87880
|
-
}
|
|
87881
|
-
function processTasksUpdate(tasks, runtime4, effectContext2, dedup, cooldown, agentMgr, sessionDeps) {
|
|
88135
|
+
function processTasksUpdate(tasks, runtime4, effectContext2, cooldown, agentMgr, sessionDeps) {
|
|
87882
88136
|
const now = Date.now();
|
|
87883
88137
|
const localHealth = {
|
|
87884
88138
|
getSlot: (chatroomId, role) => agentMgr.getSlot(chatroomId, role),
|
|
87885
88139
|
isPidAlive: (pid) => isProcessAlive((p) => process.kill(p, 0), pid)
|
|
87886
88140
|
};
|
|
87887
88141
|
reviveNativeTasks(tasks, localHealth, now, cooldown, runtime4, effectContext2, agentMgr);
|
|
87888
|
-
|
|
88142
|
+
getNativeTaskDeliveryCoordinator().reconcileAssignedTasks({
|
|
88143
|
+
tasks,
|
|
88144
|
+
runtime: runtime4,
|
|
88145
|
+
effectContext: effectContext2,
|
|
88146
|
+
agentMgr,
|
|
88147
|
+
sessionDeps
|
|
88148
|
+
});
|
|
87889
88149
|
nudgeStuckTasks(tasks, now, cooldown, runtime4, effectContext2, agentMgr);
|
|
87890
88150
|
}
|
|
87891
88151
|
var startTaskMonitorSubscriptionEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
@@ -87895,7 +88155,6 @@ var startTaskMonitorSubscriptionEffect = (wsClient2) => exports_Effect.gen(funct
|
|
|
87895
88155
|
const runtime4 = yield* exports_Effect.runtime();
|
|
87896
88156
|
console.log(`[${formatTimestamp()}] \uD83D\uDCCB Starting task-monitor subscription (reactive)`);
|
|
87897
88157
|
const cooldown = new NudgeCooldown;
|
|
87898
|
-
const dedup = new NativeInjectionDedup;
|
|
87899
88158
|
let stopped = false;
|
|
87900
88159
|
const sessionDeps = {
|
|
87901
88160
|
sessionId: session2.sessionId,
|
|
@@ -87908,7 +88167,7 @@ var startTaskMonitorSubscriptionEffect = (wsClient2) => exports_Effect.gen(funct
|
|
|
87908
88167
|
const onTasksUpdate = (result) => {
|
|
87909
88168
|
if (stopped || !result?.tasks?.length)
|
|
87910
88169
|
return;
|
|
87911
|
-
processTasksUpdate(result.tasks, runtime4, effectContext2,
|
|
88170
|
+
processTasksUpdate(result.tasks, runtime4, effectContext2, cooldown, agentMgr, sessionDeps);
|
|
87912
88171
|
};
|
|
87913
88172
|
const unsubscribe = wsClient2.onUpdate(api.machines.getAssignedTasks, { sessionId: session2.sessionId, machineId: session2.machineId }, onTasksUpdate, (err) => console.warn(`[${formatTimestamp()}] Task-monitor subscription error: ${getErrorMessage(err)}`));
|
|
87914
88173
|
return {
|
|
@@ -87923,8 +88182,7 @@ var init_task_monitor = __esm(() => {
|
|
|
87923
88182
|
init_parse_compress_context();
|
|
87924
88183
|
init_esm();
|
|
87925
88184
|
init_daemon_services();
|
|
87926
|
-
|
|
87927
|
-
init_native_task_injector();
|
|
88185
|
+
init_native_task_delivery_coordinator();
|
|
87928
88186
|
init_task_monitor_logic();
|
|
87929
88187
|
init_api3();
|
|
87930
88188
|
init_convex_error();
|
|
@@ -88362,13 +88620,16 @@ Listening for commands...`);
|
|
|
88362
88620
|
// src/commands/machine/daemon-start/index.ts
|
|
88363
88621
|
async function daemonStart() {
|
|
88364
88622
|
const init2 = await initDaemon();
|
|
88365
|
-
|
|
88623
|
+
const layers = daemonSessionToLayers(init2);
|
|
88624
|
+
exports_Effect.runFork(startBackgroundModelDiscoveryEffect.pipe(exports_Effect.provide(layers)));
|
|
88625
|
+
await exports_Effect.runPromise(startCommandLoopEffect.pipe(exports_Effect.provide(layers)));
|
|
88366
88626
|
}
|
|
88367
88627
|
var init_daemon_start = __esm(() => {
|
|
88368
88628
|
init_esm();
|
|
88369
88629
|
init_command_loop();
|
|
88370
88630
|
init_daemon_layers();
|
|
88371
88631
|
init_init2();
|
|
88632
|
+
init_models_refresh();
|
|
88372
88633
|
});
|
|
88373
88634
|
|
|
88374
88635
|
// src/commands/machine/daemon-stop.ts
|
|
@@ -89423,4 +89684,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
89423
89684
|
});
|
|
89424
89685
|
program2.parse();
|
|
89425
89686
|
|
|
89426
|
-
//# debugId=
|
|
89687
|
+
//# debugId=A1C383F59B3688B364756E2164756E21
|