@sema-agent/core 7.0.2 → 7.2.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 +58 -0
- package/dist/agents/cross-session-envelope.d.ts +138 -0
- package/dist/agents/cross-session-envelope.js +191 -0
- package/dist/agents/cross-session-judge.d.ts +119 -0
- package/dist/agents/cross-session-judge.js +184 -0
- package/dist/agents/cross-session-ref.d.ts +52 -0
- package/dist/agents/cross-session-ref.js +64 -0
- package/dist/agents/repair-loop.d.ts +8 -7
- package/dist/agents/roster-store.d.ts +7 -2
- package/dist/agents/send-message-tool.d.ts +13 -0
- package/dist/agents/send-message-tool.js +36 -12
- package/dist/brain/errors.d.ts +18 -0
- package/dist/brain/errors.js +3 -0
- package/dist/brain/stream-engine.js +6 -4
- package/dist/core/checkpoint-store.d.ts +189 -3
- package/dist/core/checkpoint-store.js +56 -16
- package/dist/core/context-edit.d.ts +3 -0
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +4 -0
- package/dist/core/hooks.d.ts +34 -7
- package/dist/core/hooks.js +14 -8
- package/dist/core/image-downsample.d.ts +4 -3
- package/dist/core/permission-rule-consent.d.ts +72 -23
- package/dist/core/permission-rule-consent.js +115 -26
- package/dist/core/permission-rule-model.d.ts +245 -51
- package/dist/core/permission-rule-model.js +312 -54
- package/dist/core/permission-rule-org.js +13 -6
- package/dist/core/remote-env.d.ts +8 -1
- package/dist/core/roles.d.ts +30 -8
- package/dist/core/roles.js +12 -8
- package/dist/core/runner/assemble-result.js +2 -1
- package/dist/core/runner/prepare-task.d.ts +41 -2
- package/dist/core/runner/prepare-task.js +353 -152
- package/dist/core/runner/prepare-workspace-restore.d.ts +6 -1
- package/dist/core/runner/prepare-workspace-restore.js +2 -1
- package/dist/core/runner/runtask.d.ts +12 -3
- package/dist/core/runner/runtask.js +45 -7
- package/dist/core/safety-axis-vocab.d.ts +1 -1
- package/dist/core/strategy-store.d.ts +4 -1
- package/dist/core/task-notification.d.ts +64 -5
- package/dist/core/task-notification.js +25 -4
- package/dist/core/task-registry-shared.d.ts +7 -3
- package/dist/core/tool-errors.d.ts +1 -1
- package/dist/core/tool-policy.d.ts +51 -7
- package/dist/core/tool-policy.js +63 -9
- package/dist/core/types.d.ts +110 -9
- package/dist/core/untrusted-text.js +17 -1
- package/dist/engine/compaction/compaction.js +6 -2
- package/dist/engine/harness/agent-harness.d.ts +28 -6
- package/dist/engine/harness/agent-harness.js +34 -2
- package/dist/engine/harness/messages.js +4 -0
- package/dist/engine/harness/types.d.ts +37 -0
- package/dist/engine/harness/types.js +5 -0
- package/dist/engine/session/session.js +3 -2
- package/dist/index.d.ts +6 -3
- package/dist/index.js +5 -2
- package/dist/internal/harness.d.ts +1 -0
- package/dist/internal/harness.js +1 -0
- package/dist/orchestration/builtin-workflows.d.ts +17 -9
- package/dist/orchestration/run-workflow-tool.js +7 -2
- package/dist/orchestration/workflow-governance.js +1 -1
- package/dist/orchestration/workflow-types.d.ts +1 -0
- package/dist/orchestration/workflow.js +1 -1
- package/dist/stores/file/mailbox-store.d.ts +2 -1
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +125 -1
package/dist/core/types.d.ts
CHANGED
|
@@ -3539,6 +3539,16 @@ export interface TaskResult {
|
|
|
3539
3539
|
* gate): a halt landing AFTER the abort signal already fired neither cut nor stopped anything —
|
|
3540
3540
|
* that ending belongs to the abort, and this seat stays ABSENT rather than signing someone
|
|
3541
3541
|
* else's stop with the halt caller's name. Absent everywhere else; never `false`.
|
|
3542
|
+
*
|
|
3543
|
+
* design/384 slice 2 (TRANSITIONAL narrowing): a `"suspended"` / `"needs_review"` terminal does
|
|
3544
|
+
* NOT carry this seat even when a halt was accepted — those statuses mean a durable park WON its
|
|
3545
|
+
* race with the halt (the row is committed and redeemable; the run is waiting to continue), and
|
|
3546
|
+
* "stopped by the person" beside "waiting to resume" was a self-contradictory pair. The halt's
|
|
3547
|
+
* own receipt (`{turnCut}`) and the `task.turn_interrupted` notice still stand — a seat WAS cut.
|
|
3548
|
+
* Transitional: once halt-boundary source accounting lands (slice 3), the boundary-CONSUMED
|
|
3549
|
+
* suspension arms flip to signing (a probe pinning today's suppressed shape goes red then, by
|
|
3550
|
+
* design). The pass-through law is untouched for every OTHER terminal: a halt racing a real
|
|
3551
|
+
* failure/limit — including one that outranks a committed park — still signs.
|
|
3542
3552
|
*/
|
|
3543
3553
|
haltedByUser?: true;
|
|
3544
3554
|
/**
|
|
@@ -3941,8 +3951,11 @@ export interface TaskEventIdentity {
|
|
|
3941
3951
|
}
|
|
3942
3952
|
/**
|
|
3943
3953
|
* design/99 §E3/§E10 — a BRAIN-LAYER liveness phase, surfaced so a UI can show why a
|
|
3944
|
-
* turn is stalled (the brain otherwise absorbs these silently in its connect/retry loop).
|
|
3945
|
-
*
|
|
3954
|
+
* turn is stalled (the brain otherwise absorbs these silently in its connect/retry loop). The PHASE
|
|
3955
|
+
* itself is provider-NEUTRAL — a graduated bucket this engine mints, never a provider taxonomy or a
|
|
3956
|
+
* `stop_reason`. The one provider-stated number that does cross this channel is the failing attempt's
|
|
3957
|
+
* HTTP status, and it travels on its own named seat ({@link BrainStatus.errorStatus}) in the retry
|
|
3958
|
+
* context only; the phase and the {@link BrainStatus.detail} hint stay free of it.
|
|
3946
3959
|
* A CLOSED union (type-safe) covering the core brain layer; a deployment that surfaces its OWN states
|
|
3947
3960
|
* (e.g. E25 token-refresh `authenticating`) does so on its own channel, not by widening this.
|
|
3948
3961
|
*/
|
|
@@ -3960,8 +3973,10 @@ export type BrainStatusPhase = "rate_limited" | "retrying" | "reconnecting" | "c
|
|
|
3960
3973
|
* WHY a retry wait is happening, as a closed, provider-NEUTRAL bucket — the companion to
|
|
3961
3974
|
* {@link BrainStatusPhase}, which says what the brain is doing about it. A consumer rendering an
|
|
3962
3975
|
* unattended progress line ("no answer for three minutes") needs the reason, and until this existed the
|
|
3963
|
-
* only carriers of it were the HTTP status and the syscall code, neither of which
|
|
3964
|
-
*
|
|
3976
|
+
* only carriers of it were the HTTP status and the syscall code, neither of which crossed this channel
|
|
3977
|
+
* at the time. (The status has since gained its own seat, {@link BrainStatus.errorStatus}; this bucket
|
|
3978
|
+
* remains the reason a consumer RENDERS, and it is the only carrier for the transport classes, which
|
|
3979
|
+
* have no status at all.) Values are about the SHAPE of the failure, never its provider taxonomy:
|
|
3965
3980
|
* - `connect_refused` — the attempt got a definite negative about the target itself (nothing accepts
|
|
3966
3981
|
* at that address, or the name has no address). This is the class the SHORT retry lane serves.
|
|
3967
3982
|
* - `transport` — any other transport-level failure: a connect timeout, a reset, a mid-stream
|
|
@@ -3977,7 +3992,11 @@ export type BrainRetryErrClass = "connect_refused" | "transport" | "rate_limit"
|
|
|
3977
3992
|
/** design/99 §E3/§E10 — the payload of a {@link TaskEvent} `status` event (and the brain→runner signal). */
|
|
3978
3993
|
export interface BrainStatus {
|
|
3979
3994
|
phase: BrainStatusPhase;
|
|
3980
|
-
/** Optional neutral, human-readable hint
|
|
3995
|
+
/** Optional neutral, human-readable hint. Stays free of provider/HTTP detail even now that
|
|
3996
|
+
* {@link errorStatus} exists: the machine-readable status has its own seat, and interpolating it
|
|
3997
|
+
* into the prose too would make one fact travel in two spellings a consumer has to reconcile.
|
|
3998
|
+
* (CC parity: its own retry banner renders a TRANSLATED sentence — "No response from API",
|
|
3999
|
+
* "Connection dropped" — while the raw status rides the structured key beside it.) */
|
|
3981
4000
|
detail?: string;
|
|
3982
4001
|
/** Seconds until the brain's next retry attempt (from the honored backoff / `Retry-After`), when known. */
|
|
3983
4002
|
retryInSec?: number;
|
|
@@ -4015,6 +4034,41 @@ export interface BrainStatus {
|
|
|
4015
4034
|
* the engine classified; absent on frames that are not a retry wait (`recovered`/`gave_up`) and on a
|
|
4016
4035
|
* `circuit_open` fast-fail, which is a local verdict rather than an observed failure. */
|
|
4017
4036
|
errClass?: BrainRetryErrClass;
|
|
4037
|
+
/**
|
|
4038
|
+
* #506 ㋑ — the HTTP status of the attempt that just failed, on the frame announcing the RETRY of it.
|
|
4039
|
+
* The one provider-stated number this channel carries; everything else about the failure still
|
|
4040
|
+
* crosses as the engine's own graduated buckets ({@link phase} / {@link errClass}).
|
|
4041
|
+
*
|
|
4042
|
+
* WHY IT IS HERE AT ALL, given the channel spent its life refusing it: a UI that must tell an
|
|
4043
|
+
* operator whether to wait or to go fix something needs the status, and the two neutral buckets
|
|
4044
|
+
* cannot supply it — `rate_limit` covers a 429 the provider will clear on its own AND a 429 that
|
|
4045
|
+
* means the account is out of quota, and `server` covers a 500 alongside a 503 behind a load
|
|
4046
|
+
* balancer. CC states the same number on the same occasion (`system/api_retry.error_status`, read
|
|
4047
|
+
* off `APIError.status`), so a serving layer forwarding this frame no longer has to choose between
|
|
4048
|
+
* matching CC's payload and honoring this channel's contract.
|
|
4049
|
+
*
|
|
4050
|
+
* PRESENCE — an api_retry context whose attempt got a response that NAMES the failure, and nothing
|
|
4051
|
+
* else. Present on the connect-ladder retry wait (`rate_limited` / `retrying` / `reconnecting` when
|
|
4052
|
+
* a response came back) and on the output-cap re-send (the provider's own 400). ABSENT — never
|
|
4053
|
+
* zeroed, never null — for:
|
|
4054
|
+
* · a transport failure (`connect_refused` / `transport` at the connect leg): no response existed,
|
|
4055
|
+
* so no status was ever stated. This is the arm CC spells as an explicit `null`; here it is
|
|
4056
|
+
* absence, for the same reason every other seat on this interface uses absence, and the fact is
|
|
4057
|
+
* still TOTAL rather than guessable — {@link errClass} names those two classes by construction.
|
|
4058
|
+
* · a mid-stream tear (tiers B/C): its response's own status was a SUCCESS, and a status that
|
|
4059
|
+
* failed nothing must not be published as the cause of a retry.
|
|
4060
|
+
* · a `circuit_open` fast-fail: a local verdict, nothing was sent, nobody answered.
|
|
4061
|
+
* · the terminal `recovered` / `gave_up` frames: they announce no attempt.
|
|
4062
|
+
* Same "only a status that names the failure travels" predicate as the assistant frame's
|
|
4063
|
+
* {@link AssistantMessage.apiErrorStatus} (one helper, both sites) — a 2xx never travels here either,
|
|
4064
|
+
* which is reachable on this path via a provider's own `x-should-retry` verdict on a success status.
|
|
4065
|
+
*
|
|
4066
|
+
* OPTIONAL, not CC's nullable-REQUIRED, and the difference is CC's own: CC dedicates a whole message
|
|
4067
|
+
* (`system/api_retry`) to the retry occasion and can therefore require the key on it, while this
|
|
4068
|
+
* interface is ONE shape shared by every phase — the same geometry as CC's shared
|
|
4069
|
+
* `control_request_progress` frame, where CC itself makes the key optional.
|
|
4070
|
+
*/
|
|
4071
|
+
errorStatus?: number;
|
|
4018
4072
|
}
|
|
4019
4073
|
/**
|
|
4020
4074
|
* design/97 CORE-8 (③): one lightweight TOOL-ACTIVITY beat surfaced from a running task, for a per-agent live
|
|
@@ -4575,7 +4629,9 @@ export type TaskEvent = ({
|
|
|
4575
4629
|
* silently (a 429 rate-limit / a 5xx or network retry / a reconnect / an open circuit breaker). Emitted
|
|
4576
4630
|
* the moment the brain decides to wait/retry, carrying the graduated {@link BrainStatusPhase} + an
|
|
4577
4631
|
* optional `retryInSec` so a UI can show "rate limited, retrying in Ns". EPHEMERAL — a pure liveness
|
|
4578
|
-
* signal, never persisted or replayed on resume.
|
|
4632
|
+
* signal, never persisted or replayed on resume. The phase and the hint are provider-neutral (no
|
|
4633
|
+
* provider taxonomy, no `stop_reason`); the failing attempt's HTTP status rides its own seat in the
|
|
4634
|
+
* retry context only — see {@link BrainStatus.errorStatus}.
|
|
4579
4635
|
* SCOPE: reflects THIS task's own (top-level) brain calls. A delegated sub-agent's brain liveness routes
|
|
4580
4636
|
* to the SUB-AGENT's own stream (isolated, like every child event — §E2); a background internal brain
|
|
4581
4637
|
* call (memory recall/consolidation) is intentionally not surfaced.
|
|
@@ -5092,6 +5148,15 @@ export interface TaskStream extends AsyncIterable<TaskEvent> {
|
|
|
5092
5148
|
* steer-family `steering.not_running` once the task has finished (teardown included); a halt
|
|
5093
5149
|
* issued BEFORE the run's first prompt polls the same bounded birth window as {@link steer} and
|
|
5094
5150
|
* then stops the run before its first model turn (an empty, cleanly-halted completed run).
|
|
5151
|
+
*
|
|
5152
|
+
* **Receipt tension, stated (design/384 slice 2):** `{turnCut:true}` and the
|
|
5153
|
+
* `task.turn_interrupted` notice assert facts about the CUT — a seat was cut, no new model turn
|
|
5154
|
+
* starts — and both stay true even when the gate's durable leg still collects to `suspended`:
|
|
5155
|
+
* a park whose store commit was already in flight (or committed) when the cut landed WINS the
|
|
5156
|
+
* fence race, the row is redeemable, and the result then reads `status:"suspended"` WITHOUT
|
|
5157
|
+
* {@link TaskResult.haltedByUser} (the transitional narrowing documented on that seat). A cut
|
|
5158
|
+
* observed BEFORE the commit makes the park concede instead — no row, no card, and the ordinary
|
|
5159
|
+
* halted ending.
|
|
5095
5160
|
*/
|
|
5096
5161
|
halt(): Promise<{
|
|
5097
5162
|
turnCut: boolean;
|
|
@@ -5168,9 +5233,15 @@ export interface WorkflowGovernanceBaseline {
|
|
|
5168
5233
|
* The allowed model NAMES an LLM-authored script may pick (design/98 §2.5 新洞2). A script gives a
|
|
5169
5234
|
* `modelName` string (never a `Model` object — that carries `baseUrl`/`headers` = exfil); the engine
|
|
5170
5235
|
* resolves it against this list to a deploy-configured `Model` (the script never sees the object).
|
|
5171
|
-
* **FAIL-CLOSED**: `undefined`/empty ⇒ the script CANNOT pick a model
|
|
5172
|
-
*
|
|
5173
|
-
*
|
|
5236
|
+
* **FAIL-CLOSED**: `undefined`/empty ⇒ the script CANNOT pick a model — a spec that names `modelName`
|
|
5237
|
+
* THROWS `WorkflowModelNotAllowedError` and the child is never spawned. The refusal is loud, not a
|
|
5238
|
+
* silent downgrade: the script asked for a model it may not have, so the agent call FAILS rather than
|
|
5239
|
+
* quietly running on the workflow's default role (a script that wants the default must simply OMIT
|
|
5240
|
+
* the field). The same throw covers a name that is off the list, and a listed name the `models`
|
|
5241
|
+
* catalog does not hold — so the legal set is the INTERSECTION of this list and the catalog keys
|
|
5242
|
+
* (note the catalog is the Runner's TIER-EXPANDED one, so on a deployment with `RunnerDeps.tiers`
|
|
5243
|
+
* the tier words and CC aliases are catalog keys here too, still gated by this list).
|
|
5244
|
+
* NEVER fail-open to the whole `models` catalog for an LLM-authored workflow.
|
|
5174
5245
|
*/
|
|
5175
5246
|
workflowModelAllowlist?: string[];
|
|
5176
5247
|
}
|
|
@@ -5739,6 +5810,10 @@ export interface EngineNotice {
|
|
|
5739
5810
|
* `detail: { cause: "user_halt", sessionId, runId, taskId? }` — no `inputId` and no
|
|
5740
5811
|
* `actorId`, because no text entered the model and the verb carries no caller identity. A
|
|
5741
5812
|
* consumer keying `detail.inputId` off this row must treat it as ABSENT on this lane.
|
|
5813
|
+
* Fence tension (design/384 slice 2): this notice asserts THE CUT only — when the cut
|
|
5814
|
+
* raced a durable park whose commit was already in flight, the gate's durable leg may
|
|
5815
|
+
* still collect to `suspended` (park wins, row redeemable, no `haltedByUser`); the notice
|
|
5816
|
+
* stands beside that terminal without contradiction, because a seat really was cut.
|
|
5742
5817
|
* In both lanes: one notice per REAL cut (a `now` that found nothing in flight or whose frame
|
|
5743
5818
|
* already rode the imminent boundary, and a halt with nothing in flight, announce nothing — no
|
|
5744
5819
|
* false interrupt claims); `runId` (#499) is the INVOCATION that was cut (the other two ids are
|
|
@@ -5749,6 +5824,32 @@ export interface EngineNotice {
|
|
|
5749
5824
|
* implemented, so the unhonored-knob disclosure it carried has no referent; consumers must
|
|
5750
5825
|
* judge ladder support by VERSION, never by that code's absence.
|
|
5751
5826
|
*
|
|
5827
|
+
* - `"task.halt_unconsumed"` (design/384 slice 1) — the user's stop verb ({@link TaskStream.halt})
|
|
5828
|
+
* was ANSWERED (not refused) while the run's ending was already owned by its own abort: nothing
|
|
5829
|
+
* was cut and nothing was stopped by the halt, the run's own ending stands, and the result will
|
|
5830
|
+
* NOT carry `haltedByUser` for it (the attribution seat never signs someone else's stop). This
|
|
5831
|
+
* notice is the halt's only trace on that arm — without it the verb receipt (`{turnCut:false}`)
|
|
5832
|
+
* was the sole record and the caller could not tell "my stop did nothing because the run beat
|
|
5833
|
+
* me to ending" from "my stop is being honored at the next boundary". Minted once per such verb
|
|
5834
|
+
* call (each arrival is a distinct fact); `detail: { sessionId, runId, taskId? }` — `runId` is
|
|
5835
|
+
* the run whose ending the halt failed to claim. Audience `"user"` (the person who pressed
|
|
5836
|
+
* stop). A REFUSED halt (typed `steering.not_running` throw) mints nothing: the refusal itself
|
|
5837
|
+
* is the loud answer.
|
|
5838
|
+
*
|
|
5839
|
+
* - `"task.late_approval"` (design/384 slice 1) — a synchronous ask approval was NOT CONSUMED:
|
|
5840
|
+
* a run or turn interrupt released the wait (the `resolveAsk` race arm detached the approver's
|
|
5841
|
+
* promise; an unconsumed resolve is the approver releasing its wait, never a verdict), so the
|
|
5842
|
+
* tool did NOT run and the approval was not honored. The notice asserts non-consumption ONLY —
|
|
5843
|
+
* never an arrival order: an approval and an abort settling close together read as the abort
|
|
5844
|
+
* (the resolver's documented one-directional residual — the engine never claims a person
|
|
5845
|
+
* decided something it cannot show they did, and it equally never claims which came first).
|
|
5846
|
+
* Minted only for a value that reads as an APPROVAL — an unconsumed
|
|
5847
|
+
* deny/refusal is an ordinary release and leaves no trace, and an unconsumed REJECTION goes to
|
|
5848
|
+
* `onError(phase:"hook")` instead (a failing callback, not an answer). One notice per
|
|
5849
|
+
* unconsumed approval; `detail: { toolName, toolCallId, sessionId, runId, taskId? }`. Audience `"user"`
|
|
5850
|
+
* (whoever answered the card is the one entitled to hear the answer ran nothing); a host may
|
|
5851
|
+
* forward it on its own wire.
|
|
5852
|
+
*
|
|
5752
5853
|
* - `"steering.parked_input_blocked"` (design/373 §4.3) — a PARKED steer entry was withheld when
|
|
5753
5854
|
* a resume redelivered it (any resume kind that drains parked steers — wake included) by the
|
|
5754
5855
|
* deployment's `userPromptSubmit` screen (block verdict, or a fail-closed non-answer/crash):
|
|
@@ -196,7 +196,23 @@ export const ENGINE_ENVELOPES = Object.freeze([
|
|
|
196
196
|
tag: "teammate-message",
|
|
197
197
|
kind: "framing",
|
|
198
198
|
mint: "agents/send-message-tool.ts (INTERPOLATED tag — invisible to the literal census)",
|
|
199
|
-
guard: "escapeEnvelopeTag(TEAMMATE_MESSAGE_TAG, …)
|
|
199
|
+
guard: "body through neutralizePeerBody (the authority family, ENGINE_AUTHORITY_ENVELOPE_TAGS) + escapeEnvelopeTag(TEAMMATE_MESSAGE_TAG, …); summary/teammate_id through escapeAttributeValue",
|
|
200
|
+
fenced: false,
|
|
201
|
+
disclosed: false,
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
tag: "agent-message",
|
|
205
|
+
kind: "framing",
|
|
206
|
+
mint: "core/task-notification.ts renderAgentMessageFrame (INTERPOLATED tag — invisible to the literal census; the child → parent uplink carrier)",
|
|
207
|
+
guard: "body through neutralizePeerBody (the authority family, ENGINE_AUTHORITY_ENVELOPE_TAGS — the one helper the three peer carriers share) + escapeEnvelopeTag(AGENT_MESSAGE_TAG, …); the from attribute through attrEscape",
|
|
208
|
+
fenced: false,
|
|
209
|
+
disclosed: false,
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
tag: "cross-session-message",
|
|
213
|
+
kind: "framing",
|
|
214
|
+
mint: "agents/cross-session-envelope.ts buildCrossSessionEnvelope / encodeCcPeerFrame (INTERPOLATED tag — invisible to the literal census)",
|
|
215
|
+
guard: "model-face body through neutralizePeerBody (the authority family, ENGINE_AUTHORITY_ENVELOPE_TAGS) + escapeEnvelopeTag(CROSS_SESSION_MESSAGE_TAG, …); every attribute value typed + under its own regex grammar at build, and the parser rebuilds-and-compares (round trip) before accepting any field. The CC wire codec carries bytes as-is (containment is applied at injection when the model face is re-minted)",
|
|
200
216
|
fenced: false,
|
|
201
217
|
disclosed: false,
|
|
202
218
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolveAgentCoreCompleteFn, } from "../loop/runtime-deps.js";
|
|
2
2
|
import { asAgentMessage, convertToLlm, createCompactionSummaryMessage, createCustomMessage, } from "../harness/messages.js";
|
|
3
3
|
import { buildSessionContext } from "../session/session.js";
|
|
4
|
-
import { CompactionError, err, ok, } from "../harness/types.js";
|
|
4
|
+
import { CompactionError, err, isSyntheticApiErrorMessage, ok, } from "../harness/types.js";
|
|
5
5
|
import { budgetInvokedSkillsRetention, computeFileLists, createFileOps, extractFileOpsFromMessage, extractInvokedSkills, extractPersistedOutputRefs, formatFileOperations, formatPersistedOutputRefs, PERSISTED_OUTPUT_REFS_MAX_ENTRIES, readElidedMessages, readPersistedOutputRefs, readRetainedInvokedSkills, readUnsummarizedMessages, replaceInvokedSkillBodiesForSummary, serializeConversation, stripFileOperationsFooter, } from "./utils.js";
|
|
6
6
|
import { ENGINE_AUTHORITY_ENVELOPE_TAGS, sanitizeUntrustedText } from "../../core/untrusted-text.js";
|
|
7
7
|
import { sliceHeadSafe } from "../../core/surrogate-safe-slice.js";
|
|
@@ -223,9 +223,13 @@ function findValidCutPoints(entries, startIndex, endIndex) {
|
|
|
223
223
|
case "custom":
|
|
224
224
|
case "compactionSummary":
|
|
225
225
|
case "user":
|
|
226
|
-
case "assistant":
|
|
227
226
|
cutPoints.push(i);
|
|
228
227
|
break;
|
|
228
|
+
case "assistant":
|
|
229
|
+
if (!isSyntheticApiErrorMessage(entry.message)) {
|
|
230
|
+
cutPoints.push(i);
|
|
231
|
+
}
|
|
232
|
+
break;
|
|
229
233
|
case "toolResult":
|
|
230
234
|
break;
|
|
231
235
|
}
|
|
@@ -168,16 +168,17 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
168
168
|
* gated: its splice opens a NEW run (idle-park redelivery), and a halt belongs to the run that
|
|
169
169
|
* minted it. */
|
|
170
170
|
engineInjectionsHeld?: () => boolean;
|
|
171
|
-
/** RB-30: shared recovery sweep — collects engine-note payloads from the given queues
|
|
172
|
-
* in DELIVERY order (steer before followUp, each queue forward — the live loop serves steering
|
|
173
|
-
* first, so the recovered redelivery must not present "later" frames ahead of "now/next"),
|
|
174
|
-
* removes those entries, and hands the payloads to the runner sink. Called from BOTH terminal
|
|
175
|
-
* paths: the natural agent_end AND abort() (which clears the queues before agent_end would see
|
|
176
|
-
* them — the hard-abort race that round-1 shipped would have lost). */
|
|
177
171
|
/** RB-30 R2 belt-and-braces: runner-callable idempotent recovery for exit paths that reach
|
|
178
172
|
* neither agent_end nor abort() (a pre-prompt throw after prepare). Swept entries are removed,
|
|
179
173
|
* so a double call is a no-op. */
|
|
180
174
|
recoverUndrainedEngineNotes(): void;
|
|
175
|
+
/** RB-30: shared recovery sweep — collects engine-note payloads from the given queues
|
|
176
|
+
* in DELIVERY order (steer before followUp, each queue forward — the live loop serves steering
|
|
177
|
+
* first, so the recovered redelivery must not present "later" frames ahead of "now/next"),
|
|
178
|
+
* removes those entries, and hands the payloads to the runner sink. Called from BOTH terminal
|
|
179
|
+
* paths: the natural agent_end AND abort() — which does NOT clear the queues: #389 retired that
|
|
180
|
+
* clearing, so they are LEFT STANDING (the durable-park migration reads them AFTER abort()
|
|
181
|
+
* returns) and the abort-side pass is the belt for an exit that never reached agent_end. */
|
|
181
182
|
private sweepUndrainedEngineNotes;
|
|
182
183
|
/** backlog #259 — what remains in the steer/follow-up queues AFTER the engine-note sweep is USER
|
|
183
184
|
* input that was accepted ("queued") and will never be consumed: the run reached agent_end first.
|
|
@@ -261,6 +262,27 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
261
262
|
setStopGate(gate: (() => Promise<AgentMessage[]>) | undefined): void;
|
|
262
263
|
private validateToolNames;
|
|
263
264
|
private flushPendingSessionWrites;
|
|
265
|
+
/**
|
|
266
|
+
* #506 ㋐ — write the transcript's record of a TERMINAL provider failure (CC 2.1.250 parity, `Oo`/`CIt`).
|
|
267
|
+
*
|
|
268
|
+
* A SEPARATE object, never the live frame: `failure` is the engine's terminal error shell and every
|
|
269
|
+
* other consumer of it (the run result, failover, telemetry, usage accounting) reads its real
|
|
270
|
+
* `model`, so re-stamping that field in place would corrupt all of them. The record is minted here
|
|
271
|
+
* with the reserved {@link SYNTHETIC_MESSAGE_MODEL} instead, which is what makes it recognizable — and
|
|
272
|
+
* therefore droppable — at the request boundary and at the derived-state walks.
|
|
273
|
+
*
|
|
274
|
+
* Two CC fields are deliberately NOT copied, because this tree already states the same facts more
|
|
275
|
+
* honestly: CC writes `stop_reason: "stop_sequence"` on an entry that stopped for no such reason (its
|
|
276
|
+
* own consumers must read `isApiErrorMessage` to know better), and CC writes a zero `usage` with
|
|
277
|
+
* nothing marking it synthetic. Here the stop reason stays `"error"` and `usageMissing` says the zeros
|
|
278
|
+
* are a shell rather than a measurement — the same discipline the live frame already carries.
|
|
279
|
+
*
|
|
280
|
+
* BEST-EFFORT: a record of a failure must never become a second failure. The append can lose the
|
|
281
|
+
* session's optimistic lock (another writer moved the leaf) or hit a storage fault, and the run is
|
|
282
|
+
* already over — swallowing that leaves the pre-#506 behavior (no record) rather than converting a
|
|
283
|
+
* provider outage into a harness throw on the teardown path.
|
|
284
|
+
*/
|
|
285
|
+
private recordApiFailure;
|
|
264
286
|
private handleAgentEvent;
|
|
265
287
|
private emitRunFailure;
|
|
266
288
|
private executeTurn;
|
|
@@ -4,7 +4,8 @@ import { resolveAgentCoreStreamFn } from "../loop/runtime-deps.js";
|
|
|
4
4
|
import { normalizeEngineSegments } from "../../core/untrusted-text.js";
|
|
5
5
|
import { AUTH_CARRIER_NAMES } from "../../brain/request-params.js";
|
|
6
6
|
import { convertToLlm } from "./messages.js";
|
|
7
|
-
import { AgentHarnessError, CompactionError, SessionError, toError, } from "./types.js";
|
|
7
|
+
import { AgentHarnessError, CompactionError, SessionError, SYNTHETIC_MESSAGE_MODEL, toError, } from "./types.js";
|
|
8
|
+
const API_FAILURE_RECORD_MAX_CHARS = 2000;
|
|
8
9
|
function createUserMessage(text, images, provenance) {
|
|
9
10
|
const content = text.length > 0 ? [{ type: "text", text }] : [];
|
|
10
11
|
if (images) {
|
|
@@ -603,12 +604,13 @@ export class AgentHarness {
|
|
|
603
604
|
},
|
|
604
605
|
};
|
|
605
606
|
},
|
|
606
|
-
beforeToolCall: async ({ toolCall, args }) => {
|
|
607
|
+
beforeToolCall: async ({ toolCall, args }, signal) => {
|
|
607
608
|
const result = await this.emitHook({
|
|
608
609
|
type: "tool_call",
|
|
609
610
|
toolCallId: toolCall.id,
|
|
610
611
|
toolName: toolCall.name,
|
|
611
612
|
input: args,
|
|
613
|
+
...(signal !== undefined ? { signal } : {}),
|
|
612
614
|
});
|
|
613
615
|
return result;
|
|
614
616
|
},
|
|
@@ -726,6 +728,33 @@ export class AgentHarness {
|
|
|
726
728
|
this.pendingSessionWrites.shift();
|
|
727
729
|
}
|
|
728
730
|
}
|
|
731
|
+
async recordApiFailure(failure) {
|
|
732
|
+
const raw = failure.errorMessage?.trim();
|
|
733
|
+
const detail = raw !== undefined && raw.length > API_FAILURE_RECORD_MAX_CHARS
|
|
734
|
+
? `${raw.slice(0, API_FAILURE_RECORD_MAX_CHARS)}… (truncated)`
|
|
735
|
+
: raw;
|
|
736
|
+
const record = {
|
|
737
|
+
role: "assistant",
|
|
738
|
+
content: [{ type: "text", text: detail ? `API Error: ${detail}` : "API Error" }],
|
|
739
|
+
api: failure.api,
|
|
740
|
+
provider: failure.provider,
|
|
741
|
+
model: SYNTHETIC_MESSAGE_MODEL,
|
|
742
|
+
isApiErrorMessage: true,
|
|
743
|
+
...(failure.apiErrorStatus !== undefined ? { apiErrorStatus: failure.apiErrorStatus } : {}),
|
|
744
|
+
...(failure.requestId !== undefined ? { requestId: failure.requestId } : {}),
|
|
745
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
746
|
+
usageMissing: true,
|
|
747
|
+
stopReason: "error",
|
|
748
|
+
...(failure.errorMessage !== undefined ? { errorMessage: failure.errorMessage } : {}),
|
|
749
|
+
...(failure.errorKind !== undefined ? { errorKind: failure.errorKind } : {}),
|
|
750
|
+
timestamp: failure.timestamp,
|
|
751
|
+
};
|
|
752
|
+
try {
|
|
753
|
+
await this.session.appendMessage(record);
|
|
754
|
+
}
|
|
755
|
+
catch {
|
|
756
|
+
}
|
|
757
|
+
}
|
|
729
758
|
async handleAgentEvent(event, signal) {
|
|
730
759
|
if (event.type === "message_end") {
|
|
731
760
|
let entryId;
|
|
@@ -733,6 +762,9 @@ export class AgentHarness {
|
|
|
733
762
|
entryId = await this.session.appendMessage(event.message);
|
|
734
763
|
this.settleInjectedFrame(event.message);
|
|
735
764
|
}
|
|
765
|
+
else if (event.message.isApiErrorMessage === true) {
|
|
766
|
+
await this.recordApiFailure(event.message);
|
|
767
|
+
}
|
|
736
768
|
await this.emitAny(entryId !== undefined ? { ...event, entryId } : event, signal);
|
|
737
769
|
return;
|
|
738
770
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isSyntheticApiErrorMessage } from "./types.js";
|
|
1
2
|
import { parseSessionTimestampMs, requireSessionTimestampMs } from "../session/timestamps.js";
|
|
2
3
|
export function asAgentMessage(message) {
|
|
3
4
|
return message;
|
|
@@ -155,6 +156,9 @@ export function convertToLlm(messages) {
|
|
|
155
156
|
case "user":
|
|
156
157
|
case "assistant":
|
|
157
158
|
case "toolResult":
|
|
159
|
+
if (isSyntheticApiErrorMessage(message)) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
158
162
|
return normalizeLlmMessageContent(message);
|
|
159
163
|
default:
|
|
160
164
|
return undefined;
|
|
@@ -754,6 +754,37 @@ export declare function isValidModelChange(e: {
|
|
|
754
754
|
provider?: unknown;
|
|
755
755
|
modelId?: unknown;
|
|
756
756
|
}): boolean;
|
|
757
|
+
/**
|
|
758
|
+
* #506 ㋐ — the reserved `model` value on a transcript entry NO MODEL PRODUCED. CC-verbatim
|
|
759
|
+
* (`"<synthetic>"`, CC 2.1.250's own single-occurrence constant), and single-occurrence here for the
|
|
760
|
+
* same reason: the mint site and the recognition predicate must read the same literal or the entry
|
|
761
|
+
* becomes unrecognizable the first time one of them is retyped.
|
|
762
|
+
*
|
|
763
|
+
* It is deliberately a MODEL-SHAPED string (non-empty, bounded), so an entry carrying it survives this
|
|
764
|
+
* session's own import door and round-trips — a self-generated entry its own validator rejected would
|
|
765
|
+
* be the worse failure.
|
|
766
|
+
*
|
|
767
|
+
* ACCEPTED RESIDUAL, recorded rather than defended against: nothing RESERVES this id, because model ids
|
|
768
|
+
* are caller-supplied and `isModelIdentifier` admits any bounded non-empty string. A deployment that
|
|
769
|
+
* names a real model literally `<synthetic>` AND whose Brain stamps `isApiErrorMessage` on
|
|
770
|
+
* content-bearing output would have that output treated as a record. Both halves are required, the
|
|
771
|
+
* spelling is chosen to be one no catalog would use, and CC carries the same residual for the same
|
|
772
|
+
* reason — a reserved-word door here would refuse ids this engine has no business refusing.
|
|
773
|
+
*/
|
|
774
|
+
export declare const SYNTHETIC_MESSAGE_MODEL = "<synthetic>";
|
|
775
|
+
/**
|
|
776
|
+
* #506 ㋐ — is this transcript entry the engine's own SYNTHETIC record of a terminal API failure?
|
|
777
|
+
*
|
|
778
|
+
* Such an entry is real transcript (a session that died on a provider failure must say so when it is
|
|
779
|
+
* re-read) but it is NOT model output, so it is dropped wherever transcript becomes model input, and
|
|
780
|
+
* it must not move any state derived from real turns. This predicate is the single gate for both.
|
|
781
|
+
*
|
|
782
|
+
* THREE keys, CC-anchored (`Hje`: `type==="assistant" && isApiErrorMessage===true && model===<synthetic>`),
|
|
783
|
+
* and the narrowness is the whole point. `isApiErrorMessage` alone would also match an assistant message
|
|
784
|
+
* a foreign Brain stamped while it carried REAL output — dropping that from the request view would
|
|
785
|
+
* silently delete the model's own words from its context. Only the engine's own mint sets all three.
|
|
786
|
+
*/
|
|
787
|
+
export declare function isSyntheticApiErrorMessage(m: unknown): boolean;
|
|
757
788
|
/** RB-128: a `label` / `session_info.name` that is not a string reaches `.trim()` inside
|
|
758
789
|
* `BaseSessionStorage`'s CONSTRUCTOR — and the file backend validates BEFORE constructing any storage, so
|
|
759
790
|
* the contamination lands on disk and every later `open()` throws a raw `TypeError` (not even a `SessionError`).
|
|
@@ -1077,6 +1108,12 @@ export interface ToolCallEvent {
|
|
|
1077
1108
|
toolCallId: string;
|
|
1078
1109
|
toolName: string;
|
|
1079
1110
|
input: Record<string, unknown>;
|
|
1111
|
+
/** The per-call abort signal (additive, design/384 slice 1). Present iff the loop handed its
|
|
1112
|
+
* turn-scoped signal to `beforeToolCall` — the run-level abort is composed into that controller,
|
|
1113
|
+
* so this signal fires on a turn interrupt (bare halt / steer-now) AND on a run abort. Absent on
|
|
1114
|
+
* emits that carry no per-call signal; a subscriber gating a wait on it must then fall back to
|
|
1115
|
+
* whatever run-level signal it already holds (the historical shape, byte-identical). */
|
|
1116
|
+
signal?: AbortSignal;
|
|
1080
1117
|
}
|
|
1081
1118
|
export interface ToolResultEvent {
|
|
1082
1119
|
type: "tool_result";
|
|
@@ -155,6 +155,11 @@ export function isValidThinkingLevelChange(e) {
|
|
|
155
155
|
export function isValidModelChange(e) {
|
|
156
156
|
return isModelIdentifier(e.provider) && isModelIdentifier(e.modelId);
|
|
157
157
|
}
|
|
158
|
+
export const SYNTHETIC_MESSAGE_MODEL = "<synthetic>";
|
|
159
|
+
export function isSyntheticApiErrorMessage(m) {
|
|
160
|
+
const a = m;
|
|
161
|
+
return a?.role === "assistant" && a.isApiErrorMessage === true && a.model === SYNTHETIC_MESSAGE_MODEL;
|
|
162
|
+
}
|
|
158
163
|
export function isOptionalDisplayString(v, max = 4096) {
|
|
159
164
|
return v === undefined || v === null || (typeof v === "string" && v.length <= max);
|
|
160
165
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { asAgentMessage, createCompactionSummaryMessage, createCustomMessage, } from "../harness/messages.js";
|
|
2
|
-
import { SessionError, isValidModelChange, normalizeAnnouncedListing, normalizeCompactionStateCarrier, normalizeGitAnnouncement, normalizeReminderMark, normalizeWorkspaceState } from "../harness/types.js";
|
|
2
|
+
import { SessionError, isSyntheticApiErrorMessage, isValidModelChange, normalizeAnnouncedListing, normalizeCompactionStateCarrier, normalizeGitAnnouncement, normalizeReminderMark, normalizeWorkspaceState } from "../harness/types.js";
|
|
3
3
|
import { normalizePromptEpoch } from "../../prompt-assembly/epoch.js";
|
|
4
4
|
import { budgetInvokedSkillsRetention, readElidedMessages, readRetainedInvokedSkills, readUnsummarizedMessages, renderInvokedSkillsRetention, } from "../compaction/utils.js";
|
|
5
5
|
const RETENTION_CLAMP_DEFAULT_CHARS_PER_TOKEN = 3;
|
|
@@ -25,7 +25,8 @@ export function buildSessionContext(pathEntries, opts) {
|
|
|
25
25
|
model = { provider: entry.provider, modelId: entry.modelId };
|
|
26
26
|
}
|
|
27
27
|
else if (entry.type === "message" && entry.message.role === "assistant") {
|
|
28
|
-
if (
|
|
28
|
+
if (!isSyntheticApiErrorMessage(entry.message) &&
|
|
29
|
+
isValidModelChange({ provider: entry.message.provider, modelId: entry.message.model })) {
|
|
29
30
|
model = { provider: entry.message.provider, modelId: entry.message.model };
|
|
30
31
|
}
|
|
31
32
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -95,7 +95,7 @@ export { READ_FACE_DEFAULT_DENY_ENTRIES, READ_FACE_BUILTIN_DENY_TABLE, READ_DENY
|
|
|
95
95
|
export { deploymentReadFaceClampNotice, resolveReadFace, type ReadFace, type ReadFaceInputs } from "./tools/fs/index.js";
|
|
96
96
|
export { WRITE_PROTECTED_DEFAULT_TABLE, resolveWriteProtectedTable, compileWriteProtection, type WriteProtectedEntry, type WriteProtectedRow, type WriteProtectedKind, type WriteProtectedHit, type WriteProtectionMatcher, } from "./core/write-protect.js";
|
|
97
97
|
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, assertSafeToolResultRef, buildToolResultRef, toolResultContentSegment, MAX_MINTED_TOOL_RESULT_REF_CHARS, type ToolResultProvenance, assertToolResultProvenanceMatch, normalizeToolResultProvenance, toolResultProvenanceOf, ToolResultRefConflictError, TOOL_RESULT_REF_CONFLICT_CODE, type ToolResultStore, type ToolResultSlice, type ToolResultDeletionReport, } from "./core/tool-result-store.js";
|
|
98
|
-
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointId, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, ORG_ADMISSION_CHECKPOINT_VERSION, F012_CHECKPOINT_VERSION, REAL_APPROVAL_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingTokens, winnerFromOutcome, validatePendingSteer, readPendingSteerQueue, appendPendingSteer, MAX_PENDING_STEER_CHARS, MAX_PENDING_STEER_ENTRIES, PENDING_STEER_QUEUE_BYTE_BUDGET_BYTES, PENDING_STEER_FROZEN_FIELDS, ACTOR_ASSERTION_FROZEN_FIELDS, MAX_ACTOR_FIELD_CHARS, MAX_STEER_INPUT_ID_CHARS, LEGACY_PENDING_STEER_INPUT_ID, type ActorAssertion, type PendingSteerEntry, type PendingSteerInput, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, type RiskDescriptor, type ProbeCause, type ProbeCauseOperands, type CheckpointStore, type CheckpointSummary, type Checkpoint, type CheckpointToken, type CheckpointGate, type CheckpointState, type SerializedCheckpointState, type CheckpointFaultMode, type PendingAction, type ResumeOutcome, type ResolvedOutcome, type ReopenReason, type ResolveExpectation, type SafetyAxis, type RealApprovalGateBit, type ResourceLedger, type ResourceLimitReason, type PlatformLimitReason, } from "./core/checkpoint-store.js";
|
|
98
|
+
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointId, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, ORG_ADMISSION_CHECKPOINT_VERSION, F012_CHECKPOINT_VERSION, REAL_APPROVAL_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingTokens, winnerFromOutcome, validatePendingSteer, readPendingSteerQueue, appendPendingSteer, MAX_PENDING_STEER_CHARS, MAX_PENDING_STEER_ENTRIES, PENDING_STEER_QUEUE_BYTE_BUDGET_BYTES, PENDING_STEER_FROZEN_FIELDS, ACTOR_ASSERTION_FROZEN_FIELDS, MAX_ACTOR_FIELD_CHARS, MAX_STEER_INPUT_ID_CHARS, LEGACY_PENDING_STEER_INPUT_ID, type ActorAssertion, type PendingSteerEntry, type PendingSteerInput, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, type RiskDescriptor, type ProbeCause, type ProbeCauseOperands, type CheckpointStore, type CheckpointSummary, type Checkpoint, type CheckpointToken, type CheckpointGate, type CheckpointState, type SerializedCheckpointState, type CheckpointFaultMode, type PendingAction, type ResumeOutcome, type ResolvedOutcome, type ReopenReason, type ResolveExpectation, type TerminalClaimIntent, type TerminalClaimOutcome, type SafetyAxis, type RealApprovalGateBit, type ResourceLedger, type ResourceLimitReason, type PlatformLimitReason, } from "./core/checkpoint-store.js";
|
|
99
99
|
export { InMemoryUsageWindowStore, GLOBAL_USAGE_KEY, EMPTY_USAGE_WINDOW_RECORD, chargeUsageRecord, readUsageRecord, usageRetryAfterMs, resolveUsageWindows, type UsageWindow, type UsageWindowStore, type UsageWindowReading, type UsageWindowRecord, type UsageSlot, type UsageBucketRow, } from "./core/usage-window-store.js";
|
|
100
100
|
export { FileUsageWindowStore } from "./stores/file/usage-window-store.js";
|
|
101
101
|
export { ENV_LIFETIME_SUSPEND_MARGIN_MS, USAGE_WINDOW_REAP_MARGIN_MS } from "./core/runner/prepare-task.js";
|
|
@@ -118,7 +118,7 @@ export { createSensitivePathPolicy, RECOMMENDED_SENSITIVE_PATTERNS } from "./cor
|
|
|
118
118
|
export { createFsWriteGatePolicy, type FsWriteGatePolicyOptions } from "./core/fs-write-gate-policy.js";
|
|
119
119
|
export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
|
|
120
120
|
export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
|
|
121
|
-
export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, } from "./core/task-notification.js";
|
|
121
|
+
export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, AGENT_MESSAGE_TAG, renderAgentMessageFrame, type SemaProvenance, } from "./core/task-notification.js";
|
|
122
122
|
export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveSubagentTranscriptTier, type SubagentTranscriptTier, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, type WiringManifest, type WiringFacts, type WiringLegKind, type AskSeamForm, type AskEffective, type QuestionChannelState, type SeamProvenance, type ParkLaneReason, type ManifestDurability, type StaticWiringDeps, type StaticWiringSpec, } from "./core/wiring-manifest.js";
|
|
123
123
|
export { probeParkRoundTrip, durableParkGapOf, durableParkGapFor, PARK_SELFCHECK_SCOPE_PREFIX, type ParkSelfCheckResult, type ParkProbeFinding, type ParkProbeFindingCode, } from "./core/park-selfcheck.js";
|
|
124
124
|
export { type StoreDurability } from "./core/checkpoint-store.js";
|
|
@@ -166,7 +166,7 @@ export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRul
|
|
|
166
166
|
* and nothing more. Removal is exported without ceremony, because narrowing on a user's behalf is
|
|
167
167
|
* allowed and widening is not.
|
|
168
168
|
*/
|
|
169
|
-
export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, type PersistedAllowRule, type RuleTombstone, type RuleScope, type RuleDot, type RuleAdd, type RuleAddOrigin, type RuleOffer, type SegmentRuleSuggestion, type SegmentCoverage, type RuleReject, type RuleRejectCode, type ParsedAllowRule, type PersistedRuleTool, type PersistedRuleMatch, } from "./core/permission-rule-model.js";
|
|
169
|
+
export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, type UncoveredSegmentDetail, type EditedRuleBreadthWarning, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, type PersistedAllowRule, type RuleTombstone, type RuleScope, type RuleDot, type RuleAdd, type RuleAddOrigin, type RuleOffer, type RuleOfferBatchMember, type SegmentRuleSuggestion, type SegmentCoverage, type RuleReject, type RuleRejectCode, type ParsedAllowRule, type PersistedRuleTool, type PersistedRuleMatch, } from "./core/permission-rule-model.js";
|
|
170
170
|
export { removePersistedRule, applyTombstones, sameScope, isValidConsentScope, isValidDurableScope, InMemoryPermissionRuleStore, EMPTY_RULE_STORE, type PermissionRuleStore, type PermissionRuleStoreProvider, type StoredAllowRules, type RemoveResult, type PutResult, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, type RuleSyncState, type RuleSyncFrontier, type RuleSyncDrop, type RuleSyncLandingReport, type RuleOwner, type QuarantinedRuleAdd, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, type PermissionRuleWriter, type WritablePermissionRuleStore, type RuleWriteDelta, type RuleAddDelta, type RuleDeleteDelta, type RuleSyncJoinDelta, type RawRuleSyncState, type RedemptionAuthorization, } from "./core/permission-rule-store.js";
|
|
171
171
|
export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, type PermissionRuleSyncTransport, type PermissionRuleSyncResult, type RuleSyncRequestBody, type RuleSyncResponseBody, } from "./core/permission-rule-sync.js";
|
|
172
172
|
export { InMemorySessionRuleOverlay, type SessionRuleOverlay, type SessionRuleOverlayAdd, type SessionRuleOverlayApplyResult, } from "./core/permission-rule-session.js";
|
|
@@ -252,6 +252,9 @@ export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE,
|
|
|
252
252
|
export { getSessionRetainLedger, releaseSessionRetainLedger, } from "./agents/retain-ledger.js";
|
|
253
253
|
export { createSendMessageTool, createAgentContinuationVerb, SEND_MESSAGE_TOOL_NAME, type SendMessageToolOptions, type AgentContinuationReceipt } from "./agents/send-message-tool.js";
|
|
254
254
|
export { createPeerAdmission, peerAdmissionFor, judgePeerAdmission, resolvePeerAdmissionConfig, PEER_ADMISSION_DEFAULTS, PEER_HOP_CHAIN_WINDOW, PEER_MESSAGE_NOTICE, createPeerSelfRef, createPeerInboundChainRef, peerAxisToken, appendHopToken, type PeerAdmission, type PeerAdmissionConfig, type PeerAdmissionOptions, type PeerAdmissionRequest, type PeerAdmissionVerdict, type PeerAdmissionRefusal, type PeerRefusalCode, type PeerAxisTag, type PeerIdentity, type PeerSelfRef, type PeerInboundChainRef, } from "./agents/peer-admission.js";
|
|
255
|
+
export { CROSS_SESSION_MESSAGE_TAG, CROSS_SESSION_MESSAGE_NOTICE, PERMISSION_MODE_CLASSES, isPermissionModeClass, CrossSessionCodecError, PEER_HOP_TOKEN_HEX, PEER_HOP_CHAIN_CARRY_WINDOW, encodePeerAddress, isCanonicalPeerAddress, encodeScopeAttribute, decodeScopeAttribute, canonicalPeerDisplayName, buildCrossSessionEnvelope, parseCrossSessionEnvelope, clampHopChain, encodeCcPeerFrame, decodeCcPeerFrame, type PermissionModeClass, type CrossSessionEnvelopeFields, type CrossSessionEnvelopeParse, type CrossSessionEnvelopeRefusal, type CcPeerFrameFields, type CcPeerFrameParse, } from "./agents/cross-session-envelope.js";
|
|
256
|
+
export { CROSS_SESSION_INBOUND_SETTINGS, isCrossSessionInboundSetting, resolveCrossSessionInboundSetting, CROSS_SESSION_HOLD_CAUSES, describeCrossSessionHoldCause, judgeCrossSessionInbound, foldPermissionModeClass, PEER_SEND_VERDICT_CODES, peerSendVerdictSeverity, type CrossSessionInboundSetting, type CrossSessionSettingSource, type CrossSessionInboundSettingLayers, type ResolvedCrossSessionInboundSetting, type CrossSessionHoldCause, type CrossSessionInboundVerdict, type CrossSessionInboundInput, type PeerSendVerdictCode, type PeerSendVerdict, } from "./agents/cross-session-judge.js";
|
|
257
|
+
export { PEER_REF_MIN, PEER_REF_MAX, PEER_REF_RE, mintPeerRef, formatPeerNameRef, parsePeerNameRef, normalizePeerName, PEER_ADDRESS_PREFIXES, reservedPeerNameReason, type PeerRefEntry, } from "./agents/cross-session-ref.js";
|
|
255
258
|
export { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME, type AgentTranscriptToolOptions, } from "./agents/agent-transcript-tool.js";
|
|
256
259
|
export { defineAgent } from "./agents/agent-definition.js";
|
|
257
260
|
export { builtinAgentDefinitions, BUILTIN_READONLY_DENY_TOOLS, EXPLORE_WHEN_TO_USE, EXPLORE_WHEN_TO_USE_LEAN, PLAN_WHEN_TO_USE, EXPLORE_SYSTEM_PROMPT, PLAN_SYSTEM_PROMPT, } from "./agents/builtin-agents.js";
|
package/dist/index.js
CHANGED
|
@@ -95,7 +95,7 @@ export { createSensitivePathPolicy, RECOMMENDED_SENSITIVE_PATTERNS } from "./cor
|
|
|
95
95
|
export { createFsWriteGatePolicy } from "./core/fs-write-gate-policy.js";
|
|
96
96
|
export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
|
|
97
97
|
export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
|
|
98
|
-
export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, } from "./core/task-notification.js";
|
|
98
|
+
export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, AGENT_MESSAGE_TAG, renderAgentMessageFrame, } from "./core/task-notification.js";
|
|
99
99
|
export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveSubagentTranscriptTier, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, } from "./core/wiring-manifest.js";
|
|
100
100
|
export { probeParkRoundTrip, durableParkGapOf, durableParkGapFor, PARK_SELFCHECK_SCOPE_PREFIX, } from "./core/park-selfcheck.js";
|
|
101
101
|
export {} from "./core/checkpoint-store.js";
|
|
@@ -126,7 +126,7 @@ export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/au
|
|
|
126
126
|
export { AUTO_MODE_ARMING_RECIPE_VERSION, autoModeArmingRecipeOf, sanitizeAutoModeArmingRecipe, foldAutoModeArming, } from "./core/auto-mode-arming.js";
|
|
127
127
|
export { rebuildAutoModeDecider, } from "./core/auto-mode-rebuild.js";
|
|
128
128
|
export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRule, wildcardMatch, isNamespacedCoveringRuleName, namespacedRuleNameCovers, } from "./core/permission-rules.js";
|
|
129
|
-
export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, } from "./core/permission-rule-model.js";
|
|
129
|
+
export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, } from "./core/permission-rule-model.js";
|
|
130
130
|
export { removePersistedRule, applyTombstones, sameScope, isValidConsentScope, isValidDurableScope, InMemoryPermissionRuleStore, EMPTY_RULE_STORE, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, } from "./core/permission-rule-store.js";
|
|
131
131
|
export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, } from "./core/permission-rule-sync.js";
|
|
132
132
|
export { InMemorySessionRuleOverlay, } from "./core/permission-rule-session.js";
|
|
@@ -209,6 +209,9 @@ export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE,
|
|
|
209
209
|
export { getSessionRetainLedger, releaseSessionRetainLedger, } from "./agents/retain-ledger.js";
|
|
210
210
|
export { createSendMessageTool, createAgentContinuationVerb, SEND_MESSAGE_TOOL_NAME } from "./agents/send-message-tool.js";
|
|
211
211
|
export { createPeerAdmission, peerAdmissionFor, judgePeerAdmission, resolvePeerAdmissionConfig, PEER_ADMISSION_DEFAULTS, PEER_HOP_CHAIN_WINDOW, PEER_MESSAGE_NOTICE, createPeerSelfRef, createPeerInboundChainRef, peerAxisToken, appendHopToken, } from "./agents/peer-admission.js";
|
|
212
|
+
export { CROSS_SESSION_MESSAGE_TAG, CROSS_SESSION_MESSAGE_NOTICE, PERMISSION_MODE_CLASSES, isPermissionModeClass, CrossSessionCodecError, PEER_HOP_TOKEN_HEX, PEER_HOP_CHAIN_CARRY_WINDOW, encodePeerAddress, isCanonicalPeerAddress, encodeScopeAttribute, decodeScopeAttribute, canonicalPeerDisplayName, buildCrossSessionEnvelope, parseCrossSessionEnvelope, clampHopChain, encodeCcPeerFrame, decodeCcPeerFrame, } from "./agents/cross-session-envelope.js";
|
|
213
|
+
export { CROSS_SESSION_INBOUND_SETTINGS, isCrossSessionInboundSetting, resolveCrossSessionInboundSetting, CROSS_SESSION_HOLD_CAUSES, describeCrossSessionHoldCause, judgeCrossSessionInbound, foldPermissionModeClass, PEER_SEND_VERDICT_CODES, peerSendVerdictSeverity, } from "./agents/cross-session-judge.js";
|
|
214
|
+
export { PEER_REF_MIN, PEER_REF_MAX, PEER_REF_RE, mintPeerRef, formatPeerNameRef, parsePeerNameRef, normalizePeerName, PEER_ADDRESS_PREFIXES, reservedPeerNameReason, } from "./agents/cross-session-ref.js";
|
|
212
215
|
export { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME, } from "./agents/agent-transcript-tool.js";
|
|
213
216
|
export { defineAgent } from "./agents/agent-definition.js";
|
|
214
217
|
export { builtinAgentDefinitions, BUILTIN_READONLY_DENY_TOOLS, EXPLORE_WHEN_TO_USE, EXPLORE_WHEN_TO_USE_LEAN, PLAN_WHEN_TO_USE, EXPLORE_SYSTEM_PROMPT, PLAN_SYSTEM_PROMPT, } from "./agents/builtin-agents.js";
|
|
@@ -25,3 +25,4 @@ export { uuidv7 } from "../engine/session/uuid.js";
|
|
|
25
25
|
export { SessionError } from "../engine/harness/types.js";
|
|
26
26
|
export { normalizeGitAnnouncement } from "../engine/harness/types.js";
|
|
27
27
|
export { gitFrameContextVisible } from "../engine/session/session.js";
|
|
28
|
+
export { isSyntheticApiErrorMessage } from "../engine/harness/types.js";
|
package/dist/internal/harness.js
CHANGED
|
@@ -14,3 +14,4 @@ export { uuidv7 } from "../engine/session/uuid.js";
|
|
|
14
14
|
export { SessionError } from "../engine/harness/types.js";
|
|
15
15
|
export { normalizeGitAnnouncement } from "../engine/harness/types.js";
|
|
16
16
|
export { gitFrameContextVisible } from "../engine/session/session.js";
|
|
17
|
+
export { isSyntheticApiErrorMessage } from "../engine/harness/types.js";
|