@sema-agent/core 7.50.2 → 7.51.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 +263 -0
- package/dist/agents/child-failure.d.ts +5 -16
- package/dist/agents/child-failure.js +4 -24
- package/dist/agents/subagent-steps.js +2 -2
- package/dist/agents/subagent.d.ts +4 -13
- package/dist/agents/subagent.js +94 -204
- package/dist/agents/tool-filter.d.ts +2 -2
- package/dist/brain/anthropic.d.ts +1 -1
- package/dist/brain/anthropic.js +7 -5
- package/dist/brain/open-responses.d.ts +1 -1
- package/dist/brain/open-responses.js +3 -2
- package/dist/brain/openai.d.ts +1 -1
- package/dist/brain/openai.js +3 -2
- package/dist/brain/request-route.d.ts +2 -2
- package/dist/brain/route-adjudicator.d.ts +16 -7
- package/dist/brain/route-adjudicator.js +23 -7
- package/dist/brain/route-conformance.js +23 -5
- package/dist/brain/stream-engine.js +9 -3
- package/dist/core/a2a.js +6 -8
- package/dist/core/allow-entry.d.ts +45 -26
- package/dist/core/allow-entry.js +48 -24
- package/dist/core/arg-summary.d.ts +8 -85
- package/dist/core/arg-summary.js +4 -386
- package/dist/core/ask-origin.d.ts +35 -33
- package/dist/core/ask-origin.js +9 -11
- package/dist/core/checkpoint-requirements.d.ts +6 -0
- package/dist/core/checkpoint-requirements.js +1 -0
- package/dist/core/checkpoint-store.d.ts +15 -34
- package/dist/core/checkpoint-store.js +5 -4
- package/dist/core/classifier-unavailable-arm.d.ts +12 -8
- package/dist/core/classifier-unavailable-arm.js +7 -2
- package/dist/core/credential-vocabulary.d.ts +3 -2
- package/dist/core/credential-vocabulary.js +27 -18
- package/dist/core/delegation-frames.d.ts +40 -15
- package/dist/core/delegation-frames.js +34 -0
- package/dist/core/engine-notice.d.ts +35 -11
- package/dist/core/gate-fold.js +9 -7
- package/dist/core/gate-lanes.js +6 -4
- package/dist/core/gate-outcome.d.ts +81 -15
- package/dist/core/gate-outcome.js +168 -67
- package/dist/core/governance-codes.d.ts +7 -1
- package/dist/core/governance-codes.js +9 -0
- package/dist/core/hooks.d.ts +4 -4
- package/dist/core/hooks.js +4 -3
- package/dist/core/mcp-connection-pool.d.ts +2 -0
- package/dist/core/mcp-connection-pool.js +2 -1
- package/dist/core/mcp-failure.js +2 -1
- package/dist/core/mcp-server-spec.d.ts +27 -5
- package/dist/core/mcp.d.ts +13 -38
- package/dist/core/mcp.js +28 -23
- package/dist/core/media-byte-cap.d.ts +25 -0
- package/dist/core/media-byte-cap.js +18 -2
- package/dist/core/memory-engine/consolidation-driver.js +1 -1
- package/dist/core/mode-policy.d.ts +25 -1
- package/dist/core/mode-policy.js +28 -13
- package/dist/core/own-property-receipt.d.ts +18 -0
- package/dist/core/own-property-receipt.js +39 -0
- package/dist/core/permission-rule-model.d.ts +32 -11
- package/dist/core/permission-rule-model.js +12 -7
- package/dist/core/persisted-rule-arms.d.ts +3 -3
- package/dist/core/prompt-section-seat.d.ts +54 -0
- package/dist/core/prompt-section-seat.js +49 -0
- package/dist/core/protocol-http-auth.d.ts +44 -0
- package/dist/core/protocol-http-auth.js +45 -0
- package/dist/core/read-face-seats.d.ts +30 -0
- package/dist/core/read-face-seats.js +38 -0
- package/dist/core/redaction-passes.d.ts +82 -0
- package/dist/core/redaction-passes.js +378 -0
- package/dist/core/remote-env.d.ts +4 -3
- package/dist/core/resume-startup-cause.d.ts +56 -0
- package/dist/core/resume-startup-cause.js +43 -0
- package/dist/core/rule-denial-sentence.d.ts +2 -2
- package/dist/core/runner/announce-once-ledger.js +2 -2
- package/dist/core/runner/classifier-ladder.d.ts +17 -13
- package/dist/core/runner/classifier-ladder.js +12 -10
- package/dist/core/runner/construction-doors.js +9 -20
- package/dist/core/runner/contracts.d.ts +4 -4
- package/dist/core/runner/gate-exit.js +2 -2
- package/dist/core/runner/memory-consolidation-write-judge.d.ts +53 -9
- package/dist/core/runner/memory-consolidation-write-judge.js +39 -1
- package/dist/core/runner/permission-rule-lanes.d.ts +8 -13
- package/dist/core/runner/person-path-rows.d.ts +4 -3
- package/dist/core/runner/policy-throw.js +4 -4
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -3
- package/dist/core/runner/prepare-caps-and-workflow.js +8 -6
- package/dist/core/runner/prepare-gate-stations.js +4 -4
- package/dist/core/runner/prepare-hands-readface.js +1 -19
- package/dist/core/runner/prepare-inherited-gate.js +10 -9
- package/dist/core/runner/prepare-policy-chain.d.ts +3 -5
- package/dist/core/runner/prepare-policy-chain.js +10 -13
- package/dist/core/runner/prepare-project-context.d.ts +4 -4
- package/dist/core/runner/prepare-project-context.js +2 -1
- package/dist/core/runner/prepare-prompt-assembly.js +1 -0
- package/dist/core/runner/prepare-prompt-inputs.d.ts +1 -1
- package/dist/core/runner/prepare-prompt-inputs.js +4 -4
- package/dist/core/runner/prepare-protocol-tools.d.ts +4 -3
- package/dist/core/runner/prepare-protocol-tools.js +3 -2
- package/dist/core/runner/prepare-task.js +6 -4
- package/dist/core/runner/prepare-turn-wiring.d.ts +16 -13
- package/dist/core/runner/prepare-turn-wiring.js +8 -7
- package/dist/core/runner/run-harness-handlers.js +2 -2
- package/dist/core/runner/run-leg.js +10 -9
- package/dist/core/runner/run-settle-and-teardown.js +5 -5
- package/dist/core/runner/run-turn-boundary.js +3 -2
- package/dist/core/runner/runtask.d.ts +1 -2
- package/dist/core/runner/runtask.js +8 -12
- package/dist/core/runner/session-rule-policy.d.ts +15 -11
- package/dist/core/runner/session-rule-policy.js +43 -33
- package/dist/core/runner/stream-lifecycle-verbs.js +2 -2
- package/dist/core/runner/stream-settle-backstop.js +2 -1
- package/dist/core/runner/sub-agent-deny-lists.d.ts +12 -8
- package/dist/core/runner/sub-agent-deny-lists.js +23 -12
- package/dist/core/runner/terminal-account.js +3 -3
- package/dist/core/runner/tool-output-projection.js +3 -8
- package/dist/core/runner/tool-result-media-seat.d.ts +19 -0
- package/dist/core/runner/tool-result-media-seat.js +13 -0
- package/dist/core/runner/turn-attachments.d.ts +13 -12
- package/dist/core/runner/turn-attachments.js +11 -7
- package/dist/core/runner-deps.d.ts +4 -3
- package/dist/core/safety-merge-corpus.js +21 -21
- package/dist/core/secret-env.js +1 -1
- package/dist/core/session-policy-store.d.ts +89 -72
- package/dist/core/session-policy-store.js +100 -93
- package/dist/core/shell-read-silence.d.ts +38 -4
- package/dist/core/shell-read-silence.js +102 -0
- package/dist/core/side-query.d.ts +7 -8
- package/dist/core/skill-grant-binding.d.ts +32 -11
- package/dist/core/skill-grant-binding.js +11 -3
- package/dist/core/skill-grant.d.ts +4 -3
- package/dist/core/skill-grant.js +5 -4
- package/dist/core/skills-directory.d.ts +12 -1
- package/dist/core/skills-directory.js +17 -8
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +2 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +3 -0
- package/dist/core/swappable-deps.d.ts +15 -1
- package/dist/core/swappable-deps.js +25 -1
- package/dist/core/synthetic-read-verdict.d.ts +16 -14
- package/dist/core/synthetic-read-verdict.js +28 -8
- package/dist/core/task-notification.d.ts +13 -3
- package/dist/core/task-notification.js +12 -1
- package/dist/core/task-spec.d.ts +14 -15
- package/dist/core/tool-name-readings.d.ts +0 -4
- package/dist/core/tool-name-readings.js +0 -1
- package/dist/core/tool-policy.d.ts +40 -9
- package/dist/core/tool-policy.js +25 -7
- package/dist/core/types.d.ts +3 -3
- package/dist/core/types.js +1 -1
- package/dist/core/untrusted-egress.d.ts +60 -11
- package/dist/core/untrusted-egress.js +120 -9
- package/dist/core/untrusted-text.js +16 -0
- package/dist/core/wiring-manifest.d.ts +22 -8
- package/dist/core/wiring-manifest.js +12 -4
- package/dist/engine/harness/agent-harness.d.ts +2 -1
- package/dist/engine/harness/agent-harness.js +4 -1
- package/dist/engine/harness/types.d.ts +3 -0
- package/dist/engine/llm/types.d.ts +7 -9
- package/dist/engine/loop/agent-loop.d.ts +8 -3
- package/dist/engine/loop/agent-loop.js +26 -9
- package/dist/engine/loop/types.d.ts +10 -0
- package/dist/index.d.ts +17 -5
- package/dist/index.js +14 -5
- package/dist/orchestration/run-workflow-tool.js +8 -8
- package/dist/orchestration/workflow.js +2 -2
- package/dist/prompt-assembly/assemble.d.ts +3 -1
- package/dist/prompt-assembly/assemble.js +6 -0
- package/dist/prompts/cowork.d.ts +42 -0
- package/dist/prompts/cowork.js +529 -0
- package/dist/prompts/default.d.ts +14 -1
- package/dist/prompts/default.js +3 -0
- package/dist/stores/file/session-policy-store.d.ts +6 -3
- package/dist/stores/file/session-policy-store.js +5 -16
- package/dist/tools/artifact/artifact-tool.js +2 -0
- package/dist/tools/fs/image-admission.d.ts +57 -4
- package/dist/tools/fs/image-admission.js +85 -0
- package/dist/tools/fs/path-containment.d.ts +2 -0
- package/dist/tools/fs/path-containment.js +5 -0
- package/dist/tools/fs/shell-read-check.d.ts +31 -6
- package/dist/tools/fs/shell-read-check.js +2 -4
- package/dist/tools/fs/shell-read-environment.d.ts +10 -25
- package/dist/tools/fs/shell-read-environment.js +6 -18
- package/dist/tools/fs/shell-read-establish.d.ts +3 -2
- package/dist/tools/fs/shell-read-establish.js +5 -5
- package/dist/tools/fs/shell-read-judge.d.ts +38 -8
- package/dist/tools/fs/shell-read-judge.js +12 -10
- package/dist/tools/web.js +2 -2
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +94 -10
- package/wire-changes/core@7.51.0.json +2421 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { delimitUntrusted, neutralizeForFence } from "./untrusted-text.js";
|
|
2
|
-
import { egressPasses, runRedactionPasses } from "./
|
|
3
|
-
import { CREDENTIAL_VOCABULARY, egressPassGroups, URI_SCHEME_SOURCE } from "./credential-vocabulary.js";
|
|
2
|
+
import { egressPasses, runRedactionPasses } from "./redaction-passes.js";
|
|
3
|
+
import { CREDENTIAL_VOCABULARY, egressPassGroups, isSensitiveRecordKey, URI_SCHEME_SOURCE } from "./credential-vocabulary.js";
|
|
4
|
+
import { isErrorLike, readMember, thrownText } from "./thrown-value.js";
|
|
4
5
|
import { sliceHeadSafe } from "./surrogate-safe-slice.js";
|
|
5
|
-
export { summarizeRedactions } from "./
|
|
6
|
+
export { summarizeRedactions } from "./redaction-passes.js";
|
|
6
7
|
const URL_OF_ANY_PROTOCOL = new RegExp(String.raw `${URI_SCHEME_SOURCE}:\/\/[^\s"'\`]+`, "gi");
|
|
7
8
|
const BARE_USERNAME_MAX_LEN = 20;
|
|
8
9
|
function redactUserinfo(scheme, userinfoWithAt) {
|
|
@@ -18,16 +19,126 @@ function redactUserinfo(scheme, userinfoWithAt) {
|
|
|
18
19
|
const SECRET_TIER_PASSES = egressPasses(egressPassGroups(CREDENTIAL_VOCABULARY), {
|
|
19
20
|
"url-credentials": (_m, scheme, userinfo) => redactUserinfo(scheme, userinfo),
|
|
20
21
|
});
|
|
21
|
-
export function redactSecrets(s, report) {
|
|
22
|
-
return runRedactionPasses(s, SECRET_TIER_PASSES, report);
|
|
23
|
-
}
|
|
24
22
|
const HOST_LEAK_PASSES = [
|
|
25
23
|
...SECRET_TIER_PASSES,
|
|
26
24
|
{ kind: "url", confidence: "medium", marker: "[redacted-url]", source: "untrusted-egress", re: URL_OF_ANY_PROTOCOL, replace: "[redacted-url]" },
|
|
27
25
|
{ kind: "fs-path", confidence: "low", marker: "[redacted-path]", source: "untrusted-egress", re: /(?:\/[A-Za-z0-9_.-]+){2,}/g, replace: "[redacted-path]" },
|
|
28
26
|
];
|
|
27
|
+
const TIER_PASSES = { "same-principal": SECRET_TIER_PASSES, human: HOST_LEAK_PASSES };
|
|
28
|
+
export function egressText(tier, text, report) {
|
|
29
|
+
return runRedactionPasses(text, TIER_PASSES[tier], report);
|
|
30
|
+
}
|
|
31
|
+
export function egressThrownText(tier, err) {
|
|
32
|
+
return egressText(tier, thrownText(err));
|
|
33
|
+
}
|
|
34
|
+
export function redactSecrets(s, report) {
|
|
35
|
+
return egressText("same-principal", s, report);
|
|
36
|
+
}
|
|
29
37
|
export function redactHostLeaks(s, report) {
|
|
30
|
-
return
|
|
38
|
+
return egressText("human", s, report);
|
|
39
|
+
}
|
|
40
|
+
const VALUE_DEPTH_MAX = 32;
|
|
41
|
+
const VALUE_MEMBERS_MAX = 2_000;
|
|
42
|
+
const WHOLE = "[redacted]";
|
|
43
|
+
export function egressValue(tier, value) {
|
|
44
|
+
const snapshots = new Map();
|
|
45
|
+
let budget = VALUE_MEMBERS_MAX;
|
|
46
|
+
const ownKeys = (o, all) => {
|
|
47
|
+
try {
|
|
48
|
+
return all ? Reflect.ownKeys(o) : Object.keys(o);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const prototypeOf = (o) => {
|
|
55
|
+
try {
|
|
56
|
+
return Object.getPrototypeOf(o);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return Object.prototype;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const readOwn = (o, key) => {
|
|
63
|
+
try {
|
|
64
|
+
const d = Reflect.getOwnPropertyDescriptor(o, key);
|
|
65
|
+
if (d === undefined)
|
|
66
|
+
return { value: undefined, enumerable: true };
|
|
67
|
+
return { value: "value" in d ? d.value : d.get?.call(o), enumerable: d.enumerable ?? true };
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return { value: undefined, enumerable: true };
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const member = (read, depth, name) => {
|
|
74
|
+
const out = pass(read, depth + 1, name);
|
|
75
|
+
return typeof out === "string" && isSensitiveRecordKey(name) ? WHOLE : out;
|
|
76
|
+
};
|
|
77
|
+
const fill = (o, depth, keys, snapshot) => {
|
|
78
|
+
snapshots.set(o, snapshot);
|
|
79
|
+
for (const key of keys ?? []) {
|
|
80
|
+
if (budget-- <= 0)
|
|
81
|
+
break;
|
|
82
|
+
const read = readOwn(o, key);
|
|
83
|
+
const name = typeof key === "string" ? egressText(tier, key) : key;
|
|
84
|
+
Object.defineProperty(snapshot, name, { value: member(read.value, depth, typeof key === "string" ? key : ""), enumerable: read.enumerable, writable: true, configurable: true });
|
|
85
|
+
}
|
|
86
|
+
return snapshot;
|
|
87
|
+
};
|
|
88
|
+
const errorSnapshot = (o, depth) => {
|
|
89
|
+
const snapshot = new Error();
|
|
90
|
+
for (const key of Reflect.ownKeys(snapshot))
|
|
91
|
+
Reflect.deleteProperty(snapshot, key);
|
|
92
|
+
fill(o, depth, ownKeys(o, true), snapshot);
|
|
93
|
+
for (const key of ["name", "message", "code", "stack"]) {
|
|
94
|
+
if (Object.prototype.hasOwnProperty.call(snapshot, key))
|
|
95
|
+
continue;
|
|
96
|
+
const read = readMember(o, key);
|
|
97
|
+
if (read !== undefined && typeof read !== "function")
|
|
98
|
+
Object.defineProperty(snapshot, key, { value: member(read, depth, key), enumerable: false, writable: true, configurable: true });
|
|
99
|
+
}
|
|
100
|
+
return snapshot;
|
|
101
|
+
};
|
|
102
|
+
function pass(v, depth, key) {
|
|
103
|
+
if (typeof v === "string")
|
|
104
|
+
return egressText(tier, v);
|
|
105
|
+
if (typeof v === "function")
|
|
106
|
+
return undefined;
|
|
107
|
+
if (typeof v !== "object" || v === null)
|
|
108
|
+
return v;
|
|
109
|
+
const known = snapshots.get(v);
|
|
110
|
+
if (known !== undefined)
|
|
111
|
+
return known;
|
|
112
|
+
if (depth >= VALUE_DEPTH_MAX)
|
|
113
|
+
return WHOLE;
|
|
114
|
+
if (isErrorLike(v))
|
|
115
|
+
return errorSnapshot(v, depth);
|
|
116
|
+
const toJSON = readMember(v, "toJSON");
|
|
117
|
+
if (typeof toJSON === "function") {
|
|
118
|
+
let reading;
|
|
119
|
+
try {
|
|
120
|
+
reading = toJSON.call(v, key);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return WHOLE;
|
|
124
|
+
}
|
|
125
|
+
if (reading !== v) {
|
|
126
|
+
const out = pass(reading, depth + 1, key);
|
|
127
|
+
snapshots.set(v, out);
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const array = (() => {
|
|
132
|
+
try {
|
|
133
|
+
return Array.isArray(v);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
})();
|
|
139
|
+
return fill(v, depth, ownKeys(v, false), array ? [] : prototypeOf(v) === null ? Object.create(null) : {});
|
|
140
|
+
}
|
|
141
|
+
return pass(value, 0, "");
|
|
31
142
|
}
|
|
32
143
|
const REDACTION_MARKER_RE = /\[redacted(?:-[a-z]+)?\]/g;
|
|
33
144
|
function countRedactionMarkers(s) {
|
|
@@ -85,10 +196,10 @@ function boundedString(value, max, redact) {
|
|
|
85
196
|
return out;
|
|
86
197
|
}
|
|
87
198
|
export function boundedRedactedSummary(value, max) {
|
|
88
|
-
return boundedString(value, max,
|
|
199
|
+
return boundedString(value, max, (s) => egressText("same-principal", s));
|
|
89
200
|
}
|
|
90
201
|
export function untrustedEgressForHuman(value, opts) {
|
|
91
|
-
const source = boundedString(value, Number.POSITIVE_INFINITY,
|
|
202
|
+
const source = boundedString(value, Number.POSITIVE_INFINITY, (s) => egressText("human", s));
|
|
92
203
|
const probe = (budget) => {
|
|
93
204
|
const bounded = boundedString(source, budget, (s) => s);
|
|
94
205
|
return { bounded, overflow: [...neutralizeForFence(bounded)].length - opts.max };
|
|
@@ -378,6 +378,22 @@ export const ENGINE_ENVELOPES = Object.freeze([
|
|
|
378
378
|
fenced: false,
|
|
379
379
|
disclosed: false,
|
|
380
380
|
},
|
|
381
|
+
...[
|
|
382
|
+
"additional_skills_reminder", "application_details", "artifacts", "ask_user_question_tool", "citation_requirements",
|
|
383
|
+
"claude_behavior", "computer_use", "env", "evenhandedness", "examples", "file_creation_advice", "file_handling_rules",
|
|
384
|
+
"good_file_sharing_examples", "high_level_computer_use_explanation", "knowledge_cutoff", "legal_and_financial_advice",
|
|
385
|
+
"lists_and_bullets", "notes_on_user_uploaded_files", "package_management", "producing_outputs", "product_information",
|
|
386
|
+
"refusal_handling", "responding_to_mistakes_and_criticism", "sharing_files", "strong", "suggesting_claude_actions",
|
|
387
|
+
"todo_list_tool", "tone_and_formatting", "tool_result_safety", "unnecessary_computer_use_avoidance", "user_wellbeing",
|
|
388
|
+
"verification_step", "web_content_restrictions", "working_with_user_files",
|
|
389
|
+
].map((tag) => ({
|
|
390
|
+
tag,
|
|
391
|
+
kind: "not-an-envelope",
|
|
392
|
+
mint: "prompts/cowork.ts — the Cowork base template's own section markup",
|
|
393
|
+
guard: "no run-supplied bytes reach it: the template is a constant rendered section by section, and its only fills are the two directory placeholders, engine facts",
|
|
394
|
+
fenced: false,
|
|
395
|
+
disclosed: false,
|
|
396
|
+
})),
|
|
381
397
|
]);
|
|
382
398
|
const ENVELOPES_BY_TAG = new Map(ENGINE_ENVELOPES.map((e) => [e.tag, e]));
|
|
383
399
|
export function engineEnvelope(tag) {
|
|
@@ -646,16 +646,30 @@ export declare function deriveAskEffective(form: AskSeamForm, parkEffective: boo
|
|
|
646
646
|
*/
|
|
647
647
|
export declare function askSeatEffective(manifest: Pick<WiringManifest, "ask" | "parkLane">): AskEffective;
|
|
648
648
|
/**
|
|
649
|
-
*
|
|
650
|
-
*
|
|
651
|
-
* `
|
|
652
|
-
*
|
|
653
|
-
*
|
|
654
|
-
* carrying the bit), or refused.
|
|
649
|
+
* WHERE an ask carrying `requiresRealApproval` goes from a station — the closed set of the ONE approval-seat decision:
|
|
650
|
+
* `live_approver` (a live approver callback answers it now), `durable_park` (it parks for a person to answer later),
|
|
651
|
+
* `none` (nobody can: a blanket policy seat, no seat, or a run that declared nobody can be asked — each only when no park
|
|
652
|
+
* lane is armed, since an armed park is the deployment's own statement that an answer can wait for a person — or a word that cannot be
|
|
653
|
+
* resolved — the fail-closed reading).
|
|
655
654
|
*/
|
|
656
|
-
export declare
|
|
655
|
+
export declare const APPROVAL_ROUTES: readonly ["live_approver", "durable_park", "none"];
|
|
656
|
+
export type ApprovalRoute = (typeof APPROVAL_ROUTES)[number];
|
|
657
|
+
/**
|
|
658
|
+
* The APPROVAL SEAT as a route, read off the ONE ask derivation above, never re-derived: `human_reachable` ⇒
|
|
659
|
+
* `live_approver`; `park_only` ⇒ `durable_park` (where the park cannot take the ask, a blanket seat behind it refuses the
|
|
660
|
+
* bit); `auto_allow`, `auto_deny` and `unresolved` ⇒ `none`. Every station that forks on "does a handed-on ask reach a
|
|
661
|
+
* person" reads this word — the leg's gate from the leg's seat word ({@link askSeatEffective}), an ancestor's frozen seat
|
|
662
|
+
* through {@link frozenApproverRoute} — and the fork, its observer and the sentence a person reads all read the same word.
|
|
663
|
+
*/
|
|
664
|
+
export declare function approvalRouteOf(ask: {
|
|
657
665
|
readonly effective?: AskEffective;
|
|
658
|
-
}):
|
|
666
|
+
}): ApprovalRoute;
|
|
667
|
+
/**
|
|
668
|
+
* The route from an ancestor's FROZEN approver (the inherited fold's station): the same table read with that seat's own
|
|
669
|
+
* form and no park — the inherited station resolves at the frozen seat, whose only road to a person is a live callback
|
|
670
|
+
* (the leg's park is reached only through a live approver's `unavailable`), so a blanket or absent frozen seat is `none`.
|
|
671
|
+
*/
|
|
672
|
+
export declare function frozenApproverRoute(onAsk: OnAsk | undefined): ApprovalRoute;
|
|
659
673
|
export declare function deriveWiringManifest(facts: WiringFacts): WiringManifest;
|
|
660
674
|
/** A run's approval seat as its one resolution froze it: the value every reader that needs the approver itself reads
|
|
661
675
|
* (`undefined` when nothing on this run can be asked), the form the manifest reports and every reader of the word derives
|
|
@@ -81,16 +81,18 @@ export function deriveAskEffective(form, parkEffective, mode) {
|
|
|
81
81
|
export function askSeatEffective(manifest) {
|
|
82
82
|
return deriveAskEffective(manifest.ask.form, manifest.parkLane.effective);
|
|
83
83
|
}
|
|
84
|
-
export
|
|
84
|
+
export const APPROVAL_ROUTES = Object.freeze(["live_approver", "durable_park", "none"]);
|
|
85
|
+
export function approvalRouteOf(ask) {
|
|
85
86
|
const effective = ask.effective ?? "unresolved";
|
|
86
87
|
switch (effective) {
|
|
87
88
|
case "human_reachable":
|
|
89
|
+
return "live_approver";
|
|
88
90
|
case "park_only":
|
|
89
|
-
return
|
|
91
|
+
return "durable_park";
|
|
90
92
|
case "auto_allow":
|
|
91
93
|
case "auto_deny":
|
|
92
94
|
case "unresolved":
|
|
93
|
-
return
|
|
95
|
+
return "none";
|
|
94
96
|
default: {
|
|
95
97
|
const _exhaustive = effective;
|
|
96
98
|
void _exhaustive;
|
|
@@ -98,6 +100,12 @@ export function askReachesPerson(ask) {
|
|
|
98
100
|
}
|
|
99
101
|
}
|
|
100
102
|
}
|
|
103
|
+
export function frozenApproverRoute(onAsk) {
|
|
104
|
+
return approvalRouteOf({ effective: deriveAskEffective(askSeamFormOf(onAsk) ?? "absent", false) });
|
|
105
|
+
}
|
|
106
|
+
function askSeamFormOf(v) {
|
|
107
|
+
return typeof v === "function" ? "callback" : v === "allow" ? "allow" : v === "deny" ? "deny" : v === undefined ? "absent" : undefined;
|
|
108
|
+
}
|
|
101
109
|
function deriveParkLane(facts) {
|
|
102
110
|
if (!facts.parkCapable) {
|
|
103
111
|
return { capable: false, effective: false, reasons: ["no_checkpoint_store"] };
|
|
@@ -235,7 +243,7 @@ export function resolveAskSeat(spec, deps) {
|
|
|
235
243
|
if (seat === undefined)
|
|
236
244
|
return Object.freeze(reach === undefined ? { value: undefined, form: "absent" } : { value: undefined, form: "declared_none", reach });
|
|
237
245
|
const v = seat.value;
|
|
238
|
-
const form =
|
|
246
|
+
const form = askSeamFormOf(v);
|
|
239
247
|
if (form === undefined) {
|
|
240
248
|
const e = new Error(`the resolved onAsk seat (${seat.provenance}) holds ${JSON.stringify(v)} — not an OnAsk ` +
|
|
241
249
|
`("allow" | "deny" | approver function); refusing to classify it.`);
|
|
@@ -310,6 +310,7 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
310
310
|
private abortResultDetails?;
|
|
311
311
|
private loopTrace?;
|
|
312
312
|
private onToolInputValidationFault?;
|
|
313
|
+
private onToolMediaRefused?;
|
|
313
314
|
private resilience?;
|
|
314
315
|
private maxToolConcurrency?;
|
|
315
316
|
private streamingToolExecution?;
|
|
@@ -538,7 +539,7 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
538
539
|
/**
|
|
539
540
|
* Finalize a call this harness's caller executed OUTSIDE a turn (a resumed, already-approved call) exactly as the
|
|
540
541
|
* loop finalizes its own: the same {@link finalizeToolOutcome} over the same `tool_result` emit, so the call meets the
|
|
541
|
-
* same handlers, the same patch application
|
|
542
|
+
* same handlers, the same patch application, the same throwing-hook posture and the same media admission as a live one.
|
|
542
543
|
*/
|
|
543
544
|
finalizeToolCall(toolCall: AgentToolCall, args: unknown, executed: ExecutedToolCallOutcome): Promise<ExecutedToolCallOutcome & {
|
|
544
545
|
toolCall: AgentToolCall;
|
|
@@ -294,6 +294,7 @@ export class AgentHarness {
|
|
|
294
294
|
abortResultDetails;
|
|
295
295
|
loopTrace;
|
|
296
296
|
onToolInputValidationFault;
|
|
297
|
+
onToolMediaRefused;
|
|
297
298
|
resilience;
|
|
298
299
|
maxToolConcurrency;
|
|
299
300
|
streamingToolExecution;
|
|
@@ -329,6 +330,7 @@ export class AgentHarness {
|
|
|
329
330
|
this.abortResultDetails = options.abortResultDetails;
|
|
330
331
|
this.loopTrace = options.loopTrace;
|
|
331
332
|
this.onToolInputValidationFault = options.onToolInputValidationFault;
|
|
333
|
+
this.onToolMediaRefused = options.onToolMediaRefused;
|
|
332
334
|
this.resilience = options.resilience;
|
|
333
335
|
this.maxToolConcurrency = options.maxToolConcurrency;
|
|
334
336
|
this.streamingToolExecution = options.streamingToolExecution;
|
|
@@ -640,6 +642,7 @@ export class AgentHarness {
|
|
|
640
642
|
...(this.stallTimeoutsPerCall !== undefined ? { stallTimeoutsPerCall: this.stallTimeoutsPerCall } : {}),
|
|
641
643
|
...(this.abortResultDetails !== undefined ? { abortResultDetails: this.abortResultDetails } : {}),
|
|
642
644
|
...(this.onToolInputValidationFault !== undefined ? { onToolInputValidationFault: this.onToolInputValidationFault } : {}),
|
|
645
|
+
...(this.onToolMediaRefused !== undefined ? { onToolMediaRefused: this.onToolMediaRefused } : {}),
|
|
643
646
|
...(this.resilience !== undefined ? { resilience: this.resilience } : {}),
|
|
644
647
|
...(this.maxToolConcurrency !== undefined ? { maxToolConcurrency: this.maxToolConcurrency } : {}),
|
|
645
648
|
...(this.streamingToolExecution === true && (this.getHandlers("tool_call")?.size ?? 0) === 0
|
|
@@ -1231,7 +1234,7 @@ export class AgentHarness {
|
|
|
1231
1234
|
return patch;
|
|
1232
1235
|
}
|
|
1233
1236
|
finalizeToolCall(toolCall, args, executed) {
|
|
1234
|
-
return finalizeToolOutcome(toolCall, executed, (result, isError) => this.afterToolCallHook(toolCall, args, result, isError));
|
|
1237
|
+
return finalizeToolOutcome(toolCall, executed, (result, isError) => this.afterToolCallHook(toolCall, args, result, isError), this.onToolMediaRefused);
|
|
1235
1238
|
}
|
|
1236
1239
|
getModel() {
|
|
1237
1240
|
return this.model;
|
|
@@ -1444,6 +1444,9 @@ export interface AgentHarnessOptions<TSkill extends Skill = Skill, TPromptTempla
|
|
|
1444
1444
|
/** Loop-config pass-through — see `AgentLoopConfig.onToolInputValidationFault` (a throwing
|
|
1445
1445
|
* `AgentTool.validateInput` is read as no verdict and disclosed here). */
|
|
1446
1446
|
onToolInputValidationFault?: import("../loop/types.js").AgentLoopConfig["onToolInputValidationFault"];
|
|
1447
|
+
/** Loop-config pass-through — see `AgentLoopConfig.onToolMediaRefused` (the tool-result seat's account of the media it
|
|
1448
|
+
* refused); the harness's own finalization of a resumed approved call reports through the same sink. */
|
|
1449
|
+
onToolMediaRefused?: import("../loop/types.js").AgentLoopConfig["onToolMediaRefused"];
|
|
1447
1450
|
/**
|
|
1448
1451
|
* design/131 (拍): per-task resilience intent flags, forwarded to every provider
|
|
1449
1452
|
* call (`StreamOptions.resilience`) so the deployment's decorator stack (degrading / failover /
|
|
@@ -1020,21 +1020,19 @@ export interface RouteCredential {
|
|
|
1020
1020
|
* knob+header pair counts as ONE deployment credential — see `resolveRouteCredential`). */
|
|
1021
1021
|
carrierBag?: RouteCarrierBag;
|
|
1022
1022
|
}
|
|
1023
|
-
/** The deployment half of the pairing judgment: the brain
|
|
1024
|
-
*
|
|
1025
|
-
*
|
|
1023
|
+
/** The deployment half of the pairing judgment: the root the brain sends to when an entry names none —
|
|
1024
|
+
* its construction config's DECLARED root (`baseUrl`), else the lane's own default endpoint
|
|
1025
|
+
* (`laneDefault`, a constant the brain owns; absent for a lane with no default). That root is the
|
|
1026
|
+
* deployment credential's one root (see `adjudicateModelRoute`). */
|
|
1026
1027
|
export interface RoutePairingConfig {
|
|
1027
1028
|
baseUrl?: string;
|
|
1029
|
+
laneDefault?: string;
|
|
1028
1030
|
}
|
|
1029
1031
|
/** How an OK verdict is paired.
|
|
1030
1032
|
* - `"per-model"` — per-model credential, paired by construction.
|
|
1031
|
-
* - `"paired"` — deployment credential on the deployment's own declared
|
|
1032
|
-
* - `"unpinned"` — deployment credential whose URL half is UNDECLARED (no `config.baseUrl`): allowed
|
|
1033
|
-
* for compatibility with single-endpoint configs (key on config, URL on the model), but the pairing
|
|
1034
|
-
* is unverifiable — a multi-entry deployment in this posture should declare `config.baseUrl` or move
|
|
1035
|
-
* to per-model credentials. Surfaced (not refused) so read faces can annotate it.
|
|
1033
|
+
* - `"paired"` — deployment credential on the deployment's own root (declared, or the lane default).
|
|
1036
1034
|
* - `"keyless"` — no credential anywhere; nothing to protect. */
|
|
1037
|
-
export type RoutePairingPosture = "per-model" | "paired" | "
|
|
1035
|
+
export type RoutePairingPosture = "per-model" | "paired" | "keyless";
|
|
1038
1036
|
/** Machine codes an adjudication refusal carries (minted here, forwarded verbatim by consumers). */
|
|
1039
1037
|
export type RouteRefusalCode = "route.credential_mismatch" | "route.credential_missing";
|
|
1040
1038
|
/** The structured account of a refusal — the two halves and the fix, every URL a DISPLAY spelling. */
|
|
@@ -183,10 +183,15 @@ export declare const TOOL_INPUT_VALIDATION_TIMEOUT_MS = 10000;
|
|
|
183
183
|
* The post-execution half EVERY executed tool call passes through — the loop's own calls here, and a call
|
|
184
184
|
* the harness executed outside a turn (a resumed approved call, `AgentHarness.finalizeToolCall`) through the
|
|
185
185
|
* same function, so the two cannot drift into two dialects of one finalization: the `afterToolCall` patch
|
|
186
|
-
* (content / details / terminate / isError), the D4 posture on a throwing hook,
|
|
187
|
-
*
|
|
186
|
+
* (content / details / terminate / isError), the D4 posture on a throwing hook, the delivery mark, and last
|
|
187
|
+
* the media admission — the tool-result seat every supply of media reaches after the last hand that can change
|
|
188
|
+
* it (`admitToolResultMedia`): a refused block becomes its text placeholder in the result, and `onMediaRefused`
|
|
189
|
+
* hears the call's refusals once. `after` absent and no media ⇒ the executed outcome stands as is (same object).
|
|
188
190
|
*/
|
|
189
|
-
export declare function finalizeToolOutcome<C
|
|
191
|
+
export declare function finalizeToolOutcome<C extends {
|
|
192
|
+
id: string;
|
|
193
|
+
name: string;
|
|
194
|
+
}>(toolCall: C, executed: ExecutedToolCallOutcome, after: ((result: AgentToolResult<unknown>, isError: boolean) => Promise<AfterToolCallResult | undefined>) | undefined, onMediaRefused?: AgentLoopConfig["onToolMediaRefused"]): Promise<ExecutedToolCallOutcome & {
|
|
190
195
|
toolCall: C;
|
|
191
196
|
}>;
|
|
192
197
|
export {};
|
|
@@ -3,7 +3,9 @@ import { truncateError } from "../../core/tool-errors.js";
|
|
|
3
3
|
import { judgeToolNameMiss, mountedToolNames } from "../../core/tool-name-aliases.js";
|
|
4
4
|
import { INTERRUPTED_BY_USER_FOR_TOOL_USE_MARKER, INTERRUPTED_BY_USER_MARKER, } from "../../core/session-reconcile.js";
|
|
5
5
|
import { resolveAgentCoreStreamFn } from "./runtime-deps.js";
|
|
6
|
-
import { isErrorLike, readMember, thrownMarksOf
|
|
6
|
+
import { isErrorLike, readMember, thrownMarksOf } from "../../core/thrown-value.js";
|
|
7
|
+
import { egressThrownText, egressValue } from "../../core/untrusted-egress.js";
|
|
8
|
+
import { admitToolResultMedia } from "../../tools/fs/image-admission.js";
|
|
7
9
|
function appendTextDeltaToAssistantMessage(message, contentIndex, delta) {
|
|
8
10
|
const content = [...message.content];
|
|
9
11
|
const currentContent = content[contentIndex];
|
|
@@ -1111,7 +1113,7 @@ class StreamToolExecutor {
|
|
|
1111
1113
|
this.retainCancellation(error);
|
|
1112
1114
|
entry.immediate = {
|
|
1113
1115
|
kind: "immediate",
|
|
1114
|
-
result:
|
|
1116
|
+
result: thrownErrorToolResult(error),
|
|
1115
1117
|
isError: true,
|
|
1116
1118
|
};
|
|
1117
1119
|
}
|
|
@@ -1374,7 +1376,7 @@ async function prepareToolCall(currentContext, assistantMessage, toolCall, confi
|
|
|
1374
1376
|
catch (error) {
|
|
1375
1377
|
return {
|
|
1376
1378
|
kind: "immediate",
|
|
1377
|
-
result:
|
|
1379
|
+
result: thrownErrorToolResult(error),
|
|
1378
1380
|
isError: true,
|
|
1379
1381
|
};
|
|
1380
1382
|
}
|
|
@@ -1415,7 +1417,7 @@ async function executePreparedToolCall(prepared, signal, emit, abortResultDetail
|
|
|
1415
1417
|
}
|
|
1416
1418
|
catch (error) {
|
|
1417
1419
|
outcome = {
|
|
1418
|
-
result:
|
|
1420
|
+
result: thrownErrorToolResult(error),
|
|
1419
1421
|
isError: true,
|
|
1420
1422
|
};
|
|
1421
1423
|
}
|
|
@@ -1425,7 +1427,7 @@ async function executePreparedToolCall(prepared, signal, emit, abortResultDetail
|
|
|
1425
1427
|
return outcome;
|
|
1426
1428
|
const reason = deliveryFailure.reason;
|
|
1427
1429
|
const details = annotateDeliveryFailure(outcome.result, {
|
|
1428
|
-
message:
|
|
1430
|
+
message: egressThrownText("same-principal", reason),
|
|
1429
1431
|
});
|
|
1430
1432
|
return details === UNANNOTATED ? outcome : { result: { ...outcome.result, details }, isError: outcome.isError };
|
|
1431
1433
|
})();
|
|
@@ -1497,7 +1499,7 @@ async function executePreparedWithDisclosure(currentContext, assistantMessage, p
|
|
|
1497
1499
|
if (isAbortSemanticsError(error))
|
|
1498
1500
|
throw error;
|
|
1499
1501
|
executed = {
|
|
1500
|
-
result:
|
|
1502
|
+
result: thrownErrorToolResult(error, (words) => `[tool execution harness failed: ${words}]`),
|
|
1501
1503
|
isError: true,
|
|
1502
1504
|
};
|
|
1503
1505
|
}
|
|
@@ -1506,9 +1508,9 @@ async function executePreparedWithDisclosure(currentContext, assistantMessage, p
|
|
|
1506
1508
|
function finalizeExecutedToolCall(currentContext, assistantMessage, prepared, executed, config, signal) {
|
|
1507
1509
|
return finalizeToolOutcome(prepared.toolCall, executed, config.afterToolCall === undefined
|
|
1508
1510
|
? undefined
|
|
1509
|
-
: (result, isError) => config.afterToolCall({ assistantMessage, toolCall: prepared.toolCall, args: prepared.args, result, isError, context: currentContext }, signal));
|
|
1511
|
+
: (result, isError) => config.afterToolCall({ assistantMessage, toolCall: prepared.toolCall, args: prepared.args, result, isError, context: currentContext }, signal), config.onToolMediaRefused);
|
|
1510
1512
|
}
|
|
1511
|
-
export async function finalizeToolOutcome(toolCall, executed, after) {
|
|
1513
|
+
export async function finalizeToolOutcome(toolCall, executed, after, onMediaRefused) {
|
|
1512
1514
|
let result = executed.result;
|
|
1513
1515
|
let isError = executed.isError;
|
|
1514
1516
|
const deliveryMark = readDeliveryFailureMark(executed.result.details);
|
|
@@ -1525,7 +1527,7 @@ export async function finalizeToolOutcome(toolCall, executed, after) {
|
|
|
1525
1527
|
}
|
|
1526
1528
|
}
|
|
1527
1529
|
catch (error) {
|
|
1528
|
-
const note = truncateError(`[post-tool processing failed (the tool already executed): ${
|
|
1530
|
+
const note = truncateError(`[post-tool processing failed (the tool already executed): ${egressThrownText("same-principal", error)}]`);
|
|
1529
1531
|
result = { ...result, content: [...result.content, { type: "text", text: note }] };
|
|
1530
1532
|
}
|
|
1531
1533
|
if (deliveryMark !== undefined && readDeliveryFailureMark(result.details) === undefined) {
|
|
@@ -1534,6 +1536,18 @@ export async function finalizeToolOutcome(toolCall, executed, after) {
|
|
|
1534
1536
|
result = { ...result, details };
|
|
1535
1537
|
}
|
|
1536
1538
|
}
|
|
1539
|
+
const admitting = admitToolResultMedia(result.content, toolCall.name);
|
|
1540
|
+
if (admitting !== undefined) {
|
|
1541
|
+
const admitted = await admitting;
|
|
1542
|
+
result = { ...result, content: admitted.content };
|
|
1543
|
+
if (admitted.refused.length > 0) {
|
|
1544
|
+
try {
|
|
1545
|
+
onMediaRefused?.({ toolName: toolCall.name, toolCallId: toolCall.id, refused: admitted.refused });
|
|
1546
|
+
}
|
|
1547
|
+
catch {
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1537
1551
|
return { toolCall, result, isError };
|
|
1538
1552
|
}
|
|
1539
1553
|
function safeAbortDetails(fn) {
|
|
@@ -1563,6 +1577,9 @@ function createErrorToolResult(message, source) {
|
|
|
1563
1577
|
details,
|
|
1564
1578
|
};
|
|
1565
1579
|
}
|
|
1580
|
+
function thrownErrorToolResult(error, frame = (words) => words) {
|
|
1581
|
+
return createErrorToolResult(frame(egressThrownText("same-principal", error)), { details: egressValue("same-principal", thrownMarksOf(error)) });
|
|
1582
|
+
}
|
|
1566
1583
|
async function emitToolExecutionEnd(finalized, emit) {
|
|
1567
1584
|
await emit({
|
|
1568
1585
|
type: "tool_execution_end",
|
|
@@ -566,6 +566,16 @@ export interface AgentLoopConfig extends SimpleStreamOptions {
|
|
|
566
566
|
toolCallId: string;
|
|
567
567
|
error: unknown;
|
|
568
568
|
}) => void;
|
|
569
|
+
/**
|
|
570
|
+
* Told, once per executed call, of the media blocks the tool-result seat refused (`admitToolResultMedia`, the last step
|
|
571
|
+
* of the post-execution half): each already stands in the result as a text placeholder naming the tool and the refusal,
|
|
572
|
+
* so this is the run's account of it, not a decision. Advisory: a throwing sink changes nothing.
|
|
573
|
+
*/
|
|
574
|
+
onToolMediaRefused?: (info: {
|
|
575
|
+
toolName: string;
|
|
576
|
+
toolCallId: string;
|
|
577
|
+
refused: readonly import("../../tools/fs/image-admission.js").ToolResultMediaRefusal[];
|
|
578
|
+
}) => void;
|
|
569
579
|
/**
|
|
570
580
|
* Called after a tool finishes executing, before `tool_execution_end` and tool-result message events are emitted.
|
|
571
581
|
*
|