@sema-agent/core 7.49.4 → 7.50.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 +152 -0
- package/dist/agents/observer.js +3 -10
- package/dist/agents/peer-directory.d.ts +8 -3
- package/dist/agents/peer-directory.js +5 -3
- package/dist/agents/subagent-steps.d.ts +6 -14
- package/dist/agents/subagent-steps.js +3 -17
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/core/allow-entry.d.ts +1 -1
- package/dist/core/allow-entry.js +1 -1
- package/dist/core/ask-origin.d.ts +15 -11
- package/dist/core/ask-origin.js +6 -14
- package/dist/core/auto-mode-prompt.js +6 -2
- package/dist/core/checkpoint-store.d.ts +6 -4
- package/dist/core/checkpoint-store.js +1 -1
- package/dist/core/context-edit.d.ts +2 -2
- package/dist/core/decision-receipt.d.ts +2 -2
- package/dist/core/decision-receipt.js +30 -11
- package/dist/core/delegation-frames.d.ts +66 -18
- package/dist/core/delegation-frames.js +22 -0
- package/dist/core/engine-notice.d.ts +7 -5
- package/dist/core/frame-settlement.d.ts +6 -1
- package/dist/core/gate-fold.js +19 -13
- package/dist/core/gate-lanes.js +12 -11
- package/dist/core/gate-outcome.d.ts +2 -2
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/hooks.d.ts +28 -20
- package/dist/core/human-input-projection.js +2 -0
- package/dist/core/lsp-diagnostics.d.ts +3 -0
- package/dist/core/lsp-diagnostics.js +6 -0
- package/dist/core/lsp-session.d.ts +39 -17
- package/dist/core/lsp-session.js +118 -58
- package/dist/core/lsp.d.ts +83 -3
- package/dist/core/lsp.js +146 -16
- package/dist/core/mcp.js +2 -1
- package/dist/core/media-byte-cap.d.ts +14 -0
- package/dist/core/media-byte-cap.js +15 -3
- package/dist/core/memory-engine/consolidation-driver.d.ts +23 -1
- package/dist/core/memory-engine/consolidation-driver.js +54 -6
- package/dist/core/memory-engine/consolidation-write-gate.d.ts +46 -0
- package/dist/core/memory-engine/consolidation-write-gate.js +82 -0
- package/dist/core/memory-engine/consolidation.d.ts +17 -0
- package/dist/core/memory-engine/consolidation.js +1 -0
- package/dist/core/memory-engine/distiller.d.ts +8 -2
- package/dist/core/memory-engine/distiller.js +8 -6
- package/dist/core/memory-engine/engine.d.ts +37 -4
- package/dist/core/memory-engine/engine.js +127 -38
- package/dist/core/memory-engine/file-backend.d.ts +8 -3
- package/dist/core/memory-engine/file-backend.js +44 -16
- package/dist/core/memory-engine/index.d.ts +2 -2
- package/dist/core/memory-engine/index.js +1 -1
- package/dist/core/memory-engine/landing-admission.d.ts +65 -0
- package/dist/core/memory-engine/landing-admission.js +68 -0
- package/dist/core/memory-engine/types.d.ts +23 -0
- package/dist/core/mode-policy.d.ts +3 -2
- package/dist/core/mode-policy.js +2 -0
- package/dist/core/permission-rule-model.d.ts +19 -13
- package/dist/core/permission-rule-model.js +7 -4
- package/dist/core/permission-rule-provider.d.ts +11 -0
- package/dist/core/permission-rules.d.ts +1 -1
- package/dist/core/permission-rules.js +5 -2
- package/dist/core/persisted-rule-arms.d.ts +15 -7
- package/dist/core/persisted-rule-arms.js +13 -6
- package/dist/core/posix-mode-face.d.ts +10 -0
- package/dist/core/posix-mode-face.js +3 -0
- package/dist/core/reminder-mint.d.ts +5 -0
- package/dist/core/reminder-mint.js +1 -0
- package/dist/core/retired-keys.d.ts +8 -0
- package/dist/core/retired-keys.js +4 -0
- package/dist/core/rule-lane-reads.d.ts +4 -4
- package/dist/core/rule-lane-reads.js +10 -1
- package/dist/core/runner/construction-doors.d.ts +10 -4
- package/dist/core/runner/construction-doors.js +25 -2
- package/dist/core/runner/contracts.d.ts +20 -3
- package/dist/core/runner/env-capability-census.js +1 -1
- package/dist/core/runner/gate-exit.js +2 -1
- package/dist/core/runner/memory-consolidation-driver.d.ts +6 -4
- package/dist/core/runner/memory-consolidation-driver.js +5 -2
- package/dist/core/runner/memory-consolidation-write-judge.d.ts +17 -0
- package/dist/core/runner/memory-consolidation-write-judge.js +14 -0
- package/dist/core/runner/permission-rule-lanes.d.ts +16 -22
- package/dist/core/runner/permission-rule-lanes.js +13 -43
- package/dist/core/runner/person-path-rows.d.ts +244 -0
- package/dist/core/runner/person-path-rows.js +387 -0
- package/dist/core/runner/prepare-acquire-reconcile.js +8 -1
- package/dist/core/runner/prepare-artifact.d.ts +5 -3
- package/dist/core/runner/prepare-artifact.js +2 -8
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -3
- package/dist/core/runner/prepare-caps-and-workflow.js +1 -1
- package/dist/core/runner/prepare-context-lane.js +2 -2
- package/dist/core/runner/prepare-gate-stations.d.ts +3 -3
- package/dist/core/runner/prepare-gate-stations.js +1 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +19 -10
- package/dist/core/runner/prepare-hands-readface.js +57 -43
- package/dist/core/runner/prepare-lsp.d.ts +15 -13
- package/dist/core/runner/prepare-lsp.js +11 -11
- package/dist/core/runner/prepare-policy-chain.d.ts +8 -4
- package/dist/core/runner/prepare-policy-chain.js +6 -7
- package/dist/core/runner/prepare-run-refs.js +1 -1
- package/dist/core/runner/prepare-task.js +24 -16
- package/dist/core/runner/prepare-turn-wiring.d.ts +13 -6
- package/dist/core/runner/prepare-turn-wiring.js +19 -8
- package/dist/core/runner/read-root-grant.d.ts +1 -25
- package/dist/core/runner/read-root-grant.js +1 -17
- package/dist/core/runner/retired-runner-deps.d.ts +2 -2
- package/dist/core/runner/run-brain-sinks.d.ts +1 -5
- package/dist/core/runner/run-brain-sinks.js +2 -4
- package/dist/core/runner/run-harness-handlers.js +5 -4
- package/dist/core/runner/run-identity-wiring.d.ts +4 -4
- package/dist/core/runner/run-identity-wiring.js +10 -1
- package/dist/core/runner/run-leg.d.ts +1 -1
- package/dist/core/runner/run-leg.js +22 -9
- package/dist/core/runner/run-settle-and-teardown.d.ts +0 -4
- package/dist/core/runner/run-settle-and-teardown.js +7 -4
- package/dist/core/runner/run-terminal-adoption.d.ts +1 -1
- package/dist/core/runner/run-terminal-adoption.js +1 -1
- package/dist/core/runner/run-turn-boundary.js +2 -2
- package/dist/core/runner/runtask.js +8 -8
- package/dist/core/runner/session-file-state-replay.d.ts +14 -4
- package/dist/core/runner/session-file-state-replay.js +8 -0
- package/dist/core/runner/stream-steer-verb.js +3 -0
- package/dist/core/runner/tool-end-body.d.ts +5 -4
- package/dist/core/runner/tool-end-body.js +4 -4
- package/dist/core/runner/tool-output-projection.d.ts +6 -4
- package/dist/core/runner/tool-output-projection.js +66 -47
- package/dist/core/runner-deps.d.ts +6 -3
- package/dist/core/shared-memory/types.d.ts +2 -2
- package/dist/core/shell-read-silence.d.ts +23 -0
- package/dist/core/shell-read-silence.js +18 -0
- package/dist/core/synthetic-read-verdict.d.ts +80 -21
- package/dist/core/synthetic-read-verdict.js +89 -18
- package/dist/core/task-event.d.ts +113 -25
- package/dist/core/task-spec.d.ts +44 -0
- package/dist/core/task-tool-shape.d.ts +1 -1
- package/dist/core/tool-catalog-entries.js +16 -2
- package/dist/core/tool-policy.d.ts +25 -15
- package/dist/core/tool-policy.js +9 -13
- package/dist/core/trace.d.ts +3 -2
- package/dist/core/types.d.ts +3 -3
- package/dist/core/types.js +1 -1
- package/dist/core/untrusted-text.d.ts +2 -2
- package/dist/core/user-attachment.d.ts +164 -0
- package/dist/core/user-attachment.js +437 -0
- package/dist/engine/compaction/compaction.js +10 -3
- package/dist/engine/compaction/utils.js +6 -0
- package/dist/engine/execution-env/node-execution-env.d.ts +19 -1
- package/dist/engine/execution-env/node-execution-env.js +127 -1
- package/dist/engine/harness/agent-harness.d.ts +12 -2
- package/dist/engine/harness/agent-harness.js +15 -3
- package/dist/engine/harness/types.d.ts +21 -0
- package/dist/engine/llm/content-block-render.d.ts +15 -0
- package/dist/engine/llm/content-block-render.js +10 -0
- package/dist/engine/llm/index.d.ts +1 -0
- package/dist/engine/llm/index.js +1 -0
- package/dist/engine/llm/types.d.ts +80 -4
- package/dist/engine/llm/types.js +43 -1
- package/dist/engine/session/import-validate.js +2 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +2 -1
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/llm.d.ts +2 -2
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/workflow.d.ts +4 -5
- package/dist/orchestration/workflow.js +2 -2
- package/dist/prompts/default.d.ts +1 -1
- package/dist/stores/file/permission-rule-store.d.ts +13 -1
- package/dist/stores/file/permission-rule-store.js +40 -21
- package/dist/tools/artifact/artifact-tool.js +1 -1
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/dir-entries.d.ts +4 -10
- package/dist/tools/fs/dir-entries.js +4 -11
- package/dist/tools/fs/file-read-check.js +3 -3
- package/dist/tools/fs/fs-pdf.js +2 -4
- package/dist/tools/fs/fs-read.d.ts +47 -4
- package/dist/tools/fs/fs-read.js +63 -19
- package/dist/tools/fs/fs-search-tools.d.ts +3 -3
- package/dist/tools/fs/fs-search-tools.js +7 -2
- package/dist/tools/fs/fs-write.d.ts +1 -1
- package/dist/tools/fs/fs-write.js +7 -6
- package/dist/tools/fs/index.d.ts +7 -1
- package/dist/tools/fs/index.js +56 -34
- package/dist/tools/fs/read-deny-home.d.ts +19 -1
- package/dist/tools/fs/read-deny-home.js +32 -22
- package/dist/tools/fs/read-deny.d.ts +14 -0
- package/dist/tools/fs/read-deny.js +8 -0
- package/dist/tools/fs/repo-map.d.ts +3 -2
- package/dist/tools/fs/repo-map.js +11 -3
- package/dist/tools/fs/safety.d.ts +41 -2
- package/dist/tools/fs/safety.js +12 -3
- package/dist/tools/fs/shell-read-check.d.ts +12 -3
- package/dist/tools/fs/shell-read-check.js +28 -15
- package/dist/tools/fs/shell-read-device.d.ts +1 -1
- package/dist/tools/fs/shell-read-judge.d.ts +9 -4
- package/dist/tools/fs/shell-read-judge.js +1 -1
- package/dist/tools/loop-tick.d.ts +2 -2
- package/package.json +3 -1
- package/test/export-surface.snapshot.json +39 -1
- package/wire-changes/core@7.49.5.json +104 -0
- package/wire-changes/core@7.50.0.json +1699 -0
- package/dist/core/runner/persisted-path-rows.d.ts +0 -88
- package/dist/core/runner/persisted-path-rows.js +0 -108
package/dist/core/task-spec.d.ts
CHANGED
|
@@ -31,6 +31,39 @@ export type ImageInput = {
|
|
|
31
31
|
/** URL the runner will fetch and inline as base64 before sending to the model. */
|
|
32
32
|
url: string;
|
|
33
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
* One file the user attached to the objective, by WHO HOLDS ITS BYTES (never by what kind of file it is — the engine
|
|
36
|
+
* finds that out and reports it):
|
|
37
|
+
* - `{ path, lines? }` — a file or directory the engine can reach in its workspace: the engine reads it through the
|
|
38
|
+
* Read tool's own read and admission (read-deny table, roots, the run's deny rules), as if the model had read it,
|
|
39
|
+
* minus the questions — the user's declaration is the answer to an ordinary ask; a read some layer would put to a
|
|
40
|
+
* person other than the asker (an organization rule, a deployment-authored or real-approval ask) is not attached.
|
|
41
|
+
* `lines` reads a line range (1-based, `end` inclusive).
|
|
42
|
+
* - `{ name, text, startLine? }` — text the host holds (a local file a remote engine cannot reach, an unsaved buffer):
|
|
43
|
+
* delivered as given, line-numbered from `startLine` (default 1). It opens nothing an objective could not carry,
|
|
44
|
+
* and records no read state.
|
|
45
|
+
* - `{ name, image: { data, mimeType } }` — an image file the host holds (base64), admitted like an image the Read tool
|
|
46
|
+
* serves.
|
|
47
|
+
* Each attachment reaches the model as its own message right after the objective, marked as the engine's: two
|
|
48
|
+
* marked sentences around the data, the name or path only in the data. See `USER_ATTACHMENT_SEAT` for the limits.
|
|
49
|
+
*/
|
|
50
|
+
export type UserAttachment = {
|
|
51
|
+
readonly path: string;
|
|
52
|
+
readonly lines?: {
|
|
53
|
+
readonly start: number;
|
|
54
|
+
readonly end?: number;
|
|
55
|
+
};
|
|
56
|
+
} | {
|
|
57
|
+
readonly name: string;
|
|
58
|
+
readonly text: string;
|
|
59
|
+
readonly startLine?: number;
|
|
60
|
+
} | {
|
|
61
|
+
readonly name: string;
|
|
62
|
+
readonly image: {
|
|
63
|
+
readonly data: string;
|
|
64
|
+
readonly mimeType: string;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
34
67
|
/** A single self-contained task with its full configuration. */
|
|
35
68
|
/** The shell-gate FLOOR vocabulary — {@link TaskSpec.shellGate}'s value set, the word the engine persists on a
|
|
36
69
|
* shell-gated ask (`RiskDescriptor.shellGateDoctrine`) and carries down a delegation chain. One value: `"always"`
|
|
@@ -133,6 +166,17 @@ export interface TaskSpec {
|
|
|
133
166
|
interactiveQuestionFallback?: boolean;
|
|
134
167
|
/** Optional images attached to this turn's user message (model must support vision). */
|
|
135
168
|
images?: ImageInput[];
|
|
169
|
+
/**
|
|
170
|
+
* Files the user attached to this objective ({@link UserAttachment}): at most 20, delivered after the
|
|
171
|
+
* UserPromptSubmit hook lets the objective through (a hook that blocks it reads nothing), each as its own
|
|
172
|
+
* engine-minted message right after the objective. A path entry needs a workspace (hands on). A malformed entry,
|
|
173
|
+
* a text entry over the Read limit (100 000 rendered characters), an image the API would not accept, a path entry
|
|
174
|
+
* on a run without a workspace, or any entry on a durable resume leg is refused at the door:
|
|
175
|
+
* `config.user_attachment_invalid`, the message opening with the field path (`TaskSpec.userAttachments[2].text: …`).
|
|
176
|
+
* A file the engine may not read is not refused: its message says it was not attached and why, and the
|
|
177
|
+
* `human_input` event's `attachments[]` reports each outcome.
|
|
178
|
+
*/
|
|
179
|
+
userAttachments?: readonly UserAttachment[];
|
|
136
180
|
/** Reuse an existing in-memory session for chat continuity; omit to start fresh. */
|
|
137
181
|
sessionId?: string;
|
|
138
182
|
/**
|
|
@@ -44,7 +44,7 @@ export interface TaskToolCapabilities {
|
|
|
44
44
|
/** TaskStop accepts a background agent's spawn NAME as task_id (registry name resolution only). */
|
|
45
45
|
nameAddressing: boolean;
|
|
46
46
|
}
|
|
47
|
-
/** Full-capability profile = the registry-backed mount with notifications wired (CC
|
|
47
|
+
/** Full-capability profile = the registry-backed mount with notifications wired (CC 209 verbatim form). */
|
|
48
48
|
export declare const REGISTRY_TASK_TOOL_CAPS: TaskToolCapabilities;
|
|
49
49
|
/** The env-direct thin-shell profile: cursor polling over a background shell, nothing else. */
|
|
50
50
|
export declare const ENV_DIRECT_TASK_TOOL_CAPS: TaskToolCapabilities;
|
|
@@ -97,8 +97,22 @@ export const TOOL_CATALOG_ENTRIES = [
|
|
|
97
97
|
compactable: true,
|
|
98
98
|
},
|
|
99
99
|
},
|
|
100
|
-
{
|
|
101
|
-
|
|
100
|
+
{
|
|
101
|
+
id: "repo-map", name: "RepoMap", source: "builtin", definedIn: "src/tools/fs/repo-map.ts", mountedBy: ["hands"], cards: ["repo-map"],
|
|
102
|
+
face: {
|
|
103
|
+
family: "search", effect: "read", contract: c("core.repo_map@1"),
|
|
104
|
+
pathTarget: { param: "path", access: "read", base: "root", absent: "base" },
|
|
105
|
+
ruleFace: { params: ["path", "max_chars", "max_files"] },
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: "lsp", name: "LSP", source: "builtin", definedIn: "src/core/lsp.ts", mountedBy: ["hands"], cards: [],
|
|
110
|
+
face: {
|
|
111
|
+
family: "search", effect: "read", contract: c("core.lsp@1"),
|
|
112
|
+
pathTarget: { param: "filePath", access: "read", base: "cwd", absent: "none" },
|
|
113
|
+
ruleFace: { params: ["operation", "filePath", "line", "character", "query"] },
|
|
114
|
+
},
|
|
115
|
+
},
|
|
102
116
|
{
|
|
103
117
|
id: "artifact", name: ARTIFACT_TOOL_NAME, source: "builtin", definedIn: "src/tools/artifact/artifact-tool.ts", mountedBy: ["optional"], cards: ["artifact"],
|
|
104
118
|
face: { family: "other", effect: "write", contract: c("core.artifact@1"), ruleFace: { primaryParams: ["action"] }, renderHints: { summaryParams: ["action", "file_path", "url"] } },
|
|
@@ -234,6 +234,9 @@ export interface EngineAttestation {
|
|
|
234
234
|
readonly unresolvableCause?: import("./ask-unresolvable-notice.js").AskUnresolvableCause;
|
|
235
235
|
/** The classes of the asks a policy fold collapsed — the proof behind a decision's `foldedAskClasses`. */
|
|
236
236
|
readonly foldedClasses?: readonly import("./ask-origin.js").AskClass[];
|
|
237
|
+
/** Where a path deny row refused the call — the row, the view of the target it met, the face the call is on. The gate's
|
|
238
|
+
* exit mints the refusal's card from it; the judge that found the row is its only writer. */
|
|
239
|
+
readonly pathDenial?: import("../tools/fs/safety.js").PathDenialEvidence;
|
|
237
240
|
}
|
|
238
241
|
/** The members a station attests — everything but the call binding. */
|
|
239
242
|
export type AttestationMembers = Omit<EngineAttestation, "toolCallId" | "toolName">;
|
|
@@ -302,6 +305,8 @@ export declare function screenApproverAttribution(v: unknown): {
|
|
|
302
305
|
approver?: string;
|
|
303
306
|
defect?: string;
|
|
304
307
|
};
|
|
308
|
+
/** An integrity guard an ask stands on ({@link PermissionResult}'s `guards`). */
|
|
309
|
+
export type AskGuard = "dangerous_delete" | "unverifiable_delete" | "unverifiable_shell_text" | "transcript_write" | "artifact_shared_read";
|
|
305
310
|
/**
|
|
306
311
|
* A three-state permission decision for a tool call (design/37). Upgrades the old two-state
|
|
307
312
|
* `{allow|deny}`:
|
|
@@ -327,11 +332,13 @@ export declare function screenApproverAttribution(v: unknown): {
|
|
|
327
332
|
* record ({@link EngineAttestation}) the receipt refuses in any other form, and the gate's exit mints the one
|
|
328
333
|
* settlement record ({@link import("./gate-outcome.js").GateOutcome}) from it; a policy that puts a `settledBy`
|
|
329
334
|
* or `approver` member on its verdict is putting an unread property on it.
|
|
330
|
-
* RB-479-B① (ruled 2026-08-02): the legacy `reason` field is REMOVED — one name for one thing.
|
|
335
|
+
* RB-479-B① (ruled 2026-08-02): the legacy `reason` field is REMOVED — one name for one thing. The ask arm's one-word
|
|
336
|
+
* `guard` is retired the same way, for `guards`.
|
|
331
337
|
*
|
|
332
338
|
* The TYPE carries that retirement only where a decision is a literal in an annotated position; an inferred `check`
|
|
333
|
-
* return compiles green with a stray `reason`, so the enforcement is at RUNTIME — every point that consumes a
|
|
334
|
-
* refuses one
|
|
339
|
+
* return compiles green with a stray `reason` or `guard`, so the enforcement is at RUNTIME — every point that consumes a
|
|
340
|
+
* decision refuses one that carries a retired member ({@link RETIRED_DECISION_MEMBERS}), fail-closed
|
|
341
|
+
* ({@link refuseOutOfContractDecision}).
|
|
335
342
|
*/
|
|
336
343
|
export type PermissionResult = {
|
|
337
344
|
action: "allow";
|
|
@@ -454,18 +461,21 @@ export type PermissionResult = {
|
|
|
454
461
|
/** The ask's whole class set, in {@link import("./ask-origin.js").ASK_CLASSES} order (see
|
|
455
462
|
* {@link AskRequest.classes}). Stamped beside {@link askClass}, under the same rule. */
|
|
456
463
|
classes?: readonly import("./ask-origin.js").AskClass[];
|
|
457
|
-
/** WHICH integrity
|
|
458
|
-
* shell text the engine cannot read or
|
|
459
|
-
*
|
|
460
|
-
*
|
|
461
|
-
*
|
|
462
|
-
|
|
464
|
+
/** WHICH integrity guards stand behind this ask — a removal of a protected location, an unverifiable recursive delete,
|
|
465
|
+
* shell text the engine cannot read (or an environment that did not answer the read station), the session-transcript
|
|
466
|
+
* write. A set: one ask may stand on several, and each keeps its class. ENGINE-STAMPED by the guard policies and the
|
|
467
|
+
* gate fold; a fold-internal fact the class derivation reads ({@link import("./ask-origin.js").classifyAsk}) so the
|
|
468
|
+
* guards, which mint the same `requiresRealApproval` ask, are told apart by a fact and not by their prose. Never
|
|
469
|
+
* copied onto the approval request or the park row. Replaces the one-word `guard`, which a decision no longer carries:
|
|
470
|
+
* a decision that still does is refused by name ({@link RETIRED_DECISION_MEMBERS}). */
|
|
471
|
+
guards?: readonly AskGuard[];
|
|
463
472
|
/** The call could not be READ against a rule that may reach it — a content-form deny row, a content-form
|
|
464
|
-
* ask row,
|
|
465
|
-
*
|
|
473
|
+
* ask row, a persisted-rule row (the lexer's word), or rows the shell read station's boundary stands on that
|
|
474
|
+
* could not be read (`persisted_rows`). ENGINE-STAMPED at the four unreadable mint sites;
|
|
475
|
+
* the class derivation reads it as `rule_unreadable` (no mode releases it, a person may clear it, no
|
|
466
476
|
* automatic lane may). It replaces the former practice of stamping `matchedAskRule` on an unreadable
|
|
467
477
|
* read: a rule that COULD NOT be matched is not a rule that matched. Fold-internal; not on the request. */
|
|
468
|
-
ruleUnreadable?: "content_deny" | "content_ask" | "persisted_call";
|
|
478
|
+
ruleUnreadable?: "content_deny" | "content_ask" | "persisted_call" | "persisted_rows";
|
|
469
479
|
/** The ask was authored by the DEPLOYMENT's own governance (an operator's must-ask list, a managed command
|
|
470
480
|
* policy's default ask) — a fact a host's policy states on its own ask so the class derivation reads it
|
|
471
481
|
* as `operator_forced`: a permission mode releases nothing an operator mandated (`dontAsk` refuses it like
|
|
@@ -853,8 +863,8 @@ export declare const DECISION_MEMBERS: readonly DecisionMember[];
|
|
|
853
863
|
* taken off the carrier's own descriptor (a member outside the contract is neither read nor carried — a policy's self-declared
|
|
854
864
|
* record on another name finds no reader); any other spelling refused by name — an accessor (never invoked), a member the
|
|
855
865
|
* prototype or a non-enumerable property supplies unless that descriptor spells absence (an `undefined` data value) — judged by
|
|
856
|
-
* descriptor, never read; (3)
|
|
857
|
-
*
|
|
866
|
+
* descriptor, never read; (3) a retired member ({@link RETIRED_DECISION_MEMBERS}: `reason`, `guard`) carried by the same presence law as a contract
|
|
867
|
+
* member — own, held by an accessor, or supplied by the prototype — judged without a read (ignoring it silently dropped the policy's text or the ask's guard); (4) the VALUES, off the engine's
|
|
858
868
|
* one-read record, never a second read of the caller's object — the retired window absent, `action` in
|
|
859
869
|
* its closed set (`screenContractValues`, decision-receipt.ts — every closed-set member is held to its set there; a consumer ranks a decision by testing two of its words, so any other value used to rank as an
|
|
860
870
|
* allow; a `canUseTool` result outside its set is a failure in CC) and `decisionReason` in {@link DECISION_REASONS} when
|
|
@@ -1085,7 +1095,7 @@ export declare function createCoarseCommandNamePolicy(opts: {
|
|
|
1085
1095
|
tools?: string[];
|
|
1086
1096
|
}): ToolPolicy;
|
|
1087
1097
|
/**
|
|
1088
|
-
* CC 220 "Unverifiable Deletion Target" parity (auto-mode rule): ASK on a recursive+forced delete whose
|
|
1098
|
+
* CC 220 "Unverifiable Deletion Target" parity (auto-mode rule; its text is in 220–245, gone from 2.1.250 on): ASK on a recursive+forced delete whose
|
|
1089
1099
|
* target is a variable / substitution that cannot be resolved from the command itself — fail-closed in the
|
|
1090
1100
|
* sense that with no live classifier/approver the ask degrades to deny (see {@link PermissionResult}'s
|
|
1091
1101
|
* `ask` doc), never to allow. The guard reads ONE plan, the read station's (`removalReadingOf`,
|
package/dist/core/tool-policy.js
CHANGED
|
@@ -16,7 +16,7 @@ import { boundInputHashOf } from "./canonical-json.js";
|
|
|
16
16
|
import { delimitUntrusted, inlineUntrusted, REVIEWER_NOTE_MAX_BODY } from "./untrusted-text.js";
|
|
17
17
|
import { describeRejectedValue } from "./tool-search-setting.js";
|
|
18
18
|
import { thrownText } from "./thrown-value.js";
|
|
19
|
-
import { assertNoRetiredToolPolicyKeys } from "./retired-keys.js";
|
|
19
|
+
import { assertNoRetiredToolPolicyKeys, RETIRED_DECISION_MEMBERS } from "./retired-keys.js";
|
|
20
20
|
import { isEngineRefusal, nestedRecordsOf, receiveContract, receiveNestedRecords, refusedOutOfContract, screenContractValues } from "./decision-receipt.js";
|
|
21
21
|
export { isEngineRefusal } from "./decision-receipt.js";
|
|
22
22
|
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers, parsePermissionRule } from "./permission-rules.js";
|
|
@@ -43,6 +43,7 @@ const ATTESTATION_GROUP_OF = {
|
|
|
43
43
|
classifierRound: "classifierRound",
|
|
44
44
|
unresolvableCause: "unresolvableCause",
|
|
45
45
|
foldedClasses: "foldedClasses",
|
|
46
|
+
pathDenial: "pathDenial",
|
|
46
47
|
};
|
|
47
48
|
const ATTESTATION_MEMBERS = Object.keys(ATTESTATION_GROUP_OF);
|
|
48
49
|
const groupLead = (g) => ATTESTATION_MEMBERS.find((k) => ATTESTATION_GROUP_OF[k] === g);
|
|
@@ -238,18 +239,15 @@ export function constraintChainDigest(chain) {
|
|
|
238
239
|
}
|
|
239
240
|
const ALLOW = Object.freeze({ action: "allow" });
|
|
240
241
|
const ALLOW_BY_RULE = Object.freeze({ action: "allow", decisionReason: "rule" });
|
|
241
|
-
const RETIRED_TEXT_FIELD = "reason";
|
|
242
242
|
export const DECISION_MEMBERS = Object.keys({
|
|
243
243
|
action: 0, updatedInput: 0, message: 0, decisionReason: 0, requiresRealApproval: 0, denialLimitFallback: 0, classifierNoRuling: 0, allowRuleShadowed: 0, probeReason: 0,
|
|
244
244
|
probeCause: 0, probeMandated: 0, mandated: 0, mandate: 0, probeReadRootCandidate: 0, matchedAskRule: 0, ruleEvidence: 0, segmentCoverage: 0,
|
|
245
|
-
origin: 0, askClass: 0, classes: 0,
|
|
245
|
+
origin: 0, askClass: 0, classes: 0, guards: 0, ruleUnreadable: 0, authoredBy: 0, foldedAskClasses: 0, attestation: 0,
|
|
246
246
|
});
|
|
247
247
|
const HOOK_RESULT_MEMBERS = [...DECISION_MEMBERS, "additionalContext"];
|
|
248
248
|
const HOOK_SEAM_UNREAD = new Set(["decisionReason"]);
|
|
249
249
|
const HOOK_SEAM_OPTIONAL = new Set(["action"]);
|
|
250
250
|
const HOOK_RECEIPTS = new WeakSet();
|
|
251
|
-
const RETIRED_TEXT_FIELD_DENY_MESSAGE = `a permission decision carries the retired "${RETIRED_TEXT_FIELD}" field — rename it to "message" (the one text field ` +
|
|
252
|
-
`a decision carries); denied fail-closed rather than executing a decision whose text this layer cannot read`;
|
|
253
251
|
const ENGINE_RECEIPTS = new WeakSet();
|
|
254
252
|
export function refuseOutOfContractDecision(d, opts) {
|
|
255
253
|
const hookSeam = opts?.reasonIsNonInput === true;
|
|
@@ -260,11 +258,9 @@ export function refuseOutOfContractDecision(d, opts) {
|
|
|
260
258
|
}
|
|
261
259
|
if ((hookSeam ? HOOK_RECEIPTS : ENGINE_RECEIPTS).has(d) || isEngineRefusal(d))
|
|
262
260
|
return d;
|
|
263
|
-
const decision = receiveContract(d, hookSeam ? HOOK_RESULT_MEMBERS : DECISION_MEMBERS, "");
|
|
261
|
+
const decision = receiveContract(d, hookSeam ? HOOK_RESULT_MEMBERS : DECISION_MEMBERS, "", RETIRED_DECISION_MEMBERS);
|
|
264
262
|
if (decision.kind === "refused")
|
|
265
263
|
return decision.refused;
|
|
266
|
-
if (Object.prototype.hasOwnProperty.call(d, RETIRED_TEXT_FIELD))
|
|
267
|
-
return refusedOutOfContract(RETIRED_TEXT_FIELD_DENY_MESSAGE);
|
|
268
264
|
const contract = decision.held;
|
|
269
265
|
const refused = receiveNestedRecords(contract) ?? screenContractValues(contract, hookSeam ? { skip: HOOK_SEAM_UNREAD, optional: HOOK_SEAM_OPTIONAL } : undefined);
|
|
270
266
|
if (refused !== undefined)
|
|
@@ -293,9 +289,9 @@ export function refuseOutOfContractDecision(d, opts) {
|
|
|
293
289
|
`the engine keeps its own copy of what it read; denied fail-closed`);
|
|
294
290
|
}
|
|
295
291
|
const receipt = Object.freeze(attestation !== undefined ? { ...detached.value, attestation } : detached.value);
|
|
296
|
-
for (const
|
|
297
|
-
if (
|
|
298
|
-
Object.freeze(
|
|
292
|
+
for (const v of Object.values(receipt))
|
|
293
|
+
if (Array.isArray(v))
|
|
294
|
+
Object.freeze(v);
|
|
299
295
|
for (const record of nestedRecordsOf(receipt)) {
|
|
300
296
|
for (const v of Object.values(record))
|
|
301
297
|
if (Array.isArray(v))
|
|
@@ -711,7 +707,7 @@ function removalAsk(guard, text) {
|
|
|
711
707
|
unverifiable_delete: `Unverifiable recursive delete (fail-closed unless cleared): ${text}. Re-run the delete with the resolved literal path written into the command itself (or assign the variable a literal path in the same command, e.g. \`DIR=/exact/path; rm -rf "$DIR"\`) so the target can be verified.`,
|
|
712
708
|
unverifiable_shell_text: `Unverifiable shell text (fail-closed unless cleared): ${text}. Write the text into the command itself (a \`-c\` string, a here-document or a here-string) and the engine reads it as it reads any command.`,
|
|
713
709
|
};
|
|
714
|
-
return { action: "ask", decisionReason: "safety", requiresRealApproval: true, guard, message: messages[guard] };
|
|
710
|
+
return { action: "ask", decisionReason: "safety", requiresRealApproval: true, guards: [guard], message: messages[guard] };
|
|
715
711
|
}
|
|
716
712
|
function pathSegments(p) {
|
|
717
713
|
return p.split(/[\\/]/).filter(Boolean);
|
|
@@ -784,7 +780,7 @@ export function createTranscriptIntegrityPolicy(opts) {
|
|
|
784
780
|
action: "ask",
|
|
785
781
|
decisionReason: "safety",
|
|
786
782
|
requiresRealApproval: true,
|
|
787
|
-
|
|
783
|
+
guards: ["transcript_write"],
|
|
788
784
|
message: `Session-transcript write (fail-closed unless cleared): ${what}. Session transcripts (the .jsonl files ` +
|
|
789
785
|
`under the agent data dir's sessions/ directory) are harness-written session state, not agent working ` +
|
|
790
786
|
`files — modifying or deleting them tampers with the run's own audit trail. Reading them (ls/cat/grep ` +
|
package/dist/core/trace.d.ts
CHANGED
|
@@ -475,8 +475,9 @@ export type TraceEvent = {
|
|
|
475
475
|
} | {
|
|
476
476
|
/**
|
|
477
477
|
* design/179 — the person's persisted rule store could not be read (at prepare, or for one call), so
|
|
478
|
-
* that read's rows took no part:
|
|
479
|
-
* per-read record; the person hears it once per run
|
|
478
|
+
* that read's rows took no part: a call it served was judged without them — and, at a call, asks a person (the
|
|
479
|
+
* rows could hold a deny). The operator's per-read record; the person hears it once per run
|
|
480
|
+
* (`permission.rule_store_unavailable`).
|
|
480
481
|
*/
|
|
481
482
|
kind: "permission.rule_store_unreadable";
|
|
482
483
|
version: 1;
|
package/dist/core/types.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ import type { AgentTool, ThinkingLevel, ToolInputValidationContext, ToolInputVer
|
|
|
13
13
|
import type { Model, StreamFn } from "../internal/llm.js";
|
|
14
14
|
export type { ModelRef, ModelRole, RoleSpec, ModelRoles, Brain } from "./model-seat.js";
|
|
15
15
|
export { MODEL_ROLES } from "./model-seat.js";
|
|
16
|
-
export type { StaleToolResultOffloadOptions, ImageInput, TaskSpec, ShellGateDoctrine } from "./task-spec.js";
|
|
16
|
+
export type { StaleToolResultOffloadOptions, ImageInput, TaskSpec, ShellGateDoctrine, UserAttachment } from "./task-spec.js";
|
|
17
17
|
export type { PermissionMode } from "./ask-origin.js";
|
|
18
18
|
export type { ToolEffect, ToolContentOrigin, ReversibilityVerdict, ReadRootGrantCandidate, ToolSpec, ToolReturn, NestedUsage, NestedUsageAccum, ToolExecuteContext } from "./tool-spec.js";
|
|
19
19
|
export type { BeforeWriteRequest, BeforeWriteResult, BeforeWriteHook, TrackEditRequest, TrackEditResult, TrackFileEditHook, FileEditedNotice, FileEditedHook, HandsBandOptions } from "./hands-band.js";
|
|
@@ -22,12 +22,12 @@ export type { McpServerSpec, A2aServerSpec, McpElicitRequest, McpElicitResponse,
|
|
|
22
22
|
export type { TaskLimits } from "./task-limits.js";
|
|
23
23
|
export type { TaskStatus, RemoteEnvFailureNote, EffectiveMemoryScopes, TaskResult, HumanReviewGateRow } from "./task-result.js";
|
|
24
24
|
export type { TerminalCause, PausedCause } from "./terminal-cause.js";
|
|
25
|
-
export type { TaskEventIdentity, BrainStatusPhase, BrainRetryErrClass, BrainStatus, ToolActivity, HumanInputSource, HumanInputDelivery, DelegationTaskType, TaskEvent, HumanInputEvent, CompactOutcome } from "./task-event.js";
|
|
25
|
+
export type { TaskEventIdentity, BrainStatusPhase, BrainRetryErrClass, BrainStatus, ToolActivity, HumanInputSource, HumanInputDelivery, DelegationTaskType, TaskEvent, HumanInputEvent, HumanInputAttachment, CompactOutcome } from "./task-event.js";
|
|
26
26
|
export type { TaskStream } from "./task-stream.js";
|
|
27
27
|
export type { WorkflowGovernanceBaseline, RuntimeCaps, AutoModeDenySource } from "./runtime-caps.js";
|
|
28
28
|
export { AUTO_MODE_DENY_SOURCES, isAutoModeDenySource } from "./runtime-caps.js";
|
|
29
29
|
export type { BackgroundChildEvent, DelegationLifecycleEvent } from "./delegation-frames.js";
|
|
30
|
-
export { __resetMalformedDelegationSeatAnnouncement, deliverDelegationLifecycle } from "./delegation-frames.js";
|
|
30
|
+
export { __resetMalformedDelegationSeatAnnouncement, deliverDelegationLifecycle, emitsChildRowFrames, taskStartedFrame } from "./delegation-frames.js";
|
|
31
31
|
export type { ProjectMemoryLoad, ResumePreflightInfo, ResumePreflightVerdict, RunnerDeps } from "./runner-deps.js";
|
|
32
32
|
export type { EngineNotice, OwedUserInputAccount, UserInputUndrainedCause } from "./engine-notice.js";
|
|
33
33
|
export { __resetMalformedNoticeSeatAnnouncement, deliverEngineNotice, owedUserInputCounts, parentLegIds, settleOwedUserInput, undrainedUserInputNotices, USER_INPUT_UNDRAINED_CAUSES, USER_INPUT_UNDRAINED_FAMILIES } from "./engine-notice.js";
|
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
|
-
export { __resetMalformedDelegationSeatAnnouncement, deliverDelegationLifecycle } from "./delegation-frames.js";
|
|
3
|
+
export { __resetMalformedDelegationSeatAnnouncement, deliverDelegationLifecycle, emitsChildRowFrames, taskStartedFrame } from "./delegation-frames.js";
|
|
4
4
|
export { __resetMalformedNoticeSeatAnnouncement, deliverEngineNotice, owedUserInputCounts, parentLegIds, settleOwedUserInput, undrainedUserInputNotices, USER_INPUT_UNDRAINED_CAUSES, USER_INPUT_UNDRAINED_FAMILIES } from "./engine-notice.js";
|
|
@@ -330,8 +330,8 @@ export declare function cutEngineSegments(text: string, segments: unknown): {
|
|
|
330
330
|
* offsets are DEFINED: a user-lane message qualifies only when its content is a plain string or a
|
|
331
331
|
* SINGLE text block (whose text is that same string). Multi-block / image-bearing content returns
|
|
332
332
|
* `undefined` and consumers render the message VERBATIM with their own local flatten — the two
|
|
333
|
-
* projection sides flatten blocks DIFFERENTLY (the auto-mode window joins with `\n` + `[image]`
|
|
334
|
-
*
|
|
333
|
+
* projection sides flatten blocks DIFFERENTLY (the auto-mode window joins with `\n` + `[image: …]`
|
|
334
|
+
* block markers; the compaction serializer drops non-text blocks and joins with no separator), so a
|
|
335
335
|
* single `[start, end)` range would point at different characters on each side. The restriction
|
|
336
336
|
* costs nothing real: every engine-assembled prefixed/segmented message (first-frame objective
|
|
337
337
|
* concatenation, resume continuation) is minted from ONE plain string — the sole exception is a
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The USER-ATTACHMENT SEAT — the one road a file the user hands the model takes:
|
|
3
|
+
*
|
|
4
|
+
* the host declares it on the objective (`TaskSpec.userAttachments`) → the engine screens the declaration at the
|
|
5
|
+
* door → after the UserPromptSubmit hook lets the objective through, the engine reads a path entry with the Read
|
|
6
|
+
* tool's own read (`ModelFileReader.readForModel`) under the run's synthetic-Read judge, or takes the host's bytes →
|
|
7
|
+
* it mints ONE message per attachment that trails the human message: an engine note whose marked blocks hold only
|
|
8
|
+
* static sentences and whose data (the name or path, then the contents or the refusal) sits between them → the
|
|
9
|
+
* message's delivery record (`UserMessage.attachment`) is the one source of "what was delivered".
|
|
10
|
+
*
|
|
11
|
+
* This module owns the three steps no other module may repeat: the screen (`screenUserAttachments`), the mint
|
|
12
|
+
* (`readUserAttachments` → the frame seeds, the `human_input` projection and the pending commits) and the settlement
|
|
13
|
+
* (`createAttachmentDelivery`: a read's effects commit when its frame reaches the transcript, keyed by
|
|
14
|
+
* `(inputId, ordinal)` — never at read time, never by text).
|
|
15
|
+
*
|
|
16
|
+
* The frame, per attachment (blocks in order):
|
|
17
|
+
* <system-reminder mark="…">\n<opening sentence>\n</system-reminder>\n — static, the attachment's number only
|
|
18
|
+
* Path: "<declared path>"\n or Name: "<name>"\n — data (lossless quoted label)
|
|
19
|
+
* <data blocks> — the file's own blocks / the refusal
|
|
20
|
+
* \n\n<system-reminder mark="…">\n<note sentence>\n</system-reminder> — one per engine note, static
|
|
21
|
+
* \n\n<system-reminder mark="…">\nEnd of attachment <n>.\n</system-reminder>
|
|
22
|
+
* Every marked block after data opens after a blank line (`MARKED_BLOCK_AFTER_DATA`): the completions lanes join a
|
|
23
|
+
* message's text blocks with no separator.
|
|
24
|
+
*/
|
|
25
|
+
import type { ImageContent, TextContent, UserAttachmentSupply, UserMessageAttachment } from "../internal/llm.js";
|
|
26
|
+
import type { HumanInputAttachment } from "./task-event.js";
|
|
27
|
+
import { type ModelFileReader } from "../tools/fs/fs-read.js";
|
|
28
|
+
import type { SyntheticReadJudge } from "./synthetic-read-verdict.js";
|
|
29
|
+
import { type ReminderDisclosureCounts } from "./reminder-disclosure.js";
|
|
30
|
+
/** At most this many attachments on one objective. */
|
|
31
|
+
export declare const USER_ATTACHMENTS_MAX = 20;
|
|
32
|
+
/** The longest path or name an entry may carry (the platform path limit). */
|
|
33
|
+
export declare const USER_ATTACHMENT_LABEL_MAX = 4096;
|
|
34
|
+
/** What the engine found an attachment to be (an output, never declared): the Read lanes, a directory, host bytes. */
|
|
35
|
+
export declare const USER_ATTACHMENT_KINDS: readonly ["text", "notebook", "image", "pdf", "directory", "client_text", "client_image"];
|
|
36
|
+
/** Who held the bytes — the entry's arm. */
|
|
37
|
+
export declare const USER_ATTACHMENT_SUPPLIES: readonly ["path", "content_text", "content_image"];
|
|
38
|
+
/** What reached the model of an attachment's contents — the Read layer's own outcome words, the same frozen array. */
|
|
39
|
+
export declare const USER_ATTACHMENT_OUTCOMES: readonly ["attached", "partial", "unchanged", "not_attached"];
|
|
40
|
+
/**
|
|
41
|
+
* The seat's capability descriptor — what a host reads to decide, per attachment, whether to declare it here: its kind
|
|
42
|
+
* is in `kinds` and its arm in `supplies` ⇒ declare it on the objective; otherwise (a kind this seat does not carry, or
|
|
43
|
+
* an engine without the descriptor) the host carries it some other way. `entries`: the objective only — a steer carries
|
|
44
|
+
* no attachments (they go with the next objective).
|
|
45
|
+
*/
|
|
46
|
+
export declare const USER_ATTACHMENT_SEAT: Readonly<{
|
|
47
|
+
entries: readonly ["objective"];
|
|
48
|
+
kinds: readonly ["text", "notebook", "image", "pdf", "directory", "client_text", "client_image"];
|
|
49
|
+
supplies: readonly ["path", "content_text", "content_image"];
|
|
50
|
+
limits: Readonly<{
|
|
51
|
+
maxEntries: 20;
|
|
52
|
+
maxRenderedTextChars: 100000;
|
|
53
|
+
}>;
|
|
54
|
+
}>;
|
|
55
|
+
/** One declaration as the door captured it: the caller's object read once, members copied. */
|
|
56
|
+
export type ScreenedUserAttachment = {
|
|
57
|
+
readonly supply: "path";
|
|
58
|
+
readonly path: string;
|
|
59
|
+
readonly lines?: {
|
|
60
|
+
readonly start: number;
|
|
61
|
+
readonly end?: number;
|
|
62
|
+
};
|
|
63
|
+
} | {
|
|
64
|
+
readonly supply: "content_text";
|
|
65
|
+
readonly name: string;
|
|
66
|
+
readonly text: string;
|
|
67
|
+
readonly startLine: number;
|
|
68
|
+
readonly rendered: string;
|
|
69
|
+
} | {
|
|
70
|
+
readonly supply: "content_image";
|
|
71
|
+
readonly name: string;
|
|
72
|
+
readonly data: string;
|
|
73
|
+
readonly mimeType: string;
|
|
74
|
+
};
|
|
75
|
+
/** The door's refusal: one code, the field named first. */
|
|
76
|
+
export declare function userAttachmentRefusal(field: string, detail: string): Error & {
|
|
77
|
+
code: "config.user_attachment_invalid";
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* The door: screen the seat's value (synchronous; the caller's object is read once, member by member, before the
|
|
81
|
+
* first await of the run). `undefined` / an empty array ⇒ no attachments. `resumeLeg`: a durable resume mints no new
|
|
82
|
+
* human message, so any entry there is refused. Throws `config.user_attachment_invalid` naming the field.
|
|
83
|
+
*/
|
|
84
|
+
export declare function screenUserAttachments(seat: unknown, opts: {
|
|
85
|
+
resumeLeg: boolean;
|
|
86
|
+
}): readonly ScreenedUserAttachment[] | undefined;
|
|
87
|
+
/** A path entry on a run with no workspace: there is nothing the engine could read it from. */
|
|
88
|
+
export declare function refuseUserAttachmentPathsWithoutWorkspace(screened: readonly ScreenedUserAttachment[] | undefined): void;
|
|
89
|
+
/** One declared attachment as the UserPromptSubmit hook sees it (`UserPromptSubmitContext.userAttachments`). */
|
|
90
|
+
export interface UserAttachmentDeclaration {
|
|
91
|
+
/** 1-based position among the objective's attachments. */
|
|
92
|
+
readonly ordinal: number;
|
|
93
|
+
/** Who holds the bytes: `path` (the engine reads it), `content_text` / `content_image` (the host sent them). */
|
|
94
|
+
readonly supply: UserAttachmentSupply;
|
|
95
|
+
readonly path?: string;
|
|
96
|
+
readonly name?: string;
|
|
97
|
+
/** A host entry's size in bytes (text as UTF-8, an image decoded). */
|
|
98
|
+
readonly bytes?: number;
|
|
99
|
+
}
|
|
100
|
+
/** The UserPromptSubmit hook's view of the declarations. */
|
|
101
|
+
export declare function userAttachmentDeclarations(screened: readonly ScreenedUserAttachment[]): readonly UserAttachmentDeclaration[];
|
|
102
|
+
/**
|
|
103
|
+
* The host images' byte admission — the one function an image the Read tool serves passes. Asynchronous (it decodes),
|
|
104
|
+
* run on the captured values before any attachment is read or delivered. Throws `config.user_attachment_invalid`.
|
|
105
|
+
*/
|
|
106
|
+
export declare function admitUserAttachmentImages(screened: readonly ScreenedUserAttachment[]): Promise<ReadonlyMap<number, ImageContent>>;
|
|
107
|
+
/** One minted frame: the trailing message's seed, and the commit its delivery owes (absent ⇒ nothing to commit). */
|
|
108
|
+
export interface MintedAttachmentFrame {
|
|
109
|
+
readonly seed: {
|
|
110
|
+
readonly content: ReadonlyArray<TextContent | ImageContent>;
|
|
111
|
+
readonly attachment: UserMessageAttachment;
|
|
112
|
+
};
|
|
113
|
+
readonly commit?: () => void;
|
|
114
|
+
}
|
|
115
|
+
export interface ReadUserAttachmentsInput {
|
|
116
|
+
screened: readonly ScreenedUserAttachment[];
|
|
117
|
+
/** The human input the attachments belong to (minted before the frames and the event, shared by both). */
|
|
118
|
+
inputId: string;
|
|
119
|
+
/** The leg's one file reader (absent on a run without a workspace — then only host entries exist). */
|
|
120
|
+
reader: ModelFileReader | undefined;
|
|
121
|
+
/** The run's synthetic-Read judge. */
|
|
122
|
+
judge: SyntheticReadJudge;
|
|
123
|
+
/** The admitted host images, by ordinal. */
|
|
124
|
+
images: ReadonlyMap<number, ImageContent>;
|
|
125
|
+
/** The tracked working directory a relative path resolves against (the Read tool's own). */
|
|
126
|
+
cwd: string | undefined;
|
|
127
|
+
mark: string | undefined;
|
|
128
|
+
counts: ReminderDisclosureCounts | undefined;
|
|
129
|
+
signal: AbortSignal;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Read every declared attachment and mint its frame. Side-effect free toward the run: nothing is committed here — each
|
|
133
|
+
* frame carries the commit its delivery owes, run only when the frame is in the transcript.
|
|
134
|
+
*/
|
|
135
|
+
export declare function readUserAttachments(input: ReadUserAttachmentsInput): Promise<MintedAttachmentFrame[]>;
|
|
136
|
+
/** The objective lane's read: once the UserPromptSubmit hook let the objective through (a blocked objective reads
|
|
137
|
+
* nothing), and before the pre-call gate, which prices the frames (`chars`). Commits nothing. */
|
|
138
|
+
export declare function readObjectiveAttachments(prepared: Pick<import("./runner/contracts.js").Prepared, "userAttachments" | "modelFileReader" | "syntheticReadVerdict" | "cwdRef" | "reminderMark" | "reminderDisclosureCounts" | "abortController">, inputId: string, blocked: boolean): Promise<{
|
|
139
|
+
frames: MintedAttachmentFrame[];
|
|
140
|
+
chars: number;
|
|
141
|
+
}>;
|
|
142
|
+
/** The last attachment frame of the group the message `id` opens, or `id` when it has none (a `resumeAt` that keeps the
|
|
143
|
+
* message keeps its group). The frames of one input are appended one after another under its message (each the child of
|
|
144
|
+
* the one before), all carrying its input id. */
|
|
145
|
+
export declare function lastAttachmentFrameOf(entries: ReadonlyArray<{
|
|
146
|
+
id: string;
|
|
147
|
+
parentId: string | null;
|
|
148
|
+
type: string;
|
|
149
|
+
message?: unknown;
|
|
150
|
+
}>, id: string): string;
|
|
151
|
+
/** The `human_input` projection of the minted frames. */
|
|
152
|
+
export declare function humanInputAttachmentsOf(frames: readonly MintedAttachmentFrame[]): HumanInputAttachment[];
|
|
153
|
+
/**
|
|
154
|
+
* The run's pending attachment commits, keyed by `(inputId, ordinal)`. A frame's commit runs exactly once, when the
|
|
155
|
+
* harness reports that frame in the transcript; a frame that never got there (a refused pre-call budget, an abort, a
|
|
156
|
+
* failed append) commits nothing — its entry is simply never settled.
|
|
157
|
+
*/
|
|
158
|
+
export interface AttachmentDelivery {
|
|
159
|
+
/** Stage the minted frames of one input — called only once every gate before the append has passed. */
|
|
160
|
+
stage(inputId: string, frames: readonly MintedAttachmentFrame[]): void;
|
|
161
|
+
/** The frame `(inputId, ordinal)` is in the transcript: run its commit (once) and forget it. */
|
|
162
|
+
settle(inputId: string, ordinal: number): void;
|
|
163
|
+
}
|
|
164
|
+
export declare function createAttachmentDelivery(): AttachmentDelivery;
|