foundr-companion 0.1.6 → 0.1.7
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/bridge/fleet/fleet-cli.mjs +2 -0
- package/dist/bridge/fleet/supervisor.d.mts +2 -1
- package/dist/bridge/fleet/supervisor.d.mts.map +1 -1
- package/dist/bridge/fleet/supervisor.mjs +11 -4
- package/dist/bridge/fleet/supervisor.mjs.map +1 -1
- package/dist/bridge/fleet/worker.d.mts +2 -1
- package/dist/bridge/fleet/worker.d.mts.map +1 -1
- package/dist/bridge/fleet/worker.mjs +22 -10
- package/dist/bridge/fleet/worker.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -191,6 +191,7 @@ export async function runFleet({ log = console.error, signal, workers = DEFAULT_
|
|
|
191
191
|
hostId,
|
|
192
192
|
mcpUrl,
|
|
193
193
|
bearer,
|
|
194
|
+
log,
|
|
194
195
|
deps: {
|
|
195
196
|
ensureWorktree,
|
|
196
197
|
stageWorkerCodexConfig: stageCodexConfig,
|
|
@@ -219,6 +220,7 @@ export async function runFleet({ log = console.error, signal, workers = DEFAULT_
|
|
|
219
220
|
runWorker,
|
|
220
221
|
seats,
|
|
221
222
|
signal: ac.signal,
|
|
223
|
+
log,
|
|
222
224
|
})
|
|
223
225
|
} finally {
|
|
224
226
|
process.off?.('SIGINT', stop)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Top-level fleet supervisor: register host, then loop polling for assigned
|
|
2
2
|
* missions and running a worker per mission, bounded by the worker-seat pool. */
|
|
3
|
-
export function runSupervisor({ registerHost, heartbeatHost, pollMissions, runWorker, seats, intervalMs, signal }: {
|
|
3
|
+
export function runSupervisor({ registerHost, heartbeatHost, pollMissions, runWorker, seats, intervalMs, signal, log }: {
|
|
4
4
|
registerHost: any;
|
|
5
5
|
heartbeatHost: any;
|
|
6
6
|
pollMissions: any;
|
|
@@ -8,5 +8,6 @@ export function runSupervisor({ registerHost, heartbeatHost, pollMissions, runWo
|
|
|
8
8
|
seats: any;
|
|
9
9
|
intervalMs?: number | undefined;
|
|
10
10
|
signal: any;
|
|
11
|
+
log?: (() => void) | undefined;
|
|
11
12
|
}): Promise<void>;
|
|
12
13
|
//# sourceMappingURL=supervisor.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supervisor.d.mts","sourceRoot":"","sources":["../../../src/bridge/fleet/supervisor.mjs"],"names":[],"mappings":"AAOA;kFACkF;AAClF
|
|
1
|
+
{"version":3,"file":"supervisor.d.mts","sourceRoot":"","sources":["../../../src/bridge/fleet/supervisor.mjs"],"names":[],"mappings":"AAOA;kFACkF;AAClF;;;;;;;;;kBAuBC"}
|
|
@@ -7,18 +7,25 @@ const sleep = (ms, signal) => new Promise((resolve) => {
|
|
|
7
7
|
|
|
8
8
|
/** Top-level fleet supervisor: register host, then loop polling for assigned
|
|
9
9
|
* missions and running a worker per mission, bounded by the worker-seat pool. */
|
|
10
|
-
export async function runSupervisor({ registerHost, heartbeatHost, pollMissions, runWorker, seats, intervalMs = 5000, signal }) {
|
|
10
|
+
export async function runSupervisor({ registerHost, heartbeatHost, pollMissions, runWorker, seats, intervalMs = 5000, signal, log = () => {} }) {
|
|
11
11
|
const host = await registerHost()
|
|
12
12
|
const pool = new SeatPool(seats)
|
|
13
|
+
const inFlight = new Set()
|
|
13
14
|
while (!signal?.aborted) {
|
|
14
15
|
await heartbeatHost?.(host.id).catch?.(() => {})
|
|
15
|
-
const missions = await pollMissions(host.id).catch(() =>
|
|
16
|
+
const missions = await pollMissions(host.id).catch((e) => {
|
|
17
|
+
log(`poll failed: ${e instanceof Error ? e.message : String(e)}`)
|
|
18
|
+
return []
|
|
19
|
+
})
|
|
16
20
|
for (const mission of missions) {
|
|
21
|
+
if (inFlight.has(mission.id)) continue // already being worked this round
|
|
17
22
|
const seat = pool.acquire(mission.id)
|
|
18
23
|
if (!seat) break // no free seats this round
|
|
24
|
+
inFlight.add(mission.id)
|
|
25
|
+
log(`picked up mission ${mission.id} (slot ${seat})`)
|
|
19
26
|
void Promise.resolve(runWorker({ mission, hostId: host.id, seat }))
|
|
20
|
-
.catch(() => {})
|
|
21
|
-
.finally(() => pool.release(seat))
|
|
27
|
+
.catch((e) => log(`worker error on ${mission.id}: ${e instanceof Error ? e.message : String(e)}`))
|
|
28
|
+
.finally(() => { pool.release(seat); inFlight.delete(mission.id) })
|
|
22
29
|
}
|
|
23
30
|
if (signal?.aborted) break
|
|
24
31
|
await sleep(intervalMs, signal)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supervisor.mjs","sourceRoot":"","sources":["../../../src/bridge/fleet/supervisor.mjs"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C,MAAM,KAAK,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;;IACpD,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;IACjC,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,gBAAgB,uDAAG,OAAO,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;AAC3F,CAAC,CAAC,CAAA;AAEF;kFACkF;AAClF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,EAAE,MAAM,EAAE;;
|
|
1
|
+
{"version":3,"file":"supervisor.mjs","sourceRoot":"","sources":["../../../src/bridge/fleet/supervisor.mjs"],"names":[],"mappings":"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"}
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
* orchestration is unit-tested without real Codex/git/MCP. Model 1: the worker
|
|
3
3
|
* codex self-surfaces done/blocked via its staged Foundr MCP; we backstop
|
|
4
4
|
* `failed` on crash/budget (and `done` on a clean finish). */
|
|
5
|
-
export function runMissionWorker({ mission, hostId, mcpUrl, bearer, leaseSeconds, deps }: {
|
|
5
|
+
export function runMissionWorker({ mission, hostId, mcpUrl, bearer, leaseSeconds, deps, log }: {
|
|
6
6
|
mission: any;
|
|
7
7
|
hostId: any;
|
|
8
8
|
mcpUrl: any;
|
|
9
9
|
bearer: any;
|
|
10
10
|
leaseSeconds?: number | undefined;
|
|
11
11
|
deps: any;
|
|
12
|
+
log?: (() => void) | undefined;
|
|
12
13
|
}): Promise<void>;
|
|
13
14
|
//# sourceMappingURL=worker.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.mts","sourceRoot":"","sources":["../../../src/bridge/fleet/worker.mjs"],"names":[],"mappings":"AAAA;;;+DAG+D;AAC/D
|
|
1
|
+
{"version":3,"file":"worker.d.mts","sourceRoot":"","sources":["../../../src/bridge/fleet/worker.mjs"],"names":[],"mappings":"AAAA;;;+DAG+D;AAC/D;;;;;;;;kBAyCC"}
|
|
@@ -2,17 +2,25 @@
|
|
|
2
2
|
* orchestration is unit-tested without real Codex/git/MCP. Model 1: the worker
|
|
3
3
|
* codex self-surfaces done/blocked via its staged Foundr MCP; we backstop
|
|
4
4
|
* `failed` on crash/budget (and `done` on a clean finish). */
|
|
5
|
-
export async function runMissionWorker({ mission, hostId, mcpUrl, bearer, leaseSeconds = 1800, deps }) {
|
|
5
|
+
export async function runMissionWorker({ mission, hostId, mcpUrl, bearer, leaseSeconds = 1800, deps, log = () => {} }) {
|
|
6
6
|
const { ensureWorktree, stageWorkerCodexConfig, claimMission, surfaceMission, makeAdapter, makeBudget } = deps
|
|
7
|
-
const surface = (state, payload = {}) =>
|
|
7
|
+
const surface = (state, payload = {}) =>
|
|
8
|
+
surfaceMission({ missionId: mission.id, state, payload })
|
|
9
|
+
.catch((e) => log(`mission ${mission.id}: surface ${state} failed: ${e instanceof Error ? e.message : String(e)}`))
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const budget = makeBudget()
|
|
14
|
-
const adapter = makeAdapter({ cwd: worktreePath, codexHome })
|
|
11
|
+
// EVERYTHING is inside the try — a worktree/config/claim failure must surface
|
|
12
|
+
// `failed` (so the mission leaves the 'planned' poll instead of retrying
|
|
13
|
+
// forever) and be logged, not propagate silently to the supervisor's catch.
|
|
14
|
+
let adapter
|
|
15
15
|
try {
|
|
16
|
+
log(`mission ${mission.id}: ${mission.repo} @ ${mission.worktree_branch} — making worktree`)
|
|
17
|
+
const worktreePath = await ensureWorktree({ repoPath: mission.repo, branch: mission.worktree_branch })
|
|
18
|
+
const codexHome = await stageWorkerCodexConfig({ worktreePath, mcpUrl, bearer })
|
|
19
|
+
await claimMission({ missionId: mission.id, hostId, repo: mission.repo, worktreeBranch: mission.worktree_branch, leaseSeconds })
|
|
20
|
+
log(`mission ${mission.id}: claimed, starting codex in ${worktreePath}`)
|
|
21
|
+
|
|
22
|
+
const budget = makeBudget()
|
|
23
|
+
adapter = makeAdapter({ cwd: worktreePath, codexHome })
|
|
16
24
|
await adapter.start()
|
|
17
25
|
const envelope = { message: { body: mission.brief ?? mission.title ?? '' }, mission: { id: mission.id } }
|
|
18
26
|
let budgetTripped = false
|
|
@@ -22,13 +30,17 @@ export async function runMissionWorker({ mission, hostId, mcpUrl, bearer, leaseS
|
|
|
22
30
|
},
|
|
23
31
|
})
|
|
24
32
|
if (budgetTripped || budget.exceeded()) {
|
|
33
|
+
log(`mission ${mission.id}: budget exceeded`)
|
|
25
34
|
await surface('failed', { reason: 'budget', detail: 'mission budget exceeded' })
|
|
26
35
|
} else {
|
|
36
|
+
log(`mission ${mission.id}: completed`)
|
|
27
37
|
await surface('done', { result: result?.text ?? '' })
|
|
28
38
|
}
|
|
29
39
|
} catch (error) {
|
|
30
|
-
|
|
40
|
+
const msg = error instanceof Error ? error.message : String(error)
|
|
41
|
+
log(`mission ${mission.id}: FAILED — ${msg}`)
|
|
42
|
+
await surface('failed', { error: msg })
|
|
31
43
|
} finally {
|
|
32
|
-
adapter
|
|
44
|
+
adapter?.close?.()
|
|
33
45
|
}
|
|
34
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.mjs","sourceRoot":"","sources":["../../../src/bridge/fleet/worker.mjs"],"names":[],"mappings":"AAAA;;;+DAG+D;AAC/D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,EAAE,IAAI,EAAE;;
|
|
1
|
+
{"version":3,"file":"worker.mjs","sourceRoot":"","sources":["../../../src/bridge/fleet/worker.mjs"],"names":[],"mappings":"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"}
|