totemlayer 0.1.5 → 0.1.11

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.
@@ -1,3 +1,4 @@
1
+ import { runInfrastructureWorkerCycle } from "./mission-infrastructure.mjs";
1
2
  import { spawn } from "node:child_process";
2
3
  import { createHash } from "node:crypto";
3
4
  import {
@@ -20,6 +21,7 @@ import { setTimeout as sleep } from "node:timers/promises";
20
21
  import { inspectLocalRepository } from "./repository.mjs";
21
22
  import { localClientEnvironment } from "./platform-client.mjs";
22
23
  import { localModelEndpoint } from "./local-model-provider.mjs";
24
+ import { externalModelReply, isExternalModelProvider } from "./model-adapter.mjs";
23
25
  import { runDockerNodeTests } from "./docker-test-sandbox.mjs";
24
26
  import { acquireMissionAgentSession, assertMissionAgentSession } from "./mission-agent-session.mjs";
25
27
 
@@ -52,7 +54,10 @@ const SOURCE_CHANGE = {
52
54
  ...FILE_CHANGE,
53
55
  properties: {
54
56
  ...FILE_CHANGE.properties,
55
- path: { ...CODE_PATH, pattern: CODE_PATH.pattern.replace("^(src|test|tests)/", "^src/") },
57
+ path: {
58
+ ...CODE_PATH,
59
+ pattern: CODE_PATH.pattern.replace("^(src|test|tests)/", "^src/"),
60
+ },
56
61
  },
57
62
  };
58
63
  const TEST_CHANGE = {
@@ -98,7 +103,10 @@ const OUTPUT_SCHEMAS = {
98
103
  },
99
104
  engineering: {
100
105
  summary: TEXT,
101
- verdict: { type: "string", enum: ["feasible", "changes_required", "rejected"] },
106
+ verdict: {
107
+ type: "string",
108
+ enum: ["feasible", "changes_required", "rejected"],
109
+ },
102
110
  findings: STRINGS,
103
111
  spec: TEXT,
104
112
  candidateTitle: TEXT,
@@ -113,11 +121,19 @@ const OUTPUT_SCHEMAS = {
113
121
  code: {
114
122
  summary: TEXT,
115
123
  changes: { type: "array", items: SOURCE_CHANGE, minItems: 1, maxItems: 3 },
116
- testChanges: { type: "array", items: TEST_CHANGE, minItems: 1, maxItems: 1 },
124
+ testChanges: {
125
+ type: "array",
126
+ items: TEST_CHANGE,
127
+ minItems: 1,
128
+ maxItems: 1,
129
+ },
117
130
  },
118
131
  review: {
119
132
  summary: TEXT,
120
- verdict: { type: "string", enum: ["approved", "changes_required", "rejected"] },
133
+ verdict: {
134
+ type: "string",
135
+ enum: ["approved", "changes_required", "rejected"],
136
+ },
121
137
  findings: STRINGS,
122
138
  probes: { type: "array", items: REVIEW_PROBE, maxItems: 3 },
123
139
  },
@@ -189,6 +205,7 @@ function localOllamaBaseUrl(value = "http://127.0.0.1:11434") {
189
205
  }
190
206
 
191
207
  export function missionModelEndpoint(provider = "qwen-local", { ollamaUrl, qwenUrl, nimUrl } = {}) {
208
+ if (isExternalModelProvider(provider)) return null;
192
209
  if (!["qwen-local", "ollama-local", "nim-local"].includes(provider))
193
210
  throw new Error("Choose qwen-local, ollama-local, or nim-local.");
194
211
  return localModelEndpoint(provider, { ollamaUrl, qwenUrl, nimUrl });
@@ -252,7 +269,12 @@ function rejectedResponseEvidence(response) {
252
269
  } catch {
253
270
  // Malformed text cannot be safely interpreted as credential-bearing fields.
254
271
  // Preserve a fingerprint and length without storing its raw fragments.
255
- return { ...metadata, response: null, responseOmitted: "malformed_json", truncated: false };
272
+ return {
273
+ ...metadata,
274
+ response: null,
275
+ responseOmitted: "malformed_json",
276
+ truncated: false,
277
+ };
256
278
  }
257
279
  }
258
280
 
@@ -449,7 +471,9 @@ function structuredEvent(stage, response) {
449
471
  outcome: output.outcome.slice(0, 4000),
450
472
  selected: output.selected,
451
473
  ...(typeof output.selectedCandidateTitle === "string"
452
- ? { selectedCandidateTitle: output.selectedCandidateTitle.slice(0, 160) }
474
+ ? {
475
+ selectedCandidateTitle: output.selectedCandidateTitle.slice(0, 160),
476
+ }
453
477
  : {}),
454
478
  ...(typeof output.rationale === "string"
455
479
  ? { rationale: output.rationale.slice(0, 4000) }
@@ -461,7 +485,10 @@ function structuredEvent(stage, response) {
461
485
  break;
462
486
  return {
463
487
  type: "completion",
464
- payload: { summary: output.summary.slice(0, 4000), result: output.result },
488
+ payload: {
489
+ summary: output.summary.slice(0, 4000),
490
+ result: output.result,
491
+ },
465
492
  };
466
493
  }
467
494
  throw new Error("The agent returned a malformed stage result.");
@@ -498,6 +525,23 @@ export function verifiedHandoff(mission, events, response) {
498
525
  } catch {
499
526
  /* no structured review */
500
527
  }
528
+ const infrastructure = artifacts.filter((artifact) => artifact.kind === "infrastructure");
529
+ const localDeployment = [...infrastructure]
530
+ .reverse()
531
+ .find(
532
+ (artifact) =>
533
+ artifact.metadata?.receipt?.provider === "local-static" &&
534
+ !artifact.metadata.receipt.deploymentEffectId,
535
+ );
536
+ const localVerification = [...infrastructure]
537
+ .reverse()
538
+ .find(
539
+ (artifact) =>
540
+ artifact.metadata?.receipt?.deploymentEffectId ===
541
+ localDeployment?.metadata?.receipt?.operationId,
542
+ );
543
+ if (mission.infrastructure && !localVerification && model.result === "completed")
544
+ throw new Error("Complete the infrastructure verification before a successful handoff.");
501
545
  const branch = code?.metadata?.branch;
502
546
  const headCommit = code?.metadata?.headCommit;
503
547
  const changedFiles = Array.isArray(code?.metadata?.changedFiles)
@@ -532,7 +576,15 @@ export function verifiedHandoff(mission, events, response) {
532
576
  agentReportedLimitations: Array.isArray(model.limitations) ? model.limitations : [],
533
577
  pullRequestOpened: Boolean(code?.metadata?.pullRequestUrl),
534
578
  pullRequestUrl: code?.metadata?.pullRequestUrl ?? null,
535
- deployed: false,
579
+ deployed: Boolean(localVerification),
580
+ deploymentScope: localVerification ? "local" : null,
581
+ infrastructure: localDeployment
582
+ ? {
583
+ deployment: localDeployment.metadata.receipt,
584
+ verification: localVerification?.metadata?.receipt ?? null,
585
+ availability: "Available on the deployment agent's computer while it is connected.",
586
+ }
587
+ : null,
536
588
  },
537
589
  };
538
590
  }
@@ -540,13 +592,22 @@ export function verifiedHandoff(mission, events, response) {
540
592
  export function runFile(
541
593
  command,
542
594
  args,
543
- { cwd, input, signal, timeoutMs = 15 * 60_000, env, acceptNonZero = false } = {},
595
+ {
596
+ cwd,
597
+ input,
598
+ signal,
599
+ timeoutMs = 15 * 60_000,
600
+ env,
601
+ acceptNonZero = false,
602
+ platform = process.platform,
603
+ spawnProcess = spawn,
604
+ } = {},
544
605
  ) {
545
606
  if (signal?.aborted)
546
607
  return Promise.reject(signal.reason ?? new Error("The command was interrupted."));
547
608
  return new Promise((resolveRun, rejectRun) => {
548
- const grouped = process.platform !== "win32";
549
- const child = spawn(command, args, {
609
+ const grouped = platform !== "win32";
610
+ const child = spawnProcess(command, args, {
550
611
  cwd,
551
612
  env,
552
613
  shell: false,
@@ -597,13 +658,25 @@ export function runFile(
597
658
  if (!grouped) {
598
659
  // Windows has no POSIX process groups; taskkill /T includes descendants.
599
660
  await new Promise((resolveKill, rejectKill) => {
600
- const killer = spawn("taskkill", ["/PID", String(child.pid), "/T", "/F"], {
661
+ const killer = spawnProcess("taskkill", ["/PID", String(child.pid), "/T", "/F"], {
601
662
  shell: false,
602
663
  stdio: "ignore",
603
664
  windowsHide: true,
604
665
  });
605
- killer.once("error", rejectKill);
606
- killer.once("close", resolveKill);
666
+ const killTimer = setTimeout(() => {
667
+ killer.kill("SIGKILL");
668
+ rejectKill(new Error("Windows process-tree cleanup timed out."));
669
+ }, 5_000);
670
+ killer.once("error", (error) => {
671
+ clearTimeout(killTimer);
672
+ rejectKill(error);
673
+ });
674
+ killer.once("close", (code) => {
675
+ clearTimeout(killTimer);
676
+ if (code === 0) resolveKill();
677
+ else
678
+ rejectKill(new Error(`Windows process-tree cleanup exited with status ${code}.`));
679
+ });
607
680
  });
608
681
  return;
609
682
  }
@@ -622,6 +695,8 @@ export function runFile(
622
695
  // Give the kernel time to reap killed descendants before checkout cleanup.
623
696
  for (let wait = 0; wait < 20 && groupExists(); wait += 1) await sleep(25);
624
697
  })().catch((cleanupError) => {
698
+ // Report an uncertain cleanup failure even if the client never closes.
699
+ closed = true;
625
700
  stopError = new Error(
626
701
  `${command} was interrupted but process cleanup failed: ${cleanupError.message}`,
627
702
  );
@@ -1021,7 +1096,15 @@ function testSourceTokens(source) {
1021
1096
  }
1022
1097
  if (char === "\\") {
1023
1098
  const escaped = source[index++];
1024
- const simple = { n: "\n", r: "\r", t: "\t", b: "\b", f: "\f", v: "\v", 0: "\0" };
1099
+ const simple = {
1100
+ n: "\n",
1101
+ r: "\r",
1102
+ t: "\t",
1103
+ b: "\b",
1104
+ f: "\f",
1105
+ v: "\v",
1106
+ 0: "\0",
1107
+ };
1025
1108
  if (escaped === "\n") continue;
1026
1109
  if (escaped === "\r") {
1027
1110
  if (source[index] === "\n") index += 1;
@@ -1294,7 +1377,9 @@ async function existingNodeTestTitles(checkout) {
1294
1377
  let entriesSeen = 0;
1295
1378
  let bytes = 0;
1296
1379
  const visit = async (relative = "") => {
1297
- for (const entry of await readdir(join(checkout, relative), { withFileTypes: true })) {
1380
+ for (const entry of await readdir(join(checkout, relative), {
1381
+ withFileTypes: true,
1382
+ })) {
1298
1383
  if ([".git", "node_modules"].includes(entry.name)) continue;
1299
1384
  if (++entriesSeen > 5000)
1300
1385
  throw new Error(
@@ -1483,6 +1568,7 @@ async function runStructuredMissionAgent({
1483
1568
  repair = false,
1484
1569
  reasoning = false,
1485
1570
  rejectionEvidenceDirectory,
1571
+ adapterSettings = {},
1486
1572
  }) {
1487
1573
  const regressionFile =
1488
1574
  stage === "code" && !repair ? await selectMissionRegressionTestFile(checkout) : null;
@@ -1498,7 +1584,10 @@ async function runStructuredMissionAgent({
1498
1584
  ...TEST_CHANGE,
1499
1585
  properties: {
1500
1586
  ...TEST_CHANGE.properties,
1501
- path: { ...TEST_CHANGE.properties.path, const: regressionFile.path },
1587
+ path: {
1588
+ ...TEST_CHANGE.properties.path,
1589
+ const: regressionFile.path,
1590
+ },
1502
1591
  },
1503
1592
  },
1504
1593
  },
@@ -1511,7 +1600,26 @@ async function runStructuredMissionAgent({
1511
1600
  required: Object.keys(properties),
1512
1601
  additionalProperties: false,
1513
1602
  };
1514
- const endpoint = missionModelEndpoint(provider, { ollamaUrl, qwenUrl, nimUrl });
1603
+ const requestModel = isExternalModelProvider(provider)
1604
+ ? async (_url, options) => {
1605
+ const body = JSON.parse(options.body);
1606
+ const content = await externalModelReply({
1607
+ ...adapterSettings,
1608
+ provider,
1609
+ model,
1610
+ messages: body.messages,
1611
+ schema: body.response_format?.json_schema?.schema,
1612
+ signal: options.signal,
1613
+ timeoutMs,
1614
+ });
1615
+ return { choices: [{ message: { content } }] };
1616
+ }
1617
+ : requestLocalModel;
1618
+ const endpoint = missionModelEndpoint(provider, {
1619
+ ollamaUrl,
1620
+ qwenUrl,
1621
+ nimUrl,
1622
+ });
1515
1623
  model ??=
1516
1624
  provider === "qwen-local"
1517
1625
  ? "qwen3.5-9b"
@@ -1533,7 +1641,7 @@ async function runStructuredMissionAgent({
1533
1641
  const useReasoning = reasoning === true && ["code", "review"].includes(stage);
1534
1642
  for (let attempt = 0; attempt < (stage === "code" ? 2 : 1); attempt += 1) {
1535
1643
  const generationLimit = useReasoning ? 8192 : stage === "code" ? 4096 : 2048;
1536
- const data = await requestLocalModel(endpoint, {
1644
+ const data = await requestModel(endpoint, {
1537
1645
  method: "POST",
1538
1646
  headers: { "content-type": "application/json" },
1539
1647
  signal: combined,
@@ -1556,7 +1664,11 @@ async function runStructuredMissionAgent({
1556
1664
  : {
1557
1665
  think: useReasoning,
1558
1666
  format: schema,
1559
- options: { num_ctx: 16_384, num_predict: generationLimit, temperature: 0.1 },
1667
+ options: {
1668
+ num_ctx: 16_384,
1669
+ num_predict: generationLimit,
1670
+ temperature: 0.1,
1671
+ },
1560
1672
  }),
1561
1673
  messages: [
1562
1674
  {
@@ -1585,7 +1697,10 @@ async function runStructuredMissionAgent({
1585
1697
  });
1586
1698
  } catch (error) {
1587
1699
  if (rejectionEvidenceDirectory) {
1588
- await mkdir(rejectionEvidenceDirectory, { recursive: true, mode: 0o700 });
1700
+ await mkdir(rejectionEvidenceDirectory, {
1701
+ recursive: true,
1702
+ mode: 0o700,
1703
+ });
1589
1704
  await chmod(rejectionEvidenceDirectory, 0o700);
1590
1705
  await saveJournal(join(rejectionEvidenceDirectory, `response-${attempt + 1}.json`), {
1591
1706
  capturedAt: new Date().toISOString(),
@@ -1654,7 +1769,9 @@ export async function preflightMissionRepository(mission, repositoryRoot) {
1654
1769
  const base = mission.repository?.baseRevision;
1655
1770
  if (!mission.repository || !COMMIT.test(base ?? ""))
1656
1771
  throw new Error("The mission needs a selected repository with a full commit revision.");
1657
- const local = await inspectLocalRepository({ TOTEM_REPOSITORY_ROOT: repositoryRoot });
1772
+ const local = await inspectLocalRepository({
1773
+ TOTEM_REPOSITORY_ROOT: repositoryRoot,
1774
+ });
1658
1775
  if (local.repository !== mission.repository.url)
1659
1776
  throw new Error("The configured local repository does not match the mission repository.");
1660
1777
  if ((await git(repositoryRoot, "cat-file", "-t", base)) !== "commit")
@@ -1676,7 +1793,9 @@ export async function prepareMissionCheckout(
1676
1793
  throw new Error("Mission code work needs an immutable repository revision and work item ID.");
1677
1794
  if (retryAttempt !== undefined && (!Number.isInteger(retryAttempt) || retryAttempt < 2))
1678
1795
  throw new Error("A retry checkout needs a later server work-item attempt.");
1679
- const local = await inspectLocalRepository({ TOTEM_REPOSITORY_ROOT: repositoryRoot });
1796
+ const local = await inspectLocalRepository({
1797
+ TOTEM_REPOSITORY_ROOT: repositoryRoot,
1798
+ });
1680
1799
  if (local.repository !== mission.repository.url)
1681
1800
  throw new Error("The selected local checkout does not match the mission repository.");
1682
1801
  const base = await git(repositoryRoot, "rev-parse", mission.repository.baseRevision);
@@ -1714,7 +1833,10 @@ export async function prepareMissionCheckout(
1714
1833
  } catch (error) {
1715
1834
  if (error.code !== "ENOENT") throw error;
1716
1835
  }
1717
- await mkdir(join(stateDirectory, "checkouts"), { recursive: true, mode: 0o700 });
1836
+ await mkdir(join(stateDirectory, "checkouts"), {
1837
+ recursive: true,
1838
+ mode: 0o700,
1839
+ });
1718
1840
  await git(repositoryRoot, "worktree", "add", "-b", branch, checkout, startRevision);
1719
1841
  return { checkout, branch, baseRevision: base, startRevision };
1720
1842
  }
@@ -1732,7 +1854,9 @@ export async function prepareReviewCheckout(mission, workItem, repositoryRoot, s
1732
1854
  !UUID.test(workItem.id)
1733
1855
  )
1734
1856
  throw new Error("Review requires a visible local code artifact with full Git revisions.");
1735
- const local = await inspectLocalRepository({ TOTEM_REPOSITORY_ROOT: repositoryRoot });
1857
+ const local = await inspectLocalRepository({
1858
+ TOTEM_REPOSITORY_ROOT: repositoryRoot,
1859
+ });
1736
1860
  if (local.repository !== mission.repository.url)
1737
1861
  throw new Error("The selected checkout does not match the mission repository.");
1738
1862
  const [resolvedHead, mergeBase] = await Promise.all([
@@ -1753,16 +1877,26 @@ export async function prepareReviewCheckout(mission, workItem, repositoryRoot, s
1753
1877
  } catch (error) {
1754
1878
  if (error.code !== "ENOENT") throw error;
1755
1879
  }
1756
- await mkdir(join(stateDirectory, "checkouts"), { recursive: true, mode: 0o700 });
1880
+ await mkdir(join(stateDirectory, "checkouts"), {
1881
+ recursive: true,
1882
+ mode: 0o700,
1883
+ });
1757
1884
  await git(repositoryRoot, "worktree", "add", "--detach", checkout, head);
1758
- return { checkout, baseRevision: base, headCommit: head, branch: codeArtifact.metadata?.branch };
1885
+ return {
1886
+ checkout,
1887
+ baseRevision: base,
1888
+ headCommit: head,
1889
+ branch: codeArtifact.metadata?.branch,
1890
+ };
1759
1891
  }
1760
1892
 
1761
1893
  export async function prepareBaseReadCheckout(mission, workItem, repositoryRoot, stateDirectory) {
1762
1894
  const base = mission.repository?.baseRevision;
1763
1895
  if (!mission.repository || !COMMIT.test(base ?? "") || !UUID.test(workItem.id))
1764
1896
  throw new Error("Engineering needs a selected immutable repository revision.");
1765
- const local = await inspectLocalRepository({ TOTEM_REPOSITORY_ROOT: repositoryRoot });
1897
+ const local = await inspectLocalRepository({
1898
+ TOTEM_REPOSITORY_ROOT: repositoryRoot,
1899
+ });
1766
1900
  if (local.repository !== mission.repository.url)
1767
1901
  throw new Error("The local repository does not match the mission selection.");
1768
1902
  const resolved = await git(repositoryRoot, "rev-parse", base);
@@ -1777,7 +1911,10 @@ export async function prepareBaseReadCheckout(mission, workItem, repositoryRoot,
1777
1911
  } catch (error) {
1778
1912
  if (error.code !== "ENOENT") throw error;
1779
1913
  }
1780
- await mkdir(join(stateDirectory, "checkouts"), { recursive: true, mode: 0o700 });
1914
+ await mkdir(join(stateDirectory, "checkouts"), {
1915
+ recursive: true,
1916
+ mode: 0o700,
1917
+ });
1781
1918
  await git(repositoryRoot, "worktree", "add", "--detach", checkout, base);
1782
1919
  return { checkout, baseRevision: base };
1783
1920
  }
@@ -1950,7 +2087,10 @@ export async function runIndependentReviewProbes(checkout, changedFiles, probes,
1950
2087
  try {
1951
2088
  await writeFile(probePath, contents, { flag: "wx", mode: 0o600 });
1952
2089
  const check = await runIsolatedNodeTests(checkoutPath, signal);
1953
- return { ...check, command: `${check.command}; independent reviewer probes` };
2090
+ return {
2091
+ ...check,
2092
+ command: `${check.command}; independent reviewer probes`,
2093
+ };
1954
2094
  } finally {
1955
2095
  await rm(probePath, { force: true });
1956
2096
  }
@@ -2106,7 +2246,9 @@ async function settleKnownLocalTestFailure(
2106
2246
  checkoutInfo: record.checkoutInfo,
2107
2247
  failure: record.failure,
2108
2248
  });
2109
- const remote = await client.missions.listEffects(missionId, workItemId, { signal });
2249
+ const remote = await client.missions.listEffects(missionId, workItemId, {
2250
+ signal,
2251
+ });
2110
2252
  for (const [index, effectId] of record.effectIds.entries()) {
2111
2253
  const effect = remote.find((item) => item.id === effectId);
2112
2254
  if (
@@ -2171,7 +2313,11 @@ async function recoverKnownLocalTestFailures(
2171
2313
  );
2172
2314
  } catch (error) {
2173
2315
  if (error.status === 401 || error.status === 403) throw error;
2174
- emit({ type: "recovery_waiting", workItemId, message: String(error.message ?? error) });
2316
+ emit({
2317
+ type: "recovery_waiting",
2318
+ workItemId,
2319
+ message: String(error.message ?? error),
2320
+ });
2175
2321
  }
2176
2322
  }
2177
2323
  return handled;
@@ -2207,7 +2353,9 @@ async function settleCompletedResult(client, missionId, workItemId, path, record
2207
2353
  throw new CompletedResultReconciliationFailed(
2208
2354
  "The completed local result cannot be safely reconciled.",
2209
2355
  );
2210
- const remote = await client.missions.listEffects(missionId, workItemId, { signal });
2356
+ const remote = await client.missions.listEffects(missionId, workItemId, {
2357
+ signal,
2358
+ });
2211
2359
  const effects = record.effectIds.map((id, index) => {
2212
2360
  const effect = remote.find((entry) => entry.id === id);
2213
2361
  if (
@@ -2284,7 +2432,10 @@ async function recoverReadyCompletions(
2284
2432
  "Review the saved result and its lease or assignment before continuing. The worker will not repeat completed actions.",
2285
2433
  },
2286
2434
  },
2287
- { idempotencyKey: key(agentId, workItemId, "completion-blocker"), signal },
2435
+ {
2436
+ idempotencyKey: key(agentId, workItemId, "completion-blocker"),
2437
+ signal,
2438
+ },
2288
2439
  );
2289
2440
  await saveJournal(path, { ...blocked, blockerRecorded: true });
2290
2441
  };
@@ -2301,7 +2452,11 @@ async function recoverReadyCompletions(
2301
2452
  completionInput(workItemId, record.leaseToken, record.result),
2302
2453
  { idempotencyKey: key(agentId, workItemId, "complete"), signal },
2303
2454
  );
2304
- await saveJournal(path, { state: "done", stage: record.stage, result: record.result });
2455
+ await saveJournal(path, {
2456
+ state: "done",
2457
+ stage: record.stage,
2458
+ result: record.result,
2459
+ });
2305
2460
  emit({ type: "work_recovered", workItemId });
2306
2461
  } catch (error) {
2307
2462
  if (error.status === 401 || error.status === 403) throw error;
@@ -2323,13 +2478,23 @@ async function recoverReadyCompletions(
2323
2478
  }
2324
2479
  continue;
2325
2480
  }
2326
- emit({ type: "recovery_waiting", workItemId, message: String(error.message ?? error) });
2481
+ emit({
2482
+ type: "recovery_waiting",
2483
+ workItemId,
2484
+ message: String(error.message ?? error),
2485
+ });
2327
2486
  }
2328
2487
  }
2329
2488
  return handled;
2330
2489
  }
2331
2490
 
2332
2491
  export async function runMissionWorkerCycle(options) {
2492
+ if (
2493
+ (options.recoveryOnly ||
2494
+ options.candidateWorkItem?.metadata?.kind?.startsWith("infrastructure_")) &&
2495
+ (await runInfrastructureWorkerCycle(options))
2496
+ )
2497
+ return;
2333
2498
  return runMissionWorker({ ...options, once: true, _singleCycle: true });
2334
2499
  }
2335
2500
 
@@ -2355,6 +2520,7 @@ export async function runMissionWorker({
2355
2520
  signal,
2356
2521
  emit = () => {},
2357
2522
  runAgent = runLocalMissionAgent,
2523
+ adapterSettings = {},
2358
2524
  }) {
2359
2525
  if (!UUID.test(missionId)) throw new Error("Provide a valid mission ID.");
2360
2526
  missionModelEndpoint(provider, { ollamaUrl, qwenUrl, nimUrl });
@@ -2509,7 +2675,10 @@ export async function runMissionWorker({
2509
2675
  "Assign a runtime that supports this work item, or set its stage to a supported kind.",
2510
2676
  },
2511
2677
  },
2512
- { idempotencyKey: key(agent.id, workItem.id, "unsupported-stage"), signal },
2678
+ {
2679
+ idempotencyKey: key(agent.id, workItem.id, "unsupported-stage"),
2680
+ signal,
2681
+ },
2513
2682
  )
2514
2683
  .catch(() => {});
2515
2684
  emit({
@@ -2525,7 +2694,11 @@ export async function runMissionWorker({
2525
2694
  if (prior?.state === "claim_blocked") {
2526
2695
  if (!reportedAttention.has(workItem.id)) {
2527
2696
  await recordRecoveryBlocker(prior.pendingWorkItem, prior.message);
2528
- emit({ type: "needs_attention", workItemId: workItem.id, message: prior.message });
2697
+ emit({
2698
+ type: "needs_attention",
2699
+ workItemId: workItem.id,
2700
+ message: prior.message,
2701
+ });
2529
2702
  }
2530
2703
  continue;
2531
2704
  }
@@ -2745,7 +2918,10 @@ export async function runMissionWorker({
2745
2918
  // preceded the request, so another worker's later effects cannot
2746
2919
  // be bypassed by a claim key which never owned that attempt.
2747
2920
  if (claimRecord.previousState) {
2748
- const restored = { ...claimRecord, state: claimRecord.previousState };
2921
+ const restored = {
2922
+ ...claimRecord,
2923
+ state: claimRecord.previousState,
2924
+ };
2749
2925
  for (const field of [
2750
2926
  "claimKey",
2751
2927
  "expectedPriorAttempt",
@@ -2769,7 +2945,11 @@ export async function runMissionWorker({
2769
2945
  };
2770
2946
  await saveJournal(journalPath, blocked);
2771
2947
  await recordRecoveryBlocker(claimRecord.pendingWorkItem, blocked.message);
2772
- emit({ type: "needs_attention", workItemId: workItem.id, message: blocked.message });
2948
+ emit({
2949
+ type: "needs_attention",
2950
+ workItemId: workItem.id,
2951
+ message: blocked.message,
2952
+ });
2773
2953
  continue;
2774
2954
  }
2775
2955
  // Another worker may have claimed a stale listing, or the mission may
@@ -2810,7 +2990,9 @@ export async function runMissionWorker({
2810
2990
  }, 10_000);
2811
2991
  const renew = setInterval(() => {
2812
2992
  void client.missions
2813
- .renew(missionId, workItem.id, claim.leaseToken, { signal: combined })
2993
+ .renew(missionId, workItem.id, claim.leaseToken, {
2994
+ signal: combined,
2995
+ })
2814
2996
  .catch((error) => {
2815
2997
  renewError = error;
2816
2998
  workSignal.abort();
@@ -2909,7 +3091,11 @@ export async function runMissionWorker({
2909
3091
  });
2910
3092
  }
2911
3093
  if (effectIds.length) {
2912
- await saveJournal(journalPath, { state: "dispatching", stage, effectIds });
3094
+ await saveJournal(journalPath, {
3095
+ state: "dispatching",
3096
+ stage,
3097
+ effectIds,
3098
+ });
2913
3099
  for (const effectId of effectIds) {
2914
3100
  const dispatch = await client.missions.dispatchEffect(
2915
3101
  missionId,
@@ -2984,6 +3170,7 @@ export async function runMissionWorker({
2984
3170
  write: stage === "code",
2985
3171
  model,
2986
3172
  provider,
3173
+ adapterSettings,
2987
3174
  ollamaUrl,
2988
3175
  qwenUrl,
2989
3176
  nimUrl,
@@ -3008,6 +3195,7 @@ export async function runMissionWorker({
3008
3195
  write: false,
3009
3196
  model,
3010
3197
  provider,
3198
+ adapterSettings,
3011
3199
  ollamaUrl,
3012
3200
  qwenUrl,
3013
3201
  nimUrl,
@@ -3029,7 +3217,9 @@ export async function runMissionWorker({
3029
3217
  }
3030
3218
  for (const event of promptEvents(events).filter((item) => UUID.test(item.id ?? ""))) {
3031
3219
  try {
3032
- await client.missions.events.ack(missionId, event.id, { signal: combined });
3220
+ await client.missions.events.ack(missionId, event.id, {
3221
+ signal: combined,
3222
+ });
3033
3223
  } catch (error) {
3034
3224
  emit({
3035
3225
  type: "event_ack_pending",
@@ -3046,7 +3236,10 @@ export async function runMissionWorker({
3046
3236
  for (let repair = 0; repair < 3; repair += 1) {
3047
3237
  await authorizeLocalLaunch();
3048
3238
  const check = await runIsolatedNodeTests(checkout, combined);
3049
- commands.push({ command: check.command, exitCode: check.exitCode });
3239
+ commands.push({
3240
+ command: check.command,
3241
+ exitCode: check.exitCode,
3242
+ });
3050
3243
  localTestRuns.push(check);
3051
3244
  if (check.exitCode === 0) break;
3052
3245
  if (repair === 2) throw new LocalCodeTestsFailed(localTestRuns);
@@ -3065,6 +3258,7 @@ export async function runMissionWorker({
3065
3258
  write: true,
3066
3259
  model,
3067
3260
  provider,
3261
+ adapterSettings,
3068
3262
  ollamaUrl,
3069
3263
  qwenUrl,
3070
3264
  nimUrl,
@@ -3131,6 +3325,7 @@ export async function runMissionWorker({
3131
3325
  write: false,
3132
3326
  model,
3133
3327
  provider,
3328
+ adapterSettings,
3134
3329
  ollamaUrl,
3135
3330
  qwenUrl,
3136
3331
  nimUrl,
@@ -3186,12 +3381,18 @@ export async function runMissionWorker({
3186
3381
  if (reviewCheck)
3187
3382
  generated.commands = [
3188
3383
  ...(generated.commands ?? []),
3189
- { command: reviewCheck.command, exitCode: reviewCheck.exitCode },
3384
+ {
3385
+ command: reviewCheck.command,
3386
+ exitCode: reviewCheck.exitCode,
3387
+ },
3190
3388
  ];
3191
3389
  if (reviewProbeCheck)
3192
3390
  generated.commands = [
3193
3391
  ...(generated.commands ?? []),
3194
- { command: reviewProbeCheck.command, exitCode: reviewProbeCheck.exitCode },
3392
+ {
3393
+ command: reviewProbeCheck.command,
3394
+ exitCode: reviewProbeCheck.exitCode,
3395
+ },
3195
3396
  ];
3196
3397
  const resultSummary = handoff?.summary ?? generated.text.slice(0, 2000);
3197
3398
  result = {
@@ -3224,7 +3425,10 @@ export async function runMissionWorker({
3224
3425
  contentText: handoff
3225
3426
  ? JSON.stringify(handoff.detail, null, 2).slice(0, 32000)
3226
3427
  : generated.text.slice(0, 32000),
3227
- metadata: { ...(evidence ?? {}), commands: generated.commands ?? [] },
3428
+ metadata: {
3429
+ ...(evidence ?? {}),
3430
+ commands: generated.commands ?? [],
3431
+ },
3228
3432
  },
3229
3433
  };
3230
3434
  if (effectIds.length) {
@@ -3260,7 +3464,10 @@ export async function runMissionWorker({
3260
3464
  missionId,
3261
3465
  workItem.id,
3262
3466
  completionInput(workItem.id, claim.leaseToken, result),
3263
- { idempotencyKey: key(agent.id, workItem.id, "complete"), signal: combined },
3467
+ {
3468
+ idempotencyKey: key(agent.id, workItem.id, "complete"),
3469
+ signal: combined,
3470
+ },
3264
3471
  );
3265
3472
  await saveJournal(journalPath, { state: "done", stage, result });
3266
3473
  reportedAttention.delete(workItem.id);
@@ -3301,7 +3508,10 @@ export async function runMissionWorker({
3301
3508
  prior?.state === "local_tests_failed"
3302
3509
  ? (prior.verifiedFailedEffectIds ?? prior.effectIds ?? [])
3303
3510
  : [],
3304
- failure: { checks: error.checks, completedAt: new Date().toISOString() },
3511
+ failure: {
3512
+ checks: error.checks,
3513
+ completedAt: new Date().toISOString(),
3514
+ },
3305
3515
  };
3306
3516
  await saveJournal(journalPath, record);
3307
3517
  knownLocalTestFailure = true;