@sema-agent/core 1.292.0 → 1.294.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/agents/subagent.d.ts.map +1 -1
- package/dist/agents/subagent.js +1 -0
- package/dist/agents/subagent.js.map +1 -1
- package/dist/agents/verify.d.ts +1 -0
- package/dist/agents/verify.d.ts.map +1 -1
- package/dist/agents/verify.js +1 -1
- package/dist/agents/verify.js.map +1 -1
- package/dist/core/auto-compaction.d.ts +2 -0
- package/dist/core/auto-compaction.d.ts.map +1 -1
- package/dist/core/auto-compaction.js +32 -5
- package/dist/core/auto-compaction.js.map +1 -1
- package/dist/core/checkpoint-store.d.ts +14 -2
- package/dist/core/checkpoint-store.d.ts.map +1 -1
- package/dist/core/checkpoint-store.js.map +1 -1
- package/dist/core/fs-write-gate-policy.d.ts +1 -0
- package/dist/core/fs-write-gate-policy.d.ts.map +1 -1
- package/dist/core/fs-write-gate-policy.js +16 -0
- package/dist/core/fs-write-gate-policy.js.map +1 -1
- package/dist/core/hooks.d.ts.map +1 -1
- package/dist/core/hooks.js.map +1 -1
- package/dist/core/runner/prepare-task.d.ts +17 -1
- package/dist/core/runner/prepare-task.d.ts.map +1 -1
- package/dist/core/runner/prepare-task.js +269 -8
- package/dist/core/runner/prepare-task.js.map +1 -1
- package/dist/core/runner/runtask.d.ts +3 -1
- package/dist/core/runner/runtask.d.ts.map +1 -1
- package/dist/core/runner/runtask.js +120 -20
- package/dist/core/runner/runtask.js.map +1 -1
- package/dist/core/runner/synthetic-tools.d.ts +7 -1
- package/dist/core/runner/synthetic-tools.d.ts.map +1 -1
- package/dist/core/runner/synthetic-tools.js +62 -6
- package/dist/core/runner/synthetic-tools.js.map +1 -1
- package/dist/core/trace.d.ts +1 -1
- package/dist/core/trace.d.ts.map +1 -1
- package/dist/core/trace.js.map +1 -1
- package/dist/core/types.d.ts +6 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/engine/compaction/compaction.d.ts +4 -2
- package/dist/engine/compaction/compaction.d.ts.map +1 -1
- package/dist/engine/compaction/compaction.js +21 -6
- package/dist/engine/compaction/compaction.js.map +1 -1
- package/dist/engine/compaction/utils.d.ts +13 -0
- package/dist/engine/compaction/utils.d.ts.map +1 -1
- package/dist/engine/compaction/utils.js +126 -0
- package/dist/engine/compaction/utils.js.map +1 -1
- package/dist/engine/harness/agent-harness.d.ts.map +1 -1
- package/dist/engine/harness/agent-harness.js +5 -1
- package/dist/engine/harness/agent-harness.js.map +1 -1
- package/dist/engine/harness/types.d.ts +5 -1
- package/dist/engine/harness/types.d.ts.map +1 -1
- package/dist/engine/harness/types.js.map +1 -1
- package/dist/engine/session/session.d.ts +3 -2
- package/dist/engine/session/session.d.ts.map +1 -1
- package/dist/engine/session/session.js +14 -4
- package/dist/engine/session/session.js.map +1 -1
- package/dist/internal/harness.d.ts +3 -1
- package/dist/internal/harness.d.ts.map +1 -1
- package/dist/internal/harness.js +2 -1
- package/dist/internal/harness.js.map +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +2 -0
- package/dist/orchestration/run-workflow-tool.d.ts.map +1 -1
- package/dist/orchestration/run-workflow-tool.js +13 -3
- package/dist/orchestration/run-workflow-tool.js.map +1 -1
- package/dist/orchestration/workflow.d.ts +5 -1
- package/dist/orchestration/workflow.d.ts.map +1 -1
- package/dist/orchestration/workflow.js +8 -2
- package/dist/orchestration/workflow.js.map +1 -1
- package/dist/prompts/supervisor.d.ts +1 -1
- package/dist/prompts/supervisor.d.ts.map +1 -1
- package/dist/prompts/supervisor.js +9 -4
- package/dist/prompts/supervisor.js.map +1 -1
- 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, isCompactionWalltimeAbort, maybeCompact, nextTrimForceBackoff, recordCompactionAndCheckRapidRefill } from "../auto-compaction.js";
|
|
5
|
+
import { DEFAULT_COMPACTION_INSTRUCTIONS, createRapidRefillState, isCompactionManualCancel, 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";
|
|
@@ -41,7 +41,7 @@ import { createBrainMemorySelector } from "../memory-recall.js";
|
|
|
41
41
|
import { buildRecallQuery, runDynamicRecall } from "../dynamic-recall.js";
|
|
42
42
|
import { guardedMemoryStore } from "../memory.js";
|
|
43
43
|
import { releaseSession } from "../../agents/session-util.js";
|
|
44
|
-
export const DEFAULT_MAX_TURNS =
|
|
44
|
+
export const DEFAULT_MAX_TURNS = 1000;
|
|
45
45
|
const MAX_CONSECUTIVE_COMPACTION_FAILURES = 3;
|
|
46
46
|
const STOP_HOOK_BLOCK_CAP = 8;
|
|
47
47
|
const COMPACTION_REGROWTH_FACTOR = 1.5;
|
|
@@ -213,6 +213,8 @@ export class Runner {
|
|
|
213
213
|
sessionLocks = new Map();
|
|
214
214
|
snapshotTooLargeRoots = new Map();
|
|
215
215
|
pendingSessionNotifications = new PendingSessionNotifications();
|
|
216
|
+
parentConstraintRegistry = new Map();
|
|
217
|
+
static PARENT_CONSTRAINT_REGISTRY_CAP = 1024;
|
|
216
218
|
constructor(deps) {
|
|
217
219
|
this.deps = deps.memoryStore
|
|
218
220
|
? { ...deps, memoryStore: guardedMemoryStore(deps.memoryStore, deps.utilityGate) }
|
|
@@ -335,9 +337,8 @@ export class Runner {
|
|
|
335
337
|
const manualCompactRef = { requested: false, waiters: [] };
|
|
336
338
|
const drainManualCompactWaiters = (outcome) => {
|
|
337
339
|
manualCompactRef.requested = false;
|
|
338
|
-
manualCompactRef.instructions = undefined;
|
|
339
340
|
for (const w of manualCompactRef.waiters.splice(0))
|
|
340
|
-
w(outcome);
|
|
341
|
+
w.resolve(outcome);
|
|
341
342
|
};
|
|
342
343
|
const runStartedAt = Date.now();
|
|
343
344
|
const taskIdRef = { current: spec.taskId, sessionId: spec.sessionId };
|
|
@@ -348,6 +349,18 @@ export class Runner {
|
|
|
348
349
|
try {
|
|
349
350
|
await this.runLocked(spec, queue, (r) => {
|
|
350
351
|
resultValue = r;
|
|
352
|
+
const pcs = internals?.inheritedGate?.parentConstraints;
|
|
353
|
+
if (resume !== undefined && r.checkpointToken !== resume.cp.token) {
|
|
354
|
+
this.parentConstraintRegistry.delete(resume.cp.token);
|
|
355
|
+
}
|
|
356
|
+
if (r.status === "suspended" && r.checkpointToken !== undefined && pcs !== undefined && pcs.length > 0) {
|
|
357
|
+
if (this.parentConstraintRegistry.size >= Runner.PARENT_CONSTRAINT_REGISTRY_CAP) {
|
|
358
|
+
const oldest = this.parentConstraintRegistry.keys().next().value;
|
|
359
|
+
if (oldest !== undefined)
|
|
360
|
+
this.parentConstraintRegistry.delete(oldest);
|
|
361
|
+
}
|
|
362
|
+
this.parentConstraintRegistry.set(r.checkpointToken, pcs);
|
|
363
|
+
}
|
|
351
364
|
}, (p) => {
|
|
352
365
|
consolidationDone = p;
|
|
353
366
|
}, (p) => {
|
|
@@ -366,7 +379,7 @@ export class Runner {
|
|
|
366
379
|
}
|
|
367
380
|
})();
|
|
368
381
|
const settled = run.catch(async (err) => {
|
|
369
|
-
|
|
382
|
+
let code = errorCodeOf(err);
|
|
370
383
|
const reopenReason = code === "resume.env_failed"
|
|
371
384
|
? "env_failed"
|
|
372
385
|
: code === "resume.tool_unavailable"
|
|
@@ -377,10 +390,20 @@ export class Runner {
|
|
|
377
390
|
try {
|
|
378
391
|
await resume.onEnvRestoreFailed(reopenReason);
|
|
379
392
|
}
|
|
380
|
-
catch {
|
|
393
|
+
catch (reopenErr) {
|
|
394
|
+
this.parentConstraintRegistry.delete(resume.cp.token);
|
|
395
|
+
if (errorCodeOf(reopenErr) === "checkpoint.reopen_failed") {
|
|
396
|
+
const original = err instanceof Error ? err : new Error(String(err));
|
|
397
|
+
const reopenMsg = reopenErr instanceof Error ? reopenErr.message : String(reopenErr);
|
|
398
|
+
err = Object.assign(new Error(`${reopenMsg} (original resume failure: ${original.message})`, { cause: original }), {
|
|
399
|
+
code: "checkpoint.reopen_failed",
|
|
400
|
+
});
|
|
401
|
+
code = "checkpoint.reopen_failed";
|
|
402
|
+
}
|
|
381
403
|
}
|
|
382
404
|
}
|
|
383
|
-
else if (resume
|
|
405
|
+
else if (resume) {
|
|
406
|
+
this.parentConstraintRegistry.delete(resume.cp.token);
|
|
384
407
|
try {
|
|
385
408
|
await this.sessions.unpin?.(resume.cp.sessionId);
|
|
386
409
|
}
|
|
@@ -446,6 +469,7 @@ export class Runner {
|
|
|
446
469
|
}
|
|
447
470
|
if (!won)
|
|
448
471
|
return;
|
|
472
|
+
this.parentConstraintRegistry.delete(rh.token);
|
|
449
473
|
if (rh.env && hasDestroy(rh.env)) {
|
|
450
474
|
try {
|
|
451
475
|
await rh.env.destroy();
|
|
@@ -532,15 +556,39 @@ export class Runner {
|
|
|
532
556
|
compact: async (opts) => {
|
|
533
557
|
if (resultValue)
|
|
534
558
|
throw steeringError("the task has already finished");
|
|
559
|
+
if (opts?.signal?.aborted)
|
|
560
|
+
return "mooted";
|
|
535
561
|
const h = handle ?? (await orTimeout(ready));
|
|
536
562
|
if (!h)
|
|
537
563
|
throw steeringError("the task is not running");
|
|
564
|
+
if (opts?.signal?.aborted)
|
|
565
|
+
return "mooted";
|
|
538
566
|
return new Promise((resolve) => {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
567
|
+
const signal = opts?.signal;
|
|
568
|
+
const entry = {
|
|
569
|
+
resolve,
|
|
570
|
+
...(signal !== undefined ? { signal } : {}),
|
|
571
|
+
...(opts?.instructions !== undefined ? { instructions: opts.instructions } : {}),
|
|
572
|
+
};
|
|
573
|
+
if (signal !== undefined) {
|
|
574
|
+
const onAbort = () => {
|
|
575
|
+
const i = manualCompactRef.waiters.indexOf(entry);
|
|
576
|
+
if (i >= 0) {
|
|
577
|
+
manualCompactRef.waiters.splice(i, 1);
|
|
578
|
+
if (manualCompactRef.waiters.length === 0) {
|
|
579
|
+
manualCompactRef.requested = false;
|
|
580
|
+
}
|
|
581
|
+
entry.resolve("mooted");
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
entry.resolve = (outcome) => {
|
|
585
|
+
signal.removeEventListener("abort", onAbort);
|
|
586
|
+
resolve(outcome);
|
|
587
|
+
};
|
|
588
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
542
589
|
}
|
|
543
|
-
manualCompactRef.
|
|
590
|
+
manualCompactRef.requested = true;
|
|
591
|
+
manualCompactRef.waiters.push(entry);
|
|
544
592
|
});
|
|
545
593
|
},
|
|
546
594
|
detach: (toolCallId) => {
|
|
@@ -1626,9 +1674,8 @@ export class Runner {
|
|
|
1626
1674
|
let trimForceBackoff = false;
|
|
1627
1675
|
const drainManualCompact = (outcome) => {
|
|
1628
1676
|
manualCompactRef.requested = false;
|
|
1629
|
-
manualCompactRef.instructions = undefined;
|
|
1630
1677
|
for (const w of manualCompactRef.waiters.splice(0))
|
|
1631
|
-
w(outcome);
|
|
1678
|
+
w.resolve(outcome);
|
|
1632
1679
|
};
|
|
1633
1680
|
const onTurnBoundary = async (event) => {
|
|
1634
1681
|
let boundarySteered = false;
|
|
@@ -1863,17 +1910,35 @@ export class Runner {
|
|
|
1863
1910
|
return undefined;
|
|
1864
1911
|
}
|
|
1865
1912
|
const claimedManual = forceManual
|
|
1866
|
-
?
|
|
1913
|
+
? (() => {
|
|
1914
|
+
const waiters = manualCompactRef.waiters.splice(0);
|
|
1915
|
+
let instructions;
|
|
1916
|
+
for (let i = waiters.length - 1; i >= 0; i--) {
|
|
1917
|
+
if (waiters[i].instructions !== undefined) {
|
|
1918
|
+
instructions = waiters[i].instructions;
|
|
1919
|
+
break;
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
return { instructions, waiters };
|
|
1923
|
+
})()
|
|
1867
1924
|
: undefined;
|
|
1868
1925
|
if (forceManual) {
|
|
1869
1926
|
manualCompactRef.requested = false;
|
|
1870
|
-
manualCompactRef.instructions = undefined;
|
|
1871
1927
|
}
|
|
1872
1928
|
const resolveClaimedWaiters = (outcome) => {
|
|
1873
1929
|
if (claimedManual !== undefined)
|
|
1874
1930
|
for (const w of claimedManual.waiters.splice(0))
|
|
1875
|
-
w(outcome);
|
|
1931
|
+
w.resolve(outcome);
|
|
1876
1932
|
};
|
|
1933
|
+
const claimedCancelSignals = claimedManual?.waiters.flatMap((w) => (w.signal !== undefined ? [w.signal] : [])) ?? [];
|
|
1934
|
+
const manualCancelSignal = claimedCancelSignals.length === 0
|
|
1935
|
+
? undefined
|
|
1936
|
+
: claimedCancelSignals.length === 1
|
|
1937
|
+
? claimedCancelSignals[0]
|
|
1938
|
+
: AbortSignal.any(claimedCancelSignals);
|
|
1939
|
+
const compactionPassSignal = claimedCancelSignals.length > 0
|
|
1940
|
+
? AbortSignal.any([prepared.abortController.signal, ...claimedCancelSignals])
|
|
1941
|
+
: prepared.abortController.signal;
|
|
1877
1942
|
const trimPressureArmed = prepared.trimPressureRef.droppedMessages;
|
|
1878
1943
|
if (trimPressureArmed)
|
|
1879
1944
|
prepared.trimPressureRef.droppedMessages = false;
|
|
@@ -1893,7 +1958,8 @@ export class Runner {
|
|
|
1893
1958
|
thinking: prepared.thinking,
|
|
1894
1959
|
settings: { ...DEFAULT_COMPACTION_SETTINGS, ...spec.compaction },
|
|
1895
1960
|
customInstructions: manualInstructions ?? spec.compaction?.instructions ?? DEFAULT_COMPACTION_INSTRUCTIONS,
|
|
1896
|
-
signal:
|
|
1961
|
+
signal: compactionPassSignal,
|
|
1962
|
+
...(manualCancelSignal !== undefined ? { manualCancelSignal } : {}),
|
|
1897
1963
|
minTokens: forceManual ? 0 : compactionFloor,
|
|
1898
1964
|
force: forceManual,
|
|
1899
1965
|
onInputTruncated: (info) => emitTrace(tracer, () => ({ kind: "compaction.input_truncated", version: 1, taskId, label: info.label, droppedChars: info.droppedChars, keptChars: info.keptChars, ts: Date.now() })),
|
|
@@ -1984,7 +2050,12 @@ export class Runner {
|
|
|
1984
2050
|
}
|
|
1985
2051
|
}
|
|
1986
2052
|
catch (err) {
|
|
1987
|
-
|
|
2053
|
+
const manualCancelAbort = !prepared.abortController.signal.aborted && isCompactionManualCancel(err);
|
|
2054
|
+
if (manualCancelAbort) {
|
|
2055
|
+
emitTrace(tracer, () => ({ kind: "compaction.mooted", version: 1, taskId, reason: "cancelled", ts: Date.now() }));
|
|
2056
|
+
manualOutcome = "mooted";
|
|
2057
|
+
}
|
|
2058
|
+
else if (!prepared.abortController.signal.aborted) {
|
|
1988
2059
|
const walltimeAbort = isCompactionWalltimeAbort(err);
|
|
1989
2060
|
if (!walltimeAbort)
|
|
1990
2061
|
compactionBreaker.failures += 1;
|
|
@@ -2617,6 +2688,15 @@ export class Runner {
|
|
|
2617
2688
|
if (!cp) {
|
|
2618
2689
|
throw new CheckpointError("checkpoint.not_found", "no checkpoint found for the supplied token");
|
|
2619
2690
|
}
|
|
2691
|
+
if ((internals?.inheritedGate?.parentConstraints?.length ?? 0) === 0) {
|
|
2692
|
+
const parked = this.parentConstraintRegistry.get(token);
|
|
2693
|
+
if (parked !== undefined) {
|
|
2694
|
+
internals = {
|
|
2695
|
+
...(internals ?? {}),
|
|
2696
|
+
inheritedGate: { ...(internals?.inheritedGate ?? {}), parentConstraints: parked },
|
|
2697
|
+
};
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2620
2700
|
let wakeMessage;
|
|
2621
2701
|
if (outcome.gate === "wake") {
|
|
2622
2702
|
const gk = cp.gate.kind;
|
|
@@ -2710,12 +2790,28 @@ export class Runner {
|
|
|
2710
2790
|
if (cp.state.workspaceHandle !== undefined && this.deps.executionEnvFactory === undefined) {
|
|
2711
2791
|
throw new CheckpointError("checkpoint.unsupported_version", "checkpoint has a remote workspaceHandle but no RunnerDeps.executionEnvFactory is wired to rebuild the env");
|
|
2712
2792
|
}
|
|
2793
|
+
if (cp.state.inheritedGate?.requiresParentConstraint === true) {
|
|
2794
|
+
const supplied = internals?.inheritedGate?.parentConstraints?.length ?? 0;
|
|
2795
|
+
if (supplied === 0) {
|
|
2796
|
+
throw new CheckpointError("resume.parent_constraint_missing", "this checkpoint's task ran under inherited parent-policy constraints (state.inheritedGate.requiresParentConstraint) " +
|
|
2797
|
+
"— the live policy/onAsk closures cannot be persisted, so the resume must re-supply them via " +
|
|
2798
|
+
"resumeStream(token, outcome, taskConfig, internals) with internals.inheritedGate.parentConstraints; " +
|
|
2799
|
+
"rejected pre-CAS (the checkpoint stays pending) rather than silently dropping the ancestors' gate");
|
|
2800
|
+
}
|
|
2801
|
+
const expected = cp.state.inheritedGate.parentConstraintCount;
|
|
2802
|
+
if (expected !== undefined && supplied !== expected) {
|
|
2803
|
+
throw new CheckpointError("resume.parent_constraint_mismatch", `re-supplied ${supplied} parent constraint(s) but the checkpoint recorded ${expected} — a partial/mismatched ` +
|
|
2804
|
+
"re-supply would run the resumed leg under a different ancestor chain than it suspended with; " +
|
|
2805
|
+
"rejected pre-CAS (the checkpoint stays pending) — re-resume with the full original chain");
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2713
2808
|
const won = await store.resolve(token, cp.scope, outcome, { rev: cp.rev ?? 0 });
|
|
2714
2809
|
if (!won) {
|
|
2715
2810
|
const live = await store.get(token);
|
|
2716
2811
|
if (live?.status === "pending") {
|
|
2717
2812
|
throw new CheckpointError("checkpoint.reopened_concurrently", "checkpoint changed concurrently (its revision advanced via a resolve/reopen cycle since this resume validated) — not executed; re-resume against the current state");
|
|
2718
2813
|
}
|
|
2814
|
+
this.parentConstraintRegistry.delete(token);
|
|
2719
2815
|
throw new CheckpointError("checkpoint.already_resolved", "checkpoint already resolved or expired — not re-executed (idempotent)");
|
|
2720
2816
|
}
|
|
2721
2817
|
const spec = {
|
|
@@ -2724,9 +2820,13 @@ export class Runner {
|
|
|
2724
2820
|
sessionId: cp.sessionId,
|
|
2725
2821
|
preemptSignal: taskConfig.preemptSignal?.aborted ? undefined : taskConfig.preemptSignal,
|
|
2726
2822
|
};
|
|
2727
|
-
const
|
|
2823
|
+
const reopenFn = store.reopen?.bind(store);
|
|
2824
|
+
const onEnvRestoreFailed = reopenFn
|
|
2728
2825
|
? async (reason) => {
|
|
2729
|
-
await
|
|
2826
|
+
const reopened = await reopenFn(token, cp.scope, reason);
|
|
2827
|
+
if (!reopened) {
|
|
2828
|
+
throw new CheckpointError("checkpoint.reopen_failed", "checkpoint could not be reopened for a retry (missing, expired, or changed concurrently) — the resume failure is terminal");
|
|
2829
|
+
}
|
|
2730
2830
|
}
|
|
2731
2831
|
: undefined;
|
|
2732
2832
|
return this.runTaskStream(spec, { cp, outcome, onEnvRestoreFailed, ...(wakeMessage !== undefined ? { wakeMessage } : {}) }, internals);
|