chatroom-cli 1.98.6 → 1.99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/build/assets/index-DKoewUK4.css +1 -0
- package/dist/client/build/assets/{index-6IhLktfo.js → index-LbWoI4E4.js} +23 -23
- package/dist/client/build/index.html +2 -2
- package/dist/index.js +733 -446
- package/dist/index.js.map +42 -34
- package/package.json +1 -1
- package/dist/client/build/assets/index-TiUlJQMc.css +0 -1
package/dist/index.js
CHANGED
|
@@ -83515,6 +83515,321 @@ function harnessCapabilitiesFingerprint(harnesses, versions) {
|
|
|
83515
83515
|
return `${h}::${v3}`;
|
|
83516
83516
|
}
|
|
83517
83517
|
|
|
83518
|
+
// src/daemon/infrastructure/outbox/lib/durable-fifo-queue-schema.ts
|
|
83519
|
+
var DURABLE_FIFO_QUEUE_MIGRATIONS;
|
|
83520
|
+
var init_durable_fifo_queue_schema = __esm(() => {
|
|
83521
|
+
DURABLE_FIFO_QUEUE_MIGRATIONS = [
|
|
83522
|
+
`CREATE TABLE IF NOT EXISTS schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`,
|
|
83523
|
+
`CREATE TABLE IF NOT EXISTS fifo_outbox_entries (id INTEGER PRIMARY KEY AUTOINCREMENT, delivery_key TEXT NOT NULL, payload_json TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending', attempts INTEGER NOT NULL DEFAULT 0, last_error TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`,
|
|
83524
|
+
`CREATE INDEX IF NOT EXISTS idx_fifo_outbox_pending ON fifo_outbox_entries(delivery_key, status, id)`
|
|
83525
|
+
];
|
|
83526
|
+
});
|
|
83527
|
+
|
|
83528
|
+
// src/daemon/infrastructure/outbox/lib/durable-fifo-queue-store.ts
|
|
83529
|
+
import { DatabaseSync } from "node:sqlite";
|
|
83530
|
+
import { mkdirSync as mkdirSync4 } from "node:fs";
|
|
83531
|
+
import { dirname as dirname9 } from "node:path";
|
|
83532
|
+
function openDurableFifoQueueStore(dbPath) {
|
|
83533
|
+
mkdirSync4(dirname9(dbPath), { recursive: true });
|
|
83534
|
+
const db = new DatabaseSync(dbPath);
|
|
83535
|
+
for (const sql of DURABLE_FIFO_QUEUE_MIGRATIONS)
|
|
83536
|
+
db.exec(sql);
|
|
83537
|
+
db.prepare("UPDATE fifo_outbox_entries SET status='pending', updated_at=? WHERE status='in_flight'").run(Date.now());
|
|
83538
|
+
return {
|
|
83539
|
+
enqueue: (key, payloadJson) => {
|
|
83540
|
+
const now = Date.now();
|
|
83541
|
+
return Number(db.prepare("INSERT INTO fifo_outbox_entries(delivery_key,payload_json,created_at,updated_at) VALUES(?,?,?,?) RETURNING id").get(key, payloadJson, now, now).id);
|
|
83542
|
+
},
|
|
83543
|
+
claimNextBatch: (key, limit) => db.prepare("UPDATE fifo_outbox_entries SET status='in_flight', attempts=attempts+1, updated_at=? WHERE id IN (SELECT id FROM fifo_outbox_entries WHERE delivery_key=? AND status='pending' ORDER BY id LIMIT ?) RETURNING id, delivery_key as deliveryKey, payload_json as payloadJson, attempts").all(Date.now(), key, limit),
|
|
83544
|
+
markDone: (id3) => {
|
|
83545
|
+
db.prepare("DELETE FROM fifo_outbox_entries WHERE id=?").run(id3);
|
|
83546
|
+
},
|
|
83547
|
+
markPending: (id3) => {
|
|
83548
|
+
db.prepare("UPDATE fifo_outbox_entries SET status='pending', last_error=NULL, updated_at=? WHERE id=?").run(Date.now(), id3);
|
|
83549
|
+
},
|
|
83550
|
+
updatePayload: (id3, payloadJson) => {
|
|
83551
|
+
db.prepare("UPDATE fifo_outbox_entries SET payload_json=?, updated_at=? WHERE id=?").run(payloadJson, Date.now(), id3);
|
|
83552
|
+
},
|
|
83553
|
+
markPendingRetry: (id3, error) => {
|
|
83554
|
+
db.prepare("UPDATE fifo_outbox_entries SET status='pending', last_error=?, updated_at=? WHERE id=?").run(String(error), Date.now(), id3);
|
|
83555
|
+
},
|
|
83556
|
+
listPendingForRecovery: (key) => db.prepare("SELECT id, delivery_key as deliveryKey, payload_json as payloadJson, attempts FROM fifo_outbox_entries WHERE delivery_key=? AND status IN ('pending','in_flight') ORDER BY id").all(key),
|
|
83557
|
+
close: () => db.close()
|
|
83558
|
+
};
|
|
83559
|
+
}
|
|
83560
|
+
var init_durable_fifo_queue_store = __esm(() => {
|
|
83561
|
+
init_durable_fifo_queue_schema();
|
|
83562
|
+
});
|
|
83563
|
+
|
|
83564
|
+
// src/daemon/infrastructure/outbox/lib/outbox-retry-backoff.ts
|
|
83565
|
+
function computeExponentialRetryDelayMs(attempt, retryDelayMs, maxRetryDelayMs) {
|
|
83566
|
+
const exponent = Math.min(Math.max(0, attempt), MAX_RETRY_EXPONENT);
|
|
83567
|
+
return Math.min(retryDelayMs * 2 ** exponent, maxRetryDelayMs);
|
|
83568
|
+
}
|
|
83569
|
+
var MAX_RETRY_EXPONENT = 20;
|
|
83570
|
+
|
|
83571
|
+
// src/daemon/infrastructure/outbox/lib/fifo-batched-outbox.ts
|
|
83572
|
+
function createFifoBatchedOutbox(o) {
|
|
83573
|
+
const waiters = new Map;
|
|
83574
|
+
let running3;
|
|
83575
|
+
let stopped = false;
|
|
83576
|
+
let retryTimer;
|
|
83577
|
+
let retryAttempt = 0;
|
|
83578
|
+
const retryDelay = () => computeExponentialRetryDelayMs(retryAttempt++, o.retryDelayMs ?? 500, o.maxRetryDelayMs ?? 5000);
|
|
83579
|
+
const scheduleRetry = () => {
|
|
83580
|
+
if (!stopped && !retryTimer) {
|
|
83581
|
+
retryTimer = setTimeout(() => {
|
|
83582
|
+
retryTimer = undefined;
|
|
83583
|
+
drain().catch(() => {
|
|
83584
|
+
return;
|
|
83585
|
+
});
|
|
83586
|
+
}, retryDelay());
|
|
83587
|
+
retryTimer.unref?.();
|
|
83588
|
+
}
|
|
83589
|
+
};
|
|
83590
|
+
const drain = async () => {
|
|
83591
|
+
if (running3)
|
|
83592
|
+
return running3;
|
|
83593
|
+
running3 = (async () => {
|
|
83594
|
+
while (true) {
|
|
83595
|
+
const rows = o.store.claimNextBatch(o.deliveryKey, o.batchSize);
|
|
83596
|
+
if (!rows.length)
|
|
83597
|
+
break;
|
|
83598
|
+
try {
|
|
83599
|
+
const results = await o.send(rows.map((r) => o.deserialize(r.payloadJson)));
|
|
83600
|
+
let hasRetry = false;
|
|
83601
|
+
for (let i2 = 0;i2 < results.length; i2++) {
|
|
83602
|
+
const item = o.deserialize(rows[i2].payloadJson);
|
|
83603
|
+
const outcome = o.classifyOutcome?.(results[i2], item) ?? { kind: "success" };
|
|
83604
|
+
if (outcome.kind === "retry") {
|
|
83605
|
+
o.store.updatePayload(rows[i2].id, o.serialize(outcome.item));
|
|
83606
|
+
o.store.markPending(rows[i2].id);
|
|
83607
|
+
hasRetry = true;
|
|
83608
|
+
continue;
|
|
83609
|
+
}
|
|
83610
|
+
o.store.markDone(rows[i2].id);
|
|
83611
|
+
waiters.get(rows[i2].id)?.resolve(results[i2]);
|
|
83612
|
+
waiters.delete(rows[i2].id);
|
|
83613
|
+
}
|
|
83614
|
+
for (let i2 = results.length;i2 < rows.length; i2++)
|
|
83615
|
+
o.store.markPending(rows[i2].id);
|
|
83616
|
+
if (hasRetry) {
|
|
83617
|
+
scheduleRetry();
|
|
83618
|
+
break;
|
|
83619
|
+
}
|
|
83620
|
+
retryAttempt = 0;
|
|
83621
|
+
} catch (e) {
|
|
83622
|
+
o.onError?.(e);
|
|
83623
|
+
for (const r of rows)
|
|
83624
|
+
o.store.markPendingRetry(r.id, e);
|
|
83625
|
+
scheduleRetry();
|
|
83626
|
+
break;
|
|
83627
|
+
}
|
|
83628
|
+
}
|
|
83629
|
+
})().finally(() => {
|
|
83630
|
+
running3 = undefined;
|
|
83631
|
+
});
|
|
83632
|
+
return running3;
|
|
83633
|
+
};
|
|
83634
|
+
const enqueue = (item) => {
|
|
83635
|
+
if (stopped)
|
|
83636
|
+
return Promise.reject(new Error("Outbox is stopped"));
|
|
83637
|
+
const id3 = o.store.enqueue(o.deliveryKey, o.serialize(item));
|
|
83638
|
+
const p = new Promise((resolve4, reject) => waiters.set(id3, { resolve: resolve4, reject }));
|
|
83639
|
+
drain().catch(() => {
|
|
83640
|
+
return;
|
|
83641
|
+
});
|
|
83642
|
+
return p;
|
|
83643
|
+
};
|
|
83644
|
+
const flushNow = async () => {
|
|
83645
|
+
while (o.store.listPendingForRecovery(o.deliveryKey).length) {
|
|
83646
|
+
await drain();
|
|
83647
|
+
}
|
|
83648
|
+
};
|
|
83649
|
+
const stop4 = async () => {
|
|
83650
|
+
if (stopped)
|
|
83651
|
+
return;
|
|
83652
|
+
if (retryTimer)
|
|
83653
|
+
clearTimeout(retryTimer);
|
|
83654
|
+
retryTimer = undefined;
|
|
83655
|
+
await flushNow();
|
|
83656
|
+
stopped = true;
|
|
83657
|
+
};
|
|
83658
|
+
return { enqueue, flushNow, stop: stop4 };
|
|
83659
|
+
}
|
|
83660
|
+
var init_fifo_batched_outbox = () => {};
|
|
83661
|
+
|
|
83662
|
+
// src/daemon/infrastructure/outbox/lib/keyed-fifo-batched-outbox-registry.ts
|
|
83663
|
+
function createKeyedFifoBatchedOutboxRegistry(o) {
|
|
83664
|
+
const boxes = new Map;
|
|
83665
|
+
const get13 = (key) => {
|
|
83666
|
+
let b = boxes.get(key);
|
|
83667
|
+
if (!b) {
|
|
83668
|
+
b = createFifoBatchedOutbox({
|
|
83669
|
+
batchSize: o.batchSize,
|
|
83670
|
+
send: o.createSend(key),
|
|
83671
|
+
store: o.store,
|
|
83672
|
+
deliveryKey: key,
|
|
83673
|
+
serialize: o.serialize,
|
|
83674
|
+
deserialize: o.deserialize,
|
|
83675
|
+
retryDelayMs: o.retryDelayMs,
|
|
83676
|
+
maxRetryDelayMs: o.maxRetryDelayMs,
|
|
83677
|
+
onError: (e) => o.onError?.(key, e),
|
|
83678
|
+
classifyOutcome: o.classifyOutcome
|
|
83679
|
+
});
|
|
83680
|
+
boxes.set(key, b);
|
|
83681
|
+
}
|
|
83682
|
+
return b;
|
|
83683
|
+
};
|
|
83684
|
+
const stop4 = async (k) => {
|
|
83685
|
+
const b = boxes.get(k);
|
|
83686
|
+
if (b) {
|
|
83687
|
+
await b.stop();
|
|
83688
|
+
boxes.delete(k);
|
|
83689
|
+
}
|
|
83690
|
+
};
|
|
83691
|
+
return {
|
|
83692
|
+
enqueue: (k, i2) => get13(k).enqueue(i2),
|
|
83693
|
+
flushNow: async (k) => {
|
|
83694
|
+
if (k)
|
|
83695
|
+
await get13(k).flushNow();
|
|
83696
|
+
else
|
|
83697
|
+
for (const b of boxes.values())
|
|
83698
|
+
await b.flushNow();
|
|
83699
|
+
},
|
|
83700
|
+
stop: stop4,
|
|
83701
|
+
stopAll: async () => {
|
|
83702
|
+
for (const k of [...boxes.keys()])
|
|
83703
|
+
await stop4(k);
|
|
83704
|
+
o.store.close();
|
|
83705
|
+
}
|
|
83706
|
+
};
|
|
83707
|
+
}
|
|
83708
|
+
var init_keyed_fifo_batched_outbox_registry = __esm(() => {
|
|
83709
|
+
init_fifo_batched_outbox();
|
|
83710
|
+
});
|
|
83711
|
+
|
|
83712
|
+
// src/daemon/infrastructure/outbox/outbox-db-path.ts
|
|
83713
|
+
import { homedir as homedir5 } from "node:os";
|
|
83714
|
+
import { join as join17 } from "node:path";
|
|
83715
|
+
function resolveOutboxDbPath(machineId, kind) {
|
|
83716
|
+
return join17(homedir5(), ".chatroom", "daemon", machineId, `outbox-${kind}.sqlite`);
|
|
83717
|
+
}
|
|
83718
|
+
var init_outbox_db_path = () => {};
|
|
83719
|
+
|
|
83720
|
+
// src/daemon/domain/entities/agent-lifecycle-fact.ts
|
|
83721
|
+
function buildExitedLifecycleFact(auditArgs, emittedAt) {
|
|
83722
|
+
const { sessionId: _sessionId, machineId: _machineId, ...fields } = auditArgs;
|
|
83723
|
+
return {
|
|
83724
|
+
kind: "exited",
|
|
83725
|
+
...fields,
|
|
83726
|
+
revisionKey: buildAgentLifecycleRevisionKey("exited", {
|
|
83727
|
+
chatroomId: auditArgs.chatroomId,
|
|
83728
|
+
role: auditArgs.role,
|
|
83729
|
+
pid: auditArgs.pid,
|
|
83730
|
+
emittedAt
|
|
83731
|
+
}),
|
|
83732
|
+
emittedAt
|
|
83733
|
+
};
|
|
83734
|
+
}
|
|
83735
|
+
function normalizeAgentLifecycleFact(raw) {
|
|
83736
|
+
if (!raw || typeof raw !== "object") {
|
|
83737
|
+
throw new Error("Invalid agent lifecycle fact");
|
|
83738
|
+
}
|
|
83739
|
+
const value = raw;
|
|
83740
|
+
const { sessionId: _sessionId, machineId: _machineId, ...rest } = value;
|
|
83741
|
+
const kind = rest.kind;
|
|
83742
|
+
if (kind === "cleared_all_pids") {
|
|
83743
|
+
return {
|
|
83744
|
+
kind: "cleared_all_pids",
|
|
83745
|
+
revisionKey: String(rest.revisionKey),
|
|
83746
|
+
emittedAt: Number(rest.emittedAt)
|
|
83747
|
+
};
|
|
83748
|
+
}
|
|
83749
|
+
if (kind === "spawned" || kind === "exited") {
|
|
83750
|
+
return rest;
|
|
83751
|
+
}
|
|
83752
|
+
throw new Error(`Unknown agent lifecycle fact kind: ${String(kind)}`);
|
|
83753
|
+
}
|
|
83754
|
+
function agentLifecycleDeliveryKey(machineId, fact) {
|
|
83755
|
+
if (fact.kind === "cleared_all_pids")
|
|
83756
|
+
return `${machineId}:__machine__`;
|
|
83757
|
+
return `${machineId}:${fact.chatroomId}:${fact.role.toLowerCase()}`;
|
|
83758
|
+
}
|
|
83759
|
+
function buildAgentLifecycleRevisionKey(prefix, parts2) {
|
|
83760
|
+
return `${prefix}:${Object.entries(parts2).filter(([, v3]) => v3 !== undefined).map(([k, v3]) => `${k}=${v3}`).join(":")}`;
|
|
83761
|
+
}
|
|
83762
|
+
|
|
83763
|
+
// src/daemon/infrastructure/outbox/agent-lifecycle-outbox.ts
|
|
83764
|
+
function createAgentLifecycleOutboxRegistry(machineId, createSend, options) {
|
|
83765
|
+
const store = openDurableFifoQueueStore(resolveOutboxDbPath(machineId, "agent-lifecycle"));
|
|
83766
|
+
return createKeyedFifoBatchedOutboxRegistry({
|
|
83767
|
+
store,
|
|
83768
|
+
batchSize: AGENT_LIFECYCLE_OUTBOX_BATCH_SIZE,
|
|
83769
|
+
createSend: (key) => async (facts) => {
|
|
83770
|
+
const results = [];
|
|
83771
|
+
for (const fact of facts)
|
|
83772
|
+
results.push(await createSend(key)(fact));
|
|
83773
|
+
return results;
|
|
83774
|
+
},
|
|
83775
|
+
serialize: JSON.stringify,
|
|
83776
|
+
deserialize: (serialized) => normalizeAgentLifecycleFact(JSON.parse(serialized)),
|
|
83777
|
+
retryDelayMs: 500,
|
|
83778
|
+
maxRetryDelayMs: 5 * 60000,
|
|
83779
|
+
onError: options?.onError,
|
|
83780
|
+
classifyOutcome: () => ({ kind: "success" })
|
|
83781
|
+
});
|
|
83782
|
+
}
|
|
83783
|
+
function agentLifecycleKey(machineId, fact) {
|
|
83784
|
+
return agentLifecycleDeliveryKey(machineId, fact);
|
|
83785
|
+
}
|
|
83786
|
+
var AGENT_LIFECYCLE_OUTBOX_BATCH_SIZE = 1;
|
|
83787
|
+
var init_agent_lifecycle_outbox = __esm(() => {
|
|
83788
|
+
init_durable_fifo_queue_store();
|
|
83789
|
+
init_keyed_fifo_batched_outbox_registry();
|
|
83790
|
+
init_outbox_db_path();
|
|
83791
|
+
});
|
|
83792
|
+
|
|
83793
|
+
// src/daemon/infrastructure/outbox/agent-lifecycle-send.ts
|
|
83794
|
+
function toConvexLifecycleFact(fact) {
|
|
83795
|
+
const normalized = normalizeAgentLifecycleFact(fact);
|
|
83796
|
+
if (normalized.kind === "cleared_all_pids")
|
|
83797
|
+
return normalized;
|
|
83798
|
+
return {
|
|
83799
|
+
...normalized,
|
|
83800
|
+
chatroomId: normalized.chatroomId
|
|
83801
|
+
};
|
|
83802
|
+
}
|
|
83803
|
+
function createAgentLifecycleSend(session2) {
|
|
83804
|
+
return async (fact) => {
|
|
83805
|
+
const args2 = {
|
|
83806
|
+
sessionId: session2.sessionId,
|
|
83807
|
+
machineId: session2.machineId,
|
|
83808
|
+
fact: toConvexLifecycleFact(fact)
|
|
83809
|
+
};
|
|
83810
|
+
return await session2.backend.mutation(api.machines.projectAgentLifecycleFact, args2);
|
|
83811
|
+
};
|
|
83812
|
+
}
|
|
83813
|
+
var init_agent_lifecycle_send = __esm(() => {
|
|
83814
|
+
init_api3();
|
|
83815
|
+
});
|
|
83816
|
+
|
|
83817
|
+
// src/daemon/entry/agent-lifecycle-outbox-runtime.ts
|
|
83818
|
+
function createAgentLifecycleOutboxForSession(args2) {
|
|
83819
|
+
return createAgentLifecycleOutboxRegistry(args2.machineId, () => createAgentLifecycleSend({
|
|
83820
|
+
sessionId: args2.sessionId,
|
|
83821
|
+
machineId: args2.machineId,
|
|
83822
|
+
backend: args2.backend
|
|
83823
|
+
}));
|
|
83824
|
+
}
|
|
83825
|
+
function enqueueAgentLifecycleFact(registry2, machineId, fact) {
|
|
83826
|
+
return registry2.enqueue(agentLifecycleKey(machineId, fact), fact);
|
|
83827
|
+
}
|
|
83828
|
+
var init_agent_lifecycle_outbox_runtime = __esm(() => {
|
|
83829
|
+
init_agent_lifecycle_outbox();
|
|
83830
|
+
init_agent_lifecycle_send();
|
|
83831
|
+
});
|
|
83832
|
+
|
|
83518
83833
|
// src/daemon/entry/daemon-services.ts
|
|
83519
83834
|
function DaemonMutableStateServiceLive(init2) {
|
|
83520
83835
|
return exports_Layer.effect(DaemonMutableStateService, exports_Effect.gen(function* () {
|
|
@@ -83526,7 +83841,10 @@ function DaemonMutableStateServiceLive(init2) {
|
|
|
83526
83841
|
};
|
|
83527
83842
|
}));
|
|
83528
83843
|
}
|
|
83529
|
-
var
|
|
83844
|
+
var AgentLifecycleOutboxService, AgentLifecycleOutboxServiceLive = (registry2, machineId) => exports_Layer.succeed(AgentLifecycleOutboxService, {
|
|
83845
|
+
enqueue: (fact) => exports_Effect.promise(() => enqueueAgentLifecycleFact(registry2, machineId, fact)),
|
|
83846
|
+
stopAll: () => exports_Effect.promise(() => registry2.stopAll())
|
|
83847
|
+
}), DaemonMachineService, DaemonMachineServiceLive = (ops) => exports_Layer.succeed(DaemonMachineService, {
|
|
83530
83848
|
clearAgentPid: (machineId, chatroomId, role) => exports_Effect.promise(() => ops.clearAgentPid(machineId, chatroomId, role)),
|
|
83531
83849
|
persistAgentPid: (machineId, chatroomId, role, pid, harness) => exports_Effect.promise(() => ops.persistAgentPid(machineId, chatroomId, role, pid, harness)),
|
|
83532
83850
|
listAgentEntries: (machineId) => exports_Effect.promise(() => ops.listAgentEntries(machineId)),
|
|
@@ -83550,6 +83868,9 @@ var DaemonMachineService, DaemonMachineServiceLive = (ops) => exports_Layer.succ
|
|
|
83550
83868
|
}), DaemonSessionService, DaemonMutableStateService;
|
|
83551
83869
|
var init_daemon_services = __esm(() => {
|
|
83552
83870
|
init_esm();
|
|
83871
|
+
init_agent_lifecycle_outbox_runtime();
|
|
83872
|
+
AgentLifecycleOutboxService = class AgentLifecycleOutboxService extends exports_Context.Tag("AgentLifecycleOutboxService")() {
|
|
83873
|
+
};
|
|
83553
83874
|
DaemonMachineService = class DaemonMachineService extends exports_Context.Tag("DaemonMachineService")() {
|
|
83554
83875
|
};
|
|
83555
83876
|
DaemonSpawningService = class DaemonSpawningService extends exports_Context.Tag("DaemonSpawningService")() {
|
|
@@ -83572,7 +83893,7 @@ function daemonSessionToLayers(init2) {
|
|
|
83572
83893
|
return exports_Layer.mergeAll(BackendServiceLive({
|
|
83573
83894
|
mutation: (e, a) => init2.backend.mutation(e, a),
|
|
83574
83895
|
query: (e, a) => init2.backend.query(e, a)
|
|
83575
|
-
}), ProcessServiceLive, ClockServiceLive, FsServiceLive, DaemonMachineServiceLive(init2.machine), DaemonSpawningServiceLive(init2.spawning), DaemonAgentProcessManagerServiceLive(init2.agentProcessManager), DaemonMutableStateServiceLive({
|
|
83896
|
+
}), ProcessServiceLive, ClockServiceLive, FsServiceLive, DaemonMachineServiceLive(init2.machine), AgentLifecycleOutboxServiceLive(init2.agentLifecycleOutbox, init2.machineId), DaemonSpawningServiceLive(init2.spawning), DaemonAgentProcessManagerServiceLive(init2.agentProcessManager), DaemonMutableStateServiceLive({
|
|
83576
83897
|
lastPushedGitState: init2.lastPushedGitState,
|
|
83577
83898
|
lastPushedModels: init2.lastPushedModels,
|
|
83578
83899
|
lastPushedHarnessFingerprint: init2.lastPushedHarnessFingerprint,
|
|
@@ -83696,10 +84017,18 @@ var init_register_listeners = __esm(() => {
|
|
|
83696
84017
|
|
|
83697
84018
|
// src/daemon/entry/handlers/daemon-restart-cleanup.ts
|
|
83698
84019
|
var clearStaleSpawnedPidsEffect = () => exports_Effect.gen(function* () {
|
|
83699
|
-
const
|
|
84020
|
+
const outbox = yield* AgentLifecycleOutboxService;
|
|
83700
84021
|
const session2 = yield* DaemonSessionService;
|
|
83701
|
-
const
|
|
83702
|
-
|
|
84022
|
+
const emittedAt = Date.now();
|
|
84023
|
+
const result = yield* outbox.enqueue({
|
|
84024
|
+
kind: "cleared_all_pids",
|
|
84025
|
+
revisionKey: buildAgentLifecycleRevisionKey("cleared_all", {
|
|
84026
|
+
machineId: session2.machineId,
|
|
84027
|
+
emittedAt
|
|
84028
|
+
}),
|
|
84029
|
+
emittedAt
|
|
84030
|
+
});
|
|
84031
|
+
return result.clearedCount ?? 0;
|
|
83703
84032
|
}), reapOrphanCommandRunsEffect = () => exports_Effect.gen(function* () {
|
|
83704
84033
|
const backend2 = yield* BackendService;
|
|
83705
84034
|
const session2 = yield* DaemonSessionService;
|
|
@@ -83737,26 +84066,26 @@ import { createHash as createHash2 } from "node:crypto";
|
|
|
83737
84066
|
import {
|
|
83738
84067
|
appendFileSync,
|
|
83739
84068
|
existsSync as existsSync6,
|
|
83740
|
-
mkdirSync as
|
|
84069
|
+
mkdirSync as mkdirSync5,
|
|
83741
84070
|
readFileSync as readFileSync8,
|
|
83742
84071
|
renameSync,
|
|
83743
84072
|
unlinkSync,
|
|
83744
84073
|
writeFileSync as writeFileSync3
|
|
83745
84074
|
} from "node:fs";
|
|
83746
|
-
import { homedir as
|
|
83747
|
-
import { join as
|
|
84075
|
+
import { homedir as homedir6 } from "node:os";
|
|
84076
|
+
import { join as join18 } from "node:path";
|
|
83748
84077
|
function getUrlHash() {
|
|
83749
84078
|
const url2 = getConvexUrl();
|
|
83750
84079
|
return createHash2("sha256").update(url2).digest("hex").substring(0, 8);
|
|
83751
84080
|
}
|
|
83752
84081
|
function getChildPidsFilePath() {
|
|
83753
|
-
const dir =
|
|
83754
|
-
return
|
|
84082
|
+
const dir = join18(homedir6(), ".chatroom");
|
|
84083
|
+
return join18(dir, `daemon-children-${getUrlHash()}.pids`);
|
|
83755
84084
|
}
|
|
83756
84085
|
function ensureChatroomDir2() {
|
|
83757
|
-
const dir =
|
|
84086
|
+
const dir = join18(homedir6(), ".chatroom");
|
|
83758
84087
|
if (!existsSync6(dir)) {
|
|
83759
|
-
|
|
84088
|
+
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
83760
84089
|
}
|
|
83761
84090
|
}
|
|
83762
84091
|
function readPids() {
|
|
@@ -83869,7 +84198,7 @@ var init_orphan_tracker = __esm(() => {
|
|
|
83869
84198
|
// src/daemon/entry/handlers/process/output-store.ts
|
|
83870
84199
|
import { appendFile as appendFile2, mkdir as mkdir8, readFile as readFile6, rm as rm2 } from "node:fs/promises";
|
|
83871
84200
|
import { tmpdir } from "node:os";
|
|
83872
|
-
import { join as
|
|
84201
|
+
import { join as join19 } from "node:path";
|
|
83873
84202
|
|
|
83874
84203
|
class TempFileOutputStore {
|
|
83875
84204
|
state;
|
|
@@ -83932,7 +84261,7 @@ function createOutputStore(runId) {
|
|
|
83932
84261
|
if (!RUN_ID_RE.test(runId)) {
|
|
83933
84262
|
throw new Error(`Invalid runId: ${runId}`);
|
|
83934
84263
|
}
|
|
83935
|
-
const filePath =
|
|
84264
|
+
const filePath = join19(TEMP_DIR, `${runId}.log`);
|
|
83936
84265
|
return new TempFileOutputStore(filePath);
|
|
83937
84266
|
}
|
|
83938
84267
|
async function ensureTempDir() {
|
|
@@ -83946,7 +84275,7 @@ async function cleanOrphanTempFiles() {
|
|
|
83946
84275
|
var TAIL_WINDOW_BYTES, TEMP_DIR, RUN_ID_RE, MAX_TAIL_LINES_V2 = 50;
|
|
83947
84276
|
var init_output_store = __esm(() => {
|
|
83948
84277
|
TAIL_WINDOW_BYTES = 32 * 1024;
|
|
83949
|
-
TEMP_DIR =
|
|
84278
|
+
TEMP_DIR = join19(tmpdir(), "chatroom-cli", "runs");
|
|
83950
84279
|
RUN_ID_RE = /^[a-z0-9]+$/i;
|
|
83951
84280
|
});
|
|
83952
84281
|
|
|
@@ -84015,7 +84344,7 @@ async function logDaemonAuditEvent(logEvent, event) {
|
|
|
84015
84344
|
}
|
|
84016
84345
|
|
|
84017
84346
|
// ../../services/backend/config/reliability.ts
|
|
84018
|
-
var HARNESS_SESSION_READY_TIMEOUT_MS = 5000,
|
|
84347
|
+
var HARNESS_SESSION_READY_TIMEOUT_MS = 5000, DAEMON_HEARTBEAT_INTERVAL_MS, DAEMON_HEARTBEAT_TTL_MS, AGENT_REQUEST_DEADLINE_MS = 120000, OBSERVED_FULL_PUSH_INTERVAL_MS, OBSERVED_SYNC_RECONCILE_MS, WORKSPACE_RECENCY_WINDOW_MS, WORKSPACE_LIST_RECONCILE_MS, CONNECTION_CLOSE_REQUEST_TTL_MS, ENHANCER_TERMINAL_JOB_RETENTION_MS;
|
|
84019
84348
|
var init_reliability = __esm(() => {
|
|
84020
84349
|
DAEMON_HEARTBEAT_INTERVAL_MS = 5 * 60000;
|
|
84021
84350
|
DAEMON_HEARTBEAT_TTL_MS = 6 * DAEMON_HEARTBEAT_INTERVAL_MS;
|
|
@@ -98743,8 +99072,6 @@ var init_assigned_task_snapshot_contract = __esm(() => {
|
|
|
98743
99072
|
assignedTo: exports_external.string().optional(),
|
|
98744
99073
|
lastSeenAction: exports_external.string().nullable().optional(),
|
|
98745
99074
|
lastStatus: exports_external.string().nullable().optional(),
|
|
98746
|
-
spawnedAgentPid: exports_external.number().optional(),
|
|
98747
|
-
desiredState: agentDesiredStateSchema.optional(),
|
|
98748
99075
|
sessionAugmentation: sessionAugmentationSchema.optional()
|
|
98749
99076
|
};
|
|
98750
99077
|
assignedTaskSignalSchema = exports_external.object(assignedTaskSignalBootstrapFields);
|
|
@@ -98821,13 +99148,99 @@ function getNativeDeliveryLedger() {
|
|
|
98821
99148
|
}
|
|
98822
99149
|
var sharedLedger;
|
|
98823
99150
|
|
|
99151
|
+
// src/daemon/infrastructure/agent-operational/agent-operational-read-model.ts
|
|
99152
|
+
function isOperationalDesiredRunning(row) {
|
|
99153
|
+
return row?.operationalState === "running" || row?.operationalState === "starting";
|
|
99154
|
+
}
|
|
99155
|
+
|
|
99156
|
+
class AgentOperationalReadModel {
|
|
99157
|
+
rows = new Map;
|
|
99158
|
+
replace(rows) {
|
|
99159
|
+
const changed = [];
|
|
99160
|
+
const nextKeys = new Set;
|
|
99161
|
+
for (const row of rows) {
|
|
99162
|
+
const key = roleKey(row.chatroomId, row.role);
|
|
99163
|
+
nextKeys.add(key);
|
|
99164
|
+
const prev = this.rows.get(key);
|
|
99165
|
+
if (!prev || prev.revisionKey !== row.revisionKey)
|
|
99166
|
+
changed.push({ chatroomId: row.chatroomId, role: row.role });
|
|
99167
|
+
this.rows.set(key, row);
|
|
99168
|
+
}
|
|
99169
|
+
for (const [key, prev] of this.rows) {
|
|
99170
|
+
if (!nextKeys.has(key)) {
|
|
99171
|
+
changed.push({ chatroomId: prev.chatroomId, role: prev.role });
|
|
99172
|
+
this.rows.delete(key);
|
|
99173
|
+
}
|
|
99174
|
+
}
|
|
99175
|
+
return changed;
|
|
99176
|
+
}
|
|
99177
|
+
get(chatroomId, role) {
|
|
99178
|
+
return this.rows.get(roleKey(chatroomId, role));
|
|
99179
|
+
}
|
|
99180
|
+
}
|
|
99181
|
+
var roleKey = (chatroomId, role) => `${chatroomId}:${role.toLowerCase()}`;
|
|
99182
|
+
|
|
99183
|
+
// src/daemon/infrastructure/inbox/task-snapshot-state.ts
|
|
99184
|
+
function snapshotKey(taskId, role) {
|
|
99185
|
+
return `${taskId}:${role.toLowerCase()}`;
|
|
99186
|
+
}
|
|
99187
|
+
|
|
99188
|
+
class MachineTaskSnapshotState {
|
|
99189
|
+
snapshots = new Map;
|
|
99190
|
+
replace(snapshots) {
|
|
99191
|
+
this.snapshots.clear();
|
|
99192
|
+
this.upsert(snapshots);
|
|
99193
|
+
}
|
|
99194
|
+
applySignalPage(signals, snapshots) {
|
|
99195
|
+
const snapshotsByKey = new Map(snapshots.map((snapshot) => [
|
|
99196
|
+
snapshotKey(snapshot.taskId, snapshot.agentConfig.role),
|
|
99197
|
+
snapshot
|
|
99198
|
+
]));
|
|
99199
|
+
for (const signal of signals) {
|
|
99200
|
+
const key = snapshotKey(signal.taskId, signal.targetRole);
|
|
99201
|
+
const snapshot = snapshotsByKey.get(key);
|
|
99202
|
+
if (snapshot) {
|
|
99203
|
+
this.snapshots.set(key, snapshot);
|
|
99204
|
+
} else {
|
|
99205
|
+
this.snapshots.delete(key);
|
|
99206
|
+
}
|
|
99207
|
+
}
|
|
99208
|
+
}
|
|
99209
|
+
listForRole(chatroomId, role) {
|
|
99210
|
+
const roleLower = role.toLowerCase();
|
|
99211
|
+
return [...this.snapshots.values()].filter((snapshot) => snapshot.chatroomId === chatroomId && snapshot.agentConfig.role.toLowerCase() === roleLower);
|
|
99212
|
+
}
|
|
99213
|
+
listAll() {
|
|
99214
|
+
return [...this.snapshots.values()];
|
|
99215
|
+
}
|
|
99216
|
+
upsert(snapshots) {
|
|
99217
|
+
for (const snapshot of snapshots) {
|
|
99218
|
+
this.snapshots.set(snapshotKey(snapshot.taskId, snapshot.agentConfig.role), snapshot);
|
|
99219
|
+
}
|
|
99220
|
+
}
|
|
99221
|
+
}
|
|
99222
|
+
|
|
99223
|
+
// src/daemon/entry/native-delivery/native-delivery-session-registry.ts
|
|
99224
|
+
function registerNativeDeliverySession(ctx) {
|
|
99225
|
+
registered = {
|
|
99226
|
+
...ctx,
|
|
99227
|
+
taskSnapshotState: ctx.taskSnapshotState ?? new MachineTaskSnapshotState,
|
|
99228
|
+
agentOperationalReadModel: ctx.agentOperationalReadModel ?? new AgentOperationalReadModel
|
|
99229
|
+
};
|
|
99230
|
+
}
|
|
99231
|
+
function unregisterNativeDeliverySession() {
|
|
99232
|
+
registered = null;
|
|
99233
|
+
}
|
|
99234
|
+
function getNativeDeliverySession() {
|
|
99235
|
+
return registered;
|
|
99236
|
+
}
|
|
99237
|
+
var registered = null;
|
|
99238
|
+
var init_native_delivery_session_registry = () => {};
|
|
99239
|
+
|
|
98824
99240
|
// src/daemon/domain/entities/assigned-task.ts
|
|
98825
99241
|
function isDeliverableTaskStatus(status3) {
|
|
98826
99242
|
return status3 === "pending" || status3 === "acknowledged";
|
|
98827
99243
|
}
|
|
98828
|
-
function isAgentDesiredRunning(desiredState) {
|
|
98829
|
-
return desiredState === "running";
|
|
98830
|
-
}
|
|
98831
99244
|
var init_assigned_task = () => {};
|
|
98832
99245
|
|
|
98833
99246
|
// src/daemon/domain/usecase/check-agent-slot.ts
|
|
@@ -98857,19 +99270,20 @@ function explainAgentReadyForNativeDeliveryBlock(task, slot) {
|
|
|
98857
99270
|
if (!isNativeHarness(agentConfig.agentHarness)) {
|
|
98858
99271
|
return `not_native_harness (harness=${agentConfig.agentHarness})`;
|
|
98859
99272
|
}
|
|
98860
|
-
|
|
98861
|
-
|
|
98862
|
-
|
|
98863
|
-
if (agentConfig.spawnedAgentPid == null) {
|
|
98864
|
-
return "spawned_pid_missing";
|
|
99273
|
+
const operational = getNativeDeliverySession()?.agentOperationalReadModel?.get(task.chatroomId, agentConfig.role);
|
|
99274
|
+
if (!isOperationalDesiredRunning(operational)) {
|
|
99275
|
+
return `operational_state_not_running (state=${operational?.operationalState ?? "missing"})`;
|
|
98865
99276
|
}
|
|
98866
99277
|
if (!slot) {
|
|
98867
|
-
return `slot_missing (expectedPid=${agentConfig.spawnedAgentPid})`;
|
|
99278
|
+
return agentConfig.spawnedAgentPid == null ? "spawned_pid_missing" : `slot_missing (expectedPid=${agentConfig.spawnedAgentPid})`;
|
|
98868
99279
|
}
|
|
98869
99280
|
if (!isSlotRunning(slot.state)) {
|
|
98870
|
-
return `slot_not_running (slotState=${slot.state}, expectedPid=${agentConfig.spawnedAgentPid})`;
|
|
99281
|
+
return `slot_not_running (slotState=${slot.state}, expectedPid=${agentConfig.spawnedAgentPid ?? "none"})`;
|
|
98871
99282
|
}
|
|
98872
|
-
if (slot.pid
|
|
99283
|
+
if (slot.pid == null) {
|
|
99284
|
+
return "slot_pid_missing";
|
|
99285
|
+
}
|
|
99286
|
+
if (agentConfig.spawnedAgentPid != null && slot.pid !== agentConfig.spawnedAgentPid) {
|
|
98873
99287
|
return `pid_mismatch (slotPid=${slot.pid ?? "none"}, snapshotPid=${agentConfig.spawnedAgentPid})`;
|
|
98874
99288
|
}
|
|
98875
99289
|
if (typeof slot.harnessSessionId !== "string" || slot.harnessSessionId.length === 0) {
|
|
@@ -98886,6 +99300,7 @@ function isDeliverableNativeTaskStatus(status3) {
|
|
|
98886
99300
|
}
|
|
98887
99301
|
var init_native_ready_invariant = __esm(() => {
|
|
98888
99302
|
init_types();
|
|
99303
|
+
init_native_delivery_session_registry();
|
|
98889
99304
|
init_assigned_task();
|
|
98890
99305
|
init_check_agent_slot();
|
|
98891
99306
|
});
|
|
@@ -98911,18 +99326,6 @@ function logNativeDeliveryNoTasks(role, chatroomId) {
|
|
|
98911
99326
|
console.log(`[NativeDelivery:skip] ${role}@${chatroomId} — no pending tasks for role`);
|
|
98912
99327
|
}
|
|
98913
99328
|
|
|
98914
|
-
// src/daemon/entry/native-delivery/native-delivery-session-registry.ts
|
|
98915
|
-
function registerNativeDeliverySession(ctx) {
|
|
98916
|
-
registered = ctx;
|
|
98917
|
-
}
|
|
98918
|
-
function unregisterNativeDeliverySession() {
|
|
98919
|
-
registered = null;
|
|
98920
|
-
}
|
|
98921
|
-
function getNativeDeliverySession() {
|
|
98922
|
-
return registered;
|
|
98923
|
-
}
|
|
98924
|
-
var registered = null;
|
|
98925
|
-
|
|
98926
99329
|
// src/daemon/entry/native-delivery/native-stale-turn-phase.ts
|
|
98927
99330
|
function isStaleTurnInFlightWhileWaiting(task, slot) {
|
|
98928
99331
|
if (!slot || isTurnPhaseIdle(slot.nativeTurnPhase ?? "idle"))
|
|
@@ -99409,38 +99812,21 @@ function mapAssignedTaskSnapshotList(rows) {
|
|
|
99409
99812
|
return rows.map(mapAssignedTaskSnapshot);
|
|
99410
99813
|
}
|
|
99411
99814
|
|
|
99412
|
-
// src/daemon/infrastructure/inbox/fetch-machine-assigned-task-snapshots.ts
|
|
99413
|
-
async function fetchMachineAssignedTaskSnapshots(sessionDeps, machineId) {
|
|
99414
|
-
const result = await sessionDeps.backend.query(api.machines.listMachineAssignedTaskSnapshots, {
|
|
99415
|
-
sessionId: sessionDeps.sessionId,
|
|
99416
|
-
machineId
|
|
99417
|
-
});
|
|
99418
|
-
return mapAssignedTaskSnapshotList(parseAssignedTaskSnapshotRows(result?.tasks ?? []));
|
|
99419
|
-
}
|
|
99420
|
-
function filterSnapshotsForRole(snapshots, chatroomId, role) {
|
|
99421
|
-
const roleLower = role.toLowerCase();
|
|
99422
|
-
return snapshots.filter((row) => row.chatroomId === chatroomId && row.agentConfig.role.toLowerCase() === roleLower);
|
|
99423
|
-
}
|
|
99424
|
-
var init_fetch_machine_assigned_task_snapshots = __esm(() => {
|
|
99425
|
-
init_assigned_task_snapshot_contract();
|
|
99426
|
-
init_api3();
|
|
99427
|
-
});
|
|
99428
|
-
|
|
99429
99815
|
// src/daemon/entry/restart-orchestrator-in-flight.ts
|
|
99430
|
-
function
|
|
99816
|
+
function roleKey2(chatroomId, role) {
|
|
99431
99817
|
return `${chatroomId}:${role.toLowerCase()}`;
|
|
99432
99818
|
}
|
|
99433
99819
|
function markRestartOrchestratorInFlight(chatroomId, role, correlationId) {
|
|
99434
|
-
inFlight.set(
|
|
99820
|
+
inFlight.set(roleKey2(chatroomId, role), correlationId);
|
|
99435
99821
|
}
|
|
99436
99822
|
function clearRestartOrchestratorInFlight(chatroomId, role, correlationId) {
|
|
99437
|
-
const key =
|
|
99823
|
+
const key = roleKey2(chatroomId, role);
|
|
99438
99824
|
if (correlationId !== undefined && inFlight.get(key) !== correlationId)
|
|
99439
99825
|
return;
|
|
99440
99826
|
inFlight.delete(key);
|
|
99441
99827
|
}
|
|
99442
99828
|
function isRestartOrchestratorInFlight(chatroomId, role) {
|
|
99443
|
-
return inFlight.has(
|
|
99829
|
+
return inFlight.has(roleKey2(chatroomId, role));
|
|
99444
99830
|
}
|
|
99445
99831
|
function filterSnapshotsExcludingRestartInFlight(snapshots) {
|
|
99446
99832
|
return snapshots.filter((row) => !isRestartOrchestratorInFlight(row.chatroomId, row.agentConfig.role));
|
|
@@ -99451,7 +99837,7 @@ var init_restart_orchestrator_in_flight = __esm(() => {
|
|
|
99451
99837
|
});
|
|
99452
99838
|
|
|
99453
99839
|
// src/daemon/entry/role-delivery-state.ts
|
|
99454
|
-
function
|
|
99840
|
+
function roleKey3(chatroomId, role) {
|
|
99455
99841
|
return `${chatroomId}:${role.toLowerCase()}`;
|
|
99456
99842
|
}
|
|
99457
99843
|
|
|
@@ -99460,10 +99846,10 @@ class RoleDeliveryState {
|
|
|
99460
99846
|
inFlight = new Set;
|
|
99461
99847
|
nativeNudgeFailures = new Map;
|
|
99462
99848
|
getGeneration(chatroomId, role) {
|
|
99463
|
-
return this.generation.get(
|
|
99849
|
+
return this.generation.get(roleKey3(chatroomId, role)) ?? 0;
|
|
99464
99850
|
}
|
|
99465
99851
|
resetDeliveryState(chatroomId, role) {
|
|
99466
|
-
const key =
|
|
99852
|
+
const key = roleKey3(chatroomId, role);
|
|
99467
99853
|
const next4 = (this.generation.get(key) ?? 0) + 1;
|
|
99468
99854
|
this.generation.set(key, next4);
|
|
99469
99855
|
this.inFlight.delete(key);
|
|
@@ -99471,26 +99857,26 @@ class RoleDeliveryState {
|
|
|
99471
99857
|
return next4;
|
|
99472
99858
|
}
|
|
99473
99859
|
tryAcquireDelivery(chatroomId, role) {
|
|
99474
|
-
const key =
|
|
99860
|
+
const key = roleKey3(chatroomId, role);
|
|
99475
99861
|
if (this.inFlight.has(key))
|
|
99476
99862
|
return false;
|
|
99477
99863
|
this.inFlight.add(key);
|
|
99478
99864
|
return true;
|
|
99479
99865
|
}
|
|
99480
99866
|
releaseDelivery(chatroomId, role) {
|
|
99481
|
-
this.inFlight.delete(
|
|
99867
|
+
this.inFlight.delete(roleKey3(chatroomId, role));
|
|
99482
99868
|
}
|
|
99483
99869
|
recordNativeNudgeFailure(chatroomId, role) {
|
|
99484
|
-
const key =
|
|
99870
|
+
const key = roleKey3(chatroomId, role);
|
|
99485
99871
|
const count3 = (this.nativeNudgeFailures.get(key) ?? 0) + 1;
|
|
99486
99872
|
this.nativeNudgeFailures.set(key, count3);
|
|
99487
99873
|
return count3;
|
|
99488
99874
|
}
|
|
99489
99875
|
clearNativeNudgeFailures(chatroomId, role) {
|
|
99490
|
-
this.nativeNudgeFailures.delete(
|
|
99876
|
+
this.nativeNudgeFailures.delete(roleKey3(chatroomId, role));
|
|
99491
99877
|
}
|
|
99492
99878
|
getNativeNudgeFailures(chatroomId, role) {
|
|
99493
|
-
return this.nativeNudgeFailures.get(
|
|
99879
|
+
return this.nativeNudgeFailures.get(roleKey3(chatroomId, role)) ?? 0;
|
|
99494
99880
|
}
|
|
99495
99881
|
}
|
|
99496
99882
|
function getRoleDeliveryState() {
|
|
@@ -99517,22 +99903,18 @@ class NativeTaskDeliveryCoordinator {
|
|
|
99517
99903
|
if (!session2)
|
|
99518
99904
|
return;
|
|
99519
99905
|
const { runtime: runtime4, effectContext: effectContext2, agentMgr, sessionDeps, machineId } = session2;
|
|
99520
|
-
|
|
99521
|
-
|
|
99522
|
-
|
|
99523
|
-
|
|
99524
|
-
|
|
99525
|
-
|
|
99526
|
-
|
|
99527
|
-
|
|
99528
|
-
|
|
99529
|
-
|
|
99530
|
-
|
|
99531
|
-
|
|
99532
|
-
machineId
|
|
99533
|
-
});
|
|
99534
|
-
}).catch((err) => {
|
|
99535
|
-
console.warn(`[NativeTaskDelivery] rehydrate failed for ${role}@${chatroomId}: ${getErrorMessage(err)}`);
|
|
99906
|
+
const tasks = session2.taskSnapshotState?.listForRole(chatroomId, role) ?? [];
|
|
99907
|
+
if (tasks.length === 0) {
|
|
99908
|
+
logNativeDeliveryNoTasks(role, chatroomId);
|
|
99909
|
+
return;
|
|
99910
|
+
}
|
|
99911
|
+
this.reconcileAssignedTasks({
|
|
99912
|
+
tasks,
|
|
99913
|
+
runtime: runtime4,
|
|
99914
|
+
effectContext: effectContext2,
|
|
99915
|
+
agentMgr,
|
|
99916
|
+
sessionDeps,
|
|
99917
|
+
machineId
|
|
99536
99918
|
});
|
|
99537
99919
|
}
|
|
99538
99920
|
reconcileAssignedTasks(params) {
|
|
@@ -99652,13 +100034,13 @@ function notifyNativeTurnIdle(params) {
|
|
|
99652
100034
|
var coordinator;
|
|
99653
100035
|
var init_native_task_delivery_coordinator = __esm(() => {
|
|
99654
100036
|
init_esm();
|
|
100037
|
+
init_native_delivery_session_registry();
|
|
99655
100038
|
init_native_stale_turn_phase();
|
|
99656
100039
|
init_native_task_injector_logic();
|
|
99657
100040
|
init_native_task_injector();
|
|
99658
100041
|
init_api3();
|
|
99659
100042
|
init_assigned_task();
|
|
99660
100043
|
init_convex_error();
|
|
99661
|
-
init_fetch_machine_assigned_task_snapshots();
|
|
99662
100044
|
init_restart_orchestrator_in_flight();
|
|
99663
100045
|
});
|
|
99664
100046
|
|
|
@@ -99880,15 +100262,19 @@ var init_restart_orchestrator = __esm(() => {
|
|
|
99880
100262
|
function createStartAgentDeps(agentMgr, session2) {
|
|
99881
100263
|
return {
|
|
99882
100264
|
agentProcessManager: {
|
|
99883
|
-
ensureRunning: async (args2) =>
|
|
99884
|
-
|
|
99885
|
-
|
|
99886
|
-
|
|
99887
|
-
|
|
99888
|
-
|
|
99889
|
-
|
|
99890
|
-
|
|
99891
|
-
|
|
100265
|
+
ensureRunning: async (args2) => {
|
|
100266
|
+
const result = await exports_Effect.runPromise(agentMgr.ensureRunning({
|
|
100267
|
+
chatroomId: args2.chatroomId,
|
|
100268
|
+
role: args2.role,
|
|
100269
|
+
agentHarness: args2.agentHarness,
|
|
100270
|
+
model: args2.model,
|
|
100271
|
+
workingDir: args2.workingDir,
|
|
100272
|
+
reason: args2.reason,
|
|
100273
|
+
wantResume: args2.wantResume
|
|
100274
|
+
}));
|
|
100275
|
+
if (!result.success) {}
|
|
100276
|
+
return result;
|
|
100277
|
+
}
|
|
99892
100278
|
},
|
|
99893
100279
|
session: {
|
|
99894
100280
|
sessionId: session2.sessionId,
|
|
@@ -100144,9 +100530,9 @@ var init_daemon_process_scan = __esm(() => {
|
|
|
100144
100530
|
|
|
100145
100531
|
// src/commands/machine/pid.ts
|
|
100146
100532
|
import { createHash as createHash3 } from "node:crypto";
|
|
100147
|
-
import { existsSync as existsSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync4, unlinkSync as unlinkSync2, mkdirSync as
|
|
100148
|
-
import { homedir as
|
|
100149
|
-
import { join as
|
|
100533
|
+
import { existsSync as existsSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync4, unlinkSync as unlinkSync2, mkdirSync as mkdirSync6 } from "node:fs";
|
|
100534
|
+
import { homedir as homedir7 } from "node:os";
|
|
100535
|
+
import { join as join20 } from "node:path";
|
|
100150
100536
|
function getUrlHash2() {
|
|
100151
100537
|
const url3 = getConvexUrl();
|
|
100152
100538
|
return createHash3("sha256").update(url3).digest("hex").substring(0, 8);
|
|
@@ -100156,11 +100542,11 @@ function getPidFileName() {
|
|
|
100156
100542
|
}
|
|
100157
100543
|
function ensureChatroomDir3() {
|
|
100158
100544
|
if (!existsSync8(CHATROOM_DIR4)) {
|
|
100159
|
-
|
|
100545
|
+
mkdirSync6(CHATROOM_DIR4, { recursive: true, mode: 448 });
|
|
100160
100546
|
}
|
|
100161
100547
|
}
|
|
100162
100548
|
function getPidFilePath() {
|
|
100163
|
-
return
|
|
100549
|
+
return join20(CHATROOM_DIR4, getPidFileName());
|
|
100164
100550
|
}
|
|
100165
100551
|
function isProcessRunning(pid) {
|
|
100166
100552
|
try {
|
|
@@ -100306,7 +100692,7 @@ var CHATROOM_DIR4, LOCK_RETRY_INTERVAL_MS = 500, LOCK_RETRY_MAX_WAIT_MS = 15000,
|
|
|
100306
100692
|
var init_pid = __esm(() => {
|
|
100307
100693
|
init_daemon_process_scan();
|
|
100308
100694
|
init_client2();
|
|
100309
|
-
CHATROOM_DIR4 =
|
|
100695
|
+
CHATROOM_DIR4 = join20(homedir7(), ".chatroom");
|
|
100310
100696
|
});
|
|
100311
100697
|
|
|
100312
100698
|
// src/infrastructure/machine/crash-loop-tracker.ts
|
|
@@ -102052,9 +102438,8 @@ class AgentProcessManager {
|
|
|
102052
102438
|
console.log(` ⚠️ ${failureLog}: ${err.message}`);
|
|
102053
102439
|
this.queueExitRetry({ role, args: exitArgs });
|
|
102054
102440
|
});
|
|
102055
|
-
this.deps.
|
|
102056
|
-
|
|
102057
|
-
});
|
|
102441
|
+
const emittedAt = this.deps.clock.now();
|
|
102442
|
+
this.deps.lifecycleOutbox.enqueue(buildExitedLifecycleFact(exitArgs, emittedAt)).catch((err) => console.log(` ⚠️ Failed to enqueue agent exited lifecycle fact: ${err.message}`));
|
|
102058
102443
|
}
|
|
102059
102444
|
async clearAgentPidQuietly(chatroomId, role) {
|
|
102060
102445
|
try {
|
|
@@ -102458,28 +102843,23 @@ class AgentProcessManager {
|
|
|
102458
102843
|
}).catch((err) => {
|
|
102459
102844
|
console.log(` ⚠️ Failed to record agent.started event: ${err.message}`);
|
|
102460
102845
|
});
|
|
102461
|
-
this.deps.
|
|
102462
|
-
|
|
102463
|
-
|
|
102846
|
+
const emittedAt = this.deps.clock.now();
|
|
102847
|
+
this.deps.lifecycleOutbox.enqueue({
|
|
102848
|
+
kind: "spawned",
|
|
102464
102849
|
chatroomId: opts.chatroomId,
|
|
102465
102850
|
role: opts.role,
|
|
102466
102851
|
pid,
|
|
102467
102852
|
model: opts.model,
|
|
102468
102853
|
reason: opts.reason,
|
|
102469
|
-
...spawnResult.harnessSessionId ? { harnessSessionId: spawnResult.harnessSessionId } : {}
|
|
102470
|
-
|
|
102471
|
-
|
|
102472
|
-
|
|
102473
|
-
|
|
102474
|
-
|
|
102475
|
-
|
|
102476
|
-
|
|
102477
|
-
|
|
102478
|
-
pid,
|
|
102479
|
-
model: opts.model
|
|
102480
|
-
}).catch((err) => {
|
|
102481
|
-
console.log(` ⚠️ Failed to update PID in backend: ${err.message}`);
|
|
102482
|
-
});
|
|
102854
|
+
...spawnResult.harnessSessionId ? { harnessSessionId: spawnResult.harnessSessionId } : {},
|
|
102855
|
+
revisionKey: buildAgentLifecycleRevisionKey("spawned", {
|
|
102856
|
+
chatroomId: opts.chatroomId,
|
|
102857
|
+
role: opts.role,
|
|
102858
|
+
pid,
|
|
102859
|
+
emittedAt
|
|
102860
|
+
}),
|
|
102861
|
+
emittedAt
|
|
102862
|
+
}).catch((err) => console.log(` ⚠️ Failed to enqueue agent spawned lifecycle fact: ${err.message}`));
|
|
102483
102863
|
}
|
|
102484
102864
|
registerSpawnCallbacks(slot, opts, spawnResult, pid) {
|
|
102485
102865
|
if (spawnResult.onLogLine) {
|
|
@@ -102834,6 +103214,11 @@ function assembleDaemonSessionInit(args2) {
|
|
|
102834
103214
|
} = args2;
|
|
102835
103215
|
deps.backend.mutation = (endpoint, args3) => client4.mutation(endpoint, args3);
|
|
102836
103216
|
deps.backend.query = (endpoint, args3) => client4.query(endpoint, args3);
|
|
103217
|
+
const agentLifecycleOutbox = createAgentLifecycleOutboxForSession({
|
|
103218
|
+
sessionId: typedSessionId,
|
|
103219
|
+
machineId,
|
|
103220
|
+
backend: deps.backend
|
|
103221
|
+
});
|
|
102837
103222
|
deps.agentProcessManager = new AgentProcessManager({
|
|
102838
103223
|
logEvent: activeLogEvent ?? (async () => {
|
|
102839
103224
|
return;
|
|
@@ -102849,7 +103234,8 @@ function assembleDaemonSessionInit(args2) {
|
|
|
102849
103234
|
persistence: deps.machine,
|
|
102850
103235
|
spawning: deps.spawning,
|
|
102851
103236
|
crashLoop: new CrashLoopTracker,
|
|
102852
|
-
convexUrl
|
|
103237
|
+
convexUrl,
|
|
103238
|
+
lifecycleOutbox: { enqueue: (fact) => enqueueAgentLifecycleFact(agentLifecycleOutbox, machineId, fact) }
|
|
102853
103239
|
});
|
|
102854
103240
|
return {
|
|
102855
103241
|
client: client4,
|
|
@@ -102862,6 +103248,7 @@ function assembleDaemonSessionInit(args2) {
|
|
|
102862
103248
|
machine: deps.machine,
|
|
102863
103249
|
spawning: deps.spawning,
|
|
102864
103250
|
agentProcessManager: deps.agentProcessManager,
|
|
103251
|
+
agentLifecycleOutbox,
|
|
102865
103252
|
events: new DaemonEventBus,
|
|
102866
103253
|
agentServices,
|
|
102867
103254
|
lastPushedGitState: new Map,
|
|
@@ -103094,6 +103481,8 @@ var init_init_daemon = __esm(() => {
|
|
|
103094
103481
|
init_daemon_startup_log();
|
|
103095
103482
|
init_orphan_tracker();
|
|
103096
103483
|
init_output_store();
|
|
103484
|
+
init_agent_lifecycle_outbox_runtime();
|
|
103485
|
+
init_agent_lifecycle_outbox_runtime();
|
|
103097
103486
|
init_state_recovery();
|
|
103098
103487
|
init_pid();
|
|
103099
103488
|
init_storage();
|
|
@@ -105724,6 +106113,14 @@ var init_workspace_cache = __esm(() => {
|
|
|
105724
106113
|
|
|
105725
106114
|
// src/daemon/infrastructure/git/run-command.ts
|
|
105726
106115
|
import { spawn as spawn4 } from "node:child_process";
|
|
106116
|
+
function enqueueGit(cwd, task) {
|
|
106117
|
+
const tail = gitQueues.get(cwd) ?? Promise.resolve();
|
|
106118
|
+
const run3 = tail.then(task, task);
|
|
106119
|
+
gitQueues.set(cwd, run3.catch(() => {
|
|
106120
|
+
return;
|
|
106121
|
+
}));
|
|
106122
|
+
return run3;
|
|
106123
|
+
}
|
|
105727
106124
|
function runCommandSpawn(command, args2, cwd, options) {
|
|
105728
106125
|
const successExitCodes = options?.successExitCodes ?? [0];
|
|
105729
106126
|
return new Promise((resolve4) => {
|
|
@@ -105769,7 +106166,7 @@ function runCommandSpawn(command, args2, cwd, options) {
|
|
|
105769
106166
|
});
|
|
105770
106167
|
}
|
|
105771
106168
|
function runGit(args2, cwd, options) {
|
|
105772
|
-
return runCommandSpawn("git", args2, cwd, options);
|
|
106169
|
+
return enqueueGit(cwd, () => runCommandSpawn("git", options?.readOnly ? ["--no-optional-locks", ...args2] : args2, cwd, options));
|
|
105773
106170
|
}
|
|
105774
106171
|
function runGh(args2, cwd, options) {
|
|
105775
106172
|
return runCommandSpawn("gh", args2, cwd, {
|
|
@@ -105777,7 +106174,7 @@ function runGh(args2, cwd, options) {
|
|
|
105777
106174
|
env: { ...process.env, NO_COLOR: "1" }
|
|
105778
106175
|
});
|
|
105779
106176
|
}
|
|
105780
|
-
var DEFAULT_GIT_ENV;
|
|
106177
|
+
var DEFAULT_GIT_ENV, gitQueues;
|
|
105781
106178
|
var init_run_command = __esm(() => {
|
|
105782
106179
|
DEFAULT_GIT_ENV = {
|
|
105783
106180
|
...process.env,
|
|
@@ -105785,6 +106182,7 @@ var init_run_command = __esm(() => {
|
|
|
105785
106182
|
GIT_PAGER: "cat",
|
|
105786
106183
|
NO_COLOR: "1"
|
|
105787
106184
|
};
|
|
106185
|
+
gitQueues = new Map;
|
|
105788
106186
|
});
|
|
105789
106187
|
|
|
105790
106188
|
// src/daemon/infrastructure/git/types.ts
|
|
@@ -105794,6 +106192,9 @@ function makeGitStateKey(machineId, workingDir) {
|
|
|
105794
106192
|
var FULL_DIFF_MAX_BYTES = 500000, COMMITS_PER_PAGE = 20;
|
|
105795
106193
|
|
|
105796
106194
|
// src/daemon/infrastructure/git/git-reader.ts
|
|
106195
|
+
function runGit2(args2, cwd, options) {
|
|
106196
|
+
return runGit(cwd ? args2 : args2, cwd, { ...options, readOnly: true });
|
|
106197
|
+
}
|
|
105797
106198
|
function repoArgs(repoSlug) {
|
|
105798
106199
|
return repoSlug ? ["--repo", repoSlug] : [];
|
|
105799
106200
|
}
|
|
@@ -105810,14 +106211,14 @@ function isEmptyRepo(stderr) {
|
|
|
105810
106211
|
return stderr.includes("does not have any commits yet") || stderr.includes("no commits yet") || stderr.includes("ambiguous argument 'HEAD'") || stderr.includes("unknown revision or path");
|
|
105811
106212
|
}
|
|
105812
106213
|
async function listUntrackedFiles(workingDir) {
|
|
105813
|
-
const result = await
|
|
106214
|
+
const result = await runGit2(["ls-files", "--others", "--exclude-standard"], workingDir);
|
|
105814
106215
|
if ("error" in result)
|
|
105815
106216
|
return [];
|
|
105816
106217
|
return result.stdout.split(`
|
|
105817
106218
|
`).map((line) => line.trim()).filter(Boolean);
|
|
105818
106219
|
}
|
|
105819
106220
|
async function getUntrackedFileDiff(workingDir, filePath) {
|
|
105820
|
-
const result = await
|
|
106221
|
+
const result = await runGit2(["diff", "--no-index", "--", NULL_DEVICE, filePath], workingDir, {
|
|
105821
106222
|
successExitCodes: [0, 1]
|
|
105822
106223
|
});
|
|
105823
106224
|
if ("error" in result)
|
|
@@ -105878,7 +106279,7 @@ function truncateDiffContent(raw) {
|
|
|
105878
106279
|
return { status: "available", content: raw, truncated: false };
|
|
105879
106280
|
}
|
|
105880
106281
|
async function runTrackedHeadDiff(workingDir, args2, options) {
|
|
105881
|
-
const result = await
|
|
106282
|
+
const result = await runGit2(args2, workingDir, options);
|
|
105882
106283
|
if ("error" in result) {
|
|
105883
106284
|
const errMsg = result.error.message;
|
|
105884
106285
|
if (isEmptyRepo(errMsg))
|
|
@@ -105907,13 +106308,13 @@ function classifyError(errMessage) {
|
|
|
105907
106308
|
return { status: "error", message: errMessage.trim() };
|
|
105908
106309
|
}
|
|
105909
106310
|
async function isGitRepo(workingDir) {
|
|
105910
|
-
const result = await
|
|
106311
|
+
const result = await runGit2(["rev-parse", "--git-dir"], workingDir);
|
|
105911
106312
|
if ("error" in result)
|
|
105912
106313
|
return false;
|
|
105913
106314
|
return result.stdout.trim().length > 0;
|
|
105914
106315
|
}
|
|
105915
106316
|
async function getBranch(workingDir) {
|
|
105916
|
-
const result = await
|
|
106317
|
+
const result = await runGit2(["rev-parse", "--abbrev-ref", "HEAD"], workingDir);
|
|
105917
106318
|
if ("error" in result) {
|
|
105918
106319
|
const errMsg = result.error.message;
|
|
105919
106320
|
if (errMsg.includes("unknown revision") || errMsg.includes("No such file or directory") || errMsg.includes("does not have any commits")) {
|
|
@@ -105928,7 +106329,7 @@ async function getBranch(workingDir) {
|
|
|
105928
106329
|
return { status: "available", branch };
|
|
105929
106330
|
}
|
|
105930
106331
|
async function isDirty(workingDir) {
|
|
105931
|
-
const result = await
|
|
106332
|
+
const result = await runGit2(["status", "--porcelain"], workingDir);
|
|
105932
106333
|
if ("error" in result)
|
|
105933
106334
|
return false;
|
|
105934
106335
|
return result.stdout.trim().length > 0;
|
|
@@ -105998,7 +106399,7 @@ async function getRecentCommits(workingDir, count3 = 20, skip = 0) {
|
|
|
105998
106399
|
if (skip > 0)
|
|
105999
106400
|
logArgs.push(`--skip=${skip}`);
|
|
106000
106401
|
logArgs.push(`--format=${format4}`);
|
|
106001
|
-
const result = await
|
|
106402
|
+
const result = await runGit2(logArgs, workingDir);
|
|
106002
106403
|
if ("error" in result) {
|
|
106003
106404
|
return [];
|
|
106004
106405
|
}
|
|
@@ -106020,7 +106421,7 @@ async function getRecentCommits(workingDir, count3 = 20, skip = 0) {
|
|
|
106020
106421
|
return commits;
|
|
106021
106422
|
}
|
|
106022
106423
|
async function getCommitDetail(workingDir, sha) {
|
|
106023
|
-
const result = await
|
|
106424
|
+
const result = await runGit2(["show", sha, "--format=", "--stat", "-p"], workingDir);
|
|
106024
106425
|
if ("error" in result) {
|
|
106025
106426
|
const errMsg = result.error.message;
|
|
106026
106427
|
const classified = classifyError(errMsg);
|
|
@@ -106041,7 +106442,7 @@ async function getCommitDetail(workingDir, sha) {
|
|
|
106041
106442
|
}
|
|
106042
106443
|
async function getCommitMetadata(workingDir, sha) {
|
|
106043
106444
|
const format4 = "%s%x1f%b%x1f%an%x1f%aI";
|
|
106044
|
-
const result = await
|
|
106445
|
+
const result = await runGit2(["log", "-1", `--format=${format4}`, sha], workingDir);
|
|
106045
106446
|
if ("error" in result)
|
|
106046
106447
|
return null;
|
|
106047
106448
|
const output = result.stdout.trim();
|
|
@@ -106067,7 +106468,7 @@ function parseRepoSlug(remoteUrl) {
|
|
|
106067
106468
|
return null;
|
|
106068
106469
|
}
|
|
106069
106470
|
async function getOriginRepoSlug(cwd) {
|
|
106070
|
-
const result = await
|
|
106471
|
+
const result = await runGit2(["remote", "get-url", "origin"], cwd);
|
|
106071
106472
|
if ("error" in result)
|
|
106072
106473
|
return null;
|
|
106073
106474
|
const url3 = result.stdout.trim();
|
|
@@ -106204,7 +106605,7 @@ async function getPRCommits(cwd, prNumber) {
|
|
|
106204
106605
|
}
|
|
106205
106606
|
}
|
|
106206
106607
|
async function getRemotes(cwd) {
|
|
106207
|
-
const result = await
|
|
106608
|
+
const result = await runGit2(["remote", "-v"], cwd);
|
|
106208
106609
|
if ("error" in result)
|
|
106209
106610
|
return [];
|
|
106210
106611
|
if (!result.stdout.trim())
|
|
@@ -106228,14 +106629,14 @@ async function getRemotes(cwd) {
|
|
|
106228
106629
|
return remotes;
|
|
106229
106630
|
}
|
|
106230
106631
|
async function getCommitsAhead(workingDir) {
|
|
106231
|
-
const result = await
|
|
106632
|
+
const result = await runGit2(["rev-list", "--count", "@{upstream}..HEAD"], workingDir);
|
|
106232
106633
|
if ("error" in result)
|
|
106233
106634
|
return 0;
|
|
106234
106635
|
const count3 = parseInt(result.stdout.trim(), 10);
|
|
106235
106636
|
return Number.isNaN(count3) ? 0 : count3;
|
|
106236
106637
|
}
|
|
106237
106638
|
async function getCommitsBehind(workingDir) {
|
|
106238
|
-
const result = await
|
|
106639
|
+
const result = await runGit2(["rev-list", "--count", "HEAD..@{upstream}"], workingDir);
|
|
106239
106640
|
if ("error" in result)
|
|
106240
106641
|
return 0;
|
|
106241
106642
|
const count3 = parseInt(result.stdout.trim(), 10);
|
|
@@ -106329,16 +106730,12 @@ class GitStatePipeline {
|
|
|
106329
106730
|
const results = new Map(preCollected);
|
|
106330
106731
|
if (this.fields.length === 0)
|
|
106331
106732
|
return results;
|
|
106332
|
-
const
|
|
106733
|
+
for (const field of this.fields.filter((f) => !results.has(f.key))) {
|
|
106333
106734
|
try {
|
|
106334
|
-
|
|
106335
|
-
return { key: field.key, raw };
|
|
106735
|
+
results.set(field.key, await field.collect(workingDir));
|
|
106336
106736
|
} catch {
|
|
106337
|
-
|
|
106737
|
+
results.set(field.key, field.defaultValue);
|
|
106338
106738
|
}
|
|
106339
|
-
}));
|
|
106340
|
-
for (const { key, raw } of entries2) {
|
|
106341
|
-
results.set(key, raw);
|
|
106342
106739
|
}
|
|
106343
106740
|
return results;
|
|
106344
106741
|
}
|
|
@@ -107503,16 +107900,16 @@ var init_jsonc = __esm(() => {
|
|
|
107503
107900
|
|
|
107504
107901
|
// src/infrastructure/services/workspace/workspace-resolver.ts
|
|
107505
107902
|
import { readFile as readFile7, readdir, stat as stat3 } from "node:fs/promises";
|
|
107506
|
-
import { join as
|
|
107903
|
+
import { join as join21, basename, resolve as resolve4 } from "node:path";
|
|
107507
107904
|
async function resolveGlobPatternStar(rootDir, cleaned) {
|
|
107508
|
-
const parentDir =
|
|
107905
|
+
const parentDir = join21(rootDir, cleaned.slice(0, -2));
|
|
107509
107906
|
try {
|
|
107510
107907
|
const entries2 = await readdir(parentDir, { withFileTypes: true });
|
|
107511
107908
|
const dirs = [];
|
|
107512
107909
|
for (const entry of entries2) {
|
|
107513
107910
|
if (!entry.isDirectory())
|
|
107514
107911
|
continue;
|
|
107515
|
-
const dirPath =
|
|
107912
|
+
const dirPath = join21(parentDir, entry.name);
|
|
107516
107913
|
if (resolve4(dirPath).startsWith(resolve4(rootDir))) {
|
|
107517
107914
|
dirs.push(dirPath);
|
|
107518
107915
|
}
|
|
@@ -107523,7 +107920,7 @@ async function resolveGlobPatternStar(rootDir, cleaned) {
|
|
|
107523
107920
|
}
|
|
107524
107921
|
}
|
|
107525
107922
|
async function resolveLiteralPath(rootDir, cleaned) {
|
|
107526
|
-
const dir =
|
|
107923
|
+
const dir = join21(rootDir, cleaned);
|
|
107527
107924
|
try {
|
|
107528
107925
|
if (!resolve4(dir).startsWith(resolve4(rootDir)))
|
|
107529
107926
|
return [];
|
|
@@ -107543,7 +107940,7 @@ async function resolveGlobPattern(rootDir, pattern) {
|
|
|
107543
107940
|
}
|
|
107544
107941
|
async function readPackageJson(dir) {
|
|
107545
107942
|
try {
|
|
107546
|
-
const content = await readFile7(
|
|
107943
|
+
const content = await readFile7(join21(dir, "package.json"), "utf-8");
|
|
107547
107944
|
const pkg = JSON.parse(content);
|
|
107548
107945
|
return {
|
|
107549
107946
|
name: pkg.name || basename(dir),
|
|
@@ -107555,7 +107952,7 @@ async function readPackageJson(dir) {
|
|
|
107555
107952
|
}
|
|
107556
107953
|
async function readPnpmWorkspacePatterns(rootDir) {
|
|
107557
107954
|
try {
|
|
107558
|
-
const content = await readFile7(
|
|
107955
|
+
const content = await readFile7(join21(rootDir, "pnpm-workspace.yaml"), "utf-8");
|
|
107559
107956
|
const patterns = [];
|
|
107560
107957
|
let inPackages = false;
|
|
107561
107958
|
for (const line of content.split(`
|
|
@@ -107582,7 +107979,7 @@ async function readPnpmWorkspacePatterns(rootDir) {
|
|
|
107582
107979
|
}
|
|
107583
107980
|
async function readPackageJsonWorkspacePatterns(rootDir) {
|
|
107584
107981
|
try {
|
|
107585
|
-
const content = await readFile7(
|
|
107982
|
+
const content = await readFile7(join21(rootDir, "package.json"), "utf-8");
|
|
107586
107983
|
const pkg = JSON.parse(content);
|
|
107587
107984
|
if (!pkg.workspaces)
|
|
107588
107985
|
return [];
|
|
@@ -107663,11 +108060,11 @@ var MAX_NAME_LENGTH = 256;
|
|
|
107663
108060
|
|
|
107664
108061
|
// src/infrastructure/services/workspace/command-discovery.ts
|
|
107665
108062
|
import { access as access2, readFile as readFile8 } from "node:fs/promises";
|
|
107666
|
-
import { join as
|
|
108063
|
+
import { join as join22, relative, basename as basename2 } from "node:path";
|
|
107667
108064
|
async function detectPackageManager(workingDir) {
|
|
107668
108065
|
for (const { file: file2, manager } of LOCKFILE_MAP) {
|
|
107669
108066
|
try {
|
|
107670
|
-
await access2(
|
|
108067
|
+
await access2(join22(workingDir, file2));
|
|
107671
108068
|
return manager;
|
|
107672
108069
|
} catch {}
|
|
107673
108070
|
}
|
|
@@ -107736,7 +108133,7 @@ function collectRootScriptCommands(scripts, pm, scriptPrefix, rootSw) {
|
|
|
107736
108133
|
}
|
|
107737
108134
|
async function readRootPackageJson(workingDir, pm, scriptPrefix) {
|
|
107738
108135
|
let rootPackageName = basename2(workingDir);
|
|
107739
|
-
const pkg = await readJsonFile(
|
|
108136
|
+
const pkg = await readJsonFile(join22(workingDir, "package.json"), "root package.json");
|
|
107740
108137
|
if (!pkg)
|
|
107741
108138
|
return { commands: [], rootPackageName };
|
|
107742
108139
|
if (pkg.name)
|
|
@@ -107752,7 +108149,7 @@ async function readRootPackageJson(workingDir, pm, scriptPrefix) {
|
|
|
107752
108149
|
}
|
|
107753
108150
|
async function readTurboJson(workingDir, _turboPrefix, _rootSubWorkspace) {
|
|
107754
108151
|
const turboTaskNames = [];
|
|
107755
|
-
const turbo = await readJsonFile(
|
|
108152
|
+
const turbo = await readJsonFile(join22(workingDir, "turbo.json"), "turbo.json");
|
|
107756
108153
|
if (!turbo?.tasks || typeof turbo.tasks !== "object")
|
|
107757
108154
|
return turboTaskNames;
|
|
107758
108155
|
for (const taskName of Object.keys(turbo.tasks)) {
|
|
@@ -107765,7 +108162,7 @@ async function readTurboJson(workingDir, _turboPrefix, _rootSubWorkspace) {
|
|
|
107765
108162
|
async function readDenoJson(workingDir) {
|
|
107766
108163
|
const commands = [];
|
|
107767
108164
|
for (const fileName of ["deno.json", "deno.jsonc"]) {
|
|
107768
|
-
const deno = await readJsonFile(
|
|
108165
|
+
const deno = await readJsonFile(join22(workingDir, fileName), fileName);
|
|
107769
108166
|
if (!deno?.tasks || typeof deno.tasks !== "object")
|
|
107770
108167
|
continue;
|
|
107771
108168
|
const pkgName = deno.name ?? basename2(workingDir);
|
|
@@ -107788,7 +108185,7 @@ async function readMakefile(workingDir) {
|
|
|
107788
108185
|
const commands = [];
|
|
107789
108186
|
for (const fileName of ["Makefile", "makefile"]) {
|
|
107790
108187
|
try {
|
|
107791
|
-
const content = await readFile8(
|
|
108188
|
+
const content = await readFile8(join22(workingDir, fileName), "utf-8");
|
|
107792
108189
|
const targets = parseMakefileTargets(content);
|
|
107793
108190
|
if (targets.length === 0)
|
|
107794
108191
|
continue;
|
|
@@ -109994,7 +110391,7 @@ var init_assert_registered_working_dir = __esm(() => {
|
|
|
109994
110391
|
|
|
109995
110392
|
// src/infrastructure/services/workspace/workspace-path-security.ts
|
|
109996
110393
|
import { realpath } from "node:fs/promises";
|
|
109997
|
-
import { dirname as
|
|
110394
|
+
import { dirname as dirname10, isAbsolute, relative as relative2, resolve as resolve5, sep } from "node:path";
|
|
109998
110395
|
import { gunzipSync } from "node:zlib";
|
|
109999
110396
|
function validateRelativePathSegments(filePath) {
|
|
110000
110397
|
if (filePath.includes("\x00"))
|
|
@@ -110022,7 +110419,7 @@ function assertContained(workspaceRoot, targetPath) {
|
|
|
110022
110419
|
return { ok: true };
|
|
110023
110420
|
}
|
|
110024
110421
|
async function resolveNonExistentTarget(workspaceRoot, candidate) {
|
|
110025
|
-
let current =
|
|
110422
|
+
let current = dirname10(candidate);
|
|
110026
110423
|
for (;; ) {
|
|
110027
110424
|
try {
|
|
110028
110425
|
const ancestorReal = await realpath(current);
|
|
@@ -110040,7 +110437,7 @@ async function resolveNonExistentTarget(workspaceRoot, candidate) {
|
|
|
110040
110437
|
if (code2 !== "ENOENT") {
|
|
110041
110438
|
return { ok: false, error: "Invalid file path" };
|
|
110042
110439
|
}
|
|
110043
|
-
const parent =
|
|
110440
|
+
const parent = dirname10(current);
|
|
110044
110441
|
if (parent === current) {
|
|
110045
110442
|
return { ok: false, error: "Path escapes workspace" };
|
|
110046
110443
|
}
|
|
@@ -110851,16 +111248,16 @@ var require_ignore = __commonJS((exports, module) => {
|
|
|
110851
111248
|
// src/infrastructure/services/workspace/workspace-ignore.ts
|
|
110852
111249
|
import { promises as fsPromises } from "node:fs";
|
|
110853
111250
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
110854
|
-
import { homedir as
|
|
111251
|
+
import { homedir as homedir8 } from "node:os";
|
|
110855
111252
|
import path3 from "node:path";
|
|
110856
111253
|
function normalizeRelativePath(relativePath) {
|
|
110857
111254
|
return relativePath.replace(/\\/g, "/").replace(/^\.?\//, "").replace(/\/+$/, "");
|
|
110858
111255
|
}
|
|
110859
111256
|
function expandUserPath(filePath) {
|
|
110860
111257
|
if (filePath === "~")
|
|
110861
|
-
return
|
|
111258
|
+
return homedir8();
|
|
110862
111259
|
if (filePath.startsWith("~/"))
|
|
110863
|
-
return path3.join(
|
|
111260
|
+
return path3.join(homedir8(), filePath.slice(2));
|
|
110864
111261
|
return filePath;
|
|
110865
111262
|
}
|
|
110866
111263
|
function readExcludesFileFromGitconfig(content) {
|
|
@@ -110891,11 +111288,11 @@ async function readGitconfigExcludesFilePath(configPath) {
|
|
|
110891
111288
|
return path3.isAbsolute(raw) ? expandUserPath(raw) : path3.resolve(path3.dirname(configPath), raw);
|
|
110892
111289
|
}
|
|
110893
111290
|
async function resolveGitExtraExcludeFilePaths(rootDir) {
|
|
110894
|
-
const globalConfig2 = process.env.GIT_CONFIG_GLOBAL?.length ? process.env.GIT_CONFIG_GLOBAL : path3.join(
|
|
111291
|
+
const globalConfig2 = process.env.GIT_CONFIG_GLOBAL?.length ? process.env.GIT_CONFIG_GLOBAL : path3.join(homedir8(), ".gitconfig");
|
|
110895
111292
|
const localConfig = path3.join(rootDir, ".git", "config");
|
|
110896
111293
|
let excludesFile = await readGitconfigExcludesFilePath(localConfig) ?? await readGitconfigExcludesFilePath(globalConfig2);
|
|
110897
111294
|
if (!excludesFile) {
|
|
110898
|
-
excludesFile = path3.join(process.env.XDG_CONFIG_HOME?.length ? process.env.XDG_CONFIG_HOME : path3.join(
|
|
111295
|
+
excludesFile = path3.join(process.env.XDG_CONFIG_HOME?.length ? process.env.XDG_CONFIG_HOME : path3.join(homedir8(), ".config"), "git", "ignore");
|
|
110899
111296
|
}
|
|
110900
111297
|
const candidates = [excludesFile, path3.join(rootDir, ".git", "info", "exclude")];
|
|
110901
111298
|
const existing = [];
|
|
@@ -111347,7 +111744,8 @@ function porcelainUntrackedDeletedEvents(args2) {
|
|
|
111347
111744
|
}
|
|
111348
111745
|
async function readGitHead(workTree) {
|
|
111349
111746
|
const result = await runGit(["rev-parse", "HEAD"], workTree, {
|
|
111350
|
-
timeout: GIT_POLL_TIMEOUT_MS
|
|
111747
|
+
timeout: GIT_POLL_TIMEOUT_MS,
|
|
111748
|
+
readOnly: true
|
|
111351
111749
|
});
|
|
111352
111750
|
if ("error" in result) {
|
|
111353
111751
|
if (isEmptyRepoHeadError(result.error))
|
|
@@ -111371,7 +111769,10 @@ async function readGitPorcelainStatus(node) {
|
|
|
111371
111769
|
const args2 = ["status", "--porcelain=v1", "-z", "-uall", "--"];
|
|
111372
111770
|
if (node.pathspec.length > 0)
|
|
111373
111771
|
args2.push(...node.pathspec);
|
|
111374
|
-
const result = await runGit(args2, node.workTree, {
|
|
111772
|
+
const result = await runGit(args2, node.workTree, {
|
|
111773
|
+
timeout: GIT_POLL_TIMEOUT_MS,
|
|
111774
|
+
readOnly: true
|
|
111775
|
+
});
|
|
111375
111776
|
if ("error" in result) {
|
|
111376
111777
|
throw new GitWorkspaceCommandError({
|
|
111377
111778
|
operation: "readGitPorcelainStatus",
|
|
@@ -111509,35 +111910,31 @@ function createGitWorkspaceChangeSource(options) {
|
|
|
111509
111910
|
let needsReconcile = false;
|
|
111510
111911
|
let tickHadFailure = false;
|
|
111511
111912
|
let maxNodeFailures = 0;
|
|
111512
|
-
const
|
|
111513
|
-
|
|
111514
|
-
|
|
111515
|
-
|
|
111516
|
-
|
|
111517
|
-
|
|
111518
|
-
|
|
111519
|
-
|
|
111520
|
-
|
|
111521
|
-
|
|
111522
|
-
|
|
111523
|
-
|
|
111524
|
-
|
|
111525
|
-
needsReconcile
|
|
111526
|
-
|
|
111527
|
-
|
|
111528
|
-
|
|
111529
|
-
|
|
111530
|
-
|
|
111531
|
-
|
|
111532
|
-
|
|
111533
|
-
|
|
111534
|
-
|
|
111535
|
-
|
|
111536
|
-
|
|
111537
|
-
const prevFailures = nodeFailureCounts.get(node.workTree) ?? 0;
|
|
111538
|
-
const nextFailures = prevFailures + 1;
|
|
111539
|
-
nodeFailureCounts.set(node.workTree, nextFailures);
|
|
111540
|
-
maxNodeFailures = Math.max(maxNodeFailures, nextFailures);
|
|
111913
|
+
for (const node of nodes) {
|
|
111914
|
+
try {
|
|
111915
|
+
const prev = state.get(node.workTree) ?? {
|
|
111916
|
+
prevEntries: [],
|
|
111917
|
+
prevHead: { head: null },
|
|
111918
|
+
baselineEstablished: false
|
|
111919
|
+
};
|
|
111920
|
+
const result = await pollGitWorkspaceNode({
|
|
111921
|
+
options,
|
|
111922
|
+
node,
|
|
111923
|
+
prev
|
|
111924
|
+
});
|
|
111925
|
+
allEvents.push(...result.events);
|
|
111926
|
+
if (result.needsReconcile)
|
|
111927
|
+
needsReconcile = true;
|
|
111928
|
+
state.set(node.workTree, result.nextState);
|
|
111929
|
+
nodeFailureCounts.set(node.workTree, 0);
|
|
111930
|
+
} catch (reason) {
|
|
111931
|
+
tickHadFailure = true;
|
|
111932
|
+
options.onError?.(reason);
|
|
111933
|
+
const prevFailures = nodeFailureCounts.get(node.workTree) ?? 0;
|
|
111934
|
+
const nextFailures = prevFailures + 1;
|
|
111935
|
+
nodeFailureCounts.set(node.workTree, nextFailures);
|
|
111936
|
+
maxNodeFailures = Math.max(maxNodeFailures, nextFailures);
|
|
111937
|
+
}
|
|
111541
111938
|
}
|
|
111542
111939
|
if (tickHadFailure) {
|
|
111543
111940
|
consecutiveFailureTicks += 1;
|
|
@@ -111595,7 +111992,7 @@ function createGitWorkspaceChangeSource(options) {
|
|
|
111595
111992
|
}
|
|
111596
111993
|
};
|
|
111597
111994
|
}
|
|
111598
|
-
var DEFAULT_POLL_INTERVAL_MS =
|
|
111995
|
+
var DEFAULT_POLL_INTERVAL_MS = 3000, MAX_BACKOFF_MS = 30000, PERSISTENT_FAILURE_THRESHOLD = 3;
|
|
111599
111996
|
var init_git_workspace_change_source = __esm(() => {
|
|
111600
111997
|
init_git_workspace_porcelain();
|
|
111601
111998
|
});
|
|
@@ -112024,9 +112421,9 @@ class NodeFsHandler {
|
|
|
112024
112421
|
if (this.fsw.closed) {
|
|
112025
112422
|
return;
|
|
112026
112423
|
}
|
|
112027
|
-
const
|
|
112424
|
+
const dirname12 = sp.dirname(file2);
|
|
112028
112425
|
const basename4 = sp.basename(file2);
|
|
112029
|
-
const parent = this.fsw._getWatchedDir(
|
|
112426
|
+
const parent = this.fsw._getWatchedDir(dirname12);
|
|
112030
112427
|
let prevStats = stats;
|
|
112031
112428
|
if (parent.has(basename4))
|
|
112032
112429
|
return;
|
|
@@ -112053,7 +112450,7 @@ class NodeFsHandler {
|
|
|
112053
112450
|
prevStats = newStats2;
|
|
112054
112451
|
}
|
|
112055
112452
|
} catch (error51) {
|
|
112056
|
-
this.fsw._remove(
|
|
112453
|
+
this.fsw._remove(dirname12, basename4);
|
|
112057
112454
|
}
|
|
112058
112455
|
} else if (parent.has(basename4)) {
|
|
112059
112456
|
const at = newStats.atimeMs;
|
|
@@ -113442,8 +113839,8 @@ function diffPathIndexes(previous, next4) {
|
|
|
113442
113839
|
// src/infrastructure/services/workspace/workspace-sync-state.ts
|
|
113443
113840
|
import { createHash as createHash7, randomUUID as randomUUID9 } from "node:crypto";
|
|
113444
113841
|
import * as fs11 from "node:fs/promises";
|
|
113445
|
-
import { homedir as
|
|
113446
|
-
import { join as
|
|
113842
|
+
import { homedir as homedir9 } from "node:os";
|
|
113843
|
+
import { join as join25 } from "node:path";
|
|
113447
113844
|
function workspaceKeyFor(workingDir) {
|
|
113448
113845
|
const normalized = normalizeWorkingDirForLookup(workingDir);
|
|
113449
113846
|
return createHash7("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
@@ -113457,10 +113854,10 @@ function buildPathIndex(entries2) {
|
|
|
113457
113854
|
}
|
|
113458
113855
|
function manifestPath(machineId, workingDir) {
|
|
113459
113856
|
const key = workspaceKeyFor(workingDir);
|
|
113460
|
-
return
|
|
113857
|
+
return join25(SYNC_STATE_DIR, machineId, key, "manifest.json");
|
|
113461
113858
|
}
|
|
113462
113859
|
async function ensureDir(filePath) {
|
|
113463
|
-
await fs11.mkdir(
|
|
113860
|
+
await fs11.mkdir(join25(filePath, ".."), { recursive: true, mode: 448 });
|
|
113464
113861
|
}
|
|
113465
113862
|
async function loadWorkspaceSyncManifest(machineId, workingDir) {
|
|
113466
113863
|
try {
|
|
@@ -113520,7 +113917,7 @@ function entriesFromPathIndex(paths) {
|
|
|
113520
113917
|
}
|
|
113521
113918
|
var SYNC_STATE_VERSION = "2", SYNC_STATE_DIR;
|
|
113522
113919
|
var init_workspace_sync_state = __esm(() => {
|
|
113523
|
-
SYNC_STATE_DIR =
|
|
113920
|
+
SYNC_STATE_DIR = join25(homedir9(), ".chatroom", "sync-state");
|
|
113524
113921
|
});
|
|
113525
113922
|
|
|
113526
113923
|
// src/infrastructure/services/workspace/workspace-file-tree-coordinator.ts
|
|
@@ -113897,12 +114294,12 @@ var init_durable_coalescing_state_schema = __esm(() => {
|
|
|
113897
114294
|
});
|
|
113898
114295
|
|
|
113899
114296
|
// src/daemon/infrastructure/outbox/lib/durable-coalescing-state-store.ts
|
|
113900
|
-
import { mkdirSync as
|
|
113901
|
-
import { dirname as
|
|
113902
|
-
import { DatabaseSync } from "node:sqlite";
|
|
114297
|
+
import { mkdirSync as mkdirSync7 } from "node:fs";
|
|
114298
|
+
import { dirname as dirname13 } from "node:path";
|
|
114299
|
+
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
113903
114300
|
function openDurableCoalescingStateStore(path8) {
|
|
113904
|
-
|
|
113905
|
-
const db = new
|
|
114301
|
+
mkdirSync7(dirname13(path8), { recursive: true });
|
|
114302
|
+
const db = new DatabaseSync2(path8);
|
|
113906
114303
|
for (const sql of DURABLE_COALESCING_STATE_MIGRATIONS)
|
|
113907
114304
|
db.exec(sql);
|
|
113908
114305
|
db.prepare("UPDATE coalescing_outbox_entries SET status='pending' WHERE status='in_flight'").run();
|
|
@@ -113919,13 +114316,6 @@ var init_durable_coalescing_state_store = __esm(() => {
|
|
|
113919
114316
|
init_durable_coalescing_state_schema();
|
|
113920
114317
|
});
|
|
113921
114318
|
|
|
113922
|
-
// src/daemon/infrastructure/outbox/lib/outbox-retry-backoff.ts
|
|
113923
|
-
function computeExponentialRetryDelayMs(attempt, retryDelayMs, maxRetryDelayMs) {
|
|
113924
|
-
const exponent = Math.min(Math.max(0, attempt), MAX_RETRY_EXPONENT);
|
|
113925
|
-
return Math.min(retryDelayMs * 2 ** exponent, maxRetryDelayMs);
|
|
113926
|
-
}
|
|
113927
|
-
var MAX_RETRY_EXPONENT = 20;
|
|
113928
|
-
|
|
113929
114319
|
// src/daemon/infrastructure/outbox/lib/coalescing-state-outbox.ts
|
|
113930
114320
|
function createCoalescingStateOutbox(options) {
|
|
113931
114321
|
const durable = [options.store, options.deliveryKey, options.serialize, options.deserialize];
|
|
@@ -114102,14 +114492,6 @@ var init_keyed_coalescing_state_outbox_registry = __esm(() => {
|
|
|
114102
114492
|
init_coalescing_state_outbox();
|
|
114103
114493
|
});
|
|
114104
114494
|
|
|
114105
|
-
// src/daemon/infrastructure/outbox/outbox-db-path.ts
|
|
114106
|
-
import { homedir as homedir9 } from "node:os";
|
|
114107
|
-
import { join as join25 } from "node:path";
|
|
114108
|
-
function resolveOutboxDbPath(machineId, kind) {
|
|
114109
|
-
return join25(homedir9(), ".chatroom", "daemon", machineId, `outbox-${kind}.sqlite`);
|
|
114110
|
-
}
|
|
114111
|
-
var init_outbox_db_path = () => {};
|
|
114112
|
-
|
|
114113
114495
|
// src/daemon/infrastructure/outbox/workspace-file-tree-checkpoint-outbox.ts
|
|
114114
114496
|
function createWorkspaceFileTreeCheckpointOutboxRegistry(machineId, createSend, options) {
|
|
114115
114497
|
return createKeyedCoalescingStateOutboxRegistry({
|
|
@@ -114131,193 +114513,6 @@ var init_workspace_file_tree_checkpoint_outbox = __esm(() => {
|
|
|
114131
114513
|
WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_MAX_RETRY_DELAY_MS = 5 * 60000;
|
|
114132
114514
|
});
|
|
114133
114515
|
|
|
114134
|
-
// src/daemon/infrastructure/outbox/lib/durable-fifo-queue-schema.ts
|
|
114135
|
-
var DURABLE_FIFO_QUEUE_MIGRATIONS;
|
|
114136
|
-
var init_durable_fifo_queue_schema = __esm(() => {
|
|
114137
|
-
DURABLE_FIFO_QUEUE_MIGRATIONS = [
|
|
114138
|
-
`CREATE TABLE IF NOT EXISTS schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`,
|
|
114139
|
-
`CREATE TABLE IF NOT EXISTS fifo_outbox_entries (id INTEGER PRIMARY KEY AUTOINCREMENT, delivery_key TEXT NOT NULL, payload_json TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending', attempts INTEGER NOT NULL DEFAULT 0, last_error TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`,
|
|
114140
|
-
`CREATE INDEX IF NOT EXISTS idx_fifo_outbox_pending ON fifo_outbox_entries(delivery_key, status, id)`
|
|
114141
|
-
];
|
|
114142
|
-
});
|
|
114143
|
-
|
|
114144
|
-
// src/daemon/infrastructure/outbox/lib/durable-fifo-queue-store.ts
|
|
114145
|
-
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
114146
|
-
import { mkdirSync as mkdirSync7 } from "node:fs";
|
|
114147
|
-
import { dirname as dirname13 } from "node:path";
|
|
114148
|
-
function openDurableFifoQueueStore(dbPath) {
|
|
114149
|
-
mkdirSync7(dirname13(dbPath), { recursive: true });
|
|
114150
|
-
const db = new DatabaseSync2(dbPath);
|
|
114151
|
-
for (const sql of DURABLE_FIFO_QUEUE_MIGRATIONS)
|
|
114152
|
-
db.exec(sql);
|
|
114153
|
-
db.prepare("UPDATE fifo_outbox_entries SET status='pending', updated_at=? WHERE status='in_flight'").run(Date.now());
|
|
114154
|
-
return {
|
|
114155
|
-
enqueue: (key, payloadJson) => {
|
|
114156
|
-
const now = Date.now();
|
|
114157
|
-
return Number(db.prepare("INSERT INTO fifo_outbox_entries(delivery_key,payload_json,created_at,updated_at) VALUES(?,?,?,?) RETURNING id").get(key, payloadJson, now, now).id);
|
|
114158
|
-
},
|
|
114159
|
-
claimNextBatch: (key, limit) => db.prepare("UPDATE fifo_outbox_entries SET status='in_flight', attempts=attempts+1, updated_at=? WHERE id IN (SELECT id FROM fifo_outbox_entries WHERE delivery_key=? AND status='pending' ORDER BY id LIMIT ?) RETURNING id, delivery_key as deliveryKey, payload_json as payloadJson, attempts").all(Date.now(), key, limit),
|
|
114160
|
-
markDone: (id3) => {
|
|
114161
|
-
db.prepare("DELETE FROM fifo_outbox_entries WHERE id=?").run(id3);
|
|
114162
|
-
},
|
|
114163
|
-
markPending: (id3) => {
|
|
114164
|
-
db.prepare("UPDATE fifo_outbox_entries SET status='pending', last_error=NULL, updated_at=? WHERE id=?").run(Date.now(), id3);
|
|
114165
|
-
},
|
|
114166
|
-
updatePayload: (id3, payloadJson) => {
|
|
114167
|
-
db.prepare("UPDATE fifo_outbox_entries SET payload_json=?, updated_at=? WHERE id=?").run(payloadJson, Date.now(), id3);
|
|
114168
|
-
},
|
|
114169
|
-
markPendingRetry: (id3, error51) => {
|
|
114170
|
-
db.prepare("UPDATE fifo_outbox_entries SET status='pending', last_error=?, updated_at=? WHERE id=?").run(String(error51), Date.now(), id3);
|
|
114171
|
-
},
|
|
114172
|
-
listPendingForRecovery: (key) => db.prepare("SELECT id, delivery_key as deliveryKey, payload_json as payloadJson, attempts FROM fifo_outbox_entries WHERE delivery_key=? AND status IN ('pending','in_flight') ORDER BY id").all(key),
|
|
114173
|
-
close: () => db.close()
|
|
114174
|
-
};
|
|
114175
|
-
}
|
|
114176
|
-
var init_durable_fifo_queue_store = __esm(() => {
|
|
114177
|
-
init_durable_fifo_queue_schema();
|
|
114178
|
-
});
|
|
114179
|
-
|
|
114180
|
-
// src/daemon/infrastructure/outbox/lib/fifo-batched-outbox.ts
|
|
114181
|
-
function createFifoBatchedOutbox(o) {
|
|
114182
|
-
const waiters = new Map;
|
|
114183
|
-
let running3;
|
|
114184
|
-
let stopped = false;
|
|
114185
|
-
let retryTimer;
|
|
114186
|
-
let retryAttempt = 0;
|
|
114187
|
-
const retryDelay = () => computeExponentialRetryDelayMs(retryAttempt++, o.retryDelayMs ?? 500, o.maxRetryDelayMs ?? 5000);
|
|
114188
|
-
const scheduleRetry = () => {
|
|
114189
|
-
if (!stopped && !retryTimer) {
|
|
114190
|
-
retryTimer = setTimeout(() => {
|
|
114191
|
-
retryTimer = undefined;
|
|
114192
|
-
drain2().catch(() => {
|
|
114193
|
-
return;
|
|
114194
|
-
});
|
|
114195
|
-
}, retryDelay());
|
|
114196
|
-
retryTimer.unref?.();
|
|
114197
|
-
}
|
|
114198
|
-
};
|
|
114199
|
-
const drain2 = async () => {
|
|
114200
|
-
if (running3)
|
|
114201
|
-
return running3;
|
|
114202
|
-
running3 = (async () => {
|
|
114203
|
-
while (true) {
|
|
114204
|
-
const rows = o.store.claimNextBatch(o.deliveryKey, o.batchSize);
|
|
114205
|
-
if (!rows.length)
|
|
114206
|
-
break;
|
|
114207
|
-
try {
|
|
114208
|
-
const results = await o.send(rows.map((r) => o.deserialize(r.payloadJson)));
|
|
114209
|
-
let hasRetry = false;
|
|
114210
|
-
for (let i2 = 0;i2 < results.length; i2++) {
|
|
114211
|
-
const item = o.deserialize(rows[i2].payloadJson);
|
|
114212
|
-
const outcome = o.classifyOutcome?.(results[i2], item) ?? { kind: "success" };
|
|
114213
|
-
if (outcome.kind === "retry") {
|
|
114214
|
-
o.store.updatePayload(rows[i2].id, o.serialize(outcome.item));
|
|
114215
|
-
o.store.markPending(rows[i2].id);
|
|
114216
|
-
hasRetry = true;
|
|
114217
|
-
continue;
|
|
114218
|
-
}
|
|
114219
|
-
o.store.markDone(rows[i2].id);
|
|
114220
|
-
waiters.get(rows[i2].id)?.resolve(results[i2]);
|
|
114221
|
-
waiters.delete(rows[i2].id);
|
|
114222
|
-
}
|
|
114223
|
-
for (let i2 = results.length;i2 < rows.length; i2++)
|
|
114224
|
-
o.store.markPending(rows[i2].id);
|
|
114225
|
-
if (hasRetry) {
|
|
114226
|
-
scheduleRetry();
|
|
114227
|
-
break;
|
|
114228
|
-
}
|
|
114229
|
-
retryAttempt = 0;
|
|
114230
|
-
} catch (e) {
|
|
114231
|
-
o.onError?.(e);
|
|
114232
|
-
for (const r of rows)
|
|
114233
|
-
o.store.markPendingRetry(r.id, e);
|
|
114234
|
-
scheduleRetry();
|
|
114235
|
-
break;
|
|
114236
|
-
}
|
|
114237
|
-
}
|
|
114238
|
-
})().finally(() => {
|
|
114239
|
-
running3 = undefined;
|
|
114240
|
-
});
|
|
114241
|
-
return running3;
|
|
114242
|
-
};
|
|
114243
|
-
const enqueue = (item) => {
|
|
114244
|
-
if (stopped)
|
|
114245
|
-
return Promise.reject(new Error("Outbox is stopped"));
|
|
114246
|
-
const id3 = o.store.enqueue(o.deliveryKey, o.serialize(item));
|
|
114247
|
-
const p = new Promise((resolve8, reject) => waiters.set(id3, { resolve: resolve8, reject }));
|
|
114248
|
-
drain2().catch(() => {
|
|
114249
|
-
return;
|
|
114250
|
-
});
|
|
114251
|
-
return p;
|
|
114252
|
-
};
|
|
114253
|
-
const flushNow = async () => {
|
|
114254
|
-
while (o.store.listPendingForRecovery(o.deliveryKey).length) {
|
|
114255
|
-
await drain2();
|
|
114256
|
-
}
|
|
114257
|
-
};
|
|
114258
|
-
const stop4 = async () => {
|
|
114259
|
-
if (stopped)
|
|
114260
|
-
return;
|
|
114261
|
-
if (retryTimer)
|
|
114262
|
-
clearTimeout(retryTimer);
|
|
114263
|
-
retryTimer = undefined;
|
|
114264
|
-
await flushNow();
|
|
114265
|
-
stopped = true;
|
|
114266
|
-
};
|
|
114267
|
-
return { enqueue, flushNow, stop: stop4 };
|
|
114268
|
-
}
|
|
114269
|
-
var init_fifo_batched_outbox = () => {};
|
|
114270
|
-
|
|
114271
|
-
// src/daemon/infrastructure/outbox/lib/keyed-fifo-batched-outbox-registry.ts
|
|
114272
|
-
function createKeyedFifoBatchedOutboxRegistry(o) {
|
|
114273
|
-
const boxes = new Map;
|
|
114274
|
-
const get13 = (key) => {
|
|
114275
|
-
let b = boxes.get(key);
|
|
114276
|
-
if (!b) {
|
|
114277
|
-
b = createFifoBatchedOutbox({
|
|
114278
|
-
batchSize: o.batchSize,
|
|
114279
|
-
send: o.createSend(key),
|
|
114280
|
-
store: o.store,
|
|
114281
|
-
deliveryKey: key,
|
|
114282
|
-
serialize: o.serialize,
|
|
114283
|
-
deserialize: o.deserialize,
|
|
114284
|
-
retryDelayMs: o.retryDelayMs,
|
|
114285
|
-
maxRetryDelayMs: o.maxRetryDelayMs,
|
|
114286
|
-
onError: (e) => o.onError?.(key, e),
|
|
114287
|
-
classifyOutcome: o.classifyOutcome
|
|
114288
|
-
});
|
|
114289
|
-
boxes.set(key, b);
|
|
114290
|
-
}
|
|
114291
|
-
return b;
|
|
114292
|
-
};
|
|
114293
|
-
const stop4 = async (k) => {
|
|
114294
|
-
const b = boxes.get(k);
|
|
114295
|
-
if (b) {
|
|
114296
|
-
await b.stop();
|
|
114297
|
-
boxes.delete(k);
|
|
114298
|
-
}
|
|
114299
|
-
};
|
|
114300
|
-
return {
|
|
114301
|
-
enqueue: (k, i2) => get13(k).enqueue(i2),
|
|
114302
|
-
flushNow: async (k) => {
|
|
114303
|
-
if (k)
|
|
114304
|
-
await get13(k).flushNow();
|
|
114305
|
-
else
|
|
114306
|
-
for (const b of boxes.values())
|
|
114307
|
-
await b.flushNow();
|
|
114308
|
-
},
|
|
114309
|
-
stop: stop4,
|
|
114310
|
-
stopAll: async () => {
|
|
114311
|
-
for (const k of [...boxes.keys()])
|
|
114312
|
-
await stop4(k);
|
|
114313
|
-
o.store.close();
|
|
114314
|
-
}
|
|
114315
|
-
};
|
|
114316
|
-
}
|
|
114317
|
-
var init_keyed_fifo_batched_outbox_registry = __esm(() => {
|
|
114318
|
-
init_fifo_batched_outbox();
|
|
114319
|
-
});
|
|
114320
|
-
|
|
114321
114516
|
// src/daemon/infrastructure/outbox/workspace-file-tree-delta-outbox.ts
|
|
114322
114517
|
function createWorkspaceFileTreeDeltaOutboxRegistry(machineId, createSend, options) {
|
|
114323
114518
|
const store = openDurableFifoQueueStore(resolveOutboxDbPath(machineId, "file-tree-delta"));
|
|
@@ -114352,6 +114547,8 @@ var init_workspace_file_tree_delta_outbox = __esm(() => {
|
|
|
114352
114547
|
var init_outbox = __esm(() => {
|
|
114353
114548
|
init_workspace_file_tree_checkpoint_outbox();
|
|
114354
114549
|
init_workspace_file_tree_delta_outbox();
|
|
114550
|
+
init_agent_lifecycle_outbox();
|
|
114551
|
+
init_agent_lifecycle_send();
|
|
114355
114552
|
});
|
|
114356
114553
|
|
|
114357
114554
|
// ../../services/backend/src/domain/workspace-file-tree/types.ts
|
|
@@ -115760,7 +115957,8 @@ var init_command_run_subscription = __esm(() => {
|
|
|
115760
115957
|
// src/daemon/entry/task-delivery/task-delivery-logic.ts
|
|
115761
115958
|
function isPendingAliveRunningTask(task) {
|
|
115762
115959
|
const { agentConfig, status: status3 } = task;
|
|
115763
|
-
|
|
115960
|
+
const op = getNativeDeliverySession()?.agentOperationalReadModel?.get(task.chatroomId, agentConfig.role);
|
|
115961
|
+
return status3 === "pending" && (agentConfig.spawnedAgentPid != null || op?.isAlive === true) && isOperationalDesiredRunning(op);
|
|
115764
115962
|
}
|
|
115765
115963
|
function isSlotUnavailableForPid(slot, pid, isPidAlive, now = Date.now()) {
|
|
115766
115964
|
if (!slot) {
|
|
@@ -115783,7 +115981,7 @@ function isSlotUnavailableForPid(slot, pid, isPidAlive, now = Date.now()) {
|
|
|
115783
115981
|
function isNativeRevivableTaskStatus(task) {
|
|
115784
115982
|
const { status: status3 } = task;
|
|
115785
115983
|
if (status3 === "pending") {
|
|
115786
|
-
return
|
|
115984
|
+
return true;
|
|
115787
115985
|
}
|
|
115788
115986
|
if (status3 === "acknowledged") {
|
|
115789
115987
|
return task.assignedTo?.toLowerCase() === task.agentConfig.role.toLowerCase();
|
|
@@ -115803,7 +116001,8 @@ function isNativeAgentSlotDown(task, health, now = Date.now()) {
|
|
|
115803
116001
|
function isNativeActiveTaskAgentDown(task, health, now) {
|
|
115804
116002
|
if (!isNativeHarness(task.agentConfig.agentHarness))
|
|
115805
116003
|
return false;
|
|
115806
|
-
|
|
116004
|
+
const op = getNativeDeliverySession()?.agentOperationalReadModel?.get(task.chatroomId, task.agentConfig.role);
|
|
116005
|
+
if (!isOperationalDesiredRunning(op))
|
|
115807
116006
|
return false;
|
|
115808
116007
|
if (!isNativeRevivableTaskStatus(task))
|
|
115809
116008
|
return false;
|
|
@@ -115827,7 +116026,8 @@ function isNativePendingTaskNeedingWake(task) {
|
|
|
115827
116026
|
return false;
|
|
115828
116027
|
if (task.status !== "pending")
|
|
115829
116028
|
return false;
|
|
115830
|
-
|
|
116029
|
+
const op = getNativeDeliverySession()?.agentOperationalReadModel?.get(task.chatroomId, task.agentConfig.role);
|
|
116030
|
+
if (isOperationalDesiredRunning(op))
|
|
115831
116031
|
return false;
|
|
115832
116032
|
return Boolean(task.agentConfig.workingDir);
|
|
115833
116033
|
}
|
|
@@ -115903,10 +116103,10 @@ function listTasksReadyForNudge(tasks, now, cooldown, getSlot) {
|
|
|
115903
116103
|
}
|
|
115904
116104
|
var PENDING_IDLE_NUDGE_MS = 15000, NUDGE_COOLDOWN_MS = 60000;
|
|
115905
116105
|
var init_task_delivery_logic = __esm(() => {
|
|
115906
|
-
init_assigned_task();
|
|
115907
116106
|
init_check_agent_slot();
|
|
115908
116107
|
init_predicates();
|
|
115909
116108
|
init_agent_process_manager();
|
|
116109
|
+
init_native_delivery_session_registry();
|
|
115910
116110
|
init_native_ready_invariant();
|
|
115911
116111
|
init_native_task_injector_logic();
|
|
115912
116112
|
});
|
|
@@ -116006,7 +116206,7 @@ function runNativeWakeEffect(task, runtime4, effectContext2, agentMgr) {
|
|
|
116006
116206
|
if (!ctx)
|
|
116007
116207
|
return;
|
|
116008
116208
|
const { chatroomId, agentConfig, role, workingDir, wantResume } = ctx;
|
|
116009
|
-
console.log(`[TaskMonitor] native wake ${role}@${chatroomId} —
|
|
116209
|
+
console.log(`[TaskMonitor] native wake ${role}@${chatroomId} — operational_state=stopped with pending task ${task.taskId}`);
|
|
116010
116210
|
exports_Runtime.runFork(runtime4)(exports_Effect.gen(function* () {
|
|
116011
116211
|
yield* agentMgr.ensureRunning({
|
|
116012
116212
|
chatroomId,
|
|
@@ -116072,7 +116272,7 @@ async function wakeStoppedAgentsForPendingTasks(tasks, now, cooldown, runtime4,
|
|
|
116072
116272
|
}
|
|
116073
116273
|
}
|
|
116074
116274
|
async function processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, machineId, _pass, options) {
|
|
116075
|
-
const tasks =
|
|
116275
|
+
const tasks = [...options.snapshots];
|
|
116076
116276
|
const filteredTasks = filterSnapshotsExcludingRestartInFlight(tasks);
|
|
116077
116277
|
if (filteredTasks.length === 0)
|
|
116078
116278
|
return;
|
|
@@ -116104,11 +116304,48 @@ var init_task_delivery_processor = __esm(() => {
|
|
|
116104
116304
|
init_native_task_injector_logic();
|
|
116105
116305
|
init_api3();
|
|
116106
116306
|
init_convex_error();
|
|
116107
|
-
init_fetch_machine_assigned_task_snapshots();
|
|
116108
116307
|
init_restart_orchestrator_in_flight();
|
|
116109
116308
|
init_task_delivery_logic();
|
|
116110
116309
|
});
|
|
116111
116310
|
|
|
116311
|
+
// src/daemon/infrastructure/agent-operational/enrich-snapshot-with-operational.ts
|
|
116312
|
+
function enrichSnapshotWithOperational(snapshot) {
|
|
116313
|
+
const op = getNativeDeliverySession()?.agentOperationalReadModel?.get(snapshot.chatroomId, snapshot.agentConfig.role);
|
|
116314
|
+
if (!op)
|
|
116315
|
+
return snapshot;
|
|
116316
|
+
return { ...snapshot, agentConfig: { ...snapshot.agentConfig, desiredState: isOperationalDesiredRunning(op) ? "running" : "stopped" } };
|
|
116317
|
+
}
|
|
116318
|
+
function enrichSnapshotsWithOperational(snapshots) {
|
|
116319
|
+
return snapshots.map(enrichSnapshotWithOperational);
|
|
116320
|
+
}
|
|
116321
|
+
var init_enrich_snapshot_with_operational = __esm(() => {
|
|
116322
|
+
init_native_delivery_session_registry();
|
|
116323
|
+
});
|
|
116324
|
+
|
|
116325
|
+
// src/daemon/infrastructure/agent-operational/subscribe-machine-agent-operational-status.ts
|
|
116326
|
+
function subscribeMachineAgentOperationalStatus(client4, options, onRows) {
|
|
116327
|
+
return client4.onUpdate(api.machines.subscribeMachineAgentOperationalStatus, { sessionId: options.sessionId, machineId: options.machineId }, (result) => {
|
|
116328
|
+
if (Array.isArray(result))
|
|
116329
|
+
onRows(result);
|
|
116330
|
+
});
|
|
116331
|
+
}
|
|
116332
|
+
var init_subscribe_machine_agent_operational_status = __esm(() => {
|
|
116333
|
+
init_api3();
|
|
116334
|
+
});
|
|
116335
|
+
|
|
116336
|
+
// src/daemon/infrastructure/inbox/fetch-machine-assigned-task-snapshots.ts
|
|
116337
|
+
async function fetchMachineAssignedTaskSnapshots(sessionDeps, machineId) {
|
|
116338
|
+
const result = await sessionDeps.backend.query(api.machines.listMachineAssignedTaskSnapshots, {
|
|
116339
|
+
sessionId: sessionDeps.sessionId,
|
|
116340
|
+
machineId
|
|
116341
|
+
});
|
|
116342
|
+
return mapAssignedTaskSnapshotList(parseAssignedTaskSnapshotRows(result?.tasks ?? []));
|
|
116343
|
+
}
|
|
116344
|
+
var init_fetch_machine_assigned_task_snapshots = __esm(() => {
|
|
116345
|
+
init_assigned_task_snapshot_contract();
|
|
116346
|
+
init_api3();
|
|
116347
|
+
});
|
|
116348
|
+
|
|
116112
116349
|
// src/daemon/infrastructure/inbox/store/schema.ts
|
|
116113
116350
|
var SCHEMA_VERSION = 1, MIGRATIONS;
|
|
116114
116351
|
var init_schema = __esm(() => {
|
|
@@ -116261,12 +116498,16 @@ var init_inbox = __esm(() => {
|
|
|
116261
116498
|
|
|
116262
116499
|
// src/daemon/infrastructure/inbox/task-inbox-delivery.ts
|
|
116263
116500
|
async function handleTaskInboxUpdate(update6, deps) {
|
|
116501
|
+
const taskSnapshotState = deps.taskSnapshotState ?? getNativeDeliverySession()?.taskSnapshotState;
|
|
116502
|
+
taskSnapshotState?.applySignalPage(update6.signals, update6.snapshots);
|
|
116264
116503
|
if (update6.snapshots.length === 0)
|
|
116265
116504
|
return;
|
|
116266
|
-
await processTasksUpdate(deps.runtime, deps.effectContext, deps.cooldown, deps.agentMgr, deps.sessionDeps, deps.machineId, "inbox-signal");
|
|
116505
|
+
await processTasksUpdate(deps.runtime, deps.effectContext, deps.cooldown, deps.agentMgr, deps.sessionDeps, deps.machineId, "inbox-signal", { snapshots: enrichSnapshotsWithOperational(update6.snapshots) });
|
|
116267
116506
|
}
|
|
116268
116507
|
var init_task_inbox_delivery = __esm(() => {
|
|
116508
|
+
init_native_delivery_session_registry();
|
|
116269
116509
|
init_task_delivery_processor();
|
|
116510
|
+
init_enrich_snapshot_with_operational();
|
|
116270
116511
|
});
|
|
116271
116512
|
|
|
116272
116513
|
// src/daemon/infrastructure/inbox/task.ts
|
|
@@ -116376,14 +116617,19 @@ var init_task = __esm(() => {
|
|
|
116376
116617
|
|
|
116377
116618
|
// src/daemon/entry/task-inbox-runtime.ts
|
|
116378
116619
|
async function bootstrapMachineAssignedTaskSnapshots(deps) {
|
|
116620
|
+
await deps.sessionDeps.backend.mutation(api.machines.backfillAgentOperationalStatusForMachine, {
|
|
116621
|
+
sessionId: deps.sessionDeps.sessionId,
|
|
116622
|
+
machineId: deps.machineId
|
|
116623
|
+
});
|
|
116379
116624
|
await deps.sessionDeps.backend.mutation(api.machines.syncMachineAssignedTaskSnapshotsMutation, {
|
|
116380
116625
|
sessionId: deps.sessionDeps.sessionId,
|
|
116381
116626
|
machineId: deps.machineId
|
|
116382
116627
|
});
|
|
116383
116628
|
const tasks = await fetchMachineAssignedTaskSnapshots(deps.sessionDeps, deps.machineId);
|
|
116629
|
+
deps.taskSnapshotState?.replace(tasks);
|
|
116384
116630
|
if (!tasks.length)
|
|
116385
116631
|
return;
|
|
116386
|
-
await processTasksUpdate(deps.runtime, deps.effectContext, deps.cooldown, deps.agentMgr, deps.sessionDeps, deps.machineId, "bootstrap", { snapshots: tasks });
|
|
116632
|
+
await processTasksUpdate(deps.runtime, deps.effectContext, deps.cooldown, deps.agentMgr, deps.sessionDeps, deps.machineId, "bootstrap", { snapshots: enrichSnapshotsWithOperational(tasks) });
|
|
116387
116633
|
}
|
|
116388
116634
|
function isAbortError(error51) {
|
|
116389
116635
|
return error51 instanceof Error && error51.name === "AbortError";
|
|
@@ -116403,7 +116649,7 @@ async function runInboxLoopWithRestart(options, onUpdate, isStopped) {
|
|
|
116403
116649
|
}
|
|
116404
116650
|
}
|
|
116405
116651
|
}
|
|
116406
|
-
var INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInboxEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
116652
|
+
var NATIVE_DELIVERY_RECONCILE_MS = 1e4, INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInboxEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
116407
116653
|
const session2 = yield* DaemonSessionService;
|
|
116408
116654
|
const agentMgr = yield* DaemonAgentProcessManagerService;
|
|
116409
116655
|
const effectContext2 = yield* exports_Effect.context();
|
|
@@ -116426,14 +116672,20 @@ var INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInbo
|
|
|
116426
116672
|
});
|
|
116427
116673
|
const abort = new AbortController;
|
|
116428
116674
|
let stopped = false;
|
|
116675
|
+
const taskSnapshotState = new MachineTaskSnapshotState;
|
|
116676
|
+
const agentOperationalReadModel = new AgentOperationalReadModel;
|
|
116429
116677
|
registerNativeDeliverySession({
|
|
116430
116678
|
runtime: runtime4,
|
|
116431
116679
|
effectContext: effectContext2,
|
|
116432
116680
|
agentMgr,
|
|
116433
116681
|
sessionDeps,
|
|
116434
|
-
machineId: session2.machineId
|
|
116682
|
+
machineId: session2.machineId,
|
|
116683
|
+
taskSnapshotState,
|
|
116684
|
+
agentOperationalReadModel
|
|
116435
116685
|
});
|
|
116436
116686
|
const cooldown = new RecoveryCooldown;
|
|
116687
|
+
let inboxUpdateInFlight = false;
|
|
116688
|
+
let reconcileInFlight = false;
|
|
116437
116689
|
const inboxOptions = {
|
|
116438
116690
|
client: wsClient2,
|
|
116439
116691
|
sessionId: session2.sessionId,
|
|
@@ -116443,36 +116695,62 @@ var INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInbo
|
|
|
116443
116695
|
signal: abort.signal
|
|
116444
116696
|
};
|
|
116445
116697
|
const inboxHandler = async (update6) => {
|
|
116446
|
-
|
|
116447
|
-
|
|
116448
|
-
|
|
116449
|
-
|
|
116450
|
-
|
|
116451
|
-
|
|
116452
|
-
|
|
116453
|
-
|
|
116454
|
-
|
|
116698
|
+
inboxUpdateInFlight = true;
|
|
116699
|
+
try {
|
|
116700
|
+
await handleTaskInboxUpdate(update6, {
|
|
116701
|
+
runtime: runtime4,
|
|
116702
|
+
effectContext: effectContext2,
|
|
116703
|
+
cooldown,
|
|
116704
|
+
agentMgr,
|
|
116705
|
+
sessionDeps,
|
|
116706
|
+
machineId: session2.machineId,
|
|
116707
|
+
taskSnapshotState
|
|
116708
|
+
});
|
|
116709
|
+
inboxStore.save({ inboxType: "task", scopeKey: session2.machineId }, { afterSignalKey: update6.throughSignalKey });
|
|
116710
|
+
} finally {
|
|
116711
|
+
inboxUpdateInFlight = false;
|
|
116712
|
+
}
|
|
116455
116713
|
};
|
|
116456
|
-
const reconcileTimer = setInterval(() => {
|
|
116457
|
-
if (stopped)
|
|
116458
|
-
return;
|
|
116459
|
-
processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, session2.machineId, "periodic-reconcile");
|
|
116460
|
-
}, NATIVE_DELIVERY_RECONCILE_MS);
|
|
116461
116714
|
yield* exports_Effect.tryPromise(() => bootstrapMachineAssignedTaskSnapshots({
|
|
116462
116715
|
sessionDeps,
|
|
116463
116716
|
runtime: runtime4,
|
|
116464
116717
|
effectContext: effectContext2,
|
|
116465
116718
|
cooldown,
|
|
116466
116719
|
agentMgr,
|
|
116467
|
-
machineId: session2.machineId
|
|
116720
|
+
machineId: session2.machineId,
|
|
116721
|
+
taskSnapshotState
|
|
116468
116722
|
})).pipe(exports_Effect.catchAll((error51) => {
|
|
116469
116723
|
console.warn("[TaskInbox] bootstrap failed:", error51);
|
|
116470
116724
|
return exports_Effect.void;
|
|
116471
116725
|
}));
|
|
116726
|
+
const unsubscribeOperational = subscribeMachineAgentOperationalStatus(wsClient2, {
|
|
116727
|
+
sessionId: session2.sessionId,
|
|
116728
|
+
machineId: session2.machineId,
|
|
116729
|
+
signal: abort.signal
|
|
116730
|
+
}, (rows) => {
|
|
116731
|
+
if (stopped)
|
|
116732
|
+
return;
|
|
116733
|
+
const changed = agentOperationalReadModel.replace(rows);
|
|
116734
|
+
const snapshots = changed.flatMap(({ chatroomId, role }) => taskSnapshotState.listForRole(chatroomId, role));
|
|
116735
|
+
if (snapshots.length === 0)
|
|
116736
|
+
return;
|
|
116737
|
+
processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, session2.machineId, "operational-status", { snapshots: enrichSnapshotsWithOperational(snapshots) }).catch((error51) => console.warn("[TaskInbox] operational-status reconcile failed:", error51));
|
|
116738
|
+
}) ?? (() => {});
|
|
116739
|
+
const reconcileTimer = setInterval(() => {
|
|
116740
|
+
if (stopped || inboxUpdateInFlight || reconcileInFlight)
|
|
116741
|
+
return;
|
|
116742
|
+
reconcileInFlight = true;
|
|
116743
|
+
processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr, sessionDeps, session2.machineId, "periodic-reconcile", { snapshots: enrichSnapshotsWithOperational(taskSnapshotState.listAll()) }).catch((error51) => {
|
|
116744
|
+
console.warn("[TaskInbox] local delivery reconciliation failed:", error51);
|
|
116745
|
+
}).finally(() => {
|
|
116746
|
+
reconcileInFlight = false;
|
|
116747
|
+
});
|
|
116748
|
+
}, NATIVE_DELIVERY_RECONCILE_MS);
|
|
116472
116749
|
runInboxLoopWithRestart(inboxOptions, inboxHandler, () => stopped);
|
|
116473
116750
|
return {
|
|
116474
116751
|
stop() {
|
|
116475
116752
|
stopped = true;
|
|
116753
|
+
unsubscribeOperational();
|
|
116476
116754
|
abort.abort();
|
|
116477
116755
|
clearInterval(reconcileTimer);
|
|
116478
116756
|
unregisterNativeDeliverySession();
|
|
@@ -116481,12 +116759,14 @@ var INBOX_RESTART_INITIAL_MS = 1000, INBOX_RESTART_MAX_MS = 30000, startTaskInbo
|
|
|
116481
116759
|
};
|
|
116482
116760
|
});
|
|
116483
116761
|
var init_task_inbox_runtime = __esm(() => {
|
|
116484
|
-
init_reliability();
|
|
116485
116762
|
init_esm();
|
|
116486
116763
|
init_daemon_services();
|
|
116487
116764
|
init_api3();
|
|
116765
|
+
init_native_delivery_session_registry();
|
|
116488
116766
|
init_task_delivery_processor();
|
|
116489
116767
|
init_task_delivery_logic();
|
|
116768
|
+
init_enrich_snapshot_with_operational();
|
|
116769
|
+
init_subscribe_machine_agent_operational_status();
|
|
116490
116770
|
init_fetch_machine_assigned_task_snapshots();
|
|
116491
116771
|
init_inbox();
|
|
116492
116772
|
init_task_inbox_delivery();
|
|
@@ -116944,6 +117224,9 @@ function createDaemonRuntime(deps) {
|
|
|
116944
117224
|
shutdownWatchdog.unref?.();
|
|
116945
117225
|
if (heartbeatTimer)
|
|
116946
117226
|
clearInterval(heartbeatTimer);
|
|
117227
|
+
await deps.agentLifecycleOutbox?.stopAll().catch(() => {
|
|
117228
|
+
return;
|
|
117229
|
+
});
|
|
116947
117230
|
stopWorkers();
|
|
116948
117231
|
await withTimeout2(exports_Effect.runPromise(exports_Effect.gen(function* () {
|
|
116949
117232
|
const effectContext2 = yield* exports_Effect.context();
|
|
@@ -118163,10 +118446,10 @@ function startWorkspaceListSubscriber(deps, onEvent) {
|
|
|
118163
118446
|
const unsub = deps.wsClient.onUpdate(api.workspaces.listRecentlyObservedWorkspacesForMachine, queryArgs, (workspaces) => {
|
|
118164
118447
|
if (workspaces == null)
|
|
118165
118448
|
return;
|
|
118166
|
-
const
|
|
118167
|
-
if (
|
|
118449
|
+
const snapshotKey2 = JSON.stringify(workspaces);
|
|
118450
|
+
if (snapshotKey2 === lastSnapshotKey)
|
|
118168
118451
|
return;
|
|
118169
|
-
lastSnapshotKey =
|
|
118452
|
+
lastSnapshotKey = snapshotKey2;
|
|
118170
118453
|
onEvent({ type: "workspace.list-changed", machineId: deps.machineId });
|
|
118171
118454
|
}, (err) => {
|
|
118172
118455
|
console.warn(`[daemon] workspace-list subscriber error: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -132765,7 +133048,11 @@ async function startDaemon() {
|
|
|
132765
133048
|
console.log(`[daemon] Local web UI: http://127.0.0.1:${localWeb.port}/`);
|
|
132766
133049
|
const layers = daemonSessionToLayers(init2);
|
|
132767
133050
|
startBackgroundMachineCapabilitiesDiscovery(createStartBackgroundCapabilitiesDiscoveryDeps(layers));
|
|
132768
|
-
const runtime4 = createDaemonRuntime({
|
|
133051
|
+
const runtime4 = createDaemonRuntime({
|
|
133052
|
+
wsClient: wsClient2,
|
|
133053
|
+
layers,
|
|
133054
|
+
agentLifecycleOutbox: init2.agentLifecycleOutbox
|
|
133055
|
+
});
|
|
132769
133056
|
try {
|
|
132770
133057
|
await runtime4.run();
|
|
132771
133058
|
} finally {
|
|
@@ -134010,4 +134297,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
134010
134297
|
});
|
|
134011
134298
|
program2.parse();
|
|
134012
134299
|
|
|
134013
|
-
//# debugId=
|
|
134300
|
+
//# debugId=D5DF842800E395EE64756E2164756E21
|