@sema-agent/core 7.14.0 → 7.16.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/CHANGELOG.md +59 -0
- package/dist/core/ask-origin.d.ts +2 -2
- package/dist/core/checkpoint-store.d.ts +14 -15
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/hooks.d.ts +4 -3
- package/dist/core/memory-engine/delegation-settlement.d.ts +37 -12
- package/dist/core/memory-engine/delegation-settlement.js +128 -39
- package/dist/core/memory-engine/engine.d.ts +9 -8
- package/dist/core/memory-engine/engine.js +115 -120
- package/dist/core/memory-engine/file-backend.d.ts +17 -5
- package/dist/core/memory-engine/file-backend.js +78 -34
- package/dist/core/memory-engine/index.d.ts +2 -2
- package/dist/core/memory-engine/index.js +2 -2
- package/dist/core/memory-engine/layout.d.ts +152 -54
- package/dist/core/memory-engine/layout.js +441 -104
- package/dist/core/memory-engine/types.d.ts +8 -3
- package/dist/core/memory-engine/types.js +5 -0
- package/dist/core/runner/abort-race.d.ts +3 -3
- package/dist/core/runner/active-skill-scope.d.ts +2 -2
- package/dist/core/runner/assemble-result.d.ts +29 -29
- package/dist/core/runner/checkpoint-scope.d.ts +4 -4
- package/dist/core/runner/clock-and-limits.d.ts +3 -3
- package/dist/core/runner/compaction-call-options.d.ts +11 -11
- package/dist/core/runner/compaction-knobs.d.ts +4 -4
- package/dist/core/runner/compaction-seams.d.ts +5 -5
- package/dist/core/runner/contracts.d.ts +224 -226
- package/dist/core/runner/decide-continuation.d.ts +6 -6
- package/dist/core/runner/denial-limit-arms.d.ts +8 -8
- package/dist/core/runner/derived-route-fallback.d.ts +2 -2
- package/dist/core/runner/gate-exit.d.ts +6 -6
- package/dist/core/runner/git-status-frame.d.ts +7 -7
- package/dist/core/runner/inherited-ask-grants.d.ts +6 -6
- package/dist/core/runner/memory-capture-optout.d.ts +1 -1
- package/dist/core/runner/memory-consolidation-driver.d.ts +4 -4
- package/dist/core/runner/memory-consolidation.d.ts +6 -6
- package/dist/core/runner/park-commit.d.ts +6 -6
- package/dist/core/runner/permission-rule-lanes.d.ts +22 -20
- package/dist/core/runner/permission-rule-lanes.js +1 -1
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +4 -4
- package/dist/core/runner/prepare-ask-lane.d.ts +3 -3
- package/dist/core/runner/prepare-boundary-parks.d.ts +3 -3
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +5 -5
- package/dist/core/runner/prepare-config-doors.d.ts +21 -21
- package/dist/core/runner/prepare-context-lane.d.ts +6 -6
- package/dist/core/runner/prepare-defer-classify.d.ts +3 -3
- package/dist/core/runner/prepare-defer-classify.js +12 -10
- package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
- package/dist/core/runner/prepare-file-history.d.ts +2 -2
- package/dist/core/runner/prepare-gate-stations.d.ts +8 -9
- package/dist/core/runner/prepare-gate-stations.js +2 -2
- package/dist/core/runner/prepare-hands-readface.d.ts +41 -41
- package/dist/core/runner/prepare-hands-readface.js +27 -29
- package/dist/core/runner/prepare-inherited-gate.d.ts +6 -6
- package/dist/core/runner/prepare-listings.d.ts +3 -3
- package/dist/core/runner/prepare-lsp.d.ts +3 -3
- package/dist/core/runner/prepare-memory-engine-session.d.ts +5 -5
- package/dist/core/runner/prepare-memory.js +6 -7
- package/dist/core/runner/prepare-offload-wrappers.d.ts +2 -2
- package/dist/core/runner/prepare-park-ask.d.ts +11 -12
- package/dist/core/runner/prepare-park-ask.js +3 -3
- package/dist/core/runner/prepare-policy-chain.d.ts +6 -6
- package/dist/core/runner/prepare-policy-chain.js +2 -2
- package/dist/core/runner/prepare-prompt-inputs.d.ts +5 -5
- package/dist/core/runner/prepare-protocol-tools.d.ts +1 -1
- package/dist/core/runner/prepare-question-face.d.ts +4 -4
- package/dist/core/runner/prepare-run-refs.d.ts +11 -11
- package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
- package/dist/core/runner/prepare-suspend-saga.d.ts +4 -4
- package/dist/core/runner/prepare-task.d.ts +12 -12
- package/dist/core/runner/prepare-task.js +5 -7
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +2 -3
- package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -4
- package/dist/core/runner/prepare-workspace-restore.d.ts +1 -1
- package/dist/core/runner/remote-env-retry.d.ts +3 -3
- package/dist/core/runner/resume-admission.d.ts +1 -1
- package/dist/core/runner/resume-claim.d.ts +1 -1
- package/dist/core/runner/resume-internals-and-config.d.ts +1 -1
- package/dist/core/runner/resume-policy-outcome.d.ts +1 -1
- package/dist/core/runner/resume-preflight.d.ts +1 -1
- package/dist/core/runner/resume-review-outcome.d.ts +1 -1
- package/dist/core/runner/run-brain-sinks.d.ts +1 -1
- package/dist/core/runner/run-clock-and-content.d.ts +4 -4
- package/dist/core/runner/run-compaction-machinery.d.ts +3 -3
- package/dist/core/runner/run-git-lane.d.ts +1 -1
- package/dist/core/runner/run-harness-handlers.d.ts +2 -2
- package/dist/core/runner/run-identity-wiring.d.ts +4 -4
- package/dist/core/runner/run-leg.d.ts +3 -3
- package/dist/core/runner/run-notification-lane.d.ts +2 -2
- package/dist/core/runner/run-reasoning-seat.d.ts +2 -2
- package/dist/core/runner/run-settle-and-teardown.d.ts +4 -4
- package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +2 -2
- package/dist/core/runner/run-terminal-adoption.d.ts +5 -5
- package/dist/core/runner/runtask.d.ts +14 -14
- package/dist/core/runner/session-file-state-replay.d.ts +3 -3
- package/dist/core/runner/session-rule-policy.d.ts +2 -2
- package/dist/core/runner/steer-admission.d.ts +2 -2
- package/dist/core/runner/stream-halt-verbs.d.ts +1 -1
- package/dist/core/runner/stream-reap.d.ts +1 -1
- package/dist/core/runner/synthetic-tools.d.ts +8 -8
- package/dist/core/runner/teardown-bounded.d.ts +2 -2
- package/dist/core/runner/tool-defer-gate.d.ts +86 -0
- package/dist/core/runner/tool-defer-gate.js +57 -0
- package/dist/core/runner/tool-disclosure.d.ts +33 -69
- package/dist/core/runner/tool-disclosure.js +0 -43
- package/dist/core/runner/tool-end-body.d.ts +3 -3
- package/dist/core/runner/tool-face-overlay.d.ts +2 -2
- package/dist/core/runner/tool-output-projection.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +53 -53
- package/dist/core/runner/usage-accounting.d.ts +4 -4
- package/dist/core/runner/workspace-path.d.ts +1 -1
- package/dist/core/runner-deps.d.ts +16 -9
- package/dist/core/task-spec.d.ts +8 -2
- package/dist/core/tool-spec.d.ts +7 -4
- package/dist/core/types.d.ts +1 -1
- package/dist/engine/llm/types.d.ts +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/tools/fs/bash-readonly-classifier.d.ts +40 -40
- package/dist/tools/fs/encoding.d.ts +31 -40
- package/dist/tools/fs/fs-bash.d.ts +76 -35
- package/dist/tools/fs/fs-bash.js +86 -29
- package/dist/tools/fs/fs-pdf.d.ts +8 -8
- package/dist/tools/fs/fs-search-tools.d.ts +4 -4
- package/dist/tools/fs/fs-shared.d.ts +144 -158
- package/dist/tools/fs/fs-write.d.ts +8 -8
- package/dist/tools/fs/gh-rate-limit.d.ts +13 -14
- package/dist/tools/fs/index.d.ts +74 -78
- package/dist/tools/fs/notebook.d.ts +24 -25
- package/dist/tools/fs/pdf.d.ts +3 -3
- package/dist/tools/fs/read-deny.d.ts +22 -22
- package/dist/tools/fs/read-face.d.ts +21 -24
- package/dist/tools/fs/repo-map.d.ts +8 -8
- package/dist/tools/fs/safety.d.ts +116 -129
- package/dist/tools/fs/search.d.ts +63 -71
- package/package.json +5 -2
- package/test/export-surface.snapshot.json +9 -1
|
@@ -34,11 +34,11 @@ export interface RunHarnessHandlersResult {
|
|
|
34
34
|
type: "tool_execution_end";
|
|
35
35
|
}>) => void;
|
|
36
36
|
onTurnEnd: () => void;
|
|
37
|
-
/**
|
|
37
|
+
/** The single workspace_changed mint (cwd diff vs the closure's dedupe state); the run body
|
|
38
38
|
* calls it after a resume's approved-call resolution, which bypasses onToolEnd. */
|
|
39
39
|
announceWorkspaceMove: () => void;
|
|
40
40
|
}
|
|
41
|
-
/**
|
|
41
|
+
/** R5 抽取:runLocked 的五个 harness 事件处理器(onMessageUpdate/onMessageEnd/
|
|
42
42
|
* onToolStart/onToolEnd/onTurnEnd,~530 行)整块搬迁。正文逐字;唯一字面变化 = this.deps.onError →
|
|
43
43
|
* deps.runnerHooks.onError(1 处)。`lastWorkspaceCwd` 是纯 R5 局部(读写全在 onToolEnd 内,零段外
|
|
44
44
|
* 读者),声明随迁进工厂体——调用点放在原声明位之后,初值 `prepared.cwdRef?.current` 的求值时机不变
|
|
@@ -33,7 +33,7 @@ export interface RunIdentityWiringInput {
|
|
|
33
33
|
}) => Promise<"queued" | "parked" | "dropped_duplicate">;
|
|
34
34
|
/** borrowed-mutable — the turn-open dedup set (the cross-layer double-park dedup): a redelivered frame's key is registered here. */
|
|
35
35
|
deliveredAtTurnOpen: Set<string>;
|
|
36
|
-
/** borrowed-mutable —
|
|
36
|
+
/** borrowed-mutable — the peer inbound chain, overwritten by each consumed peer-class payload. */
|
|
37
37
|
peerInboundChainRef: PeerInboundChainRef;
|
|
38
38
|
/** borrowed-mutable — the notification lane's bindings seat (its own `let`s behind getters / setters, never a copy):
|
|
39
39
|
* this lane binds the harness, the session anchor and the identity mint the lane's closures read, and reads the
|
|
@@ -55,7 +55,7 @@ export interface RunIdentityWiringResult {
|
|
|
55
55
|
parentToolCallId?: string;
|
|
56
56
|
sourceTaskId?: string;
|
|
57
57
|
};
|
|
58
|
-
/**
|
|
58
|
+
/** The delegation-lifecycle emission closure both stations share (spawn here, terminal in the driver). */
|
|
59
59
|
emitDelegationLifecycle: (event: import("../types.js").DelegationLifecycleEvent) => void;
|
|
60
60
|
/** The loop-liveness latch and the two attribution seats (ended / userInterrupted / userHalted). */
|
|
61
61
|
loopLatch: {
|
|
@@ -65,7 +65,7 @@ export interface RunIdentityWiringResult {
|
|
|
65
65
|
};
|
|
66
66
|
/** This leg's usage counters, zeroed here; the harness-handlers lane is their writer from the first turn on. */
|
|
67
67
|
stats: Stats;
|
|
68
|
-
/**
|
|
68
|
+
/** The held agent_end account, a READ FACE over this lane's own `let` (the undrained-inputs sink writes it
|
|
69
69
|
* when the run committed a durable park); the terminal-adoption lane settles it minus what the park carried. */
|
|
70
70
|
undrainedUserAtEnd: {
|
|
71
71
|
readonly current: {
|
|
@@ -73,7 +73,7 @@ export interface RunIdentityWiringResult {
|
|
|
73
73
|
followUp: number;
|
|
74
74
|
} | undefined;
|
|
75
75
|
};
|
|
76
|
-
/**
|
|
76
|
+
/** Did the run END with a person's steer / follow-up still pending (queued, or drained at the final boundary and
|
|
77
77
|
* never served)? A READ FACE over this lane's own `let`, written by the same undrained-inputs sink on BOTH its arms
|
|
78
78
|
* (park or not): the terminal-adoption lane folds it into the answer-settled verdict — a "stop" answer the person had
|
|
79
79
|
* already asked to continue past is not a settled answer, so a stop that cut that continuation is a stop on work. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The run body's LEG (R13), verbatim from `Runner.runLocked`: the one `harness.prompt` of the leg and
|
|
3
3
|
* everything that decides whether it is issued. Two legs behind one try / catch / finally: the RESUME leg (the walltime
|
|
4
4
|
* and governance-window entrance claims, the gated decision's application, the exhaustion arms, the continuation prompt's
|
|
5
5
|
* assembly — orphaned background tasks, the git frame, the parked steer queue and the wake message each under its own trust
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* frame's primary delivery, the first-frame listings, the pre-call budget / token / entry-governance gates, the image
|
|
8
8
|
* conversion, the objective's human-input frame and the prompt itself). The resumed decision's application
|
|
9
9
|
* (`applyResumeDecision`) and the gated call's resolver (`resolvePendingCall` — the post-CAS belts, the execution record)
|
|
10
|
-
* are the lane's own module-private functions since
|
|
10
|
+
* are the lane's own module-private functions since S7, verbatim from the Runner's private methods: the resume
|
|
11
11
|
* leg is their one caller, and a sibling file would be a lane-to-lane reach (the S6 legs' reading). The tail captures the abort facts; the catch
|
|
12
12
|
* re-throws the resume-equivalent env failures after a bounded teardown and adopts everything else as the leg's throw;
|
|
13
13
|
* the finally releases the timer, the diagnostics, the signal, the content-ask bindings, flips the notification lane
|
|
@@ -99,7 +99,7 @@ export interface RunLegResult {
|
|
|
99
99
|
abortedLive: boolean;
|
|
100
100
|
/** The snapshot of `loopLatch.userInterrupted`, taken with `abortedLive`. */
|
|
101
101
|
userInterruptedLive: boolean;
|
|
102
|
-
/**
|
|
102
|
+
/** The answered-but-never-collected deliveries the finally settled. */
|
|
103
103
|
strandedHumanAnswers: ReadonlyArray<{
|
|
104
104
|
deliveryId: string;
|
|
105
105
|
toolCallId: string;
|
|
@@ -29,7 +29,7 @@ export interface RunNotificationLaneInput<R> {
|
|
|
29
29
|
/** borrowed-mutable — the Runner's per-session parked-notification store: the torn-down lane and the escalation pend here. */
|
|
30
30
|
pendingSessionNotifications: PendingSessionNotifications;
|
|
31
31
|
/** borrowed-readonly — the orchestrator's entry (a lane may not name the orchestrator; the driver hands it in), as the ONE
|
|
32
|
-
* contract the orchestrator's own declaration is pinned to ({@link PrepareTaskFn}, contracts.ts
|
|
32
|
+
* contract the orchestrator's own declaration is pinned to ({@link PrepareTaskFn}, contracts.ts). */
|
|
33
33
|
prepareTask: PrepareTaskFn;
|
|
34
34
|
/** borrowed-readonly — the lanes after this one, entered in this lane's last continuation with what it prepared and bound. */
|
|
35
35
|
next: (lane: RunNotificationLaneResult) => Promise<R>;
|
|
@@ -44,7 +44,7 @@ export interface RunNotificationLaneResult {
|
|
|
44
44
|
}) => Promise<"queued" | "parked" | "dropped_duplicate">;
|
|
45
45
|
/** The turn-open dedup set (the cross-layer double-park dedup): the identity lane registers a redelivered frame's key here. */
|
|
46
46
|
deliveredAtTurnOpen: Set<string>;
|
|
47
|
-
/**
|
|
47
|
+
/** The peer inbound chain ref this run carries (the spawn chain's, or a fresh one). */
|
|
48
48
|
peerInboundChainRef: PeerInboundChainRef;
|
|
49
49
|
/** The model catalog pinned BEFORE prepare (the natural-snapshot closure for swapDeps): the budget seats resolve against it. */
|
|
50
50
|
modelCatalog: RunnerDeps["models"];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The run body's REASONING seat (R5), verbatim from `Runner.runLocked`: the leg-entry resolution of
|
|
3
3
|
* the requested reasoning intensity against the model's real capability, the ONE publisher that writes both faces
|
|
4
4
|
* (the `reasoning.resolved` trace frame and the `TaskResult.effectiveReasoning` seat on the backstop carrier), and
|
|
5
5
|
* the wire-facts consumer that lets the leg's FIRST committed request correct the cap-blind mint (once; foreign
|
|
@@ -18,7 +18,7 @@ export interface RunReasoningSeatInput {
|
|
|
18
18
|
export interface RunReasoningSeatResult {
|
|
19
19
|
/** The CONSUMPTION half of {@link ReasoningWireFacts} — installed as the third brain ALS sink. */
|
|
20
20
|
observeReasoningWireFacts: (facts: ReasoningWireFacts) => void;
|
|
21
|
-
/**
|
|
21
|
+
/** The leg's resolution as a READ FACE over this lane's own `let` (the leg-entry mint, then at most one
|
|
22
22
|
* first-committed-request correction): the settle lane's result assembly reads it for `effectiveReasoning`. */
|
|
23
23
|
reasoningResolution: {
|
|
24
24
|
readonly current: ResolvedReasoning | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The run body's SETTLE AND TEARDOWN (R15), verbatim from `Runner.runLocked`: the end-of-task
|
|
3
3
|
* compaction's frames and detector reset, the nested-stats fold, the prefix-cache observability and its loud
|
|
4
4
|
* mismatch / low-hit disclosures, the cross-slice cumulative spend fold, the human-review and mechanism counters,
|
|
5
5
|
* the result assembly (`assembleResult` — the one place the leg's facts become a TaskResult), the resume leg's
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* prompt-suggestion kickoff — then, in its finally, the four teardown legs in the order they were: the shell-lane
|
|
11
11
|
* children settle, the background-shell sweep, the registry clears / the background-agent abort / the retained
|
|
12
12
|
* child sessions, and the owned env's teardown. The suggestion pass (`suggestNextPrompts`, with its four bounds) and the
|
|
13
|
-
* owned-env teardown (`teardownOwnedEnv`) are the lane's own module-private functions since
|
|
13
|
+
* owned-env teardown (`teardownOwnedEnv`) are the lane's own module-private functions since S7, verbatim from
|
|
14
14
|
* the Runner's private methods: each has this one caller, and a sibling file would be a lane-to-lane reach (the S6 legs' reading).
|
|
15
15
|
*
|
|
16
16
|
* Async (eleven first-level awaits, all of them the same awaits at the same positions). The `queue.push("done")` and
|
|
@@ -80,10 +80,10 @@ export interface RunSettleAndTeardownInput {
|
|
|
80
80
|
abortedLive: boolean;
|
|
81
81
|
/** borrowed-readonly — the leg's snapshot of `loopLatch.userInterrupted`: names the origin of a stop that landed after the answer settled. */
|
|
82
82
|
userInterruptedLive: boolean;
|
|
83
|
-
/** borrowed-readonly —
|
|
83
|
+
/** borrowed-readonly — the terminal-adoption lane's ONE evaluation of `answerSettled` (a clean `"stop"` final, no continuation
|
|
84
84
|
* lost). Read by the arbitration (`ResultFlags.answerSettled`), the teardown's stop-source attribution and the notice. */
|
|
85
85
|
answerSettled: boolean;
|
|
86
|
-
/** borrowed-readonly —
|
|
86
|
+
/** borrowed-readonly — the answered-but-never-collected deliveries the leg's finally settled. */
|
|
87
87
|
strandedHumanAnswers: ReadonlyArray<{
|
|
88
88
|
deliveryId: string;
|
|
89
89
|
toolCallId: string;
|
|
@@ -15,7 +15,7 @@ export interface RunTelemetryAndBudgetSeatsInput {
|
|
|
15
15
|
stats: Stats;
|
|
16
16
|
/** borrowed-mutable — the stream layer's backstop carrier: the effective task id and session id are published here. */
|
|
17
17
|
taskIdRef: TaskIdRef | undefined;
|
|
18
|
-
/** borrowed-readonly — the invocation's frozen tracer
|
|
18
|
+
/** borrowed-readonly — the invocation's frozen tracer, absence included; undefined when the seat was omitted. */
|
|
19
19
|
entryTracer: {
|
|
20
20
|
tracer: TaskSpec["tracer"];
|
|
21
21
|
} | undefined;
|
|
@@ -32,7 +32,7 @@ export interface RunTelemetryAndBudgetSeatsInput {
|
|
|
32
32
|
sessions: SessionStore;
|
|
33
33
|
}
|
|
34
34
|
export interface RunTelemetryAndBudgetSeatsResult {
|
|
35
|
-
/**
|
|
35
|
+
/** The price-table door — a table adopted MID-RUN that cannot price marks the spend unpriced. */
|
|
36
36
|
noteUnevaluablePriceTable: (p: ModelPricing) => void;
|
|
37
37
|
}
|
|
38
38
|
export declare function runTelemetryAndBudgetSeats(input: RunTelemetryAndBudgetSeatsInput): RunTelemetryAndBudgetSeatsResult;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The run body's TERMINAL ADOPTION (R14), verbatim from `Runner.runLocked`, between the leg's finally and
|
|
3
3
|
* the settle: the typed causes lifted over the leg's anonymous end (the brain-call guardrail's stall, the tool gate's own
|
|
4
4
|
* stop, the platform lane's external cause — which alone overrides a real throw), the usage ledger's FINAL charge with its
|
|
5
5
|
* slow-charge disclosure, the live-abort orphan reconcile and its synthetic `tool_end` frames, the held session-write
|
|
6
6
|
* drain, the user-interruption marker, the durable park's carried caller input and the held agent_end account's settle,
|
|
7
|
-
* the dropped post-compact announce disclosure, and the end-of-task compaction pass (`finish` — since
|
|
7
|
+
* the dropped post-compact announce disclosure, and the end-of-task compaction pass (`finish` — since S7 the lane's
|
|
8
8
|
* own module-private function, verbatim from the Runner's private method: the pass has one caller, and a sibling file would be a
|
|
9
9
|
* lane-to-lane reach, the S6 legs' reading).
|
|
10
10
|
*
|
|
@@ -58,14 +58,14 @@ export interface RunTerminalAdoptionInput<R> {
|
|
|
58
58
|
};
|
|
59
59
|
/** borrowed-readonly — the window-safety builder the end-of-task lane shares with the boundary / PTL lanes. */
|
|
60
60
|
windowSafetyOptions: (mainModel: Model) => Pick<MaybeCompactOptions, "fallbackBudget" | "onWindowSafety">;
|
|
61
|
-
/** borrowed-readonly — the held agent_end account, as the read face on the identity lane's Result
|
|
61
|
+
/** borrowed-readonly — the held agent_end account, as the read face on the identity lane's Result. */
|
|
62
62
|
undrainedUserAtEnd: {
|
|
63
63
|
readonly current: {
|
|
64
64
|
steer: number;
|
|
65
65
|
followUp: number;
|
|
66
66
|
} | undefined;
|
|
67
67
|
};
|
|
68
|
-
/** borrowed-readonly —
|
|
68
|
+
/** borrowed-readonly — did the run end with a person's steer / follow-up still pending (the identity lane's read face)? Folded
|
|
69
69
|
* into the answer-settled verdict this lane evaluates once. */
|
|
70
70
|
userInputLostAtEnd: {
|
|
71
71
|
readonly current: boolean;
|
|
@@ -92,7 +92,7 @@ export interface RunTerminalAdoptionResult {
|
|
|
92
92
|
threw: unknown;
|
|
93
93
|
/** The end-of-task compaction pass's outcome. */
|
|
94
94
|
comp: EndOfTaskCompaction;
|
|
95
|
-
/**
|
|
95
|
+
/** This lane's ONE evaluation of {@link answerSettled}: a clean `"stop"` final with no queued continuation lost. The
|
|
96
96
|
* settle lane hands it to the arbitration (`ResultFlags.answerSettled`), the teardown attribution and the notice. */
|
|
97
97
|
answerSettled: boolean;
|
|
98
98
|
}
|
|
@@ -16,7 +16,7 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
16
16
|
readonly sessions: SessionStore;
|
|
17
17
|
/** Per-sessionId serialization so two tasks never mutate one session concurrently. */
|
|
18
18
|
private sessionLocks;
|
|
19
|
-
/**
|
|
19
|
+
/** Per-session read-file-state seats (CC parity: readFileState is session-scoped;
|
|
20
20
|
* sema's map stays per-task, so the session scope lives here). A bounded CACHE, never an
|
|
21
21
|
* authority: a durable resume's checkpoint seed wins on its leg, and a miss (cross-process,
|
|
22
22
|
* evicted) falls back to the transcript-replay rung. See {@link SessionReadFileStates}. */
|
|
@@ -38,7 +38,7 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
38
38
|
* observed `already_resolved` and by the FIFO cap — an evicted entry only ever degrades to the explicit
|
|
39
39
|
* re-supply requirement (fail-loud), never fail-open. */
|
|
40
40
|
private readonly parentConstraintRegistry;
|
|
41
|
-
/**
|
|
41
|
+
/** Same-process suspended-env reap handles by token: the fence contract is
|
|
42
42
|
* "only the expire WINNER destroys the paused env", and the terminal resume-preflight arm
|
|
43
43
|
* (resumeStream) can now BE that winner — without this registry the losing stream-side
|
|
44
44
|
* reapSuspended returned early and the paused env this process holds leaked forever. Registered
|
|
@@ -47,7 +47,7 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
47
47
|
* the ORIGINAL stream's closure as the reaping owner, deliberately), and when the terminal arm
|
|
48
48
|
* wins. Bounded by live suspended streams (the closures hold the same handles). */
|
|
49
49
|
private readonly suspendedEnvReaps;
|
|
50
|
-
/**
|
|
50
|
+
/** SAME-RUNNER claim marks for {@link suspendedEnvReaps}: a token appears
|
|
51
51
|
* here from the moment an in-process actor ATTEMPTS its settling CAS (the terminal preflight's
|
|
52
52
|
* expire; a resume's resolve) until that actor's duty decision is done. The losing stream-side
|
|
53
53
|
* reap preserves a record ONLY while a local claim is in flight — a CROSS-Runner settlement
|
|
@@ -61,12 +61,12 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
61
61
|
* `swapDeps` replaces the object and a rung reading after its own await must see the replacement. */
|
|
62
62
|
private readonly depsSeat;
|
|
63
63
|
constructor(deps: RunnerDeps);
|
|
64
|
-
/**
|
|
64
|
+
/** Fire `RunnerDeps.onTaskOutcome` through the single swallow-guarded chokepoint
|
|
65
65
|
* ({@link emitTaskOutcome}: mechanical-tier only, throwing sink never breaks the caller). Public so
|
|
66
66
|
* thin compositions OVER the Runner (`runGoal`) can emit at their terminal state without reaching
|
|
67
67
|
* into private deps. */
|
|
68
68
|
emitTaskOutcome(outcome: TaskOutcome): void;
|
|
69
|
-
/**
|
|
69
|
+
/** The deployment agent catalog (RunnerDeps.agents/builtinAgents), exposed READ-ONLY
|
|
70
70
|
* so the Agent-tool lane (`createSubagentTool`) defaults to the SAME registry the workflow lane
|
|
71
71
|
* consumes (single source; the types.ts "pass the same array" follow-on made structural). The array
|
|
72
72
|
* is a fresh copy — a caller mutating it never rewrites this Runner's own deps; the definitions
|
|
@@ -77,7 +77,7 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
77
77
|
models?: Record<string, Model>;
|
|
78
78
|
roles?: ModelRoles;
|
|
79
79
|
};
|
|
80
|
-
/**
|
|
80
|
+
/** The deployment-level gating baseline, exposed READ-ONLY so thin
|
|
81
81
|
* assemblers over the Runner (`runSpec`) can COMPOSE with it. The task-level engine semantic is a
|
|
82
82
|
* WHOLE-SLOT override (`spec.toolPolicy ?? deps.toolPolicy`, same for hooks — prepare-task), so any
|
|
83
83
|
* assembler that sets `spec.toolPolicy`/`spec.hooks` without folding these in silently shadows the
|
|
@@ -124,8 +124,8 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
124
124
|
* policy gate, no accounting — caller-trusted. */
|
|
125
125
|
sideQuery(spec: SideQuerySpec): Promise<SideQueryResult>;
|
|
126
126
|
/** Run a task and stream live events; await `.result()` for the final TaskResult. `resume` (internal)
|
|
127
|
-
* drives a
|
|
128
|
-
* `internals` (internal
|
|
127
|
+
* drives a durable resume through the same loop instead of a fresh objective prompt.
|
|
128
|
+
* `internals` (internal) is a TRUSTED run-scoped channel for live per-task state the
|
|
129
129
|
* Runner cannot see from `spec` (today: a `runRepairLoop` attempt's live `repairBundle`) — NOT a
|
|
130
130
|
* `TaskSpec` field; undefined on the public path.
|
|
131
131
|
* **Eager:** the task starts executing the moment this stream is constructed (fire-and-forget), NOT lazily
|
|
@@ -133,7 +133,7 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
133
133
|
* happen. Iterating just observes events (the buffer is backpressure-free); `.result()` awaits completion. */
|
|
134
134
|
runTaskStream(spec: TaskSpec, resume?: ResumeRun, internals?: RunInternals): TaskStream;
|
|
135
135
|
/**
|
|
136
|
-
|
|
136
|
+
* The run body as ONE driver method: `runLocked`'s signature, the lane order, and the two assemblies
|
|
137
137
|
* the driver keeps (the harness handlers, the turn boundary). The lanes' products are threaded under the names they hand
|
|
138
138
|
* back; the two continuations the S6 driver spelled as private methods (`runSeatLanes` / `runAssembliesAndLegs`, joined by
|
|
139
139
|
* a `RunSeatsHandoff` re-spelling of two lanes' Results) are the `next` closures of the two async lanes they follow — the
|
|
@@ -147,7 +147,7 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
147
147
|
/** Run a task to completion and return a machine-readable result. */
|
|
148
148
|
runTask(spec: TaskSpec, internals?: RunInternals): Promise<TaskResult>;
|
|
149
149
|
/**
|
|
150
|
-
* Resume a task suspended at a durable approval gate
|
|
150
|
+
* Resume a task suspended at a durable approval gate. The token came back as
|
|
151
151
|
* `TaskResult.checkpointToken` from a `status:"suspended"` run; `outcome` carries the human/external
|
|
152
152
|
* decision (`allow`/`deny`, with an optional `updatedInput` arg rewrite or `reason`); `taskConfig`
|
|
153
153
|
* **re-supplies** the same tools / model / policy the task ran with (a token cannot reconstruct tool
|
|
@@ -164,7 +164,7 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
164
164
|
* v1 serves only the `human`/`policy_ask` gate (F4). A `task_done` checkpoint (1C Path A) is not
|
|
165
165
|
* resumable here — the caller orchestrates that one and reads its handle directly.
|
|
166
166
|
*
|
|
167
|
-
* **🔒 Authorization boundary
|
|
167
|
+
* **🔒 Authorization boundary — token-as-auth, scope is store-level
|
|
168
168
|
* isolation, NOT caller authorization.** `resume` is TOKEN-AS-AUTH: whoever presents a valid, still-`pending`
|
|
169
169
|
* checkpoint token resolves it. The scope passed to the store CAS is the checkpoint's OWN `cp.scope` (read
|
|
170
170
|
* off the row), so the store's scope-WHERE is store-level multi-tenant DATA isolation (one tenant's reaper /
|
|
@@ -192,7 +192,7 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
192
192
|
* {@link CheckpointError.code}.
|
|
193
193
|
*/
|
|
194
194
|
resume(token: CheckpointToken, outcome: ResumeOutcome, taskConfig: ResumeTaskConfig,
|
|
195
|
-
/**
|
|
195
|
+
/** Same TRUSTED run-internals seam as {@link resumeStream} — the convenience wrapper
|
|
196
196
|
* FORWARDS it (it used to silently drop a 4th arg, so a cross-process re-supply through resume()
|
|
197
197
|
* looked wired but always failed `resume.parent_constraint_missing`). */
|
|
198
198
|
internals?: RunInternals): Promise<TaskResult>;
|
|
@@ -235,7 +235,7 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
235
235
|
* catches shape MISTAKES, not a untrusted trusted caller). */
|
|
236
236
|
internals?: RunInternals): Promise<TaskStream>;
|
|
237
237
|
/**
|
|
238
|
-
*
|
|
238
|
+
* The resume decision ladder after admission (E3–E10), driving the eight `resume-*` lanes in
|
|
239
239
|
* the order the one-function ladder had: the review / park twins, the approval twin and its bindings, the
|
|
240
240
|
* checkpoint screen, the internals-and-config rungs (whose one window await is taken HERE, where the ladder
|
|
241
241
|
* took it), then the three async rungs after it — apply, preflight, claim — each entering the next in its own last
|
|
@@ -244,7 +244,7 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
244
244
|
*/
|
|
245
245
|
private resumeLadder;
|
|
246
246
|
/**
|
|
247
|
-
*
|
|
247
|
+
* The ladder's POST-CLAIM rung (E11), the driver's own: the post-consume hook, the answering
|
|
248
248
|
* face minted from the decide's answer, the resumed leg's spec (identity continuity, the existing-session
|
|
249
249
|
* requirement, the stripped pre-aborted preempt signal), the reopen compensation and the execution-record
|
|
250
250
|
* verb bound to the row, the two post-CAS abort re-checks, and the hand-off to `runTaskStream` with the plain
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
* a `git checkout`, a bash command — anything this transcript does not record) therefore fails
|
|
19
19
|
* the staleness comparison and the edit is refused, exactly as it is inside a single task. A
|
|
20
20
|
* reconstruction that re-read the file to build its hash would instead wave the dirty edit
|
|
21
|
-
* through; that is the one thing this module must never do. (
|
|
21
|
+
* through; that is the one thing this module must never do. (This is
|
|
22
22
|
* deliberately STRICTER than CC's own rehydrate, whose Edit arm re-reads the disk and would
|
|
23
23
|
* admit a between-turns external change — same gate satisfaction, no staleness give-up.)
|
|
24
24
|
* 2. **Only records whose full post-condition is PROVABLE qualify.** A whole-file `Read` and a
|
|
25
|
-
* `Write` carry the text verbatim. An `Edit` card
|
|
25
|
+
* `Write` carry the text verbatim. An `Edit` card carries a diff BASE — the
|
|
26
26
|
* pre-edit whole text plus the resolved mutations — so its post-condition is RECOMPUTED through
|
|
27
27
|
* the same single-source application step the tool itself used (`applyRecordedEdit`); a card
|
|
28
28
|
* that cannot recompute (malformed, offloaded, or its oldString absent from its own base) falls
|
|
@@ -45,7 +45,7 @@ export interface TranscriptFileRecord {
|
|
|
45
45
|
*
|
|
46
46
|
* Records are read only from SUCCESSFUL results (an `isError` result changed nothing and proves
|
|
47
47
|
* nothing). A `Write` proves the post-condition it just persisted; a whole-file `Read` proves what it
|
|
48
|
-
* just served. An `Edit` card
|
|
48
|
+
* just served. An `Edit` card proves the post-condition RECOMPUTED from its recorded
|
|
49
49
|
* diff base + mutations — or, when it cannot prove (malformed / offloaded / inconsistent), retracts
|
|
50
50
|
* whatever an earlier record said (leaving a stale entry behind would blame the user for the agent's
|
|
51
51
|
* own edit, "modified since read", the next turn). A `NotebookEdit` always retracts (deliberate
|
|
@@ -12,7 +12,7 @@ import type { SessionPermissionRules } from "../session-policy-store.js";
|
|
|
12
12
|
* `NotebookEdit` (whose target is `notebook_path`) lives in the superset
|
|
13
13
|
* {@link PATH_CONFINABLE_WRITE_TOOLS} below, NOT here: `createActiveSkillScopePolicy` reads THIS set and
|
|
14
14
|
* deliberately keeps fail-closed-denying notebooks under a manifest `allowPaths` fence (widening the
|
|
15
|
-
* skill face is a separate capability decision
|
|
15
|
+
* skill face is a separate capability decision). */
|
|
16
16
|
export declare const PATH_WRITE_TOOLS: ReadonlySet<string>;
|
|
17
17
|
/** The FULL path-confinable write-tool set: {@link PATH_WRITE_TOOLS} plus `NotebookEdit`, whose write
|
|
18
18
|
* target is `notebook_path` and is extracted by the shared tool-aware {@link writeTargetPath} (
|
|
@@ -60,7 +60,7 @@ export declare function isWithin(root: string, p: string): boolean;
|
|
|
60
60
|
* so a symlink can't carry across a write out); a write-capable tool that cannot be path-confined (e.g. `bash`)
|
|
61
61
|
* is DENIED while `allowDirs` is set (fail-closed, mirrors active-skill-scope MAJOR-2).
|
|
62
62
|
* Returns `allow` when nothing constrains the call. `env`/`rootPath` are the task's real exec env + root, so
|
|
63
|
-
* matching sees the actual filesystem (a remote/E2B task resolves in its container).
|
|
63
|
+
* matching sees the actual filesystem (a remote/E2B task resolves in its container). A relative
|
|
64
64
|
* TARGET prefers the call's live tracked cwd ({@link ToolCallRequest.cwd}) when the engine stamps one;
|
|
65
65
|
* `allowDirs` entries always resolve against `rootPath`.
|
|
66
66
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Admission bookkeeping for HUMAN INPUTS accepted mid-run
|
|
2
|
+
* Admission bookkeeping for HUMAN INPUTS accepted mid-run: the per-leg ordinal an
|
|
3
3
|
* accepted input is stamped with, and the field-for-field "is this repeat the same instruction" test the
|
|
4
4
|
* live steer verb applies under an already-used `inputId`. Two accepting arms share both — the stream's
|
|
5
5
|
* `steer` verb and the run body — which is why the ordinal is keyed on the leg's harness in a module-level
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { AcceptedSteerInput } from "./contracts.js";
|
|
12
12
|
export declare function nextHumanInputSeq(key: object): number;
|
|
13
|
-
/**
|
|
13
|
+
/** Is a repeat under an already-accepted `inputId` the SAME
|
|
14
14
|
* instruction (an idempotent retry) or a different one wearing a used key? Compared field for field,
|
|
15
15
|
* exactly like the parked leg's replay check: the key alone is never evidence of a replay, and two
|
|
16
16
|
* callers colliding on one id must not silently lose the second instruction. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The TaskStream façade's HALT verbs (T7), verbatim from `Runner.runTaskStream`: `halt` (the bare
|
|
3
3
|
* user interrupt — the finished-task refusal, the fresh liveness test on the resolved handle, `apply` with its
|
|
4
4
|
* pre-abort ownership snapshot, the conjunctive attribution seat, the unconsumed-halt and turn-cut notices, and
|
|
5
5
|
* the birth-window poll; never on the steer FIFO chain) and `destroy` (the once-memoized reap: abort, await the
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The TaskStream façade's REAP lane (T4), verbatim from `Runner.runTaskStream`: `destroy()`'s
|
|
3
3
|
* once-memoized work for a run that SUSPENDED. Runs AFTER `run` has settled (the destroy verb awaits the run before
|
|
4
4
|
* calling it), fences any concurrent resume first (the single-shot `expire` CAS — only the winner destroys the
|
|
5
5
|
* paused env; a loser retires its reap record only when no same-Runner claimant is in flight), evicts the
|
|
@@ -5,7 +5,7 @@ import type { ActiveSkillScope } from "./active-skill-scope.js";
|
|
|
5
5
|
/** Reserved name of the injected structured-output tool (CC 2.1.187 `StructuredOutput`; batch-A rename — old
|
|
6
6
|
* "submit_output" is canonicalized for pre-rename durable state). */
|
|
7
7
|
export declare const OUTPUT_TOOL_NAME = "StructuredOutput";
|
|
8
|
-
/** Reserved name of the injected blocked-report signal tool (
|
|
8
|
+
/** Reserved name of the injected blocked-report signal tool (PascalCase: `report_blocked`→`ReportBlocked`). */
|
|
9
9
|
export declare const REPORT_BLOCKED_TOOL_NAME = "ReportBlocked";
|
|
10
10
|
/** Name of the injected code-review findings echo tool (CC 2.1.207 parity — 锚 pretty.js:361412 `BCe`). */
|
|
11
11
|
export declare const REPORT_FINDINGS_TOOL_NAME = "ReportFindings";
|
|
@@ -80,7 +80,7 @@ interface SkillLike {
|
|
|
80
80
|
name: string;
|
|
81
81
|
description: string;
|
|
82
82
|
content: string;
|
|
83
|
-
/** Optional Gate-3 runtime capability manifest
|
|
83
|
+
/** Optional Gate-3 runtime capability manifest — carried through so a successful
|
|
84
84
|
* `skill` load can push its scope frame. Skills without one stay unscoped (backward-compatible). */
|
|
85
85
|
manifest?: SkillManifest;
|
|
86
86
|
/** Optional attachments (SkillSpec.files): disclosed as paths in the block, delivered inline on
|
|
@@ -102,7 +102,7 @@ export interface SkillListingEntry {
|
|
|
102
102
|
files?: Array<{
|
|
103
103
|
path: string;
|
|
104
104
|
}>;
|
|
105
|
-
/**
|
|
105
|
+
/** The skill's rank in the DEPLOYMENT'S DECLARATION order (`TaskSpec.skills`, first-wins
|
|
106
106
|
* dedupe applied, 0 = declared first). Lower = higher priority. Used ONLY to decide which skills keep
|
|
107
107
|
* their descriptions when the block overflows its byte budget ({@link buildSkillsBlock} tier B); the
|
|
108
108
|
* DISPLAY order stays name-sorted, so adding this never moves a line.
|
|
@@ -113,7 +113,7 @@ export interface SkillListingEntry {
|
|
|
113
113
|
* skill-usage store, and no bundled/user distinction (every skill arrives through the same
|
|
114
114
|
* caller-supplied `TaskSpec.skills`). Declaration order is the one priority statement the deployment
|
|
115
115
|
* can actually make here, and it is the same statement 220's bundled-pin encodes ("these matter most,
|
|
116
|
-
* keep their descriptions"). Absent ⇒ the entry's array index is used, i.e. the
|
|
116
|
+
* keep their descriptions"). Absent ⇒ the entry's array index is used, i.e. the prior behavior. */
|
|
117
117
|
declaredRank?: number;
|
|
118
118
|
}
|
|
119
119
|
/** Dedupe by name (first occurrence wins) and sort by name — one deterministic list shared by the
|
|
@@ -139,12 +139,12 @@ export declare function skillListingLine(s: SkillListingEntry): string;
|
|
|
139
139
|
* render can never blow the budget it was sized against —
|
|
140
140
|
* A. everything fits → every skill gets its full `- name: description` line (byte-identical to
|
|
141
141
|
* the pre-C4 render for every block that was legal under the old cap);
|
|
142
|
-
* B.
|
|
142
|
+
* B. (CC 220 `sbs` @317547-317586) — reserve the cap marker + EVERY skill's name-only line
|
|
143
143
|
* first, then spend the remaining slack on descriptions in PRIORITY order
|
|
144
144
|
* ({@link SkillListingEntry.declaredRank}), admitting each description whose incremental cost
|
|
145
145
|
* still fits and skipping (not stopping at) the ones that do not. Every skill stays listed;
|
|
146
146
|
* the ones that lose their description are the low-priority ones, not the alphabetically late
|
|
147
|
-
* ones. This replaces the
|
|
147
|
+
* ones. This replaces the prior "longest full-line PREFIX" cut, which had two defects the
|
|
148
148
|
* anchor does not: the surviving set was decided by name sort order (a skill named `zip-deploy`
|
|
149
149
|
* lost its description to `aardvark-lint` for no reason connected to either skill), and one
|
|
150
150
|
* oversized description truncated the block at itself instead of being skipped over;
|
|
@@ -154,7 +154,7 @@ export declare function buildSkillsBlock(skills: ReadonlyArray<SkillListingEntry
|
|
|
154
154
|
/**
|
|
155
155
|
* The injected `skill` tool: returns a skill's full body as a tool result.
|
|
156
156
|
*
|
|
157
|
-
* When a {@link ActiveSkillScope} is supplied (
|
|
157
|
+
* When a {@link ActiveSkillScope} is supplied (Gate-3) and the loaded skill carries a
|
|
158
158
|
* `manifest`, a successful load PUSHES a scope frame onto the per-task LIFO stack, so the rest of the
|
|
159
159
|
* invocation is deny-narrowed to the manifest's tools/paths. Nested loads (a skill whose body loads
|
|
160
160
|
* another skill) STACK and compose MONOTONICALLY as the INTERSECTION of every active frame's
|
|
@@ -162,7 +162,7 @@ export declare function buildSkillsBlock(skills: ReadonlyArray<SkillListingEntry
|
|
|
162
162
|
* the test/lifecycle may pop explicitly via `scope.pop()` to model a skill frame closing). Skills with
|
|
163
163
|
* NO manifest push nothing (unscoped, backward-compatible).
|
|
164
164
|
*
|
|
165
|
-
* v1 lifetime is heuristic (
|
|
165
|
+
* v1 lifetime is heuristic (a residual): the model controls its own turns, so push-on-load
|
|
166
166
|
* is the trigger and the worst case (a frame never popped) is simply continued narrowing — never a
|
|
167
167
|
* widening, so it stays safe-by-construction.
|
|
168
168
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Bounded await for BEST-EFFORT teardown /
|
|
3
3
|
* cleanup legs on a run's settle path.
|
|
4
4
|
*
|
|
5
5
|
* The defect class: `resume()`/`runTask` settle only when the run body returns, and the body's tail
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* proceeds. The abandoned leg keeps running (nothing can cancel a wedged promise); the incident
|
|
18
18
|
* report says exactly that, so a leaked env/process is attributable instead of anonymous.
|
|
19
19
|
*
|
|
20
|
-
* Timer discipline (
|
|
20
|
+
* Timer discipline (with-retry.ts same doctrine): the race timer is deliberately NOT
|
|
21
21
|
* unref'd — the caller awaits this in FOREGROUND control flow, and an unref'd timer lets an
|
|
22
22
|
* otherwise-empty event loop exit mid-wait, which un-settles the very await this module exists to
|
|
23
23
|
* bound. The timer is itself bounded, and cleared the moment the leg settles.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Model } from "../../internal/llm.js";
|
|
2
|
+
import type { ToolSpec } from "../types.js";
|
|
3
|
+
import type { ToolFingerprintInput } from "../cache-break-detector.js";
|
|
4
|
+
/**
|
|
5
|
+
* The deferral GATE: which mounted tool names ship as placeholders on a request. Pure
|
|
6
|
+
* registry logic over names and sizes — no harness, no I/O. `tool-disclosure.ts` owns the placeholder
|
|
7
|
+
* and ToolSearch mechanics that act on the set this module decides; `prepare-defer-classify.ts` is the
|
|
8
|
+
* phase that assembles the inputs from the mounted face.
|
|
9
|
+
*/
|
|
10
|
+
/** The deferral gate's threshold: the engine's candidate set is deferred when its inlined size reaches
|
|
11
|
+
* this fraction of the model's context window (that set measured, never the rest of the face). */
|
|
12
|
+
export declare const DEFER_THRESHOLD_FRACTION = 0.1;
|
|
13
|
+
/** The typed refusal a `deferMode` outside its declared domain (`"auto"` or absent) raises at the classifier —
|
|
14
|
+
* a bad value never selects an arm silently. */
|
|
15
|
+
export declare const DEFER_MODE_INVALID_CODE = "config.defer_mode_invalid";
|
|
16
|
+
/** The deferral gate's verdict — the two deferral lists, what the gate measured, and whether it opened. */
|
|
17
|
+
export interface DeferralGate {
|
|
18
|
+
/** The caller's LITERAL list: `TaskSpec.deferTools` names mounted on this face, minus the inline pins.
|
|
19
|
+
* Deferred on every request, whatever the gate says — an intentional deferral is not a size question. */
|
|
20
|
+
explicit: Set<string>;
|
|
21
|
+
/** The engine's SELF-SELECTED candidates: `ToolSpec.defer === true`, every remote-protocol name, built-ins
|
|
22
|
+
* that declare their own `defer`, and — under `deferMode: "auto"` — every caller spec; minus the inline
|
|
23
|
+
* pins and minus `explicit`. Deferred iff the gate opens. */
|
|
24
|
+
gated: Set<string>;
|
|
25
|
+
/** Σ inlined chars (name + description + serialized schema) over `gated` — the bytes the gate could reclaim. */
|
|
26
|
+
gatedChars: number;
|
|
27
|
+
/** `floor(contextTokens × fraction) × CHARS_PER_TOKEN`; the char reading of the token threshold. */
|
|
28
|
+
thresholdChars: number;
|
|
29
|
+
/** Whether `gated` is deferred on this request: `gatedChars ≥ thresholdChars`. */
|
|
30
|
+
open: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Deferral has TWO rules, and only two.
|
|
34
|
+
*
|
|
35
|
+
* ① THE CALLER'S LIST IS LITERAL. `TaskSpec.deferTools` (arriving as `callerDeferNames`, pre-filtered to
|
|
36
|
+
* mounted wire names, built-ins included) is deferred on every request; `alwaysLoad` (`ToolSpec.alwaysLoad`,
|
|
37
|
+
* `alwaysLoadNames`) is inlined on every request and is judged FIRST — a pinned name is in neither list
|
|
38
|
+
* and is never measured. Neither depends on the gate: they are the deployment's stated intent.
|
|
39
|
+
*
|
|
40
|
+
* ② THE ENGINE'S OWN CANDIDATES SIT BEHIND ONE THRESHOLD GATE. The candidates are declared: explicit
|
|
41
|
+
* `ToolSpec.defer === true` on a caller spec, every REMOTE-PROTOCOL tool name (MCP servers AND A2A peers —
|
|
42
|
+
* the caller unions them), and `builtinDeferNames` (mounted BUILT-INS that declare their own `defer`; a
|
|
43
|
+
* built-in ToolSpec never reaches `specs`, so its declaration arrives as a mounted name). `deferMode:
|
|
44
|
+
* "auto"` WIDENS the candidate set to every caller spec — undeclared caller tools included — and nothing
|
|
45
|
+
* else: it is not a second gate, and engine built-ins the deployment did not name are candidates under no
|
|
46
|
+
* setting. The gate decides the set all or nothing: deferred iff `gatedChars ≥ thresholdChars`, where the
|
|
47
|
+
* threshold is {@link DEFER_THRESHOLD_FRACTION} of the model's context window (`contextTokens ??
|
|
48
|
+
* contextWindow`, in chars at {@link CHARS_PER_TOKEN}). The measure is the candidate set ONLY — the bytes
|
|
49
|
+
* the gate could reclaim — never the caller's list, the pins, or non-candidates: a request whose weight
|
|
50
|
+
* sits elsewhere gains nothing from a ToolSearch round-trip, so nothing about it argues for one. A window
|
|
51
|
+
* of zero reads as a zero threshold (every candidate byte is over budget), so the candidates defer.
|
|
52
|
+
*
|
|
53
|
+
* Invariants: `explicit ∩ gated = ∅`; `deferred = explicit ∪ (open ? gated : ∅)`; a pinned name is in no
|
|
54
|
+
* list; the same inputs always yield the same verdict (a pure function of the request).
|
|
55
|
+
*/
|
|
56
|
+
export declare function deferralGate(opts: {
|
|
57
|
+
specs: ReadonlyArray<ToolSpec>;
|
|
58
|
+
/** Every namespaced tool a remote protocol materialized for this task (MCP servers AND A2A peers —
|
|
59
|
+
* the caller unions them). The remote-roster shape (many tools, schemas the deployment does not
|
|
60
|
+
* control, drift between tasks) is the same for every protocol, so every protocol's names are
|
|
61
|
+
* candidates by being remote. Only an inline pin (or the caller's own list) takes a name out. */
|
|
62
|
+
protocolToolNames: ReadonlyArray<string>;
|
|
63
|
+
/** The MOUNTED face — the tools whose full definitions the request would carry. The measure reads
|
|
64
|
+
* each candidate's inlined size from here; a candidate absent from it weighs nothing. */
|
|
65
|
+
fullTools: ReadonlyArray<ToolFingerprintInput>;
|
|
66
|
+
/** `"auto"` widens the candidate set to every caller spec (see above). Any other value refuses. */
|
|
67
|
+
deferMode?: "auto";
|
|
68
|
+
model: Model;
|
|
69
|
+
/** Rule ① — `TaskSpec.deferTools`: ALREADY-MOUNTED wire names (built-ins included; `ToolSpec.defer`
|
|
70
|
+
* only reaches caller specs) the caller defers on every request. Caller pre-filters to mounted names. */
|
|
71
|
+
callerDeferNames?: ReadonlyArray<string>;
|
|
72
|
+
/** Rule ② — mounted BUILT-INS that declare their own `defer` (the engine's declaration, not the
|
|
73
|
+
* caller's), so they are candidates. Caller pre-filters to mounted names. */
|
|
74
|
+
builtinDeferNames?: ReadonlyArray<string>;
|
|
75
|
+
/** Rule ① — inline-pin names (`TaskSpec.alwaysLoadTools` + the MCP tools whose server declared
|
|
76
|
+
* `_meta["anthropic/alwaysLoad"]`, caller-collected; A2A has no such per-skill declaration, so the
|
|
77
|
+
* task-level list is a peer's only inline-keep channel): exempt from BOTH lists.
|
|
78
|
+
* `ToolSpec.alwaysLoad` rides the specs directly and needs no entry here. */
|
|
79
|
+
alwaysLoadNames?: ReadonlyArray<string>;
|
|
80
|
+
}): DeferralGate;
|
|
81
|
+
/**
|
|
82
|
+
* Decide which tool names are deferred: the caller's literal list, plus the gated candidates when the gate
|
|
83
|
+
* opens. THIS CONTRACT (with {@link deferralGate}) IS THE SINGLE AUTHORITY on the deferral sources and the
|
|
84
|
+
* gate; the `TaskSpec` / `RunnerDeps` JSDoc points here.
|
|
85
|
+
*/
|
|
86
|
+
export declare function classifyDeferred(opts: Parameters<typeof deferralGate>[0]): Set<string>;
|