@sema-agent/core 1.285.0 → 1.286.1

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.
Files changed (34) hide show
  1. package/dist/agents/subagent.d.ts +1 -0
  2. package/dist/agents/subagent.d.ts.map +1 -1
  3. package/dist/agents/subagent.js +6 -3
  4. package/dist/agents/subagent.js.map +1 -1
  5. package/dist/core/auto-compaction.d.ts +29 -0
  6. package/dist/core/auto-compaction.d.ts.map +1 -1
  7. package/dist/core/auto-compaction.js +149 -8
  8. package/dist/core/auto-compaction.js.map +1 -1
  9. package/dist/core/runner/prepare-task.d.ts.map +1 -1
  10. package/dist/core/runner/prepare-task.js +21 -1
  11. package/dist/core/runner/prepare-task.js.map +1 -1
  12. package/dist/core/runner/runtask.d.ts.map +1 -1
  13. package/dist/core/runner/runtask.js +98 -8
  14. package/dist/core/runner/runtask.js.map +1 -1
  15. package/dist/core/trace.d.ts +30 -0
  16. package/dist/core/trace.d.ts.map +1 -1
  17. package/dist/core/trace.js.map +1 -1
  18. package/dist/core/types.d.ts +8 -1
  19. package/dist/core/types.d.ts.map +1 -1
  20. package/dist/engine/compaction/compaction.d.ts +9 -0
  21. package/dist/engine/compaction/compaction.d.ts.map +1 -1
  22. package/dist/engine/compaction/compaction.js +33 -0
  23. package/dist/engine/compaction/compaction.js.map +1 -1
  24. package/dist/engine/harness/types.d.ts +1 -0
  25. package/dist/engine/harness/types.d.ts.map +1 -1
  26. package/dist/engine/harness/types.js.map +1 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/internal/harness.d.ts +2 -2
  31. package/dist/internal/harness.d.ts.map +1 -1
  32. package/dist/internal/harness.js +1 -1
  33. package/dist/internal/harness.js.map +1 -1
  34. package/package.json +1 -1
@@ -2,7 +2,7 @@ import { AgentHarness, DEFAULT_COMPACTION_SETTINGS, uuidv7 } from "../../interna
2
2
  import { CheckpointError, BINDING_CHECKPOINT_VERSION, checkpointVersionOf, MAX_SUPPORTED_CHECKPOINT_VERSION, remainingBudgetMicroUsd, validatePendingSteer, winnerFromOutcome, } from "../checkpoint-store.js";
3
3
  import { effectiveCushionMs, estimateCycleMs, minLiveWriteoutWindowMs, recordCallSample, recordToolSample, recordTtftSample, softExecDeadlineMs, writeoutCushionMs } from "./call-cap.js";
4
4
  import { engineVersion } from "../version.js";
5
- import { DEFAULT_COMPACTION_INSTRUCTIONS, createRapidRefillState, maybeCompact, nextTrimForceBackoff, recordCompactionAndCheckRapidRefill } from "../auto-compaction.js";
5
+ import { DEFAULT_COMPACTION_INSTRUCTIONS, createRapidRefillState, isCompactionWalltimeAbort, maybeCompact, nextTrimForceBackoff, recordCompactionAndCheckRapidRefill } from "../auto-compaction.js";
6
6
  import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
7
7
  import { computeCostMicroUsd, modelCostToPricing } from "../pricing.js";
8
8
  import { emitTrace } from "../trace.js";
@@ -304,6 +304,7 @@ export class Runner {
304
304
  const manualCompactRef = { requested: false, waiters: [] };
305
305
  const drainManualCompactWaiters = (outcome) => {
306
306
  manualCompactRef.requested = false;
307
+ manualCompactRef.instructions = undefined;
307
308
  for (const w of manualCompactRef.waiters.splice(0))
308
309
  w(outcome);
309
310
  };
@@ -497,7 +498,7 @@ export class Runner {
497
498
  }
498
499
  notifyRef.inject(payload, opts);
499
500
  },
