@sema-agent/core 7.37.0 → 7.38.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 +170 -0
- package/dist/agents/observer.js +1 -1
- package/dist/agents/peer-notices.js +4 -4
- package/dist/agents/subagent.js +1 -1
- package/dist/agents/team-role.js +2 -2
- package/dist/brain/anthropic.js +13 -19
- package/dist/brain/errors.d.ts +26 -0
- package/dist/brain/errors.js +34 -0
- package/dist/brain/input-too-long.d.ts +0 -31
- package/dist/brain/input-too-long.js +1 -18
- package/dist/brain/open-responses.js +12 -18
- package/dist/brain/openai.js +13 -19
- package/dist/brain/status-sink.d.ts +1 -1
- package/dist/brain/stream-engine.js +10 -2
- package/dist/brain/stream-shared.d.ts +29 -0
- package/dist/brain/stream-shared.js +15 -0
- package/dist/brain/tool-call-id.d.ts +29 -8
- package/dist/brain/tool-call-id.js +36 -6
- package/dist/core/a2a-task-state.js +2 -2
- package/dist/core/artifact-host.js +6 -6
- package/dist/core/ask-origin.js +6 -6
- package/dist/core/ask-unresolvable-notice.js +1 -1
- package/dist/core/auto-mode.js +4 -4
- package/dist/core/background-agent-store.js +2 -2
- package/dist/core/checkpoint-execution-record.js +1 -1
- package/dist/core/checkpoint-store.d.ts +2 -2
- package/dist/core/checkpoint-store.js +2 -2
- package/dist/core/child-clamp-seats.js +3 -3
- package/dist/core/compliance.js +1 -1
- package/dist/core/context-edit.js +1 -1
- package/dist/core/context-guard.d.ts +0 -19
- package/dist/core/context-guard.js +0 -38
- package/dist/core/decision-receipt.d.ts +27 -1
- package/dist/core/decision-receipt.js +176 -1
- package/dist/core/engine-notice.d.ts +67 -7
- package/dist/core/engine-notice.js +2 -1
- package/dist/core/gate-fold.js +3 -2
- package/dist/core/gate-outcome.js +4 -4
- package/dist/core/governance-codes.d.ts +221 -13
- package/dist/core/governance-codes.js +106 -4
- package/dist/core/hook-seats.js +2 -2
- package/dist/core/hooks.d.ts +21 -2
- package/dist/core/hooks.js +4 -1
- package/dist/core/mailbox-store.js +3 -3
- package/dist/core/mcp-failure.js +4 -4
- package/dist/core/mcp-injection-drop.js +1 -1
- package/dist/core/memory-engine/consolidation.js +1 -1
- package/dist/core/memory-engine/delegation-settlement.d.ts +8 -0
- package/dist/core/memory-engine/delegation-settlement.js +7 -0
- package/dist/core/memory-engine/engine.d.ts +12 -2
- package/dist/core/memory-engine/engine.js +10 -6
- package/dist/core/memory-engine/export-bundle.js +1 -1
- package/dist/core/memory-engine/layout.d.ts +6 -6
- package/dist/core/memory-engine/layout.js +6 -8
- package/dist/core/memory-engine/session-write-home.d.ts +30 -0
- package/dist/core/memory-engine/session-write-home.js +34 -0
- package/dist/core/memory-engine/tools.js +1 -1
- package/dist/core/memory-engine/types.js +1 -1
- package/dist/core/memory.js +1 -1
- package/dist/core/mode-policy.d.ts +10 -1
- package/dist/core/mode-policy.js +15 -7
- package/dist/core/model-seat.js +1 -1
- package/dist/core/permission-rule-model.js +3 -3
- package/dist/core/permission-rule-store.js +2 -2
- package/dist/core/read-only-shell-table.js +8 -8
- package/dist/core/retention.js +2 -2
- package/dist/core/runner/assemble-result.js +15 -5
- package/dist/core/runner/classifier-ladder.js +1 -1
- package/dist/core/runner/denial-limit-arms.d.ts +2 -0
- package/dist/core/runner/denial-limit-arms.js +6 -2
- package/dist/core/runner/inherited-ask-grants.d.ts +6 -5
- package/dist/core/runner/inherited-ask-grants.js +3 -2
- package/dist/core/runner/prepare-context-lane.d.ts +19 -15
- package/dist/core/runner/prepare-context-lane.js +11 -15
- package/dist/core/runner/prepare-gate-stations.js +5 -5
- package/dist/core/runner/prepare-inherited-gate.js +1 -1
- package/dist/core/runner/prepare-policy-chain.js +10 -10
- package/dist/core/runner/run-harness-handlers.js +3 -0
- package/dist/core/runner/run-leg.js +2 -2
- package/dist/core/runner/run-stop-and-final-verify.js +1 -0
- package/dist/core/runner/run-turn-boundary.js +1 -1
- package/dist/core/runner/session-mode-seats.d.ts +11 -3
- package/dist/core/runner/session-mode-seats.js +6 -0
- package/dist/core/runner/session-rule-policy.js +2 -3
- package/dist/core/runner/stream-steer-verb.js +1 -1
- package/dist/core/runner/tool-call-id-fold-seat.js +16 -9
- package/dist/core/runner/tool-turn-repair-seat.d.ts +18 -0
- package/dist/core/runner/tool-turn-repair-seat.js +63 -0
- package/dist/core/runner/turn-attachments.js +1 -1
- package/dist/core/runtime-caps.js +1 -1
- package/dist/core/safety-axis-vocab.d.ts +5 -0
- package/dist/core/safety-axis-vocab.js +5 -0
- package/dist/core/session-reconcile.d.ts +44 -7
- package/dist/core/session-reconcile.js +51 -20
- package/dist/core/shared-memory/types.js +1 -1
- package/dist/core/side-query.d.ts +6 -1
- package/dist/core/side-query.js +4 -2
- package/dist/core/store-contracts/read-back-shape-contract.js +1 -1
- package/dist/core/swappable-deps.js +1 -1
- package/dist/core/task-notification.js +4 -4
- package/dist/core/task-registry-shared.js +1 -1
- package/dist/core/terminal-cause.d.ts +19 -0
- package/dist/core/tool-face.js +6 -6
- package/dist/core/tool-policy.d.ts +17 -11
- package/dist/core/tool-policy.js +38 -72
- package/dist/core/tool-roster.js +1 -1
- package/dist/core/tool-search-setting.js +1 -1
- package/dist/core/trace.d.ts +5 -4
- package/dist/core/types.d.ts +2 -2
- package/dist/core/types.js +1 -1
- package/dist/core/wiring-manifest.js +2 -2
- package/dist/core/write-protect.js +1 -1
- package/dist/engine/harness/agent-harness.d.ts +7 -0
- package/dist/engine/harness/agent-harness.js +24 -8
- package/dist/engine/llm/index.d.ts +1 -0
- package/dist/engine/llm/index.js +1 -0
- package/dist/engine/llm/tool-turns.d.ts +109 -0
- package/dist/engine/llm/tool-turns.js +145 -0
- package/dist/engine/llm/types.d.ts +11 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +4 -2
- package/dist/internal/llm.d.ts +2 -2
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/workflow-governance.js +2 -2
- package/dist/orchestration/workflow-types.js +2 -2
- package/dist/shell/lex.js +7 -7
- package/dist/tools/fs/bash-program-position.js +2 -2
- package/dist/tools/fs/read-deny.js +2 -2
- package/dist/tools/fs/safety.js +1 -1
- package/dist/tools/fs/shell-read-judge.js +2 -2
- package/dist/tools/fs/shell-read-plan.js +2 -2
- package/dist/tools/fs/shell-read-write-targets.js +1 -1
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +17 -1
- package/wire-changes/core@7.37.1.json +122 -0
- package/wire-changes/core@7.38.0.json +664 -0
package/dist/core/tool-roster.js
CHANGED
|
@@ -11,7 +11,7 @@ const Name = Type.String({ minLength: 1, maxLength: TOOL_WIRE_NAME_MAX_CHARS });
|
|
|
11
11
|
const Short = Type.String({ maxLength: TOOL_CONTRACT_MAX_CHARS });
|
|
12
12
|
const Key = Type.String({ maxLength: TOOL_KEY_MAX_CHARS });
|
|
13
13
|
const Digest16 = Type.String({ minLength: 16, maxLength: 16 });
|
|
14
|
-
export const ROSTER_SOURCES = ["builtin", "caller", "host", "mcp", "a2a", "external", "synthetic"];
|
|
14
|
+
export const ROSTER_SOURCES = Object.freeze(["builtin", "caller", "host", "mcp", "a2a", "external", "synthetic"]);
|
|
15
15
|
export const ToolRosterRenderHints = Type.Object({
|
|
16
16
|
userFacingName: Type.Optional(Type.String({ maxLength: RENDER_HINT_MAX_CHARS })),
|
|
17
17
|
activity: Type.Optional(Type.String({ maxLength: RENDER_HINT_ACTIVITY_MAX_CHARS })),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const TOOL_SEARCH_DEFAULT_THRESHOLD_PERCENT = 10;
|
|
2
2
|
export const TOOL_SEARCH_INVALID_CODE = "config.tool_search_invalid";
|
|
3
|
-
export const TOOL_SEARCH_POLICIES = ["always", "never", "auto"];
|
|
3
|
+
export const TOOL_SEARCH_POLICIES = Object.freeze(["always", "never", "auto"]);
|
|
4
4
|
export function resolveToolSearch(setting) {
|
|
5
5
|
if (setting === undefined)
|
|
6
6
|
return { policy: "auto", thresholdPercent: TOOL_SEARCH_DEFAULT_THRESHOLD_PERCENT, fraction: TOOL_SEARCH_DEFAULT_THRESHOLD_PERCENT / 100 };
|
package/dist/core/trace.d.ts
CHANGED
|
@@ -860,13 +860,14 @@ export type TraceEvent = {
|
|
|
860
860
|
} | {
|
|
861
861
|
/** A provider echo field was refused by {@link import("../brain/errors.js").PROVIDER_ECHO_SHAPE} (visible ASCII,
|
|
862
862
|
* 1–128 characters) and dropped: the response's `request-id` / `x-request-id` header values (`field:
|
|
863
|
-
* "requestId"`, read at connect — the id a failure would carry as `apiFailure.requestId`),
|
|
864
|
-
* its frames report (`field: "responseModel"`)
|
|
865
|
-
*
|
|
863
|
+
* "requestId"`, read at connect — the id a failure would carry as `apiFailure.requestId`), the model name
|
|
864
|
+
* its frames report (`field: "responseModel"`), or the word a refusal's error envelope states (`field:
|
|
865
|
+
* "apiErrorCode"`). One frame per provider response per field; the value itself is never carried
|
|
866
|
+
* (metadata-only). A count of these frames is this engine's drop count. */
|
|
866
867
|
kind: "brain.echo_dropped";
|
|
867
868
|
version: 1;
|
|
868
869
|
taskId: string;
|
|
869
|
-
field: "requestId" | "responseModel";
|
|
870
|
+
field: "requestId" | "responseModel" | "apiErrorCode";
|
|
870
871
|
ts: number;
|
|
871
872
|
} | {
|
|
872
873
|
/** C10 — a `preemptSignal` fired on a task that is NOT resource-suspend-eligible: the preempt is a
|
package/dist/core/types.d.ts
CHANGED
|
@@ -29,6 +29,6 @@ export { AUTO_MODE_DENY_SOURCES, isAutoModeDenySource } from "./runtime-caps.js"
|
|
|
29
29
|
export type { BackgroundChildEvent, DelegationLifecycleEvent } from "./delegation-frames.js";
|
|
30
30
|
export { __resetMalformedDelegationSeatAnnouncement, deliverDelegationLifecycle } from "./delegation-frames.js";
|
|
31
31
|
export type { ProjectMemoryLoad, ResumePreflightInfo, ResumePreflightVerdict, RunnerDeps } from "./runner-deps.js";
|
|
32
|
-
export type { EngineNotice, OwedUserInputAccount } from "./engine-notice.js";
|
|
33
|
-
export { __resetMalformedNoticeSeatAnnouncement, deliverEngineNotice, owedUserInputCounts, settleOwedUserInput, undrainedUserInputNotices } from "./engine-notice.js";
|
|
32
|
+
export type { EngineNotice, OwedUserInputAccount, UserSteerUndrainedCause } from "./engine-notice.js";
|
|
33
|
+
export { __resetMalformedNoticeSeatAnnouncement, deliverEngineNotice, owedUserInputCounts, settleOwedUserInput, undrainedUserInputNotices, USER_STEER_UNDRAINED_CAUSES } from "./engine-notice.js";
|
|
34
34
|
export type { AgentTool, Model, StreamFn, ThinkingLevel, ToolInputValidationContext, ToolInputVerdict };
|
package/dist/core/types.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { MODEL_ROLES } from "./model-seat.js";
|
|
2
2
|
export { AUTO_MODE_DENY_SOURCES, isAutoModeDenySource } from "./runtime-caps.js";
|
|
3
3
|
export { __resetMalformedDelegationSeatAnnouncement, deliverDelegationLifecycle } from "./delegation-frames.js";
|
|
4
|
-
export { __resetMalformedNoticeSeatAnnouncement, deliverEngineNotice, owedUserInputCounts, settleOwedUserInput, undrainedUserInputNotices } from "./engine-notice.js";
|
|
4
|
+
export { __resetMalformedNoticeSeatAnnouncement, deliverEngineNotice, owedUserInputCounts, settleOwedUserInput, undrainedUserInputNotices, USER_STEER_UNDRAINED_CAUSES } from "./engine-notice.js";
|
|
@@ -5,8 +5,8 @@ import { canonicalize } from "./canonical-json.js";
|
|
|
5
5
|
import { resolveCheckpointStore } from "./checkpoint-store.js";
|
|
6
6
|
import { isLiveQuestionFace } from "./ask-question.js";
|
|
7
7
|
import { AUTO_MODE_DENY_SOURCES, isAutoModeDenySource } from "./runtime-caps.js";
|
|
8
|
-
export const AUTO_MODE_ARM_REASONS = ["armed", "no_intent", "no_face", "denied", "resolver_fault"];
|
|
9
|
-
export const LSP_LANES = ["tool", "diagnostics", "tool_and_diagnostics"];
|
|
8
|
+
export const AUTO_MODE_ARM_REASONS = Object.freeze(["armed", "no_intent", "no_face", "denied", "resolver_fault"]);
|
|
9
|
+
export const LSP_LANES = Object.freeze(["tool", "diagnostics", "tool_and_diagnostics"]);
|
|
10
10
|
export function deriveHandsSeam(handsMounted) {
|
|
11
11
|
return handsMounted ? { mounted: true } : { mounted: false, reason: "no_execution_env" };
|
|
12
12
|
}
|
|
@@ -183,7 +183,7 @@ function relativeUnderDataRoot(path, roots) {
|
|
|
183
183
|
}
|
|
184
184
|
return null;
|
|
185
185
|
}
|
|
186
|
-
export const WRITE_PROTECTION_TARGET_VIEWS = ["spelling-only", "target"];
|
|
186
|
+
export const WRITE_PROTECTION_TARGET_VIEWS = Object.freeze(["spelling-only", "target"]);
|
|
187
187
|
export function compileWriteProtection(entries, opts) {
|
|
188
188
|
const rows = resolveWriteProtectedTable(entries);
|
|
189
189
|
if (rows.length === 0)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ActorAssertion, AssistantMessage, ImageContent, Model, UserMessage } from "../llm/index.js";
|
|
2
|
+
import { type ToolTurnRepair } from "../llm/index.js";
|
|
2
3
|
import type { HaltRemainingDirective } from "../loop/types.js";
|
|
3
4
|
import type { AgentMessage, AgentTool, LoopMalformedToolUseRecovery, LoopThinkingOnlyRecovery, LoopTruncatedOutputRecovery, QueueMode, ThinkingLevel } from "../loop/types.js";
|
|
4
5
|
import { type EngineSegment } from "../../core/untrusted-text.js";
|
|
@@ -189,6 +190,10 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
189
190
|
private thinkingLevel;
|
|
190
191
|
/** RB-30 terminal fix — runner-set sink for engine-note payloads left undrained at agent_end. */
|
|
191
192
|
onUndrainedEngineNotes?: (payloads: unknown[]) => void;
|
|
193
|
+
/** Runner-set sink for the provider boundary's tool-turn repairs ({@link ensureToolTurnInvariants}) — called
|
|
194
|
+
* with every request view that needed one (the transcript is never rewritten, so a broken turn is repaired, and
|
|
195
|
+
* reported, on each request; the sink owns its dedup). Advisory: a throwing sink never breaks the request. */
|
|
196
|
+
onToolTurnRepaired?: (repairs: readonly ToolTurnRepair[]) => void;
|
|
192
197
|
/** backlog #259 — USER-authored queue remnants at agent_end: steers/follow-ups whose receipts said
|
|
193
198
|
* "queued" but that no turn will ever drain (the run ended first). The engine-note sweep above
|
|
194
199
|
* hands ENGINE payloads back for redelivery; user inputs have no redelivery semantics (a steer
|
|
@@ -226,6 +231,8 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
226
231
|
* gated: its splice opens a NEW run (idle-park redelivery), and a halt belongs to the run that
|
|
227
232
|
* minted it. */
|
|
228
233
|
engineInjectionsHeld?: () => boolean;
|
|
234
|
+
/** The provider boundary's tool-turn law: the repaired view goes to the brain, the repairs to the runner's sink. */
|
|
235
|
+
private holdToolTurnLaw;
|
|
229
236
|
/** RB-30 R2 belt-and-braces: runner-callable idempotent recovery for exit paths that reach
|
|
230
237
|
* neither agent_end nor abort() (a pre-prompt throw after prepare). Swept entries are removed,
|
|
231
238
|
* so a double call is a no-op. */
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { createAssistantMessageEventStream, snapshotActorAssertion, stripEngineMetadata } from "../llm/index.js";
|
|
1
|
+
import { createAssistantMessageEventStream, ensureToolTurnInvariants, snapshotActorAssertion, stripEngineMetadata } from "../llm/index.js";
|
|
2
2
|
import { runAgentLoop } from "../loop/agent-loop.js";
|
|
3
3
|
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 { isProviderEchoShape } from "../../brain/errors.js";
|
|
7
7
|
import { convertToLlm } from "./messages.js";
|
|
8
|
-
import { thrownText } from "../../core/thrown-value.js";
|
|
8
|
+
import { readMember, thrownText } from "../../core/thrown-value.js";
|
|
9
9
|
import { AgentHarnessError, CompactionError, SessionError, SYNTHETIC_MESSAGE_MODEL, toError, } from "./types.js";
|
|
10
10
|
const API_FAILURE_RECORD_MAX_CHARS = 2000;
|
|
11
11
|
function createUserMessage(text, images, provenance) {
|
|
@@ -211,10 +211,22 @@ export class AgentHarness {
|
|
|
211
211
|
modelRef;
|
|
212
212
|
thinkingLevel;
|
|
213
213
|
onUndrainedEngineNotes;
|
|
214
|
+
onToolTurnRepaired;
|
|
214
215
|
onUndrainedUserInputs;
|
|
215
216
|
onEngineNoteConsumed;
|
|
216
217
|
onFrameCommitted;
|
|
217
218
|
engineInjectionsHeld;
|
|
219
|
+
holdToolTurnLaw(messages) {
|
|
220
|
+
const view = ensureToolTurnInvariants(messages);
|
|
221
|
+
if (view.repairs.length > 0) {
|
|
222
|
+
try {
|
|
223
|
+
this.onToolTurnRepaired?.(view.repairs);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return view.messages;
|
|
229
|
+
}
|
|
218
230
|
recoverUndrainedEngineNotes() {
|
|
219
231
|
this.sweepUndrainedEngineNotes([this.drainedPendingInjection, this.nextTurnQueue, this.steerQueue, this.followUpQueue]);
|
|
220
232
|
}
|
|
@@ -620,7 +632,7 @@ export class AgentHarness {
|
|
|
620
632
|
...(this.streamingToolExecution === true && (this.getHandlers("tool_call")?.size ?? 0) === 0
|
|
621
633
|
? { streamingToolExecution: true }
|
|
622
634
|
: {}),
|
|
623
|
-
convertToLlm: (messages) => stripEngineMetadata(convertToLlm(messages)),
|
|
635
|
+
convertToLlm: (messages) => this.holdToolTurnLaw(stripEngineMetadata(convertToLlm(messages))),
|
|
624
636
|
shouldStopAfterTurn: () => this.consultStopLatch("post_turn"),
|
|
625
637
|
shouldHaltBeforeTurn: () => this.consultStopLatch("pre_turn"),
|
|
626
638
|
transformContext: async (messages, signal) => {
|
|
@@ -772,7 +784,11 @@ export class AgentHarness {
|
|
|
772
784
|
}
|
|
773
785
|
}
|
|
774
786
|
async recordApiFailure(failure) {
|
|
775
|
-
const
|
|
787
|
+
const errorMessage = readMember(failure, "errorMessage");
|
|
788
|
+
const apiErrorStatus = readMember(failure, "apiErrorStatus");
|
|
789
|
+
const requestId = readMember(failure, "requestId");
|
|
790
|
+
const errorKind = readMember(failure, "errorKind");
|
|
791
|
+
const raw = typeof errorMessage === "string" ? errorMessage.trim() : undefined;
|
|
776
792
|
const detail = raw !== undefined && raw.length > API_FAILURE_RECORD_MAX_CHARS
|
|
777
793
|
? `${raw.slice(0, API_FAILURE_RECORD_MAX_CHARS)}… (truncated)`
|
|
778
794
|
: raw;
|
|
@@ -783,13 +799,13 @@ export class AgentHarness {
|
|
|
783
799
|
provider: failure.provider,
|
|
784
800
|
model: SYNTHETIC_MESSAGE_MODEL,
|
|
785
801
|
isApiErrorMessage: true,
|
|
786
|
-
...(
|
|
787
|
-
...(typeof
|
|
802
|
+
...(typeof apiErrorStatus === "number" ? { apiErrorStatus } : {}),
|
|
803
|
+
...(typeof requestId === "string" && isProviderEchoShape(requestId) ? { requestId } : {}),
|
|
788
804
|
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
789
805
|
usageMissing: true,
|
|
790
806
|
stopReason: "error",
|
|
791
|
-
...(
|
|
792
|
-
...(
|
|
807
|
+
...(typeof errorMessage === "string" ? { errorMessage } : {}),
|
|
808
|
+
...(errorKind === "length_empty" || errorKind === "degenerate" || errorKind === "input_too_long" ? { errorKind } : {}),
|
|
793
809
|
timestamp: failure.timestamp,
|
|
794
810
|
};
|
|
795
811
|
try {
|
package/dist/engine/llm/index.js
CHANGED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The request view's TOOL-TURN LAW — the structure every provider lane requires of a tool turn, restored on the
|
|
3
|
+
* way to the brain (never in the transcript).
|
|
4
|
+
*
|
|
5
|
+
* For every assistant message that carries tool calls:
|
|
6
|
+
* (i) the calls are a CONTIGUOUS TAIL of DISTINCT ids — every block that is not a call and stands after the first
|
|
7
|
+
* call (between two calls or after the last) moves ahead of the calls; blocks ahead of the first call, thinking
|
|
8
|
+
* first, keep their place (a stable partition: non-call blocks in their order, then the calls in theirs); a
|
|
9
|
+
* second call carrying an id the message already used is left out (every lane requires a request's call ids to
|
|
10
|
+
* be unique), so the message keeps the FIRST call per id and every result for that id answers it;
|
|
11
|
+
* (ii) the messages right after it are EXACTLY one result per call — a result recorded later in the transcript
|
|
12
|
+
* (behind a user message, a wake frame, another turn) is moved up into the batch, a second result for the
|
|
13
|
+
* same call is folded into the first (no recorded result is withheld), an interrupted close
|
|
14
|
+
* ({@link isInterruptedClose}) stands in only for a call with no other result (beside a recorded result it
|
|
15
|
+
* is void: it says only that none was recorded), and a call with no result at all is closed with the reconcile
|
|
16
|
+
* family's synthetic interrupted result ({@link interruptedResults}: the same text and `errorKind` a persisted
|
|
17
|
+
* reconcile writes);
|
|
18
|
+
* (iii) every result answers a call — a result with no EARLIER assistant message emitting its id (its call is gone,
|
|
19
|
+
* or it was recorded ahead of its call) answers nothing in this view and is left out. This is the one rule for
|
|
20
|
+
* that shape on every request builder (the harness's request lane and the side query alike).
|
|
21
|
+
*
|
|
22
|
+
* The three lanes carry the same requirement in three spellings — the Anthropic Messages API rejects a `tool_use`
|
|
23
|
+
* followed by any non-`tool_use` block (between two calls as after the last), or whose `tool_result` is not in the
|
|
24
|
+
* very next message; chat completions requires the `tool` messages right after the assistant's `tool_calls`; the
|
|
25
|
+
* Responses API requires a `function_call_output` for every `function_call` — and each brain's own builder only ever
|
|
26
|
+
* merged ADJACENT results. One transcript that
|
|
27
|
+
* breaks the structure (a result recorded late, a note written after the calls) was therefore rejected on every
|
|
28
|
+
* later request of its session. Holding the law here, once, at the provider boundary means the three brains read
|
|
29
|
+
* the canonical form, and a session already carrying a broken turn is repaired on its next request.
|
|
30
|
+
*
|
|
31
|
+
* Attribution (some gateways number calls per request, so an id legitimately recurs across turns): a result belongs
|
|
32
|
+
* to the NEAREST EARLIER assistant message that emitted its id — and to nothing else: its recorded tool name is not a
|
|
33
|
+
* key. That is the persisted reconcile's positional reading (a call is answered by a result standing after it and
|
|
34
|
+
* before the id's next use), so the two readers never disagree about which occurrence a result answers; a name-based
|
|
35
|
+
* reading (7.37.1) reached back past turns the model had already answered.
|
|
36
|
+
* An earlier occurrence of a reused id that has no result before the next use is therefore closed as
|
|
37
|
+
* interrupted (outcome unknown), never handed a later occurrence's success; every result after the last use is that
|
|
38
|
+
* use's (two or more are folded). A result with no earlier call carrying its id is left out (iii). Pure and
|
|
39
|
+
* deterministic (a moved result keeps its object; a synthesized one takes its assistant's timestamp), so the same
|
|
40
|
+
* transcript yields the same request bytes and the prefix cache holds.
|
|
41
|
+
* The close the view synthesizes carries NO tool-effect refinement: the view holds no tool table and no record of
|
|
42
|
+
* which calls started, so every call it closes reads the reconcile family's conservative "outcome unknown — verify"
|
|
43
|
+
* wording, whatever the tool. (The persisted reconcile refines with the run's tool effects — a read-only or
|
|
44
|
+
* idempotent call's close says it may simply be re-issued — and, on a live abort, with the calls it saw start.)
|
|
45
|
+
* Returns the SAME array when nothing needed restoring.
|
|
46
|
+
*/
|
|
47
|
+
import type { AssertAllKeysHandled } from "../../core/ask-origin.js";
|
|
48
|
+
import type { AssistantMessageDiagnostic } from "./diagnostics.js";
|
|
49
|
+
import type { Message } from "./types.js";
|
|
50
|
+
/** What the law restored — the `forms` of a `context.tool_turn_repaired` notice. */
|
|
51
|
+
export declare const TOOL_TURN_REPAIR_FORMS: readonly ["trailing_text", "late_result", "missing_result", "duplicate_result", "duplicate_call", "orphan_result"];
|
|
52
|
+
export type ToolTurnRepairForm = (typeof TOOL_TURN_REPAIR_FORMS)[number];
|
|
53
|
+
/** Does the form leave recorded content out of the request (a call, a result), rather than move, fold or add it?
|
|
54
|
+
* A request that did is a lossy projection of the session — the harness never seeds a fork summary from it. */
|
|
55
|
+
export declare const TOOL_TURN_REPAIR_DROPS: {
|
|
56
|
+
readonly trailing_text: false;
|
|
57
|
+
readonly late_result: false;
|
|
58
|
+
readonly missing_result: false;
|
|
59
|
+
readonly duplicate_result: false;
|
|
60
|
+
readonly duplicate_call: true;
|
|
61
|
+
readonly orphan_result: true;
|
|
62
|
+
};
|
|
63
|
+
export type DropsTableCoversEveryForm = AssertAllKeysHandled<Exclude<ToolTurnRepairForm, keyof typeof TOOL_TURN_REPAIR_DROPS>>;
|
|
64
|
+
/**
|
|
65
|
+
* Why a tool turn reached the model incomplete — the `task.tool_turn_incomplete` notice's `detail.cause`, the person's
|
|
66
|
+
* view of facts the model is already told in the turn itself. Closed:
|
|
67
|
+
* · `truncated` — calls whose argument bytes were cut before they parsed: dropped, the model asked to re-issue them;
|
|
68
|
+
* · `unnamed` — calls that arrived with no tool name: dropped the same way;
|
|
69
|
+
* · `bad_frame` — provider stream frames that were not valid JSON: dropped, so the response may be missing content;
|
|
70
|
+
* · `missing_result_synthesized` — a call with no recorded result, closed in the request view as interrupted with its
|
|
71
|
+
* outcome unknown (the `missing_result` repair).
|
|
72
|
+
* The first three are a brain's stream facts ({@link StreamDropCause}), stamped on the turn's own message; the fourth is
|
|
73
|
+
* the request view's.
|
|
74
|
+
*/
|
|
75
|
+
export declare const TOOL_TURN_INCOMPLETE_CAUSES: readonly ["truncated", "unnamed", "bad_frame", "missing_result_synthesized"];
|
|
76
|
+
export type ToolTurnIncompleteCause = (typeof TOOL_TURN_INCOMPLETE_CAUSES)[number];
|
|
77
|
+
/** The causes a brain's stream parse finds — what a turn's own message can report. */
|
|
78
|
+
export type StreamDropCause = Exclude<ToolTurnIncompleteCause, "missing_result_synthesized">;
|
|
79
|
+
/** One cause a turn's stream dropped content for, and how many calls (or frames) it dropped. */
|
|
80
|
+
export interface StreamDrop {
|
|
81
|
+
readonly cause: StreamDropCause;
|
|
82
|
+
readonly count: number;
|
|
83
|
+
}
|
|
84
|
+
/** Stamp a turn's stream drops on its message (`AssistantMessage.diagnostics`); nothing for a turn that dropped none. */
|
|
85
|
+
export declare function stampStreamDrops(message: {
|
|
86
|
+
diagnostics?: AssistantMessageDiagnostic[];
|
|
87
|
+
}, drops: readonly StreamDrop[]): void;
|
|
88
|
+
/** The stream drops a message reports. A host brain's message is not trusted to be well-formed: an entry counts only
|
|
89
|
+
* with a closed-set cause and a positive integer count; anything else reads as no drop. */
|
|
90
|
+
export declare function streamDropsOf(message: {
|
|
91
|
+
readonly diagnostics?: unknown;
|
|
92
|
+
}): StreamDrop[];
|
|
93
|
+
/** One restoration: on one assistant message, or — for `orphan_result` — on the view as a whole. */
|
|
94
|
+
export interface ToolTurnRepair {
|
|
95
|
+
readonly form: ToolTurnRepairForm;
|
|
96
|
+
/** The calls concerned, in call order — for `trailing_text` every call of the message; for `duplicate_call` the
|
|
97
|
+
* ids a later call of the message repeated; for `orphan_result` the ids of the results left out, once each, in
|
|
98
|
+
* transcript order; otherwise the calls whose result was moved up, synthesized, or folded with a second one. */
|
|
99
|
+
readonly toolCallIds: readonly string[];
|
|
100
|
+
}
|
|
101
|
+
export interface ToolTurnView {
|
|
102
|
+
/** The request view — the input array itself when {@link repairs} is empty. */
|
|
103
|
+
readonly messages: Message[];
|
|
104
|
+
readonly repairs: readonly ToolTurnRepair[];
|
|
105
|
+
}
|
|
106
|
+
/** The text standing between two results recorded for one call when the view folds them into one. */
|
|
107
|
+
export declare const SECOND_RESULT_SEPARATOR = "[another result was recorded for this same call:]";
|
|
108
|
+
/** Restore the tool-turn law on a provider-bound message list (see the module header). */
|
|
109
|
+
export declare function ensureToolTurnInvariants(messages: Message[]): ToolTurnView;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { interruptedResultMessage, interruptedResults, isInterruptedClose } from "../../core/session-reconcile.js";
|
|
2
|
+
export const TOOL_TURN_REPAIR_FORMS = Object.freeze(["trailing_text", "late_result", "missing_result", "duplicate_result", "duplicate_call", "orphan_result"]);
|
|
3
|
+
export const TOOL_TURN_REPAIR_DROPS = {
|
|
4
|
+
trailing_text: false,
|
|
5
|
+
late_result: false,
|
|
6
|
+
missing_result: false,
|
|
7
|
+
duplicate_result: false,
|
|
8
|
+
duplicate_call: true,
|
|
9
|
+
orphan_result: true,
|
|
10
|
+
};
|
|
11
|
+
export const TOOL_TURN_INCOMPLETE_CAUSES = Object.freeze(["truncated", "unnamed", "bad_frame", "missing_result_synthesized"]);
|
|
12
|
+
const STREAM_DROPS_DIAGNOSTIC = "stream_drops";
|
|
13
|
+
const STREAM_DROP_CAUSES = new Set(["truncated", "unnamed", "bad_frame"]);
|
|
14
|
+
export function stampStreamDrops(message, drops) {
|
|
15
|
+
if (drops.length === 0)
|
|
16
|
+
return;
|
|
17
|
+
message.diagnostics = [...(message.diagnostics ?? []), { type: STREAM_DROPS_DIAGNOSTIC, timestamp: Date.now(), details: { drops: drops.map(({ cause, count }) => ({ cause, count })) } }];
|
|
18
|
+
}
|
|
19
|
+
export function streamDropsOf(message) {
|
|
20
|
+
const out = [];
|
|
21
|
+
try {
|
|
22
|
+
const diagnostics = message.diagnostics;
|
|
23
|
+
if (!Array.isArray(diagnostics))
|
|
24
|
+
return out;
|
|
25
|
+
const entries = diagnostics;
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
if (typeof entry !== "object" || entry === null || entry.type !== STREAM_DROPS_DIAGNOSTIC)
|
|
28
|
+
continue;
|
|
29
|
+
const drops = (entry.details ?? {}).drops;
|
|
30
|
+
if (!Array.isArray(drops))
|
|
31
|
+
continue;
|
|
32
|
+
const items = drops;
|
|
33
|
+
for (const d of items) {
|
|
34
|
+
const cause = d?.cause;
|
|
35
|
+
const count = d?.count;
|
|
36
|
+
if (typeof cause === "string" && STREAM_DROP_CAUSES.has(cause) && typeof count === "number" && Number.isInteger(count) && count > 0)
|
|
37
|
+
out.push({ cause: cause, count });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
function callsOf(m) {
|
|
47
|
+
return m.role === "assistant" && Array.isArray(m.content) ? m.content.filter((c) => c?.type === "toolCall") : [];
|
|
48
|
+
}
|
|
49
|
+
export const SECOND_RESULT_SEPARATOR = "[another result was recorded for this same call:]";
|
|
50
|
+
export function ensureToolTurnInvariants(messages) {
|
|
51
|
+
const anchor = [];
|
|
52
|
+
messages.forEach((m, i) => anchor.push(m.role === "toolResult" && i > 0 ? anchor[i - 1] : i));
|
|
53
|
+
const sites = new Map();
|
|
54
|
+
const ownerOf = new Map();
|
|
55
|
+
const resultsOf = new Map();
|
|
56
|
+
const orphans = new Set();
|
|
57
|
+
messages.forEach((m, i) => {
|
|
58
|
+
if (m.role === "assistant") {
|
|
59
|
+
for (const call of callsOf(m)) {
|
|
60
|
+
const list = sites.get(call.id) ?? [];
|
|
61
|
+
if (list.at(-1) !== i)
|
|
62
|
+
list.push(i);
|
|
63
|
+
sites.set(call.id, list);
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (m.role !== "toolResult")
|
|
68
|
+
return;
|
|
69
|
+
const all = sites.get(m.toolCallId) ?? [];
|
|
70
|
+
if (all.length === 0) {
|
|
71
|
+
orphans.add(i);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const owner = all.at(-1);
|
|
75
|
+
ownerOf.set(i, owner);
|
|
76
|
+
const batch = resultsOf.get(owner);
|
|
77
|
+
if (batch === undefined)
|
|
78
|
+
resultsOf.set(owner, [i]);
|
|
79
|
+
else
|
|
80
|
+
batch.push(i);
|
|
81
|
+
});
|
|
82
|
+
const repairs = [];
|
|
83
|
+
const out = [];
|
|
84
|
+
messages.forEach((m, i) => {
|
|
85
|
+
if (ownerOf.has(i) || orphans.has(i))
|
|
86
|
+
return;
|
|
87
|
+
const calls = callsOf(m);
|
|
88
|
+
if (calls.length === 0) {
|
|
89
|
+
out.push(m);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const assistant = m;
|
|
93
|
+
const byId = new Map();
|
|
94
|
+
const repeated = [];
|
|
95
|
+
for (const call of calls) {
|
|
96
|
+
if (!byId.has(call.id))
|
|
97
|
+
byId.set(call.id, call);
|
|
98
|
+
else if (!repeated.includes(call.id))
|
|
99
|
+
repeated.push(call.id);
|
|
100
|
+
}
|
|
101
|
+
const ids = [...byId.keys()];
|
|
102
|
+
const firstCall = assistant.content.findIndex((c) => c?.type === "toolCall");
|
|
103
|
+
const trails = assistant.content.slice(firstCall).some((c) => c?.type !== "toolCall");
|
|
104
|
+
out.push(trails || repeated.length > 0 ? { ...assistant, content: [...assistant.content.filter((c) => c?.type !== "toolCall"), ...byId.values()] } : assistant);
|
|
105
|
+
if (trails)
|
|
106
|
+
repairs.push({ form: "trailing_text", toolCallIds: ids });
|
|
107
|
+
if (repeated.length > 0)
|
|
108
|
+
repairs.push({ form: "duplicate_call", toolCallIds: repeated });
|
|
109
|
+
const recorded = new Map();
|
|
110
|
+
for (const r of resultsOf.get(i) ?? []) {
|
|
111
|
+
const id = messages[r].toolCallId;
|
|
112
|
+
recorded.set(id, [...(recorded.get(id) ?? []), r]);
|
|
113
|
+
}
|
|
114
|
+
const sent = new Map();
|
|
115
|
+
const late = [];
|
|
116
|
+
const duplicate = [];
|
|
117
|
+
for (const [id, at] of recorded) {
|
|
118
|
+
const real = at.filter((r) => !isInterruptedClose(messages[r]));
|
|
119
|
+
const chosen = real.length > 0 ? real : at.slice(0, 1);
|
|
120
|
+
sent.set(id, chosen.map((r) => messages[r]).reduce(foldResults));
|
|
121
|
+
if (anchor[chosen[0]] !== i)
|
|
122
|
+
late.push(id);
|
|
123
|
+
if (at.length > 1)
|
|
124
|
+
duplicate.push(id);
|
|
125
|
+
}
|
|
126
|
+
out.push(...sent.values());
|
|
127
|
+
const missing = [...byId.values()].filter((c) => !sent.has(c.id));
|
|
128
|
+
for (const result of interruptedResults(missing.map((c) => ({ toolCallId: c.id, toolName: c.name })))) {
|
|
129
|
+
out.push(interruptedResultMessage(result, assistant.timestamp));
|
|
130
|
+
}
|
|
131
|
+
const inCallOrder = (set) => ids.filter((id) => set.includes(id));
|
|
132
|
+
if (late.length > 0)
|
|
133
|
+
repairs.push({ form: "late_result", toolCallIds: inCallOrder(late) });
|
|
134
|
+
if (missing.length > 0)
|
|
135
|
+
repairs.push({ form: "missing_result", toolCallIds: missing.map((c) => c.id) });
|
|
136
|
+
if (duplicate.length > 0)
|
|
137
|
+
repairs.push({ form: "duplicate_result", toolCallIds: inCallOrder(duplicate) });
|
|
138
|
+
});
|
|
139
|
+
if (orphans.size > 0)
|
|
140
|
+
repairs.push({ form: "orphan_result", toolCallIds: [...new Set([...orphans].map((i) => messages[i].toolCallId))] });
|
|
141
|
+
return repairs.length === 0 ? { messages, repairs } : { messages: out, repairs };
|
|
142
|
+
}
|
|
143
|
+
function foldResults(first, second) {
|
|
144
|
+
return { ...first, content: [...first.content, { type: "text", text: SECOND_RESULT_SEPARATOR }, ...second.content], isError: first.isError && second.isError };
|
|
145
|
+
}
|
|
@@ -434,6 +434,17 @@ export interface AssistantMessage {
|
|
|
434
434
|
* as `0`.
|
|
435
435
|
*/
|
|
436
436
|
apiErrorStatus?: number;
|
|
437
|
+
/**
|
|
438
|
+
* The provider's own word for a REFUSED request, read structurally from its JSON error envelope (`error.code`, else
|
|
439
|
+
* `error.type`) — e.g. `invalid_request_error`, `context_length_exceeded`. Only meaningful together with
|
|
440
|
+
* {@link isApiErrorMessage}; provider vocabulary, never an engine closed set.
|
|
441
|
+
*
|
|
442
|
+
* PRESENCE: only beside a 4xx {@link apiErrorStatus} (the provider refused the request as sent) whose envelope stated
|
|
443
|
+
* such a word in the provider echo shape (visible ASCII, 1–128 characters). ABSENT otherwise — any other status, a
|
|
444
|
+
* plain-text or torn body, an envelope with neither member, or a word outside the shape (dropped whole, never
|
|
445
|
+
* truncated). The run's `terminal.detail.code` is this value.
|
|
446
|
+
*/
|
|
447
|
+
apiErrorCode?: string;
|
|
437
448
|
diagnostics?: AssistantMessageDiagnostic[];
|
|
438
449
|
usage: Usage;
|
|
439
450
|
/** TB 尸检 T1-5: the provider never delivered a usage frame for this message (e.g. a
|
package/dist/index.d.ts
CHANGED
|
@@ -63,8 +63,10 @@ export { MCP_FAILURE_KINDS, MCP_DELIVERY_VERDICTS, MCP_LIVENESS_STATES, classify
|
|
|
63
63
|
export { MCP_INJECTION_DROP_REASONS, MCP_INJECTION_DROP_TEXT, mcpInjectionDroppedNotice, type McpInjectionDropReason, type McpInjectionDropFacts } from "./core/mcp-injection-drop.js";
|
|
64
64
|
export { askUnresolvableNotice, type AskUnresolvableFacts } from "./core/ask-unresolvable-notice.js";
|
|
65
65
|
export { ASK_UNRESOLVABLE_CAUSES } from "./core/ask-unresolvable-notice.js";
|
|
66
|
+
export { USER_STEER_UNDRAINED_CAUSES, type UserSteerUndrainedCause } from "./core/engine-notice.js";
|
|
67
|
+
export { TOOL_TURN_INCOMPLETE_CAUSES, type ToolTurnIncompleteCause } from "./internal/llm.js";
|
|
66
68
|
export { DURABLE_MANDATE_SOURCES } from "./core/tool-policy.js";
|
|
67
|
-
export { TERMINAL_CAUSE_IS_REPLAYABLE } from "./core/terminal-cause.js";
|
|
69
|
+
export { TERMINAL_CAUSE_IS_REPLAYABLE, type TerminalFailureDetail } from "./core/terminal-cause.js";
|
|
68
70
|
export { RESERVED_AGENT_NAMES } from "./agents/subagent.js";
|
|
69
71
|
export { WORKFLOW_SIZE_GUIDELINE_AGENT_CAPS } from "./orchestration/workflow-size-guideline.js";
|
|
70
72
|
export { ENGINE_AUTHORITY_ENVELOPE_TAGS } from "./core/untrusted-text.js";
|
|
@@ -79,7 +81,7 @@ export { BUILTIN_COMPLIANCE_DENIES, COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME
|
|
|
79
81
|
export { admitMemoryScopes, foldAdmissionFreeze, type OwnOrgAdmissionVerdict, type MemoryAdmissionInput, type MemoryAdmissionOutcome, type MemoryAdmissionVerdict, type MemoryScopeAdmission, type MemoryScopeOrigin, type MemoryScopeRequest, } from "./core/memory-admission.js";
|
|
80
82
|
export { assertRetentionCapability, RETENTION_CASCADE_DOMAINS, RETENTION_CASCADE_EXEMPT, type ManagedRetentionCapability, type RetentionDeclaration, type RetentionDeclaring, type RetentionPolicy, type RetentionReceipt, } from "./core/retention.js";
|
|
81
83
|
export { GOVERNANCE_CODES, governanceRetryClass, TOOL_DECLARATION_CODES, type GovernanceCode, type GovernanceRetryClass, type ToolDeclarationCode } from "./core/governance-codes.js";
|
|
82
|
-
export { NOTICE_AUDIENCE, noticeAudienceOf, ENGINE_NOTICE_CODES, type EngineNoticeCode, type NoticeAudience } from "./core/governance-codes.js";
|
|
84
|
+
export { NOTICE_AUDIENCE, noticeAudienceOf, ENGINE_NOTICE_CODES, NOTICE_MINTER, type EngineNoticeCode, type NoticeAudience, type NoticeMinter } from "./core/governance-codes.js";
|
|
83
85
|
export { TtlSessionStore, type TtlSessionStoreOptions, type EvictPolicy } from "./core/session-store.js";
|
|
84
86
|
export { reconcileInterruptedSession, findOrphanToolCalls, type OrphanToolCall, type ReconcileReport, } from "./core/session-reconcile.js";
|
|
85
87
|
export { StoredSession, InMemorySessionRepo, InMemorySessionStorage, BaseSessionStorage, leafIdAfterEntry, validateEntriesForImport, StreamingImportValidator, boundedTail, SessionError, isSessionConflict, hasSessionFork, uuidv7, type Session, type SessionStore, type AcquiredSession, type SessionStoreSummary, type SessionStorage, type SessionRepo, type SessionMetadata, type SessionTreeEntry, type SessionWriteOptions, type SessionPlacement, type SessionPlacementRecord, type PlacedSessionRow, } from "./core/session.js";
|
|
@@ -191,7 +193,7 @@ export { createAllowDenyPolicy, createApprovalPolicy,
|
|
|
191
193
|
* `Parameters<typeof createApprovalPolicy>[0]["approve"]`. */
|
|
192
194
|
type ApprovalSeatOutcome, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, wrapToolPolicy, decisionText, resolveAsk, toolPolicyNameSets, toolPolicyPathDenyRules, type ToolPolicyNameSets, type NamedToolPolicy, type ToolPolicyProjection, type ToolPolicyProjectionComponent, type ConstraintChainEntry, checkToolPolicyProjection, constraintChainEntryOf, constraintChainDigest, type ToolPolicy, type ToolCallRequest, type PermissionResult, type DecisionReason, screenApproverAttribution, APPROVER_ATTRIBUTION_MAX_CHARS, type OnAsk, type AskOutcome, type ResolvedAsk, type AskRequest, type AskDelegationProvenance, type AskRuleEvidence, type AskEvidenceAbsence, ASK_EVIDENCE_ABSENCE_VALUES, } from "./core/tool-policy.js";
|
|
193
195
|
export { type ReadRootGrantScreen } from "./core/read-root-grant-screen.js";
|
|
194
|
-
export { type AskOrigin, ASK_ORIGINS, isAskOrigin, ORIGIN_IMPLIES_REAL_APPROVAL, PERSISTED_RULE_MANDATES, type PersistedRuleMandate, isPersistedRuleMandate } from "./core/ask-origin.js";
|
|
196
|
+
export { type AskOrigin, ASK_ORIGINS, isAskOrigin, ORIGIN_IMPLIES_REAL_APPROVAL, PERSISTED_RULE_MANDATES, type PersistedRuleMandate, isPersistedRuleMandate, screenAskClassMembers } from "./core/ask-origin.js";
|
|
195
197
|
export { PERMISSION_MODES, type PermissionMode, isPermissionMode, PERMISSION_MODE_RANK, clampPermissionMode, ASK_CLASSES, type AskClass, isAskClass, MODE_ARBITRATION, type ModeArbitrationRow, RELEASABLE_ASK_CLASSES, MODE_RELEASE_REASONS, type ModeReleaseReason, isModeReleaseReason, RRA_EXPLAINERS, classifyAsk, foldArbitrationRow, type AskClassification, type AskClassFacts, type ToolMarkSource, arbitrateByMode, type Arbitration, fileCommandOptionsSentence } from "./core/ask-origin.js";
|
|
196
198
|
export { modePolicyOf, type ModePolicy, PERMISSION_MODE_FOLD_REASONS, type PermissionModeFoldReason, type PermissionModeReceipt, ACCEPT_EDITS_FILE_COMMANDS, modeAcceptsFileCommand } from "./core/mode-policy.js";
|
|
197
199
|
export { readDenyClassifierRules, renderClassifierDenyRules, type DerivedDenyRule } from "./core/auto-mode-prompt.js";
|
package/dist/index.js
CHANGED
|
@@ -49,6 +49,8 @@ export { MCP_FAILURE_KINDS, MCP_DELIVERY_VERDICTS, MCP_LIVENESS_STATES, classify
|
|
|
49
49
|
export { MCP_INJECTION_DROP_REASONS, MCP_INJECTION_DROP_TEXT, mcpInjectionDroppedNotice } from "./core/mcp-injection-drop.js";
|
|
50
50
|
export { askUnresolvableNotice } from "./core/ask-unresolvable-notice.js";
|
|
51
51
|
export { ASK_UNRESOLVABLE_CAUSES } from "./core/ask-unresolvable-notice.js";
|
|
52
|
+
export { USER_STEER_UNDRAINED_CAUSES } from "./core/engine-notice.js";
|
|
53
|
+
export { TOOL_TURN_INCOMPLETE_CAUSES } from "./internal/llm.js";
|
|
52
54
|
export { DURABLE_MANDATE_SOURCES } from "./core/tool-policy.js";
|
|
53
55
|
export { TERMINAL_CAUSE_IS_REPLAYABLE } from "./core/terminal-cause.js";
|
|
54
56
|
export { RESERVED_AGENT_NAMES } from "./agents/subagent.js";
|
|
@@ -65,7 +67,7 @@ export { BUILTIN_COMPLIANCE_DENIES, COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME
|
|
|
65
67
|
export { admitMemoryScopes, foldAdmissionFreeze, } from "./core/memory-admission.js";
|
|
66
68
|
export { assertRetentionCapability, RETENTION_CASCADE_DOMAINS, RETENTION_CASCADE_EXEMPT, } from "./core/retention.js";
|
|
67
69
|
export { GOVERNANCE_CODES, governanceRetryClass, TOOL_DECLARATION_CODES } from "./core/governance-codes.js";
|
|
68
|
-
export { NOTICE_AUDIENCE, noticeAudienceOf, ENGINE_NOTICE_CODES } from "./core/governance-codes.js";
|
|
70
|
+
export { NOTICE_AUDIENCE, noticeAudienceOf, ENGINE_NOTICE_CODES, NOTICE_MINTER } from "./core/governance-codes.js";
|
|
69
71
|
export { TtlSessionStore } from "./core/session-store.js";
|
|
70
72
|
export { reconcileInterruptedSession, findOrphanToolCalls, } from "./core/session-reconcile.js";
|
|
71
73
|
export { StoredSession, InMemorySessionRepo, InMemorySessionStorage, BaseSessionStorage, leafIdAfterEntry, validateEntriesForImport, StreamingImportValidator, boundedTail, SessionError, isSessionConflict, hasSessionFork, uuidv7, } from "./core/session.js";
|
|
@@ -156,7 +158,7 @@ export { resolveAutonomousLoopPrompt, AUTONOMOUS_LOOP_PREAMBLE, AUTONOMOUS_LOOP_
|
|
|
156
158
|
export { tightenTaskSpec, TaskSpecTightenError } from "./core/tighten-task-spec.js";
|
|
157
159
|
export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, wrapToolPolicy, decisionText, resolveAsk, toolPolicyNameSets, toolPolicyPathDenyRules, checkToolPolicyProjection, constraintChainEntryOf, constraintChainDigest, screenApproverAttribution, APPROVER_ATTRIBUTION_MAX_CHARS, ASK_EVIDENCE_ABSENCE_VALUES, } from "./core/tool-policy.js";
|
|
158
160
|
export {} from "./core/read-root-grant-screen.js";
|
|
159
|
-
export { ASK_ORIGINS, isAskOrigin, ORIGIN_IMPLIES_REAL_APPROVAL, PERSISTED_RULE_MANDATES, isPersistedRuleMandate } from "./core/ask-origin.js";
|
|
161
|
+
export { ASK_ORIGINS, isAskOrigin, ORIGIN_IMPLIES_REAL_APPROVAL, PERSISTED_RULE_MANDATES, isPersistedRuleMandate, screenAskClassMembers } from "./core/ask-origin.js";
|
|
160
162
|
export { PERMISSION_MODES, isPermissionMode, PERMISSION_MODE_RANK, clampPermissionMode, ASK_CLASSES, isAskClass, MODE_ARBITRATION, RELEASABLE_ASK_CLASSES, MODE_RELEASE_REASONS, isModeReleaseReason, RRA_EXPLAINERS, classifyAsk, foldArbitrationRow, arbitrateByMode, fileCommandOptionsSentence } from "./core/ask-origin.js";
|
|
161
163
|
export { modePolicyOf, PERMISSION_MODE_FOLD_REASONS, ACCEPT_EDITS_FILE_COMMANDS, modeAcceptsFileCommand } from "./core/mode-policy.js";
|
|
162
164
|
export { readDenyClassifierRules, renderClassifierDenyRules } from "./core/auto-mode-prompt.js";
|
package/dist/internal/llm.d.ts
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* design/118 ①②: the layer is now first-party (`src/engine/llm/`, naturalized out of the vendored
|
|
5
5
|
* llm-core); the facade stays so consumers never notice which side a symbol lives on.
|
|
6
6
|
*/
|
|
7
|
-
export { createAssistantMessageEventStream, snapshotActorAssertion, stripEngineMetadata } from "../engine/llm/index.js";
|
|
8
|
-
export type { ActorAssertion, AnthropicMessagesCompat, OpenAICompletionsCompat, OpenAIResponsesCompat, AssistantMessage, AssistantMessageDiagnostic, AssistantMessageEvent, CompleteSimpleFn, Context, DocumentContent, ImageContent, Message, Model, ResilienceOptions, RouteAdjudication, RouteCredential, RouteCredentialSource, RoutePairingConfig, RoutePairingPosture, RouteRefusalCode, RouteRefusalDetail, SimpleStreamOptions, StallTimeouts, StopReason, StreamFn, TextContent, ThinkingContent, Tool, ToolCall, ToolResultMessage, Usage, UserMessage, } from "../engine/llm/index.js";
|
|
7
|
+
export { createAssistantMessageEventStream, ensureToolTurnInvariants, snapshotActorAssertion, stampStreamDrops, streamDropsOf, stripEngineMetadata, TOOL_TURN_INCOMPLETE_CAUSES, TOOL_TURN_REPAIR_DROPS } from "../engine/llm/index.js";
|
|
8
|
+
export type { ActorAssertion, AnthropicMessagesCompat, OpenAICompletionsCompat, OpenAIResponsesCompat, AssistantMessage, AssistantMessageDiagnostic, AssistantMessageEvent, CompleteSimpleFn, Context, DocumentContent, ImageContent, Message, Model, ResilienceOptions, RouteAdjudication, RouteCredential, RouteCredentialSource, RoutePairingConfig, RoutePairingPosture, RouteRefusalCode, RouteRefusalDetail, SimpleStreamOptions, StallTimeouts, StopReason, StreamFn, TextContent, ThinkingContent, Tool, ToolCall, ToolResultMessage, StreamDrop, StreamDropCause, ToolTurnIncompleteCause, ToolTurnRepair, Usage, UserMessage, } from "../engine/llm/index.js";
|
package/dist/internal/llm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { createAssistantMessageEventStream, snapshotActorAssertion, stripEngineMetadata } from "../engine/llm/index.js";
|
|
1
|
+
export { createAssistantMessageEventStream, ensureToolTurnInvariants, snapshotActorAssertion, stampStreamDrops, streamDropsOf, stripEngineMetadata, TOOL_TURN_INCOMPLETE_CAUSES, TOOL_TURN_REPAIR_DROPS } from "../engine/llm/index.js";
|
|
@@ -15,7 +15,7 @@ export class WorkflowModelNotAllowedError extends Error {
|
|
|
15
15
|
this.name = "WorkflowModelNotAllowedError";
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
export const WHITELIST_KEYS = [
|
|
18
|
+
export const WHITELIST_KEYS = Object.freeze([
|
|
19
19
|
"objective",
|
|
20
20
|
"modelName",
|
|
21
21
|
"thinking",
|
|
@@ -25,7 +25,7 @@ export const WHITELIST_KEYS = [
|
|
|
25
25
|
"readFace",
|
|
26
26
|
"writeFace",
|
|
27
27
|
"readDenyPatterns",
|
|
28
|
-
];
|
|
28
|
+
]);
|
|
29
29
|
const WHITELIST_KEY_SET = new Set(WHITELIST_KEYS);
|
|
30
30
|
export const SPEC_KEY_ALIASES = new Map([["model", "modelName"]]);
|
|
31
31
|
export const STRIPPED_KEYS_NOTICE_CODE = "workflow.governance_key_stripped";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export const PARK_TRUTH_UNREADABLE_REASONS = ["store_threw", "record_missing", "record_not_terminal", "parks_unreadable", "admission_incomplete", "checkpoint_store_threw", "capability_not_armed"];
|
|
2
|
-
export const PARK_NOT_PENDING_STATUSES = ["resolved", "expired", "absent"];
|
|
1
|
+
export const PARK_TRUTH_UNREADABLE_REASONS = Object.freeze(["store_threw", "record_missing", "record_not_terminal", "parks_unreadable", "admission_incomplete", "checkpoint_store_threw", "capability_not_armed"]);
|
|
2
|
+
export const PARK_NOT_PENDING_STATUSES = Object.freeze(["resolved", "expired", "absent"]);
|
|
3
3
|
export class WorkflowBudgetExceededError extends Error {
|
|
4
4
|
spent;
|
|
5
5
|
total;
|
package/dist/shell/lex.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const SHELL_LEX_DIALECT = "bash";
|
|
2
|
-
export const QUOTE_KINDS = ["'", '"', "$'", '$"', "\\"];
|
|
3
|
-
export const EXPANSION_KINDS = ["parameter", "command", "process", "arithmetic", "tilde", "brace", "glob"];
|
|
4
|
-
export const UNRESOLVED_REASONS = ["ansi_c_escape", "locale_string", "parameter_text", "subscript_text", "compound_array_value"];
|
|
2
|
+
export const QUOTE_KINDS = Object.freeze(["'", '"', "$'", '$"', "\\"]);
|
|
3
|
+
export const EXPANSION_KINDS = Object.freeze(["parameter", "command", "process", "arithmetic", "tilde", "brace", "glob"]);
|
|
4
|
+
export const UNRESOLVED_REASONS = Object.freeze(["ansi_c_escape", "locale_string", "parameter_text", "subscript_text", "compound_array_value"]);
|
|
5
5
|
export const UNRESOLVED_SENTENCE = {
|
|
6
6
|
ansi_c_escape: "an ANSI-C quoted word carries an escape this lexer does not fold",
|
|
7
7
|
locale_string: "a locale-translated string carries text this lexer does not read",
|
|
@@ -9,7 +9,7 @@ export const UNRESOLVED_SENTENCE = {
|
|
|
9
9
|
subscript_text: "a subscript carries text this lexer does not read",
|
|
10
10
|
compound_array_value: "a compound assignment value is a list this lexer does not read",
|
|
11
11
|
};
|
|
12
|
-
export const PARSE_FAILURE_REASONS = [
|
|
12
|
+
export const PARSE_FAILURE_REASONS = Object.freeze([
|
|
13
13
|
"unterminated_single_quote",
|
|
14
14
|
"unterminated_double_quote",
|
|
15
15
|
"unterminated_ansi_c",
|
|
@@ -23,7 +23,7 @@ export const PARSE_FAILURE_REASONS = [
|
|
|
23
23
|
"redirect_without_target",
|
|
24
24
|
"heredoc_without_delimiter",
|
|
25
25
|
"heredoc_delimiter_expands",
|
|
26
|
-
];
|
|
26
|
+
]);
|
|
27
27
|
export const PARSE_FAILURE_SENTENCE = {
|
|
28
28
|
unterminated_single_quote: "a single-quoted word never closes",
|
|
29
29
|
unterminated_double_quote: "a double-quoted word never closes",
|
|
@@ -39,7 +39,7 @@ export const PARSE_FAILURE_SENTENCE = {
|
|
|
39
39
|
heredoc_without_delimiter: "a here-document operator names no delimiter",
|
|
40
40
|
heredoc_delimiter_expands: "a here-document delimiter is not a plain word",
|
|
41
41
|
};
|
|
42
|
-
export const BASH_ONLY_CONSTRUCTS = [
|
|
42
|
+
export const BASH_ONLY_CONSTRUCTS = Object.freeze([
|
|
43
43
|
"ansi_c_quoting",
|
|
44
44
|
"locale_string",
|
|
45
45
|
"append_assignment",
|
|
@@ -50,7 +50,7 @@ export const BASH_ONLY_CONSTRUCTS = [
|
|
|
50
50
|
"redirect_both",
|
|
51
51
|
"pipe_both",
|
|
52
52
|
"brace_expansion",
|
|
53
|
-
];
|
|
53
|
+
]);
|
|
54
54
|
export const ANSI_C_ESCAPES = {
|
|
55
55
|
a: "\x07",
|
|
56
56
|
b: "\b",
|