@sema-agent/core 7.16.0 → 7.17.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.
- package/CHANGELOG.md +209 -0
- package/dist/agents/builtin-agents.d.ts +3 -3
- package/dist/agents/cross-session-envelope.d.ts +0 -1
- package/dist/agents/cross-session-envelope.js +0 -1
- package/dist/agents/peer-notices.d.ts +0 -9
- package/dist/agents/peer-notices.js +0 -63
- package/dist/agents/subagent.js +7 -15
- package/dist/brain/request-params.d.ts +2 -2
- package/dist/config/defaults.d.ts +0 -7
- package/dist/config/defaults.js +0 -2
- package/dist/core/artifact-host.d.ts +218 -0
- package/dist/core/artifact-host.js +92 -0
- package/dist/core/ask-origin.d.ts +29 -3
- package/dist/core/ask-origin.js +17 -9
- package/dist/core/ask-question.d.ts +25 -0
- package/dist/core/ask-question.js +4 -0
- package/dist/core/ask-unresolvable-notice.d.ts +30 -21
- package/dist/core/ask-unresolvable-notice.js +16 -8
- package/dist/core/auto-compaction.d.ts +10 -10
- package/dist/core/auto-mode-arming.d.ts +2 -2
- package/dist/core/background-agent-store.d.ts +5 -5
- package/dist/core/background-shell.d.ts +1 -1
- package/dist/core/checkpoint-execution-record.d.ts +0 -3
- package/dist/core/checkpoint-execution-record.js +0 -4
- package/dist/core/checkpoint-store.d.ts +71 -99
- package/dist/core/checkpoint-store.js +9 -16
- package/dist/core/context-edit.d.ts +36 -104
- package/dist/core/context-edit.js +37 -60
- package/dist/core/effective-path-target.d.ts +68 -8
- package/dist/core/effective-path-target.js +42 -30
- package/dist/core/engine-notice.d.ts +46 -32
- package/dist/core/env-budget.d.ts +31 -0
- package/dist/core/env-budget.js +39 -0
- package/dist/core/exec-output-tail.d.ts +5 -5
- package/dist/core/file-history-store.js +3 -6
- package/dist/core/fs-write-gate-policy.d.ts +1 -1
- package/dist/core/fs-write-gate-policy.js +3 -3
- package/dist/core/gate-lanes.js +9 -15
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/hands-band.d.ts +1 -1
- package/dist/core/hooks.d.ts +18 -17
- package/dist/core/lsp-session.d.ts +1 -1
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/lsp.js +5 -4
- package/dist/core/mcp.d.ts +5 -5
- package/dist/core/mcp.js +4 -48
- package/dist/core/memory-engine/engine.js +2 -1
- package/dist/core/memory-engine/layout.d.ts +18 -6
- package/dist/core/memory-engine/layout.js +40 -21
- package/dist/core/memory-recall.d.ts +0 -8
- package/dist/core/memory.d.ts +1 -1
- package/dist/core/oracle-isolation.js +2 -2
- package/dist/core/parent-spec-seat.d.ts +66 -0
- package/dist/core/parent-spec-seat.js +47 -0
- package/dist/core/permission-rule-model.d.ts +11 -6
- package/dist/core/permission-rule-model.js +53 -37
- package/dist/core/permission-rules.js +8 -3
- package/dist/core/physical-path.d.ts +37 -0
- package/dist/core/physical-path.js +30 -0
- package/dist/core/protocol-naming.d.ts +2 -2
- package/dist/core/remote-env.d.ts +1 -1
- package/dist/core/retired-keys.d.ts +19 -0
- package/dist/core/retired-keys.js +15 -0
- package/dist/core/runner/active-skill-scope.js +3 -3
- package/dist/core/runner/assemble-result.d.ts +15 -13
- package/dist/core/runner/assemble-result.js +5 -4
- package/dist/core/runner/compaction-call-options.d.ts +25 -89
- package/dist/core/runner/contracts.d.ts +11 -10
- package/dist/core/runner/gate-exit.js +15 -1
- package/dist/core/runner/halt-attribution.d.ts +35 -0
- package/dist/core/runner/halt-attribution.js +16 -0
- package/dist/core/runner/memory-consolidation.d.ts +0 -2
- package/dist/core/runner/memory-consolidation.js +0 -1
- package/dist/core/runner/prepare-artifact.d.ts +52 -0
- package/dist/core/runner/prepare-artifact.js +63 -0
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
- package/dist/core/runner/prepare-caps-and-workflow.js +2 -3
- package/dist/core/runner/prepare-config-doors.d.ts +3 -3
- package/dist/core/runner/prepare-config-doors.js +5 -2
- package/dist/core/runner/prepare-context-lane.d.ts +2 -2
- package/dist/core/runner/prepare-context-lane.js +2 -13
- package/dist/core/runner/prepare-file-history.d.ts +1 -1
- package/dist/core/runner/prepare-file-history.js +3 -52
- package/dist/core/runner/prepare-hands-readface.d.ts +4 -7
- package/dist/core/runner/prepare-hands-readface.js +3 -2
- package/dist/core/runner/prepare-inherited-gate.d.ts +5 -2
- package/dist/core/runner/prepare-inherited-gate.js +7 -8
- package/dist/core/runner/prepare-memory.d.ts +4 -6
- package/dist/core/runner/prepare-memory.js +4 -2
- package/dist/core/runner/prepare-policy-chain.d.ts +3 -3
- package/dist/core/runner/prepare-policy-chain.js +15 -30
- package/dist/core/runner/prepare-prompt-assembly.js +1 -1
- package/dist/core/runner/prepare-question-face.js +2 -1
- package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
- package/dist/core/runner/prepare-suspend-saga.js +0 -2
- package/dist/core/runner/prepare-task.js +12 -11
- package/dist/core/runner/prepare-wiring-manifest.js +9 -7
- package/dist/core/runner/resume-admission.js +2 -1
- package/dist/core/runner/resume-internals-and-config.js +4 -0
- package/dist/core/runner/retired-runner-deps.d.ts +3 -0
- package/dist/core/runner/retired-runner-deps.js +7 -0
- package/dist/core/runner/run-harness-handlers.js +5 -3
- package/dist/core/runner/run-settle-and-teardown.d.ts +1 -1
- package/dist/core/runner/run-settle-and-teardown.js +3 -1
- package/dist/core/runner/session-file-state-replay.js +3 -3
- package/dist/core/runner/session-rule-policy.js +3 -4
- package/dist/core/runner/stream-halt-verbs.js +1 -1
- package/dist/core/runner/stream-steer-verb.js +1 -4
- package/dist/core/runner/workspace-path.js +3 -0
- package/dist/core/runner-deps.d.ts +30 -49
- package/dist/core/safe-notify.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/sensitive-path-policy.js +11 -12
- package/dist/core/session.d.ts +2 -2
- package/dist/core/skill-tool-specifier.d.ts +1 -1
- package/dist/core/skills-directory.d.ts +1 -1
- package/dist/core/skills-directory.js +4 -3
- package/dist/core/spec-contract.js +5 -4
- package/dist/core/store-contracts/checkpoint-store-contract.js +1 -1
- package/dist/core/strategy-store.d.ts +8 -11
- package/dist/core/task-event.d.ts +20 -17
- package/dist/core/task-limits.d.ts +1 -1
- package/dist/core/task-notification.d.ts +5 -5
- package/dist/core/task-registry-agent.d.ts +5 -5
- package/dist/core/task-registry-monitor.d.ts +2 -2
- package/dist/core/task-registry-shared.d.ts +32 -28
- package/dist/core/task-registry-shared.js +4 -13
- package/dist/core/task-registry.d.ts +8 -8
- package/dist/core/task-result.d.ts +37 -37
- package/dist/core/task-spec.d.ts +5 -5
- package/dist/core/task-stream.d.ts +16 -11
- package/dist/core/tool-catalog-entries.d.ts +1 -0
- package/dist/core/tool-catalog-entries.js +6 -1
- package/dist/core/tool-conformance.d.ts +0 -2
- package/dist/core/tool-conformance.js +1 -3
- package/dist/core/tool-errors.d.ts +5 -0
- package/dist/core/tool-errors.js +1 -0
- package/dist/core/tool-policy.d.ts +66 -22
- package/dist/core/tool-policy.js +31 -5
- package/dist/core/tool-result-budget.d.ts +1 -1
- package/dist/core/tool-result-store.d.ts +11 -11
- package/dist/core/tool-spec.d.ts +34 -38
- package/dist/core/tools.d.ts +2 -2
- package/dist/core/trace.d.ts +12 -15
- package/dist/core/untrusted-text.d.ts +1 -1
- package/dist/core/wiring-manifest.d.ts +4 -3
- package/dist/core/workflow-journal-store.d.ts +11 -11
- package/dist/engine/execution-env/node-execution-env.d.ts +3 -2
- package/dist/engine/execution-env/node-execution-env.js +8 -5
- package/dist/engine/harness/agent-harness.d.ts +47 -4
- package/dist/engine/harness/agent-harness.js +52 -9
- package/dist/engine/loop/agent-loop.js +15 -8
- package/dist/engine/loop/types.d.ts +5 -0
- package/dist/index.d.ts +20 -14
- package/dist/index.js +16 -10
- package/dist/internal/harness.d.ts +1 -0
- package/dist/orchestration/run-spec.d.ts +3 -0
- package/dist/orchestration/run-spec.js +3 -3
- package/dist/orchestration/run-workflow-tool.d.ts +12 -6
- package/dist/orchestration/run-workflow-tool.js +23 -5
- package/dist/orchestration/workflow-primitives.d.ts +4 -2
- package/dist/orchestration/workflow-primitives.js +1 -4
- package/dist/orchestration/workflow-script-store.js +9 -25
- package/dist/orchestration/workflow-types.d.ts +34 -4
- package/dist/orchestration/workflow-types.js +2 -0
- package/dist/orchestration/workflow.d.ts +39 -7
- package/dist/orchestration/workflow.js +237 -113
- package/dist/prompt-assembly/assemble.d.ts +2 -2
- package/dist/prompt-assembly/assemble.js +9 -9
- package/dist/prompt-assembly/composer.d.ts +6 -7
- package/dist/prompt-assembly/composer.js +10 -10
- package/dist/prompt-assembly/epoch.js +1 -1
- package/dist/prompt-assembly/event-registry.d.ts +0 -21
- package/dist/prompt-assembly/packs/sema-default.js +30 -30
- package/dist/prompt-assembly/types.d.ts +14 -14
- package/dist/prompts/coordinator.d.ts +0 -13
- package/dist/prompts/coordinator.js +0 -3
- package/dist/stores/cc/task-list-store.js +2 -10
- package/dist/stores/file/checkpoint-store.js +1 -5
- package/dist/stores/file/file-history-store.js +2 -2
- package/dist/stores/file/fs-atomic.d.ts +15 -18
- package/dist/stores/file/fs-atomic.js +4 -14
- package/dist/stores/file/mailbox-store.d.ts +7 -11
- package/dist/stores/file/mailbox-store.js +4 -11
- package/dist/stores/file/permission-rule-store.d.ts +4 -35
- package/dist/stores/file/permission-rule-store.js +4 -148
- package/dist/tools/artifact/artifact-text.d.ts +62 -0
- package/dist/tools/artifact/artifact-text.js +68 -0
- package/dist/tools/artifact/artifact-tool.d.ts +52 -0
- package/dist/tools/artifact/artifact-tool.js +351 -0
- package/dist/tools/artifact/local-stub.d.ts +26 -0
- package/dist/tools/artifact/local-stub.js +297 -0
- package/dist/tools/fs/bash-readonly-classifier.d.ts +90 -8
- package/dist/tools/fs/bash-readonly-classifier.js +294 -70
- package/dist/tools/fs/fs-bash.d.ts +14 -10
- package/dist/tools/fs/fs-bash.js +50 -33
- package/dist/tools/fs/fs-search-tools.js +5 -2
- package/dist/tools/fs/fs-shared.d.ts +2 -0
- package/dist/tools/fs/fs-shared.js +3 -11
- package/dist/tools/fs/index.d.ts +4 -0
- package/dist/tools/fs/index.js +4 -1
- package/dist/tools/fs/safety.d.ts +117 -1
- package/dist/tools/fs/safety.js +131 -31
- package/dist/tools/fs/search.js +8 -6
- package/package.json +2 -1
- package/test/export-surface.snapshot.json +119 -39
|
@@ -19,7 +19,7 @@ export function streamHaltVerbs(input) {
|
|
|
19
19
|
if (receipt.accepted && !abortOwnedBeforeHalt) {
|
|
20
20
|
h.loop.userHalted = true;
|
|
21
21
|
}
|
|
22
|
-
else {
|
|
22
|
+
else if (!h.loop.userHalted) {
|
|
23
23
|
deliverEngineNotice(runner.deps.onNotice, {
|
|
24
24
|
code: "task.halt_unconsumed",
|
|
25
25
|
message: "a user halt arrived while the run was already ending for its own reason: nothing was cut or stopped " +
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { uuidv7 } from "../../internal/harness.js";
|
|
2
2
|
import { snapshotActorAssertion } from "../../internal/llm.js";
|
|
3
|
-
import {
|
|
3
|
+
import { MAX_STEER_INPUT_ID_CHARS } from "../checkpoint-store.js";
|
|
4
4
|
import { formatHookFeedback, hookSeatExpiredError, runHookSeat } from "../hooks.js";
|
|
5
5
|
import { buildHumanInputEvent, frameMidTurnUserInput, projectHumanInput } from "../human-input-projection.js";
|
|
6
6
|
import { isSystemInjectionPriority, SYSTEM_INJECTION_PRIORITIES } from "../task-notification.js";
|
|
@@ -23,9 +23,6 @@ export function streamSteerVerb(input) {
|
|
|
23
23
|
if (inputId === "" || inputId.length > MAX_STEER_INPUT_ID_CHARS) {
|
|
24
24
|
throw steeringError(`inputId must be a non-empty string of at most ${MAX_STEER_INPUT_ID_CHARS} characters`, "steering.invalid_content");
|
|
25
25
|
}
|
|
26
|
-
if (inputId === LEGACY_PENDING_STEER_INPUT_ID) {
|
|
27
|
-
throw steeringError(`inputId "${LEGACY_PENDING_STEER_INPUT_ID}" is reserved for a pre-queue parked steer and cannot be supplied by a caller`, "steering.invalid_content");
|
|
28
|
-
}
|
|
29
26
|
}
|
|
30
27
|
const priorityIn = options?.priority;
|
|
31
28
|
if (priorityIn !== undefined && !isSystemInjectionPriority(priorityIn)) {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { isWinFormPath, pathFamilyOf } from "../../tools/fs/safety.js";
|
|
1
2
|
export function rebaseWorkspacePath(p, fromRaw, toRaw) {
|
|
2
3
|
if (p.includes("\\") || fromRaw.includes("\\") || toRaw.includes("\\"))
|
|
3
4
|
return p;
|
|
5
|
+
if (pathFamilyOf({ root: fromRaw }) !== "posix" || pathFamilyOf({ root: toRaw }) !== "posix" || isWinFormPath(p))
|
|
6
|
+
return p;
|
|
4
7
|
const stripTrail = (s) => (s.length > 1 && s.endsWith("/") ? stripTrail(s.slice(0, -1)) : s);
|
|
5
8
|
const from = stripTrail(fromRaw);
|
|
6
9
|
const to = stripTrail(toRaw);
|
|
@@ -187,7 +187,7 @@ export interface RunnerDeps {
|
|
|
187
187
|
*/
|
|
188
188
|
readDenyPatterns?: readonly import("../tools/fs/read-deny.js").ReadDenyEntry[];
|
|
189
189
|
/**
|
|
190
|
-
*
|
|
190
|
+
* The deployment's built-in deny-table TIER selection:
|
|
191
191
|
* EXACTLY the listed tiers of
|
|
192
192
|
* {@link import("../tools/fs/read-deny.js").READ_FACE_BUILTIN_DENY_TABLE} are active (`[]` = none —
|
|
193
193
|
* explicit and legal); absent = the default selection
|
|
@@ -203,7 +203,7 @@ export interface RunnerDeps {
|
|
|
203
203
|
*/
|
|
204
204
|
readDenyBuiltinTiers?: readonly string[];
|
|
205
205
|
/**
|
|
206
|
-
*
|
|
206
|
+
* Per-row removal from the built-in deny table by STABLE NAME (= the row's canonical
|
|
207
207
|
* pattern text, e.g. `".ssh"`, `".config/gcloud"`; the admin delete channel), applied after
|
|
208
208
|
* {@link readDenyBuiltinTiers} selection. Naming a row of an inactive tier is a satisfied intent
|
|
209
209
|
* (no-op); a name matching NO table row refuses loudly at prepare (#123 — never silently
|
|
@@ -490,30 +490,6 @@ export interface RunnerDeps {
|
|
|
490
490
|
* in its own audit surface. Values outside the two-member set refuse prepare loudly.
|
|
491
491
|
*/
|
|
492
492
|
onTrackFailure?: "refuse" | "proceed-unprotected";
|
|
493
|
-
/**
|
|
494
|
-
* design/381 §5.3① / §10 S-1 — the ADDITIVE discriminant for the rewind refusal that this engine
|
|
495
|
-
* cannot decide on its own. When a restore finds no boundary for the requested entry, there are
|
|
496
|
-
* two very different worlds: the boundary NEVER existed (those turns ran with no history store, or
|
|
497
|
-
* it was reaped), or it exists in the RETIRED whole-tree snapshot epoch, which the per-edited-file
|
|
498
|
-
* seat deliberately does not restore. The engine holds no whole-tree state, so absent this probe
|
|
499
|
-
* the refusal honestly names BOTH possibilities rather than picking one — the default, and the
|
|
500
|
-
* only honest wording for a deployment that never had a whole-tree epoch at all.
|
|
501
|
-
*
|
|
502
|
-
* A deployment that DOES hold the retired epoch (its assembly layer can ask the old table whether
|
|
503
|
-
* that entry has a legacy row) supplies the bit here, and the refusal splits into the two precise
|
|
504
|
-
* messages. `true` = a whole-tree-era boundary exists for that entry; `false` = it definitively
|
|
505
|
-
* does not; `undefined` = the deployment cannot tell, which reads exactly like an absent probe.
|
|
506
|
-
*
|
|
507
|
-
* Consulted ONLY on the refusal path (never on a successful restore), so a slow probe costs
|
|
508
|
-
* nothing in the ordinary case. It is a DIAGNOSTIC input, never a control input: a probe that
|
|
509
|
-
* throws, hangs past the caller's own patience, or answers a non-boolean cannot change the outcome
|
|
510
|
-
* — the refusal still happens, the wording falls back to the honest both-possibilities form, and
|
|
511
|
-
* the bad value is disclosed through `onError` (phase "rewind") rather than silently absorbed.
|
|
512
|
-
*/
|
|
513
|
-
legacyRewindBoundaryProbe?: (query: {
|
|
514
|
-
sessionId: string;
|
|
515
|
-
entryId: string;
|
|
516
|
-
}) => boolean | undefined | Promise<boolean | undefined>;
|
|
517
493
|
/**
|
|
518
494
|
* design/99 §E6 — DURABLE per-session permission rules (a deny-narrowing folded into the task-time tool
|
|
519
495
|
* policy). Omitted ⇒ the feature is OFF (no rules read, zero behavior change). A deployment supplies a
|
|
@@ -713,7 +689,7 @@ export interface RunnerDeps {
|
|
|
713
689
|
*/
|
|
714
690
|
denialLimit?: import("./auto-mode.js").AutoModeDenialLimitOptions;
|
|
715
691
|
/**
|
|
716
|
-
*
|
|
692
|
+
* OPT IN to recording this arming's serializable criteria (an
|
|
717
693
|
* {@link import("./auto-mode-arming.js").AutoModeArmingRecipe}) on the constraint-chain entries a
|
|
718
694
|
* durable park freezes, so a CROSS-PROCESS redemption can rebuild an equivalent classifier over its
|
|
719
695
|
* own model leg ({@link import("./auto-mode-rebuild.js").rebuildAutoModeDecider}) instead of
|
|
@@ -733,7 +709,7 @@ export interface RunnerDeps {
|
|
|
733
709
|
*/
|
|
734
710
|
persistArming?: boolean;
|
|
735
711
|
/**
|
|
736
|
-
*
|
|
712
|
+
* The deployment's auto-mode SETTINGS GENERATION (a config revision, a settings hash, a
|
|
737
713
|
* publish id — the string is opaque to the engine). Recorded in the arming recipe and compared at
|
|
738
714
|
* rebuild time against the REDEEMING deployment's own: it is a declaration axis that can only make
|
|
739
715
|
* the rebuild stricter (see {@link import("./auto-mode-arming.js").foldAutoModeArming}). Absent =
|
|
@@ -947,7 +923,7 @@ export interface RunnerDeps {
|
|
|
947
923
|
/** design/72 §2.2 (B): deployment default for the suspend-loop cap (see `TaskSpec.maxSuspends`).
|
|
948
924
|
* Default 5 (loose — human-approval flows re-suspend rarely). A task's own `maxSuspends` overrides. */
|
|
949
925
|
maxSuspends?: number;
|
|
950
|
-
/**
|
|
926
|
+
/** Deployment default for the outer per-brain-call guardrail — see
|
|
951
927
|
* `TaskSpec.limits.brainCallGuardrailMs` for the semantics (default one hour; `false`/`0` = off;
|
|
952
928
|
* an invalid value is a fail-loud config error). A task's own `limits.brainCallGuardrailMs`
|
|
953
929
|
* overrides it. Set it here to cover EVERY run of this Runner, delegated children included — a
|
|
@@ -1156,6 +1132,18 @@ export interface RunnerDeps {
|
|
|
1156
1132
|
* `undefined` for a file whose language has no server, and the tool degrades to "fall back to grep". A
|
|
1157
1133
|
* task's own `lspManager` overrides this. Unset ⇒ no `lsp` tool. */
|
|
1158
1134
|
lspManager?: import("./lsp.js").LspServerManager;
|
|
1135
|
+
/**
|
|
1136
|
+
* The Artifacts hosting seat — a storage/service-tier seam of the same family as
|
|
1137
|
+
* {@link checkpointStore} and {@link rosterStore}. Three states, judged once at prepare: ABSENT ⇒ no
|
|
1138
|
+
* `Artifact` tool and no announcement (the default: a library deployment has no hosting); a host
|
|
1139
|
+
* whose `capabilities()` satisfies the declaration invariants ⇒ ONE `Artifact` tool assembled from
|
|
1140
|
+
* that declaration (`plane: "hosted"` mounts the hosted face over the declared action subset,
|
|
1141
|
+
* `plane: "local-stub"` — `localArtifactStub({ dir })` — mounts the publish-only local face with
|
|
1142
|
+
* `eval-stub://` links); a host whose declaration fails an invariant ⇒ no tool and a loud
|
|
1143
|
+
* `config.artifact_host_invalid` notice. Filling the seat IS the authorization to publish: there is
|
|
1144
|
+
* no second switch. `TaskSpec.excludeTools` unmounts the tool as it does any other.
|
|
1145
|
+
*/
|
|
1146
|
+
artifactHost?: import("./artifact-host.js").ArtifactHost;
|
|
1159
1147
|
/**
|
|
1160
1148
|
* Default in-process hooks for all tasks (design/37) — the FULL lifecycle seam of the `Hooks`
|
|
1161
1149
|
* interface, not just the tool-call trio: `preToolUse` (rewrite/restrict args + inject context),
|
|
@@ -1309,27 +1297,20 @@ export interface RunnerDeps {
|
|
|
1309
1297
|
*/
|
|
1310
1298
|
toolResultThresholdChars?: number;
|
|
1311
1299
|
/**
|
|
1312
|
-
* design/374 — microCompact
|
|
1313
|
-
* default ON (`machine: "cc"`, `clearOnRejection: true`); the pre-374 behavior is the explicit
|
|
1314
|
-
* opt-out `{ machine: "legacy", clearOnRejection: false }`.
|
|
1300
|
+
* design/374 — the microCompact knobs. Both default ON (`machine: "cc"`, `clearOnRejection: true`).
|
|
1315
1301
|
*
|
|
1316
|
-
* - `machine`:
|
|
1317
|
-
*
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
*
|
|
1323
|
-
*
|
|
1324
|
-
* fallback re-ordering shipped with this default (blocking-point re-run → in-turn forced
|
|
1325
|
-
* compaction behind the adopt seam → trim demoted to the disaster-only last resort), so an
|
|
1326
|
-
* under-20k refusal no longer falls straight into a message-dropping trim.
|
|
1302
|
+
* - `machine`: `"cc"` (default: the CC 2.1.223 rejection-leg form — keep 5, ≥20k minimum-savings
|
|
1303
|
+
* gate, one deep clear beyond the keep window, CC marker bytes) or `"off"` (no proactive
|
|
1304
|
+
* frontier clearing at all — the D-2 off switch; the machine then gets its ONE shot at the
|
|
1305
|
+
* blocking point instead, the slice-3 arm A, trace trigger `"blocking"`). The vocabulary is
|
|
1306
|
+
* {@link import("./context-edit.js").MICRO_COMPACT_MACHINES}; the guard chain behind either
|
|
1307
|
+
* value is the same (blocking-point run → in-turn forced compaction behind the adopt seam →
|
|
1308
|
+
* trim demoted to the disaster-only last resort), so an under-20k refusal never falls straight
|
|
1309
|
+
* into a message-dropping trim.
|
|
1327
1310
|
* - `clearOnRejection` (MC-R, slice 2): on a provider input-too-long rejection, run ONE cheap
|
|
1328
|
-
* deterministic clear over the rejected projection (same
|
|
1329
|
-
* and retry inside the turn BEFORE the forced-compaction recovery. Default true
|
|
1330
|
-
*
|
|
1331
|
-
* `machine` — an enabled MC-R always clears in the cc form (the rejection arm has no
|
|
1332
|
-
* budget coordinate for the legacy incremental form to stop at). BUDGET ACCOUNTING (design/374
|
|
1311
|
+
* deterministic clear over the rejected projection (the same machine, savings ≥20k or nothing)
|
|
1312
|
+
* and retry inside the turn BEFORE the forced-compaction recovery. Default true. Independent of
|
|
1313
|
+
* `machine` — an enabled MC-R clears even with the frontier pass `"off"`. BUDGET ACCOUNTING (design/374
|
|
1333
1314
|
* §3.2.1, stated here because it is otherwise invisible to a deployment): a successful MC-R
|
|
1334
1315
|
* clear-and-retry SPENDS one attempt of the shared prompt-too-long recovery budget (default 2
|
|
1335
1316
|
* attempts per chain), so a chain that clears and is rejected AGAIN has one forced-compaction
|
|
@@ -1344,7 +1325,7 @@ export interface RunnerDeps {
|
|
|
1344
1325
|
* effect.
|
|
1345
1326
|
*/
|
|
1346
1327
|
microCompact?: {
|
|
1347
|
-
machine?: "
|
|
1328
|
+
machine?: import("./context-edit.js").MicroCompactMachine;
|
|
1348
1329
|
clearOnRejection?: boolean;
|
|
1349
1330
|
};
|
|
1350
1331
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Host-callback isolation, one primitive.
|
|
3
3
|
*
|
|
4
4
|
* The invariant "a callback the HOST handed us must never take the engine down" was implemented by hand at
|
|
5
5
|
* ~20 sites across 10 modules (observer taps, cascade/verify observability hooks, roster eviction sinks, the
|
|
@@ -60,7 +60,7 @@ export declare function dataRootSpellings(explicit: string | undefined): string[
|
|
|
60
60
|
* `env` is the same ExecutionEnv the hands run against (inject the one you pass to the Runner), so
|
|
61
61
|
* canonicalization sees the task's real filesystem (a remote/E2B task resolves in its container).
|
|
62
62
|
* `rootPath` is the FALLBACK base a relative path resolves against (omit = paths resolve as given).
|
|
63
|
-
*
|
|
63
|
+
* When the engine stamps a live cwd onto the request (`ToolCallRequest.cwd` — the tracked
|
|
64
64
|
* directory the shell's `cd` moves and the fs tools resolve with), THAT wins for the call's target, so
|
|
65
65
|
* the guard judges the file the tool will actually write. `rootPath` still serves every deployment that
|
|
66
66
|
* calls this policy outside a Runner.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { homedir } from "node:os";
|
|
2
2
|
import { isAbsolute, join, resolve } from "node:path";
|
|
3
|
-
import { canonicalizeTarget, expandHomeTilde,
|
|
3
|
+
import { canonicalizeTarget, expandHomeTilde, isAbsoluteForFamily, isWinFormPath, pathFamilyOf, writeTargetPath } from "../tools/fs/safety.js";
|
|
4
4
|
import { compileSegmentPattern, matchSegmentPatterns } from "../tools/fs/read-deny.js";
|
|
5
5
|
import { isProtectedWrite, protectivePathTargetOf } from "./tool-registry.js";
|
|
6
6
|
import { pathTargetBaseOf } from "./effective-path-target.js";
|
|
@@ -40,7 +40,7 @@ export function dataRootSpellings(explicit) {
|
|
|
40
40
|
const engineForm = isAbsolute(raw) ? raw : resolve(raw);
|
|
41
41
|
const out = [];
|
|
42
42
|
for (const v of [raw, tilde, engineForm]) {
|
|
43
|
-
const anchored =
|
|
43
|
+
const anchored = isAbsoluteForFamily(pathFamilyOf({ root: v }), v) ? v : resolve(v);
|
|
44
44
|
if (!out.includes(anchored))
|
|
45
45
|
out.push(anchored);
|
|
46
46
|
}
|
|
@@ -82,7 +82,7 @@ export function createSensitivePathPolicy(opts) {
|
|
|
82
82
|
const keys = [];
|
|
83
83
|
for (const spelling of dataRootPaths) {
|
|
84
84
|
try {
|
|
85
|
-
const r = await canonicalizeTarget(opts.env, spelling, signal);
|
|
85
|
+
const r = await canonicalizeTarget(opts.env, spelling, signal, pathFamilyOf({ root: spelling }));
|
|
86
86
|
if (r.ok && !keys.includes(r.key))
|
|
87
87
|
keys.push(r.key);
|
|
88
88
|
}
|
|
@@ -102,16 +102,15 @@ export function createSensitivePathPolicy(opts) {
|
|
|
102
102
|
const path = writeTargetPath(req, protective);
|
|
103
103
|
if (typeof path !== "string" || path.length === 0)
|
|
104
104
|
return { action: "allow" };
|
|
105
|
-
const canon = await canonicalizeTarget(opts.env, path, signal, pathTargetBaseOf(protective, { root: opts.rootPath, cwd: req.cwd }));
|
|
105
|
+
const canon = await canonicalizeTarget(opts.env, path, signal, pathFamilyOf({ root: opts.rootPath, cwd: req.cwd ?? opts.env.cwd }), pathTargetBaseOf(protective, { root: opts.rootPath, cwd: req.cwd }));
|
|
106
106
|
if (!canon.ok) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
return { action: "allow" };
|
|
107
|
+
return {
|
|
108
|
+
action: "deny",
|
|
109
|
+
message: canon.unresolvedSymlink
|
|
110
|
+
? `write to "${path}" is blocked: it is a symlink whose real target could not be resolved (it could point onto a guarded sensitive path)`
|
|
111
|
+
: `write to "${path}" is blocked: its target could not be resolved on this tree (${canon.refused ?? canon.message}), so the sensitive-path guard cannot judge it`,
|
|
112
|
+
decisionReason: "safety",
|
|
113
|
+
};
|
|
115
114
|
}
|
|
116
115
|
let relative = null;
|
|
117
116
|
for (const rootKey of await dataRootKeys(signal)) {
|
package/dist/core/session.d.ts
CHANGED
|
@@ -74,7 +74,7 @@ export interface SessionStoreSummary {
|
|
|
74
74
|
* Absent until a task has run on the session (recorded via {@link SessionStore.noteTaskRun}). */
|
|
75
75
|
lastTaskId?: string;
|
|
76
76
|
/**
|
|
77
|
-
*
|
|
77
|
+
* An ENGINE-minted run identity for this session ({@link import("./types.js").TaskResult.runId}),
|
|
78
78
|
* recorded by the most recent {@link SessionStore.noteTaskRun} write to LAND.
|
|
79
79
|
* {@link lastTaskId} above is `spec.taskId ?? sessionId`, so on the ordinary deployment that supplies no
|
|
80
80
|
* host task id it answers the SESSION's own id: a "last run" handle that names the session it hangs off
|
|
@@ -317,7 +317,7 @@ export declare function boundedTail(pathEntries: readonly SessionTreeEntry[]): {
|
|
|
317
317
|
* times in one prepare (project-memory phase, design/148 center adoption, the epoch-pin
|
|
318
318
|
* discriminator), and an entry-COUNT proxy at ANY of them re-creates the same lie: a host may write
|
|
319
319
|
* session_info / model_change / … rows before the first turn (naming a new chat, recording a model
|
|
320
|
-
* pick), and none of that is evidence of a prior session (
|
|
320
|
+
* pick), and none of that is evidence of a prior session (the count proxy
|
|
321
321
|
* survived at the adoption arm after the pin arm was fixed, silently costing a pre-named session
|
|
322
322
|
* its published center prompt for life). Conversation content — and only that — is the evidence.
|
|
323
323
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Pattern specifiers inside a {@link import("./types.js").SkillManifest}'s `allowTools`.
|
|
3
3
|
*
|
|
4
4
|
* An entry may be a bare tool name (`Bash`) or a name carrying a specifier (`Bash(git:*)`). A bare name
|
|
5
5
|
* claims the whole tool; a specifier claims a NARROWER slice of it. Both directions of that sentence are
|
|
@@ -42,7 +42,7 @@ export type SkillsDirectoryWarningCode =
|
|
|
42
42
|
| "name_mismatch"
|
|
43
43
|
/** Required `description` absent. */
|
|
44
44
|
| "missing_description"
|
|
45
|
-
/**
|
|
45
|
+
/** An `allowed-tools` entry carries a pattern specifier (`Bash(git:*)`) — the scope policy
|
|
46
46
|
* matches names, not patterns, so the entry cannot match and the tool is DISABLED in this skill
|
|
47
47
|
* frame. Disclosed loudly until pattern enforcement lands (the entry is deliberately NOT widened to
|
|
48
48
|
* its base name: that would turn "only git" into "all of Bash"). */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { readFileSync, readdirSync,
|
|
1
|
+
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
2
2
|
import { isAbsolute, join, relative } from "node:path";
|
|
3
|
+
import { physicalPathOf } from "./physical-path.js";
|
|
3
4
|
import { isSkillSpecifierEnforced, parseSkillToolEntry } from "./skill-tool-specifier.js";
|
|
4
5
|
const SKILL_FILE = "SKILL.md";
|
|
5
6
|
const RESOURCE_DIRS = ["assets", "references", "scripts"];
|
|
@@ -200,7 +201,7 @@ function resolveInsideSkill(abs, rel, walk) {
|
|
|
200
201
|
let real;
|
|
201
202
|
let stats;
|
|
202
203
|
try {
|
|
203
|
-
real =
|
|
204
|
+
real = physicalPathOf(abs);
|
|
204
205
|
stats = statSync(abs);
|
|
205
206
|
}
|
|
206
207
|
catch (err) {
|
|
@@ -220,7 +221,7 @@ function resolveInsideSkill(abs, rel, walk) {
|
|
|
220
221
|
function readAttachments(skillDir, skillName, budgetBytes, warn) {
|
|
221
222
|
let realRoot;
|
|
222
223
|
try {
|
|
223
|
-
realRoot =
|
|
224
|
+
realRoot = physicalPathOf(skillDir);
|
|
224
225
|
}
|
|
225
226
|
catch (err) {
|
|
226
227
|
warn({ code: "read_failed", skill: skillName, detail: `the skill directory could not be resolved (${errText(err)}) — attachments skipped` });
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
2
|
import { randomBytes } from "node:crypto";
|
|
3
|
-
import { lstatSync, readFileSync,
|
|
3
|
+
import { lstatSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { dirname, isAbsolute, resolve, sep } from "node:path";
|
|
5
|
+
import { physicalPathOf } from "./physical-path.js";
|
|
5
6
|
const DEFAULT_GATE_TIMEOUT_MS = 60_000;
|
|
6
7
|
const GATE_MAX_BUFFER = 16 * 1024 * 1024;
|
|
7
8
|
const OUTPUT_TAIL_CHARS = 1500;
|
|
@@ -139,8 +140,8 @@ export async function runOracle(gates, cwdRoot, opts) {
|
|
|
139
140
|
continue;
|
|
140
141
|
}
|
|
141
142
|
try {
|
|
142
|
-
const physRoot =
|
|
143
|
-
const phys =
|
|
143
|
+
const physRoot = physicalPathOf(root);
|
|
144
|
+
const phys = physicalPathOf(candidate);
|
|
144
145
|
if (phys !== physRoot && !phys.startsWith(physRoot + sep)) {
|
|
145
146
|
results.push(err(gate, `gate cwd physically escapes the spec root (symlink): ${gate.cwd}`));
|
|
146
147
|
continue;
|
|
@@ -247,7 +248,7 @@ function restoreOneAtomic(p, bytes) {
|
|
|
247
248
|
}
|
|
248
249
|
function safeRealpath(p) {
|
|
249
250
|
try {
|
|
250
|
-
return
|
|
251
|
+
return physicalPathOf(p);
|
|
251
252
|
}
|
|
252
253
|
catch {
|
|
253
254
|
return undefined;
|
|
@@ -185,7 +185,7 @@ export async function checkpointStoreContract(make, runAssertion) {
|
|
|
185
185
|
assert.equal(q[0].text, "go");
|
|
186
186
|
assert.equal(q[0].trusted, false);
|
|
187
187
|
assert.equal(q[0].seq, 1);
|
|
188
|
-
assert.equal((await store.get(cp.token)).state
|
|
188
|
+
assert.equal("pendingSteer" in (await store.get(cp.token)).state, false);
|
|
189
189
|
});
|
|
190
190
|
run("setPendingSteer APPENDS: two steers both survive in issue order, each keeping its frozen trust", async () => {
|
|
191
191
|
const store = make();
|
|
@@ -156,19 +156,16 @@ export declare function validateStrategyForWrite(s: StoredStrategy): void;
|
|
|
156
156
|
* source for the in-memory and file-backed stores, so retrieval semantics cannot fork between
|
|
157
157
|
* backends.
|
|
158
158
|
*
|
|
159
|
-
* TWO acceptance arms, OR-combined
|
|
159
|
+
* TWO acceptance arms, OR-combined (retrieval semantics, pinned):
|
|
160
160
|
* - full arm — every significant term (alphanumeric AND CJK) present in the problem;
|
|
161
|
-
* -
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* have silently un-matched that pair — a recall regression hiding inside a recall fix. Keeping
|
|
165
|
-
* the legacy arm costs precision only relative to a strictness nobody ever had.
|
|
161
|
+
* - alphanumeric arm — every significant ALPHANUMERIC term present (and there is ≥1), so a mixed
|
|
162
|
+
* query ("请帮我 extract tables from report.pdf") still matches an English-only stored problem —
|
|
163
|
+
* requiring the CJK boilerplate too would un-match that pair.
|
|
166
164
|
*
|
|
167
|
-
* ACCEPTED COST (documented, pinned): via the
|
|
168
|
-
* match can hit a problem whose CJK terms CONFLICT (提取 X vs 删除 X)
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* injection audit); tightening precision is a measured-recalibration change, not a retrieval patch.
|
|
165
|
+
* ACCEPTED COST (documented, pinned): via the alphanumeric arm, a mixed query whose alphanumeric
|
|
166
|
+
* terms all match can hit a problem whose CJK terms CONFLICT (提取 X vs 删除 X). The mitigation is
|
|
167
|
+
* the surrounding depth (negation preamble, verify-before-use instruction, injection audit);
|
|
168
|
+
* tightening precision is a measured-recalibration change, not a retrieval patch.
|
|
172
169
|
*/
|
|
173
170
|
export declare function compileStrategyQuery(query: string): ((problem: string) => boolean) | null;
|
|
174
171
|
export declare function normalizeStrategyText(s: string): string;
|
|
@@ -64,7 +64,7 @@ export interface TaskEventIdentity {
|
|
|
64
64
|
*/
|
|
65
65
|
export type BrainStatusPhase = "rate_limited" | "retrying" | "reconnecting" | "circuit_open"
|
|
66
66
|
/**
|
|
67
|
-
*
|
|
67
|
+
* TERMINAL frames closing a retry sequence. Without them a consumer that rendered a
|
|
68
68
|
* `rate_limited`/`retrying`/`reconnecting` frame has nothing telling it the wait is over, so the
|
|
69
69
|
* warning row stays pinned until the next unrelated event. Exactly one terminal frame is emitted,
|
|
70
70
|
* and only for a call that actually waited (a retry wait, or a `waiting_first_token` trail —
|
|
@@ -75,7 +75,7 @@ export type BrainStatusPhase = "rate_limited" | "retrying" | "reconnecting" | "c
|
|
|
75
75
|
*/
|
|
76
76
|
| "recovered" | "gave_up"
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
78
|
+
* The first-token WAIT, before any failure: a first-token watchdog is armed
|
|
79
79
|
* (`firstTokenTimeoutMs > 0`) and nothing has arrived yet. Emitted once the wait has lasted
|
|
80
80
|
* `WAITING_FIRST_TOKEN_AFTER_MS` and re-emitted every `WAITING_FIRST_TOKEN_EVERY_MS` while it goes
|
|
81
81
|
* on, carrying {@link BrainStatus.elapsedMs} and {@link BrainStatus.timeoutMs}; never carries a
|
|
@@ -126,7 +126,7 @@ export interface BrainStatus {
|
|
|
126
126
|
detail?: string;
|
|
127
127
|
/** Seconds until the brain's next retry attempt (from the honored backoff / `Retry-After`), when known. */
|
|
128
128
|
retryInSec?: number;
|
|
129
|
-
/**
|
|
129
|
+
/** Millisecond precision of {@link retryInSec}, for a client that renders a countdown.
|
|
130
130
|
* A wait longer than the re-announce slice is re-emitted with the REMAINING time, so a consumer
|
|
131
131
|
* that simply overwrites its row always shows a live number instead of a stale one. */
|
|
132
132
|
retryInMs?: number;
|
|
@@ -149,17 +149,17 @@ export interface BrainStatus {
|
|
|
149
149
|
* the authoritative RELATIVE quantity, and this seat is the absolute convenience derived from it.
|
|
150
150
|
*/
|
|
151
151
|
retryAtMs?: number;
|
|
152
|
-
/**
|
|
152
|
+
/** On a `waiting_first_token` frame: how long the first token has been awaited, ms, at the
|
|
153
153
|
* moment the frame is emitted (the emitting process's clock; approximate across a hop). Absent on
|
|
154
154
|
* every other phase. */
|
|
155
155
|
elapsedMs?: number;
|
|
156
|
-
/**
|
|
156
|
+
/** On a `waiting_first_token` frame: the armed first-token watchdog, ms — the wait's ceiling,
|
|
157
157
|
* so a consumer can render "45s of 120s". Absent on every other phase. */
|
|
158
158
|
timeoutMs?: number;
|
|
159
|
-
/**
|
|
159
|
+
/** 1-based index of the attempt that just failed (the wait precedes attempt `attempt + 1`);
|
|
160
160
|
* same numbering as the `brain.retry` telemetry frame. Absent on frames that are not a retry wait. */
|
|
161
161
|
attempt?: number;
|
|
162
|
-
/**
|
|
162
|
+
/** The retry budget of THIS lane, so a consumer can render "attempt 3 of 10". Lane, not
|
|
163
163
|
* engine: a failure class served by a shorter ladder reports that ladder's budget, so the fraction a
|
|
164
164
|
* consumer renders is the one actually in force rather than the engine-wide ceiling. */
|
|
165
165
|
maxRetries?: number;
|
|
@@ -259,7 +259,7 @@ export type TaskEvent = ({
|
|
|
259
259
|
delta: string;
|
|
260
260
|
} & TaskEventIdentity) | ({
|
|
261
261
|
/**
|
|
262
|
-
*
|
|
262
|
+
* The assistant's streaming PROSE SEGMENT is COMPLETE: the model closed the text content
|
|
263
263
|
* block whose bytes just streamed as `text_delta`s. This is the explicit segment boundary a
|
|
264
264
|
* REMOTE consumer needs so it never has to guess segment ends from wire silence (the idle-flush
|
|
265
265
|
* heuristic this retires cut one slow-model reply into N fragments). CC-aligned: CC's agent
|
|
@@ -449,7 +449,7 @@ export type TaskEvent = ({
|
|
|
449
449
|
*/
|
|
450
450
|
truncated?: boolean;
|
|
451
451
|
/**
|
|
452
|
-
*
|
|
452
|
+
* Present iff {@link truncated}: the TRUE original size (characters) of
|
|
453
453
|
* the content this event's {@link output} was degraded from — for a string result, the string's own
|
|
454
454
|
* length; for a non-string result (a blocks array), the SUM of each block's own true size (a text
|
|
455
455
|
* block's `.text.length`; an image/document block's `.data.length`, i.e. its base64 payload) — never
|
|
@@ -469,7 +469,7 @@ export type TaskEvent = ({
|
|
|
469
469
|
totalChars?: number;
|
|
470
470
|
} & TaskEventIdentity) | ({
|
|
471
471
|
/**
|
|
472
|
-
*
|
|
472
|
+
* Context occupancy at a compaction boundary, emitted on EVERY
|
|
473
473
|
* boundary (not only when a compaction fires). The three numbers are the engine's own trigger
|
|
474
474
|
* inputs, verbatim: `usedTokens > compactAtTokens` IS the predicate `shouldCompact` evaluates, so a
|
|
475
475
|
* consumer's "context is N% full" indicator and the moment compaction actually fires can never
|
|
@@ -490,15 +490,17 @@ export type TaskEvent = ({
|
|
|
490
490
|
/**
|
|
491
491
|
* Per-turn token usage + cost (the turn that just ended), for live per-turn accounting / a trace UI
|
|
492
492
|
* (service [41]). Re-priced in core from injected pricing (authoritative, like `TaskResult.stats`).
|
|
493
|
-
*
|
|
493
|
+
* ALWAYS present: a turn that produced no provider usage frame carries the counted ZEROS beside
|
|
494
|
+
* `usageMissing: true` — zero is unknown, not free, the one law `TaskResult.stats` states (numbers
|
|
495
|
+
* always present, the flag says they under-count), so a consumer handles ONE frame shape.
|
|
494
496
|
*
|
|
495
|
-
*
|
|
497
|
+
* `inputTokens` is the cache-MISS count (Anthropic-protocol shape, matches
|
|
496
498
|
* `stats.promptTokens` / the tracer's `brain.call.promptTokens`); `totalInputTokens` is the
|
|
497
499
|
* cache-INCLUSIVE total (`inputTokens + cacheReadTokens + cacheWriteTokens`) that cost is computed
|
|
498
500
|
* from. Sum `totalInputTokens` for context/window/spend views; read `inputTokens` only where the
|
|
499
501
|
* protocol's `input_tokens` is meant. Up to 2.13.x `inputTokens` carried the total.
|
|
500
502
|
*/
|
|
501
|
-
usage
|
|
503
|
+
usage: {
|
|
502
504
|
/** Cache-MISS input tokens for this turn (the Anthropic protocol's `input_tokens` meaning;
|
|
503
505
|
* matches `stats.promptTokens` / `brain.call.promptTokens`). **Up to 2.13.x this field
|
|
504
506
|
* carried the cache-INCLUSIVE total** (RB-457-a, BREAKING at 3.0.0) — that value now lives
|
|
@@ -514,9 +516,10 @@ export type TaskEvent = ({
|
|
|
514
516
|
costMicroUsd: number;
|
|
515
517
|
};
|
|
516
518
|
/** TB 尸检 T1-5: set when the turn ended WITHOUT a provider usage frame (e.g. a degenerate-repetition
|
|
517
|
-
* cutoff cancelled the stream before usage arrived)
|
|
518
|
-
* UNKNOWN — not
|
|
519
|
-
* than polluting the single-source accounting
|
|
519
|
+
* cutoff cancelled the stream before usage arrived) or the brain flagged its frame unknown. Consumers
|
|
520
|
+
* must treat `usage` as UNKNOWN — its zeros are not a measured 0 (the provider still served the
|
|
521
|
+
* request; `stats` under-counts it honestly rather than polluting the single-source accounting
|
|
522
|
+
* with an estimate). Absent on a measured turn (never `false`). */
|
|
520
523
|
usageMissing?: true;
|
|
521
524
|
/** TB telemetry B1: the NORMALIZED finish reason of the turn's LAST model call —
|
|
522
525
|
* the engine's `AssistantMessage.stopReason` (`StopReason`: `"stop"`/`"length"`/`"toolUse"`/
|
|
@@ -789,7 +792,7 @@ export type TaskEvent = ({
|
|
|
789
792
|
*/
|
|
790
793
|
taskType?: DelegationTaskType;
|
|
791
794
|
/**
|
|
792
|
-
*
|
|
795
|
+
* The registry row's STOP-CYCLE generation this tick reports from (fresh
|
|
793
796
|
* spawn = 1, every launched revival bumps it), the same counter `TaskNotificationPayload.seq`
|
|
794
797
|
* and `BackgroundChildEvent.seq` already speak — one axis, not a third spelling. It answers
|
|
795
798
|
* the one question a fleet consumer cannot otherwise decide when a frame arrives late: "late
|
|
@@ -92,7 +92,7 @@ export interface TaskLimits {
|
|
|
92
92
|
atCostFraction: number;
|
|
93
93
|
};
|
|
94
94
|
/**
|
|
95
|
-
*
|
|
95
|
+
* The OUTER wall on how long the engine waits for a single brain
|
|
96
96
|
* call, in ms. Default {@link import("../brain/timeout.js").BRAIN_CALL_GUARDRAIL_DEFAULT_MS}
|
|
97
97
|
* (one hour); `false` or `0` switches it off; any other non-positive / non-finite value is a
|
|
98
98
|
* config error (fail-loud, never folded to a default). Overrides `RunnerDeps.brainCallGuardrailMs`.
|
|
@@ -279,7 +279,7 @@ export interface SystemInjection<TPayload = unknown> {
|
|
|
279
279
|
* repeat, or refusing the repeat typed, would each turn a dedup fold into a delivery mutation. */
|
|
280
280
|
export declare function taskNotificationDedupKey(n: Pick<TaskNotificationPayload, "task_id" | "task_type" | "status" | "seq">): string;
|
|
281
281
|
/**
|
|
282
|
-
*
|
|
282
|
+
* The lane-scoped identity of a task, extracted from {@link taskNotificationDedupKey} so every
|
|
283
283
|
* place that treats "same task" as one bucket applies the SAME lane rule.
|
|
284
284
|
*
|
|
285
285
|
* The dedup key had the lane segment from the start; three other sites did not — the pending store's
|
|
@@ -397,7 +397,7 @@ export interface DrainedPendingNotifications {
|
|
|
397
397
|
priorities?: Map<TaskNotificationPayload, SystemInjectionPriority>;
|
|
398
398
|
/** task_id → notifications evicted by the bounds while pending (never delivered). `taskType` remembers
|
|
399
399
|
* the victim's lane so a survivors-none disclosure can still render an honest synthetic payload. */
|
|
400
|
-
/**
|
|
400
|
+
/** Keyed by {@link taskNotificationLaneKey}, NOT the bare `task_id` — the external lane's ids are
|
|
401
401
|
* caller-supplied, so one bare-id row could cover two lanes and name only one of their types. `taskId`
|
|
402
402
|
* carries the victim's real id back out (the lane key is process-internal and must never be rendered). */
|
|
403
403
|
dropped: Map<string, {
|
|
@@ -406,7 +406,7 @@ export interface DrainedPendingNotifications {
|
|
|
406
406
|
taskId: string;
|
|
407
407
|
}>;
|
|
408
408
|
/**
|
|
409
|
-
*
|
|
409
|
+
* Notifications lost when this whole SESSION was evicted by the
|
|
410
410
|
* session-count cap, kept OUT of `dropped`. RB-91 folded them in under a `"(evicted-session)"` string
|
|
411
411
|
* key, which put a session-level fact into a per-task ledger and broke twice for it: the key could
|
|
412
412
|
* collide with a real, free-form external `task_id` (merging two unrelated counts and mislabelling the
|
|
@@ -421,7 +421,7 @@ export declare class PendingSessionNotifications {
|
|
|
421
421
|
/** Whole sessions evicted by {@link MAX_PENDING_SESSIONS} (their pendings were never delivered). */
|
|
422
422
|
droppedSessions: number;
|
|
423
423
|
/**
|
|
424
|
-
*
|
|
424
|
+
* A TOMBSTONE per whole-session eviction, so that session's next drain
|
|
425
425
|
* can still say what it lost. The two item-level caps disclose their drops per task (they mutate a
|
|
426
426
|
* surviving session's `dropped` map), but the session-count cap deleted the whole record and only
|
|
427
427
|
* bumped a global, unattributed counter — from the evicted session's point of view its next drain
|
|
@@ -430,7 +430,7 @@ export declare class PendingSessionNotifications {
|
|
|
430
430
|
* Bounded like the sessions map itself (a tombstone is two numbers and a lane tag).
|
|
431
431
|
*/
|
|
432
432
|
private readonly evictedSessions;
|
|
433
|
-
/**
|
|
433
|
+
/** Whole-session losses whose tombstone was itself evicted — the count survives, the attribution
|
|
434
434
|
* does not. Surfaced on the next session-level disclosure so it is never simply forgotten. */
|
|
435
435
|
private unattributedDrops;
|
|
436
436
|
pend(sessionId: string, n: TaskNotificationPayload, priority?: SystemInjectionPriority): void;
|
|
@@ -173,7 +173,7 @@ export declare function parkBackgroundAgentLane(core: DurableAgentCore, id: stri
|
|
|
173
173
|
* `excludeWriterId` = this instance's writerId, so foreign (dead-process) rows are cleaned
|
|
174
174
|
* without ever touching a row this process is live-managing.
|
|
175
175
|
*
|
|
176
|
-
*
|
|
176
|
+
* The live half used to skip EVERY non-expired/missing state, `resolved` included, and
|
|
177
177
|
* that was the whole zombie: a parked row whose checkpoint was decided by the task-level
|
|
178
178
|
* `resumeCheckpoint` leg (a serving layer's documented fallback when its parked-row discriminator
|
|
179
179
|
* misses) is decided but still says `parked`, its side effects already executed by a path that never
|
|
@@ -321,7 +321,7 @@ export declare function resolveBackgroundAgentByNameLane(core: DurableAgentCore,
|
|
|
321
321
|
* a capacity/pin failure (or plain session-scope) could never drain. No-op on unknown ids. */
|
|
322
322
|
export declare function markRetainedContinuationLane(core: DurableAgentCore, id: string): void;
|
|
323
323
|
/**
|
|
324
|
-
*
|
|
324
|
+
* The stop-cycle generation of the RUN BEING SPAWNED under this row (the same counter the
|
|
325
325
|
* register/revive lanes keep on the handle: fresh spawn = 1, durable-seeded revive = the claimed
|
|
326
326
|
* row's seq, in-memory wake = the bump). The spawn lanes read it ONCE, right after registering, to
|
|
327
327
|
* thread into the child's `RunInternals.cycleSeq` — one authoritative source instead of each lane
|
|
@@ -444,7 +444,7 @@ export declare function deliverToRunningAgentLane(core: DurableAgentCore, id: st
|
|
|
444
444
|
* very rows a retry needs. The task faces' split lives in `runningAgentFooterLane` (RB-332). */
|
|
445
445
|
export declare function runningBackgroundAgentLabelsLane(core: DurableAgentCore, access: TaskAccess): string[];
|
|
446
446
|
/**
|
|
447
|
-
*
|
|
447
|
+
* The not-found FOOTER's two rows, split the way CC 220 assembles them:
|
|
448
448
|
* - `named` = CC `uG_` (220:467941-467953): the agentNameRegistry's KEYS whose task is a running local
|
|
449
449
|
* agent, listed as BARE NAMES — the string a retry should pass verbatim. sema's counterpart
|
|
450
450
|
* of "has a registry entry" is the handle carrying an explicit `name` (spawn-time label),
|
|
@@ -461,7 +461,7 @@ export declare function runningAgentFooterLane(core: DurableAgentCore, access: T
|
|
|
461
461
|
named: string[];
|
|
462
462
|
background: string[];
|
|
463
463
|
};
|
|
464
|
-
/**
|
|
464
|
+
/** The not-found TAIL both task faces share (CC `rxo`, appended by `uMs` for TaskStop
|
|
465
465
|
* and by `xwd` 220:472095-472097 for TaskOutput). Empty string when the caller has nothing running. */
|
|
466
466
|
export declare function notFoundRunningAgentsTail(footer: {
|
|
467
467
|
named: string[];
|
|
@@ -543,7 +543,7 @@ export declare function serveDurableAgentRowLane(row: BackgroundAgentRecord): Un
|
|
|
543
543
|
*/
|
|
544
544
|
export declare function spillClippedAgentResult(handle: BackgroundAgentTaskHandle, full: string, clipped: string, store: ToolResultStore | undefined, sessionId: string | undefined): Promise<string>;
|
|
545
545
|
export declare function pollBackgroundAgentLane(handle: BackgroundAgentTaskHandle, deadline?: number, signal?: AbortSignal,
|
|
546
|
-
/**
|
|
546
|
+
/** Mirrors {@link import("./types.js").TaskSpec.oneShot} (see
|
|
547
547
|
* {@link import("./task-registry.js").TaskToolOptions.oneShot} for the full contract): this run has
|
|
548
548
|
* no later turn for an async background notification to land in, so the still-running body must
|
|
549
549
|
* not teach "you will be notified when it completes". */
|