500
- compact: async () => {
501
+ compact: async (opts) => {
501
502
  if (resultValue)
502
503
  throw steeringError("the task has already finished");
503
504
  const h = handle ?? (await orTimeout(ready));
@@ -505,6 +506,9 @@ export class Runner {
505
506
  throw steeringError("the task is not running");
506
507
  return new Promise((resolve) => {
507
508
  manualCompactRef.requested = true;
509
+ if (opts?.instructions !== undefined) {
510
+ manualCompactRef.instructions = opts.instructions;
511
+ }
508
512
  manualCompactRef.waiters.push(resolve);
509
513
  });
510
514
  },
@@ -1334,6 +1338,52 @@ export class Runner {
1334
1338
  };
1335
1339
  const withinTaskCompaction = (spec.compaction?.enabled ?? true) && (spec.compaction?.withinTask ?? true);
1336
1340
  const compactionBreaker = { failures: 0 };
1341
+ const compactionThroughputRef = {};
1342
+ const windowSafetyOptions = (mainModel) => ({
1343
+ ...(maxCostMicroUsd !== undefined
1344
+ ? {
1345
+ fallbackBudget: {
1346
+ spentMicroUsd: () => stats.costMicroUsd,
1347
+ capMicroUsd: maxCostMicroUsd,
1348
+ mainInputPer1M: (this.deps.pricing?.[mainModel.id] ?? modelCostToPricing(mainModel.cost)).inputPer1M,
1349
+ },
1350
+ }
1351
+ : {}),
1352
+ ...(walltimeDeadlineMs !== undefined && prepared.callCapRef !== undefined
1353
+ ? {
1354
+ walltime: {
1355
+ deadlineMs: walltimeDeadlineMs,
1356
+ cushionMs: () => effectiveCushionMs(prepared.callCapRef) ?? 0,
1357
+ throughputRef: compactionThroughputRef,
1358
+ },
1359
+ }
1360
+ : {}),
1361
+ onWindowSafety: (info) => {
1362
+ if (info.kind === "fallback") {
1363
+ emitTrace(tracer, () => ({
1364
+ kind: "compaction.model_fallback",
1365
+ version: 1,
1366
+ taskId,
1367
+ contentTokens: info.contentTokens,
1368
+ headroomTokens: info.headroomTokens ?? 0,
1369
+ truncationRatio: info.truncationRatio,
1370
+ ...(info.estCostMicroUsd !== undefined ? { estCostMicroUsd: info.estCostMicroUsd } : {}),
1371
+ ts: Date.now(),
1372
+ }));
1373
+ }
1374
+ else {
1375
+ emitTrace(tracer, () => ({
1376
+ kind: "compaction.clamp_disclosure",
1377
+ version: 1,
1378
+ taskId,
1379
+ truncationRatio: info.truncationRatio,
1380
+ reason: info.reason ?? "tolerance",
1381
+ ...(info.estCostMicroUsd !== undefined ? { estCostMicroUsd: info.estCostMicroUsd } : {}),
1382
+ ts: Date.now(),
1383
+ }));
1384
+ }
1385
+ },
1386
+ });
1337
1387
  const stopHook = (spec.hooks ?? this.deps.hooks)?.stop;
1338
1388
  const finalVerificationOn = spec.finalVerification === true;
1339
1389
  if (stopHook || finalVerificationOn) {
@@ -1481,6 +1531,7 @@ export class Runner {
1481
1531
  }
1482
1532
  : undefined,
1483
1533
  ...this.seamCCompactionOptions(prepared),
1534
+ ...windowSafetyOptions(prepared.harness.getModel()),
1484
1535
  ...this.compactionHookOptions(spec, prepared.sessionId, "forced"),
1485
1536
  });
1486
1537
  if (comp.compacted) {
@@ -1499,6 +1550,10 @@ export class Runner {
1499
1550
  ...(comp.durationMs !== undefined ? { durationMs: comp.durationMs } : {}),
1500
1551
  ...(comp.firstKeptEntryId !== undefined ? { preserved_segment: { firstKeptEntryId: comp.firstKeptEntryId } } : {}),
1501
1552
  ...(comp.attachedFiles !== undefined ? { attachedFiles: comp.attachedFiles } : {}),
1553
+ ...(comp.modelFallback ? { modelFallback: true } : {}),
1554
+ ...(comp.fallbackReason !== undefined ? { fallbackReason: comp.fallbackReason } : {}),
1555
+ ...(comp.clampedRatio !== undefined ? { clampedRatio: comp.clampedRatio } : {}),
1556
+ ...(comp.clampReason !== undefined ? { clampReason: comp.clampReason } : {}),
1502
1557
  });
1503
1558
  prepared.cacheBreakDetector?.notifyCompaction();
1504
1559
  if (attachState !== undefined) {
@@ -1511,8 +1566,9 @@ export class Runner {
1511
1566
  }
1512
1567
  return comp.compacted === true;
1513
1568
  }
1514
- catch {
1515
- compactionBreaker.failures += 1;
1569
+ catch (err) {
1570
+ if (!isCompactionWalltimeAbort(err))
1571
+ compactionBreaker.failures += 1;
1516
1572
  return false;
1517
1573
  }
1518
1574
  },
@@ -1523,6 +1579,7 @@ export class Runner {
1523
1579
  let trimForceBackoff = false;
1524
1580
  const drainManualCompact = (outcome) => {
1525
1581
  manualCompactRef.requested = false;
1582
+ manualCompactRef.instructions = undefined;
1526
1583
  for (const w of manualCompactRef.waiters.splice(0))
1527
1584
  w(outcome);
1528
1585
  };
@@ -1758,11 +1815,27 @@ export class Runner {
1758
1815
  }
1759
1816
  return undefined;
1760
1817
  }
1818
+ const claimedManual = forceManual
1819
+ ? { instructions: manualCompactRef.instructions, waiters: manualCompactRef.waiters.splice(0) }
1820
+ : undefined;
1821
+ if (forceManual) {
1822
+ manualCompactRef.requested = false;
1823
+ manualCompactRef.instructions = undefined;
1824
+ }
1825
+ const resolveClaimedWaiters = (outcome) => {
1826
+ if (claimedManual !== undefined)
1827
+ for (const w of claimedManual.waiters.splice(0))
1828
+ w(outcome);
1829
+ };
1761
1830
  const trimPressureArmed = prepared.trimPressureRef.droppedMessages;
1762
1831
  if (trimPressureArmed)
1763
1832
  prepared.trimPressureRef.droppedMessages = false;
1764
1833
  const trimPressure = trimPressureArmed && !trimForceBackoff;
1765
1834
  let manualOutcome = "failed";
1835
+ if (finalizeInjected && forceManual) {
1836
+ emitTrace(tracer, () => ({ kind: "compaction.manual_in_finalize", version: 1, taskId, ts: Date.now() }));
1837
+ }
1838
+ const manualInstructions = claimedManual?.instructions;
1766
1839
  try {
1767
1840
  const comp = await maybeCompact({
1768
1841
  session: prepared.session,
@@ -1772,7 +1845,7 @@ export class Runner {
1772
1845
  getApiKeyAndHeaders: spec.getApiKeyAndHeaders,
1773
1846
  thinking: prepared.thinking,
1774
1847
  settings: { ...DEFAULT_COMPACTION_SETTINGS, ...spec.compaction },
1775
- customInstructions: spec.compaction?.instructions ?? DEFAULT_COMPACTION_INSTRUCTIONS,
1848
+ customInstructions: manualInstructions ?? spec.compaction?.instructions ?? DEFAULT_COMPACTION_INSTRUCTIONS,
1776
1849
  signal: prepared.abortController.signal,
1777
1850
  minTokens: forceManual ? 0 : compactionFloor,
1778
1851
  force: forceManual,
@@ -1787,6 +1860,7 @@ export class Runner {
1787
1860
  }
1788
1861
  : undefined,
1789
1862
  ...this.seamCCompactionOptions(prepared),
1863
+ ...windowSafetyOptions(event.model),
1790
1864
  ...this.compactionHookOptions(spec, prepared.sessionId, trimPressure ? "forced" : forceManual ? "manual" : "auto"),
1791
1865
  });
1792
1866
  if (comp.blocked) {
@@ -1839,6 +1913,10 @@ export class Runner {
1839
1913
  ...(comp.durationMs !== undefined ? { durationMs: comp.durationMs } : {}),
1840
1914
  ...(comp.firstKeptEntryId !== undefined ? { preserved_segment: { firstKeptEntryId: comp.firstKeptEntryId } } : {}),
1841
1915
  ...(comp.attachedFiles !== undefined ? { attachedFiles: comp.attachedFiles } : {}),
1916
+ ...(comp.modelFallback ? { modelFallback: true } : {}),
1917
+ ...(comp.fallbackReason !== undefined ? { fallbackReason: comp.fallbackReason } : {}),
1918
+ ...(comp.clampedRatio !== undefined ? { clampedRatio: comp.clampedRatio } : {}),
1919
+ ...(comp.clampReason !== undefined ? { clampReason: comp.clampReason } : {}),
1842
1920
  });
1843
1921
  prepared.cacheBreakDetector?.notifyCompaction();
1844
1922
  if (attachState !== undefined) {
@@ -1854,7 +1932,9 @@ export class Runner {
1854
1932
  }
1855
1933
  catch (err) {
1856
1934
  if (!prepared.abortController.signal.aborted) {
1857
- compactionBreaker.failures += 1;
1935
+ const walltimeAbort = isCompactionWalltimeAbort(err);
1936
+ if (!walltimeAbort)
1937
+ compactionBreaker.failures += 1;
1858
1938
  this.deps.onError?.(err, { phase: "compaction", sessionId: prepared.sessionId });
1859
1939
  const msg = String(err instanceof Error ? err.message : err);
1860
1940
  emitTrace(tracer, () => ({
@@ -1862,7 +1942,11 @@ export class Runner {
1862
1942
  version: 1,
1863
1943
  taskId,
1864
1944
  trigger: trimPressure ? "forced" : forceManual ? "manual" : "auto",
1865
- reason: msg.length > 512 ? `${msg.slice(0, 512)}…` : msg,
1945
+ reason: walltimeAbort
1946
+ ? "walltime soft-deadline abort (engine-initiated write-out protection; not counted toward the breaker)"
1947
+ : msg.length > 512
1948
+ ? `${msg.slice(0, 512)}…`
1949
+ : msg,
1866
1950
  ts: Date.now(),
1867
1951
  }));
1868
1952
  manualOutcome = "failed";
@@ -1872,7 +1956,7 @@ export class Runner {
1872
1956
  }
1873
1957
  }
1874
1958
  if (forceManual)
1875
- drainManualCompact(manualOutcome);
1959
+ resolveClaimedWaiters(manualOutcome);
1876
1960
  return undefined;
1877
1961
  };
1878
1962
  const unsubBoundary = prepared.harness.on("turn_boundary", onTurnBoundary);
@@ -2042,6 +2126,7 @@ export class Runner {
2042
2126
  skipCompaction: durablyPaused || compactionBreaker.failures >= MAX_CONSECUTIVE_COMPACTION_FAILURES,
2043
2127
  minTokens: compactionFloor,
2044
2128
  brain: compactionBrain,
2129
+ windowSafety: windowSafetyOptions(prepared.model),
2045
2130
  });
2046
2131
  try {
2047
2132
  if (comp?.compacted) {
@@ -2054,6 +2139,10 @@ export class Runner {
2054
2139
  ...(comp.durationMs !== undefined ? { durationMs: comp.durationMs } : {}),
2055
2140
  ...(comp.firstKeptEntryId !== undefined ? { preserved_segment: { firstKeptEntryId: comp.firstKeptEntryId } } : {}),
2056
2141
  ...(comp.attachedFiles !== undefined ? { attachedFiles: comp.attachedFiles } : {}),
2142
+ ...(comp.modelFallback ? { modelFallback: true } : {}),
2143
+ ...(comp.fallbackReason !== undefined ? { fallbackReason: comp.fallbackReason } : {}),
2144
+ ...(comp.clampedRatio !== undefined ? { clampedRatio: comp.clampedRatio } : {}),
2145
+ ...(comp.clampReason !== undefined ? { clampReason: comp.clampReason } : {}),
2057
2146
  });
2058
2147
  prepared.cacheBreakDetector?.notifyCompaction();
2059
2148
  }
@@ -2800,6 +2889,7 @@ export class Runner {
2800
2889
  keptChars: info.keptChars,
2801
2890
  ts: Date.now(),
2802
2891
  })),
2892
+ ...(opts?.windowSafety ?? {}),
2803
2893
  workingFileAttachments: spec.compaction?.attachWorkingFiles !== false && prepared.readTaskFile
2804
2894
  ? {
2805
2895
  readFile: prepared.readTaskFile,