@sema-agent/core 7.7.0 → 7.8.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 +37 -0
- package/dist/agents/agent-transcript-tool.js +2 -2
- package/dist/agents/list-agents-tool.js +2 -3
- package/dist/agents/observer.js +2 -2
- package/dist/agents/send-message-tool.js +2 -1
- package/dist/agents/subagent-steps.js +5 -4
- package/dist/agents/subagent.js +2 -3
- package/dist/core/ask-question.js +2 -2
- package/dist/core/checkpoint-store.d.ts +38 -4
- package/dist/core/context-edit.d.ts +0 -22
- package/dist/core/context-edit.js +2 -11
- package/dist/core/engine-notice.d.ts +6 -0
- package/dist/core/fs-write-gate-policy.d.ts +7 -1
- package/dist/core/fs-write-gate-policy.js +7 -7
- package/dist/core/gate-fold.js +2 -2
- package/dist/core/gate-lanes.js +4 -3
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +6 -0
- package/dist/core/hooks.d.ts +8 -2
- package/dist/core/hooks.js +1 -1
- package/dist/core/lsp.js +2 -2
- package/dist/core/mcp-server-spec.d.ts +17 -0
- package/dist/core/mcp.js +3 -1
- package/dist/core/memory-engine/tools.js +4 -12
- package/dist/core/permission-rules.d.ts +32 -2
- package/dist/core/permission-rules.js +43 -37
- package/dist/core/present-plan-tool.js +3 -4
- package/dist/core/runner/active-skill-scope.js +7 -4
- package/dist/core/runner/compaction-call-options.d.ts +1 -1
- package/dist/core/runner/contracts.d.ts +27 -3
- package/dist/core/runner/prepare-ask-lane.d.ts +1 -1
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +5 -4
- package/dist/core/runner/prepare-caps-and-workflow.js +16 -11
- package/dist/core/runner/prepare-defer-classify.d.ts +5 -26
- package/dist/core/runner/prepare-defer-classify.js +10 -10
- package/dist/core/runner/prepare-delegation-surface.d.ts +5 -4
- package/dist/core/runner/prepare-delegation-surface.js +15 -17
- package/dist/core/runner/prepare-gate-stations.d.ts +4 -1
- package/dist/core/runner/prepare-gate-stations.js +3 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +3 -2
- package/dist/core/runner/prepare-hands-readface.js +3 -2
- package/dist/core/runner/prepare-inherited-gate.d.ts +1 -1
- package/dist/core/runner/prepare-inherited-gate.js +1 -0
- package/dist/core/runner/prepare-lsp.d.ts +4 -3
- package/dist/core/runner/prepare-lsp.js +3 -2
- package/dist/core/runner/prepare-memory-engine-session.d.ts +4 -4
- package/dist/core/runner/prepare-memory-engine-session.js +4 -2
- package/dist/core/runner/prepare-offload-wrappers.js +7 -5
- package/dist/core/runner/prepare-park-ask.d.ts +4 -0
- package/dist/core/runner/prepare-park-ask.js +4 -1
- package/dist/core/runner/prepare-project-context.d.ts +5 -23
- package/dist/core/runner/prepare-project-context.js +7 -5
- package/dist/core/runner/prepare-prompt-assembly.d.ts +1 -1
- package/dist/core/runner/prepare-protocol-tools.d.ts +5 -1
- package/dist/core/runner/prepare-protocol-tools.js +38 -21
- package/dist/core/runner/prepare-question-face.d.ts +4 -3
- package/dist/core/runner/prepare-question-face.js +5 -3
- package/dist/core/runner/prepare-run-refs.d.ts +16 -0
- package/dist/core/runner/prepare-run-refs.js +6 -0
- package/dist/core/runner/prepare-safety-scan.js +42 -2
- package/dist/core/runner/prepare-task.js +37 -19
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +5 -2
- package/dist/core/runner/prepare-tool-disclosure-mount.js +3 -1
- package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -0
- package/dist/core/runner/prepare-wiring-manifest.js +3 -8
- package/dist/core/runner/run-harness-handlers.d.ts +46 -0
- package/dist/core/runner/run-harness-handlers.js +345 -0
- package/dist/core/runner/run-turn-boundary.d.ts +69 -0
- package/dist/core/runner/run-turn-boundary.js +694 -0
- package/dist/core/runner/runtask.js +47 -1043
- package/dist/core/runner/session-rule-policy.js +9 -4
- package/dist/core/runner/synthetic-tools.js +5 -8
- package/dist/core/runner/tool-disclosure.d.ts +4 -0
- package/dist/core/runner/tool-disclosure.js +9 -5
- package/dist/core/runner/tool-end-body.js +3 -2
- package/dist/core/runner/tool-face-overlay.d.ts +40 -0
- package/dist/core/runner/tool-face-overlay.js +125 -0
- package/dist/core/runner/tool-output-projection.d.ts +10 -0
- package/dist/core/runner/tool-output-projection.js +33 -10
- package/dist/core/sensitive-path-policy.d.ts +3 -0
- package/dist/core/sensitive-path-policy.js +6 -5
- package/dist/core/shared-memory/tools.js +3 -6
- package/dist/core/store-contracts/checkpoint-store-contract.js +23 -0
- package/dist/core/task-event.d.ts +10 -0
- package/dist/core/task-registry.js +4 -5
- package/dist/core/task-spec.d.ts +8 -0
- package/dist/core/tool-catalog-entries.d.ts +48 -0
- package/dist/core/tool-catalog-entries.js +174 -0
- package/dist/core/tool-conformance.d.ts +22 -0
- package/dist/core/tool-conformance.js +37 -0
- package/dist/core/tool-face.d.ts +171 -0
- package/dist/core/tool-face.js +25 -0
- package/dist/core/tool-policy.d.ts +24 -0
- package/dist/core/tool-policy.js +4 -2
- package/dist/core/tool-registry.d.ts +114 -0
- package/dist/core/tool-registry.js +114 -0
- package/dist/core/tool-result-budget.d.ts +0 -3
- package/dist/core/tool-result-budget.js +4 -3
- package/dist/core/tool-result-store.d.ts +0 -18
- package/dist/core/tool-result-store.js +2 -18
- package/dist/core/tool-roster.d.ts +450 -0
- package/dist/core/tool-roster.js +497 -0
- package/dist/core/tool-spec.d.ts +54 -3
- package/dist/core/tools.js +7 -0
- package/dist/core/wiring-manifest.d.ts +13 -0
- package/dist/core/wiring-manifest.js +2 -1
- package/dist/core/write-protect.d.ts +2 -1
- package/dist/core/write-protect.js +5 -4
- package/dist/engine/compaction/utils.d.ts +6 -0
- package/dist/engine/compaction/utils.js +19 -19
- package/dist/engine/loop/types.d.ts +6 -0
- package/dist/index.d.ts +15 -4
- package/dist/index.js +15 -4
- package/dist/orchestration/goal.js +2 -1
- package/dist/orchestration/run-spec.js +3 -5
- package/dist/orchestration/run-workflow-tool.js +2 -2
- package/dist/prompt-assembly/event-registry.js +3 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +2 -2
- package/dist/tools/fs/fs-bash.d.ts +1 -1
- package/dist/tools/fs/fs-bash.js +7 -11
- package/dist/tools/fs/fs-read.js +2 -2
- package/dist/tools/fs/fs-search-tools.d.ts +0 -7
- package/dist/tools/fs/fs-search-tools.js +3 -16
- package/dist/tools/fs/fs-write.js +4 -6
- package/dist/tools/fs/repo-map.js +2 -2
- package/dist/tools/fs/safety.d.ts +2 -1
- package/dist/tools/fs/safety.js +6 -5
- package/dist/tools/monitor.js +2 -2
- package/dist/tools/scheduler-tools.js +5 -8
- package/dist/tools/task-list.js +5 -8
- package/dist/tools/todo.js +2 -2
- package/dist/tools/web.js +3 -6
- package/dist/tools/worktree.js +3 -4
- package/package.json +4 -1
- package/test/export-surface.snapshot.json +147 -7
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The static tool catalog's READ FACE (design/388 §2.1): `describeToolCatalog()` and the predicates
|
|
3
|
+
* every former name table is now DERIVED from. Readable without an env, a deps object or a tool
|
|
4
|
+
* instance — a host predicts a leg's roster from it (`predictMountedToolNames`), a policy module
|
|
5
|
+
* derives its covered set from it, a shell renders it.
|
|
6
|
+
*
|
|
7
|
+
* Every predicate here answers over DEFINITIONS and folds to names with "any definition under this
|
|
8
|
+
* name matches" — the rule that pins the two fail-open shapes a per-name table had (one name, two
|
|
9
|
+
* definitions; the table could only hold one).
|
|
10
|
+
*
|
|
11
|
+
* Layer-0 vocabulary: depends on the leaf catalog and the face vocabulary only.
|
|
12
|
+
*/
|
|
13
|
+
import { type ToolCatalogEntry, type ToolMountTag, type ToolPathAccess } from "./tool-face.js";
|
|
14
|
+
/** The whole static catalog, one frozen row per definition (design/388 §2.1 `describeToolCatalog()`).
|
|
15
|
+
* Replaces the retired name-keyed exports `HAND_TOOL_EFFECTS` / `DEFAULT_BUDGET_EXEMPT_TOOLS` /
|
|
16
|
+
* `COMPACTABLE_TOOLS`: filter this instead (`e.mountedBy.includes("hands")`, `e.face.budgetExempt`,
|
|
17
|
+
* `e.face.compactable`). */
|
|
18
|
+
export declare function describeToolCatalog(): readonly ToolCatalogEntry[];
|
|
19
|
+
/** Every definition under a wire name (a name may carry more than one — the two shells). */
|
|
20
|
+
export declare function catalogEntriesNamed(name: string): readonly ToolCatalogEntry[];
|
|
21
|
+
/** Every wire name the catalog knows, aliases included (a set — the two shells fold to one name). */
|
|
22
|
+
export declare function catalogToolNames(): ReadonlySet<string>;
|
|
23
|
+
/** A-11/12/13/14 — tools this engine can CONFINE BY PATH on a write: `pathTarget.access ≠ read`.
|
|
24
|
+
* Today {Write, Edit, NotebookEdit}. */
|
|
25
|
+
export declare function pathConfinableWriteToolNames(): ReadonlySet<string>;
|
|
26
|
+
/** A-11 (the SECOND authorization domain) — the active-skill `allowPaths` face: confinable AND the
|
|
27
|
+
* definition opted into skill scoping. Today {Write, Edit} — NotebookEdit is deliberately outside. */
|
|
28
|
+
export declare function skillScopeWriteToolNames(): ReadonlySet<string>;
|
|
29
|
+
/** A-8 — every definition that names a path target at all (read or write): the file-tool glob lane. */
|
|
30
|
+
export declare function pathTargetingToolNames(): ReadonlySet<string>;
|
|
31
|
+
/** A-10 — the micro-compaction whitelist (`compactable: true`). */
|
|
32
|
+
export declare function compactableToolNames(): ReadonlySet<string>;
|
|
33
|
+
/** A-5 — the aggregate-budget exemptions (`budgetExempt: true`). */
|
|
34
|
+
export declare function budgetExemptToolNames(): ReadonlySet<string>;
|
|
35
|
+
/** The value a call's args carry under a path target: `param` first, then each alias, first non-empty string wins. */
|
|
36
|
+
export declare function pathTargetValue(args: unknown, pt: {
|
|
37
|
+
param: string;
|
|
38
|
+
aliases?: readonly string[];
|
|
39
|
+
}): string | undefined;
|
|
40
|
+
/** The path target of a wire name — the FIRST definition's (every definition under one name declares
|
|
41
|
+
* the same target; the conformance test pins that). */
|
|
42
|
+
/** A gated call as every fence sees it: the wire name, the args, and the OBJECT face a prepared leg stamped on the
|
|
43
|
+
* request (absent on a BARE request — a policy invoked outside a Runner). */
|
|
44
|
+
export interface ToolCallLike {
|
|
45
|
+
toolName: string;
|
|
46
|
+
args: unknown;
|
|
47
|
+
face?: {
|
|
48
|
+
pathTarget?: {
|
|
49
|
+
param: string;
|
|
50
|
+
aliases?: readonly string[];
|
|
51
|
+
access: ToolPathAccess;
|
|
52
|
+
};
|
|
53
|
+
} | undefined;
|
|
54
|
+
}
|
|
55
|
+
type CallPathTarget = {
|
|
56
|
+
param: string;
|
|
57
|
+
aliases?: readonly string[];
|
|
58
|
+
access: ToolPathAccess;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* design/388 B6/B17 — the path target a PROTECTIVE fence reads (a deny-list judging a write's target: sensitive paths,
|
|
62
|
+
* frozen paths, write protection, the transcript gate; edit tracking): the object face's own declaration first, the
|
|
63
|
+
* catalog's declaration for the NAME as the FLOOR — for a bare request (a policy invoked outside a Runner) and for a
|
|
64
|
+
* face that declares none. Reading the catalog for an undeclared same-name tool can only TIGHTEN a deny-list (it adds
|
|
65
|
+
* a slot to judge — the pre-388 posture, never wider), which is exactly why this floor is wrong for a grant.
|
|
66
|
+
*/
|
|
67
|
+
export declare function protectivePathTargetOf(call: ToolCallLike): CallPathTarget | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* The path target a CONTAINMENT fence reads (a grant admitting a write BY its path: session `allowDirs`, the fs-write
|
|
70
|
+
* gate's accept/exempt dirs; the active-skill allowPaths face reads its own eligibility bit the same way): the object
|
|
71
|
+
* face's OWN declaration only — a same-name tool that declares no path target is an UNCONFIRMABLE write (the catalog's
|
|
72
|
+
* slot may not be the one it writes; a decoy in that slot would buy an admission), so the fence fails closed. A BARE
|
|
73
|
+
* request (no face at all — a policy invoked outside a Runner) reads the catalog for the name: the pre-388 reading, the
|
|
74
|
+
* documented migration seam for bare producers.
|
|
75
|
+
*/
|
|
76
|
+
export declare function declaredPathTargetOf(call: ToolCallLike): CallPathTarget | undefined;
|
|
77
|
+
/** Is this call a write a PROTECTIVE fence judges (a protected target whose access ≠ read)? The name sets are its static view. */
|
|
78
|
+
export declare function isProtectedWrite(call: ToolCallLike): boolean;
|
|
79
|
+
/** Is this call a write a CONTAINMENT fence may ADMIT by its path (a declared target whose access ≠ read)? */
|
|
80
|
+
export declare function isDeclaredWrite(call: ToolCallLike): boolean;
|
|
81
|
+
/** design/388 A-18 — the file-op access a compaction summary records for a LIVE tool name: only the FILE families'
|
|
82
|
+
* path targets name a file (a search tool's `path` is a search ROOT, not a file the model read); every other name
|
|
83
|
+
* records nothing (retired spellings in persisted transcripts read the frozen history table at the call site). */
|
|
84
|
+
export declare function fileOpAccessOf(name: string): ToolPathAccess | undefined;
|
|
85
|
+
export declare function pathTargetOf(name: string): ToolCatalogEntry["face"]["pathTarget"];
|
|
86
|
+
/**
|
|
87
|
+
* The rule vocabulary of a wire name from the STATIC catalog: `primaryParams` = the declared primaries, else
|
|
88
|
+
* the path target's `param` + aliases; `params` = the declared vocabulary, else the path target's names —
|
|
89
|
+
* and UNDEFINED when the catalog cannot know the full vocabulary (a definition whose schema is built inside
|
|
90
|
+
* its factory and declares no `ruleFace.params`): the static half never claims a vocabulary it has not
|
|
91
|
+
* read, so the rule compiler judges only what it knows and the leg's roster (which reads the schema)
|
|
92
|
+
* judges the rest. `undefined` as a whole for a name with nothing to say.
|
|
93
|
+
*/
|
|
94
|
+
export declare function catalogRuleFaceOf(name: string): {
|
|
95
|
+
primaryParams: string[];
|
|
96
|
+
params?: string[];
|
|
97
|
+
} | undefined;
|
|
98
|
+
/** A-1 / server B-1 — the hand band's declared effects by name (any `hands` definition; the WRITE shell
|
|
99
|
+
* wins the name when both are listed, matching the by-name table this replaces — the read-only shell's
|
|
100
|
+
* own instance carries `effect: "read"` and the effect roster reports THAT). */
|
|
101
|
+
export declare function handBandEffects(): ReadonlyMap<string, NonNullable<ToolCatalogEntry["face"]["effect"]>>;
|
|
102
|
+
/** A-3 / L4 — every `details.type` card the engine owns: the catalog's per-definition cards plus the
|
|
103
|
+
* engine-minted ones (protocol channels, fs refusals). */
|
|
104
|
+
export declare function engineCardTypes(): ReadonlySet<string>;
|
|
105
|
+
/**
|
|
106
|
+
* L3 — the STATIC PREDICTION of a leg's core-mounted names for a set of active mount conditions:
|
|
107
|
+
* every definition listed under at least one active tag. `scenario` and `optional` definitions mount
|
|
108
|
+
* only when the vector names their tag (a host factory / a per-task opt-in decides them). Names are
|
|
109
|
+
* folded (the two shells predict one `Bash`).
|
|
110
|
+
*/
|
|
111
|
+
export declare function predictMountedToolNames(active: ReadonlySet<ToolMountTag>): ReadonlySet<string>;
|
|
112
|
+
/** The closed set as a Set, for callers that validate a tag read off the wire. */
|
|
113
|
+
export declare const TOOL_MOUNT_TAG_SET: ReadonlySet<string>;
|
|
114
|
+
export { HANDS_BAND_TAGS, MOUNT_TAG_IN_HANDS_BAND } from "./tool-face.js";
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { TOOL_MOUNT_TAGS } from "./tool-face.js";
|
|
2
|
+
import { ENGINE_CARDS, TOOL_CATALOG_ENTRIES } from "./tool-catalog-entries.js";
|
|
3
|
+
export function describeToolCatalog() {
|
|
4
|
+
return TOOL_CATALOG_ENTRIES;
|
|
5
|
+
}
|
|
6
|
+
export function catalogEntriesNamed(name) {
|
|
7
|
+
return TOOL_CATALOG_ENTRIES.filter((e) => e.name === name);
|
|
8
|
+
}
|
|
9
|
+
export function catalogToolNames() {
|
|
10
|
+
const out = new Set();
|
|
11
|
+
for (const e of TOOL_CATALOG_ENTRIES) {
|
|
12
|
+
out.add(e.name);
|
|
13
|
+
for (const a of e.face.aliases ?? [])
|
|
14
|
+
out.add(a);
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
const names = (pred) => {
|
|
19
|
+
const out = new Set();
|
|
20
|
+
for (const e of TOOL_CATALOG_ENTRIES)
|
|
21
|
+
if (pred(e))
|
|
22
|
+
out.add(e.name);
|
|
23
|
+
return out;
|
|
24
|
+
};
|
|
25
|
+
export function pathConfinableWriteToolNames() {
|
|
26
|
+
return names((e) => e.face.pathTarget !== undefined && e.face.pathTarget.access !== "read");
|
|
27
|
+
}
|
|
28
|
+
export function skillScopeWriteToolNames() {
|
|
29
|
+
return names((e) => e.face.pathTarget !== undefined && e.face.pathTarget.access !== "read" && e.face.pathTarget.skillScopeEligible === true);
|
|
30
|
+
}
|
|
31
|
+
export function pathTargetingToolNames() {
|
|
32
|
+
return names((e) => e.face.pathTarget !== undefined);
|
|
33
|
+
}
|
|
34
|
+
export function compactableToolNames() {
|
|
35
|
+
return names((e) => e.face.compactable === true);
|
|
36
|
+
}
|
|
37
|
+
export function budgetExemptToolNames() {
|
|
38
|
+
return names((e) => e.face.budgetExempt === true);
|
|
39
|
+
}
|
|
40
|
+
export function pathTargetValue(args, pt) {
|
|
41
|
+
if (args === null || typeof args !== "object")
|
|
42
|
+
return undefined;
|
|
43
|
+
const a = args;
|
|
44
|
+
for (const k of [pt.param, ...(pt.aliases ?? [])]) {
|
|
45
|
+
const v = a[k];
|
|
46
|
+
if (typeof v === "string" && v.length > 0)
|
|
47
|
+
return v;
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
export function protectivePathTargetOf(call) {
|
|
52
|
+
return call.face?.pathTarget ?? pathTargetOf(call.toolName);
|
|
53
|
+
}
|
|
54
|
+
export function declaredPathTargetOf(call) {
|
|
55
|
+
return call.face !== undefined ? call.face.pathTarget : pathTargetOf(call.toolName);
|
|
56
|
+
}
|
|
57
|
+
export function isProtectedWrite(call) {
|
|
58
|
+
const pt = protectivePathTargetOf(call);
|
|
59
|
+
return pt !== undefined && pt.access !== "read";
|
|
60
|
+
}
|
|
61
|
+
export function isDeclaredWrite(call) {
|
|
62
|
+
const pt = declaredPathTargetOf(call);
|
|
63
|
+
return pt !== undefined && pt.access !== "read";
|
|
64
|
+
}
|
|
65
|
+
export function fileOpAccessOf(name) {
|
|
66
|
+
for (const e of TOOL_CATALOG_ENTRIES) {
|
|
67
|
+
if (e.name === name && (e.face.family === "file-read" || e.face.family === "file-write") && e.face.pathTarget !== undefined)
|
|
68
|
+
return e.face.pathTarget.access;
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
export function pathTargetOf(name) {
|
|
73
|
+
for (const e of TOOL_CATALOG_ENTRIES)
|
|
74
|
+
if (e.name === name && e.face.pathTarget !== undefined)
|
|
75
|
+
return e.face.pathTarget;
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
export function catalogRuleFaceOf(name) {
|
|
79
|
+
for (const e of TOOL_CATALOG_ENTRIES) {
|
|
80
|
+
if (e.name !== name)
|
|
81
|
+
continue;
|
|
82
|
+
const pt = e.face.pathTarget;
|
|
83
|
+
const primary = e.face.ruleFace?.primaryParams ?? (pt !== undefined ? [pt.param, ...(pt.aliases ?? [])] : []);
|
|
84
|
+
const params = e.face.ruleFace?.params ?? (pt !== undefined ? [pt.param, ...(pt.aliases ?? [])] : undefined);
|
|
85
|
+
if (params === undefined && primary.length === 0)
|
|
86
|
+
continue;
|
|
87
|
+
return { primaryParams: [...primary], ...(params !== undefined ? { params: [...new Set([...params, ...primary])] } : {}) };
|
|
88
|
+
}
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
export function handBandEffects() {
|
|
92
|
+
const out = new Map();
|
|
93
|
+
for (const e of TOOL_CATALOG_ENTRIES) {
|
|
94
|
+
if (!e.mountedBy.includes("hands"))
|
|
95
|
+
continue;
|
|
96
|
+
const eff = e.face.effect ?? "write";
|
|
97
|
+
const prior = out.get(e.name);
|
|
98
|
+
if (prior === undefined || prior === "read")
|
|
99
|
+
out.set(e.name, eff);
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
export function engineCardTypes() {
|
|
104
|
+
const out = new Set(Object.keys(ENGINE_CARDS));
|
|
105
|
+
for (const e of TOOL_CATALOG_ENTRIES)
|
|
106
|
+
for (const card of e.cards)
|
|
107
|
+
out.add(card);
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
export function predictMountedToolNames(active) {
|
|
111
|
+
return names((e) => e.mountedBy.some((t) => active.has(t)));
|
|
112
|
+
}
|
|
113
|
+
export const TOOL_MOUNT_TAG_SET = new Set(TOOL_MOUNT_TAGS);
|
|
114
|
+
export { HANDS_BAND_TAGS, MOUNT_TAG_IN_HANDS_BAND } from "./tool-face.js";
|
|
@@ -46,8 +46,5 @@ export interface AggregateBudgetOptions {
|
|
|
46
46
|
results: number;
|
|
47
47
|
}) => void;
|
|
48
48
|
}
|
|
49
|
-
/** Default exemptions: tools whose result is self-bounded (read_file errors at its own token cap; the
|
|
50
|
-
* offload reader pages small slices). grep/bash/glob/web_fetch/MCP are the risk sources, NOT exempt. */
|
|
51
|
-
export declare const DEFAULT_BUDGET_EXEMPT_TOOLS: ReadonlySet<string>;
|
|
52
49
|
/** Cap each over-budget turn-batch (run of consecutive tool_result messages). Request-only; see file docs. */
|
|
53
50
|
export declare function capAggregateToolResults(messages: AgentMessage[], opts: AggregateBudgetOptions): Promise<AgentMessage[]>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isToolResult } from "./message-utils.js";
|
|
2
|
-
import { buildPreview, buildToolResultRef,
|
|
2
|
+
import { buildPreview, buildToolResultRef, PERSISTED_OUTPUT_PREFIX, toolResultContentSegment, toolResultProvenanceOf, } from "./tool-result-store.js";
|
|
3
|
+
import { budgetExemptToolNames } from "./tool-registry.js";
|
|
3
4
|
export const AGGREGATE_TOOL_RESULT_BUDGET_CHARS = 200_000;
|
|
4
5
|
const HEAD = 1_000;
|
|
5
6
|
const TAIL = 1_000;
|
|
@@ -33,10 +34,10 @@ function truncationPreview(full, head = HEAD, tail = TAIL) {
|
|
|
33
34
|
`…[${total} chars total; ${tailStart - head} omitted to fit the per-turn result budget — re-run with a narrower query to see the rest.]\n` +
|
|
34
35
|
`${full.slice(tailStart)}`);
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
const CATALOG_BUDGET_EXEMPT_TOOLS = budgetExemptToolNames();
|
|
37
38
|
export async function capAggregateToolResults(messages, opts) {
|
|
38
39
|
const budget = opts.budgetChars ?? AGGREGATE_TOOL_RESULT_BUDGET_CHARS;
|
|
39
|
-
const exempt = opts.exemptTools ??
|
|
40
|
+
const exempt = opts.exemptTools ?? CATALOG_BUDGET_EXEMPT_TOOLS;
|
|
40
41
|
let out;
|
|
41
42
|
let i = 0;
|
|
42
43
|
while (i < messages.length) {
|
|
@@ -446,24 +446,6 @@ export declare function offloadPagebackHint(ref: string, form: "preview" | "clea
|
|
|
446
446
|
export declare const PERSISTED_OUTPUT_PREFIX = "<persisted-output ref=";
|
|
447
447
|
/** Default per-result offload threshold (chars). ~5K tokens; configurable globally or per tool. */
|
|
448
448
|
export declare const DEFAULT_TOOL_RESULT_THRESHOLD_CHARS = 20000;
|
|
449
|
-
/**
|
|
450
|
-
* CC 198 per-tool persistence thresholds, mirrored for the first-party mounts (PARITY-SPOT-USAGE-CONSTANTS
|
|
451
|
-
* 2026-07-10 F1/F2). CC's GIa framework (pretty.js:286716-286721) resolves each tool's persist threshold as
|
|
452
|
-
* `min(maxResultSizeChars, w6t=50000)`:
|
|
453
|
-
* - Read declares `maxResultSizeChars: 1/0` (:478260) → **never persisted**. Read already owns its bound
|
|
454
|
-
* (25K-token first-page auto-pagination) and the aggregate budget exempts it — wrapping it in offload
|
|
455
|
-
* re-truncated a page the tool had already sized (the F1 two-layer inconsistency). Structural exemption:
|
|
456
|
-
* applies even when a deployment sets an explicit global threshold.
|
|
457
|
-
* - Bash 30000 (:335231) / Grep 20000 (:333220) / Monitor 1e4 (:450030); everything else first-party
|
|
458
|
-
* declares 1e5 (Agent :453402, Glob :333570, TaskOutput :458260, …) → min(1e5, 50000) = 50000.
|
|
459
|
-
* Unknown tools keep the deployment default ({@link DEFAULT_TOOL_RESULT_THRESHOLD_CHARS}) — we deliberately
|
|
460
|
-
* do NOT mirror KIa's bare `$xa=400000` undeclared-tool fallback: our aggregate budget is 200K chars, so a
|
|
461
|
-
* 400K inline result is unrepresentable anyway.
|
|
462
|
-
*/
|
|
463
|
-
export declare function firstPartyOffloadPolicy(toolName: string): {
|
|
464
|
-
offload?: boolean;
|
|
465
|
-
offloadThresholdChars?: number;
|
|
466
|
-
};
|
|
467
449
|
/** Head+tail preview of an offloaded result, pointing at {@link OFFLOAD_TOOL_NAME} via `ref`. Exported so
|
|
468
450
|
* the per-message aggregate budget (design/64 §17.2) produces the SAME preview format (deterministic →
|
|
469
451
|
* byte-identical across queries → prompt-cache safe).
|
|
@@ -4,6 +4,7 @@ import { uuidv7 } from "../engine/session/uuid.js";
|
|
|
4
4
|
import { defineTool, errorResult } from "./tools.js";
|
|
5
5
|
import { deliverEngineNotice } from "./types.js";
|
|
6
6
|
import { TOOL_SEARCH_NAME } from "./runner/tool-disclosure.js";
|
|
7
|
+
import { toolFace } from "./tool-catalog-entries.js";
|
|
7
8
|
export const TOOL_RESULT_REF_CONFLICT_CODE = "tool_result.ref_conflict";
|
|
8
9
|
export class ToolResultRefConflictError extends Error {
|
|
9
10
|
ref;
|
|
@@ -202,22 +203,6 @@ export function offloadPagebackHint(ref, form, reachableTools) {
|
|
|
202
203
|
}
|
|
203
204
|
export const PERSISTED_OUTPUT_PREFIX = "<persisted-output ref=";
|
|
204
205
|
export const DEFAULT_TOOL_RESULT_THRESHOLD_CHARS = 20_000;
|
|
205
|
-
export function firstPartyOffloadPolicy(toolName) {
|
|
206
|
-
switch (toolName) {
|
|
207
|
-
case "Read":
|
|
208
|
-
return { offload: false };
|
|
209
|
-
case "Write":
|
|
210
|
-
return { offload: false };
|
|
211
|
-
case "Bash":
|
|
212
|
-
return { offloadThresholdChars: 30_000 };
|
|
213
|
-
case "Grep":
|
|
214
|
-
return { offloadThresholdChars: 20_000 };
|
|
215
|
-
case "Monitor":
|
|
216
|
-
return { offloadThresholdChars: 10_000 };
|
|
217
|
-
default:
|
|
218
|
-
return { offloadThresholdChars: 50_000 };
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
206
|
const PREVIEW_HEAD_CHARS = 1_000;
|
|
222
207
|
const PREVIEW_TAIL_CHARS = 1_000;
|
|
223
208
|
const READ_DEFAULT_LIMIT = 4_000;
|
|
@@ -398,7 +383,7 @@ async function offloadOversizedDetailStrings(details, store, thresholdChars, ses
|
|
|
398
383
|
export function createReadToolResultTool(store) {
|
|
399
384
|
return defineTool({
|
|
400
385
|
name: OFFLOAD_TOOL_NAME,
|
|
401
|
-
|
|
386
|
+
...toolFace("read-tool-result"),
|
|
402
387
|
description: `Read the full content of a tool result that was too large and persisted (you saw it as ` +
|
|
403
388
|
`<persisted-output ref="..."> with a preview). Pass the ref; use offset/limit to page through it.`,
|
|
404
389
|
parameters: Type.Object({
|
|
@@ -406,7 +391,6 @@ export function createReadToolResultTool(store) {
|
|
|
406
391
|
offset: Type.Optional(Type.Number({ description: "Char offset to start at (default 0)." })),
|
|
407
392
|
limit: Type.Optional(Type.Number({ description: `Max chars to return (default ${READ_DEFAULT_LIMIT}, capped ${READ_MAX_LIMIT}).` })),
|
|
408
393
|
}),
|
|
409
|
-
effect: "read",
|
|
410
394
|
execute: async (args) => {
|
|
411
395
|
const { ref, offset, limit } = args;
|
|
412
396
|
const off = Math.max(0, intOr(offset, 0));
|