@sema-agent/core 7.9.0 → 7.9.1
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 +23 -0
- package/dist/core/ask-origin.d.ts +7 -3
- package/dist/core/checkpoint-store.d.ts +2 -7
- package/dist/core/effective-path-target.d.ts +43 -0
- package/dist/core/effective-path-target.js +56 -0
- package/dist/core/engine-notice.d.ts +8 -0
- package/dist/core/fs-write-gate-policy.js +2 -1
- package/dist/core/gate-lanes.d.ts +1 -0
- package/dist/core/gate-lanes.js +11 -5
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/hooks.d.ts +10 -1
- package/dist/core/mcp-injection-drop.d.ts +74 -0
- package/dist/core/mcp-injection-drop.js +27 -0
- package/dist/core/permission-rule-model.d.ts +91 -75
- package/dist/core/permission-rule-model.js +90 -111
- package/dist/core/permission-rule-org.d.ts +12 -6
- package/dist/core/permission-rule-org.js +9 -3
- package/dist/core/permission-rules.d.ts +3 -2
- package/dist/core/permission-rules.js +38 -15
- package/dist/core/persisted-rule-arms.d.ts +7 -2
- package/dist/core/persisted-rule-arms.js +3 -1
- package/dist/core/runner/active-skill-scope.js +2 -1
- package/dist/core/runner/permission-rule-lanes.d.ts +12 -4
- package/dist/core/runner/permission-rule-lanes.js +13 -15
- package/dist/core/runner/session-rule-policy.js +2 -1
- package/dist/core/runner/tool-face-overlay.js +22 -3
- package/dist/core/sensitive-path-policy.js +5 -3
- package/dist/core/shell-lexer.d.ts +47 -0
- package/dist/core/shell-lexer.js +478 -0
- package/dist/core/shell-scan.d.ts +60 -0
- package/dist/core/shell-scan.js +183 -0
- package/dist/core/shell-wrapper-table.d.ts +297 -0
- package/dist/core/shell-wrapper-table.js +58 -0
- package/dist/core/tool-catalog-entries.js +6 -6
- package/dist/core/tool-face.d.ts +80 -4
- package/dist/core/tool-face.js +10 -0
- package/dist/core/tool-policy.d.ts +1 -6
- package/dist/core/tool-registry.d.ts +8 -11
- package/dist/core/tool-registry.js +5 -2
- package/dist/core/tool-roster.d.ts +11 -2
- package/dist/core/tool-roster.js +21 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +5 -2
- package/dist/tools/fs/fs-search-tools.d.ts +3 -2
- package/dist/tools/fs/fs-search-tools.js +17 -9
- package/dist/tools/fs/index.js +1 -1
- package/dist/tools/fs/search.d.ts +0 -8
- package/dist/tools/fs/search.js +0 -23
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +57 -1
package/dist/core/tool-face.d.ts
CHANGED
|
@@ -46,18 +46,94 @@ export type ToolApprovalCard = (typeof TOOL_APPROVAL_CARDS)[number];
|
|
|
46
46
|
export declare const TOOL_PATH_ACCESSES: readonly ["read", "create", "edit"];
|
|
47
47
|
export type ToolPathAccess = (typeof TOOL_PATH_ACCESSES)[number];
|
|
48
48
|
/**
|
|
49
|
-
* The
|
|
50
|
-
*
|
|
51
|
-
*
|
|
49
|
+
* The BASE a RELATIVE spelling in the target slot resolves against — the tool's OWN resolution base,
|
|
50
|
+
* DECLARED so every fence resolves the very path the tool will open instead of guessing one:
|
|
51
|
+
*
|
|
52
|
+
* - `cwd` — the live tracked working directory, falling back to the task root when no tracker moved
|
|
53
|
+
* (Read / Edit / Write / NotebookEdit: each hands `cwdRef.current` to `canonicalizeTarget` as its base);
|
|
54
|
+
* - `root` — the task root, always (Grep / Glob: their `path` describes say "relative to root", and the
|
|
55
|
+
* tools hand `rootCanonical` to the same resolver whatever the shell's `cd` did).
|
|
56
|
+
*
|
|
57
|
+
* Absent ⇒ `cwd`: the pre-declaration reading every fence took, kept as the floor for a face (a caller's,
|
|
58
|
+
* an MCP server's) that declares no base. This one word is the whole difference the fences had to model,
|
|
59
|
+
* and getting it wrong is SILENT — a rule about the path the tool really opens simply never fires.
|
|
60
|
+
*/
|
|
61
|
+
export declare const TOOL_PATH_BASES: readonly ["cwd", "root"];
|
|
62
|
+
export type ToolPathBase = (typeof TOOL_PATH_BASES)[number];
|
|
63
|
+
/**
|
|
64
|
+
* What the call targets when the target slot carries NO usable spelling:
|
|
65
|
+
*
|
|
66
|
+
* - `none` — nothing. A file tool with no path names no file, so no path rule speaks about the call;
|
|
67
|
+
* - `base` — the resolution base ITSELF. A search tool with no `path` searches the WHOLE base, so a rule
|
|
68
|
+
* naming the base (or anything containing it) does reach the call.
|
|
69
|
+
*
|
|
70
|
+
* Absent ⇒ `none` (the pre-declaration reading: an absent slot was "no resolvable path" for every tool).
|
|
71
|
+
*/
|
|
72
|
+
export declare const TOOL_PATH_ABSENCES: readonly ["none", "base"];
|
|
73
|
+
export type ToolPathAbsence = (typeof TOOL_PATH_ABSENCES)[number];
|
|
74
|
+
/**
|
|
75
|
+
* The parameter that names a tool's filesystem target, how the target is touched, and how a spelling in that
|
|
76
|
+
* slot RESOLVES — as a READER sees it, whichever side it came from. Present ⇔ the tool can be confirmed BY
|
|
77
|
+
* PATH (write confinement, sensitive-path guards, edited-file tracking, the transcript-directory gate, the
|
|
78
|
+
* permission-rule path family). `param` outranks every alias (NotebookEdit's `notebook_path` beats a decoy
|
|
52
79
|
* `file_path`). `skillScopeEligible` (default false) is the SEPARATE authorization domain of the
|
|
53
80
|
* active-skill `allowPaths` face — a confinable write tool is not automatically eligible there.
|
|
81
|
+
*
|
|
82
|
+
* ONE shape, two spellings: a DECLARATION ({@link ToolPathTarget}, what a catalog row / a `ToolSpec` / an
|
|
83
|
+
* MCP overlay writes) and the roster row's NORMALIZED form (`aliases` always an array, `skillScopeEligible`
|
|
84
|
+
* always a boolean) that the wire carries and the gate stamps on a call. Both are readable through this
|
|
85
|
+
* type, which is what every fence reads — the shape used to be re-declared at each of them, and a member
|
|
86
|
+
* added to one spelling silently never reached the others.
|
|
87
|
+
*
|
|
88
|
+
* The three RESOLUTION members are read by one function (`effectivePathTargetOf`, effective-path-target.ts)
|
|
89
|
+
* that every fence and the tools themselves go through: the declaration is the single source, so a fence
|
|
90
|
+
* and the tool it fences cannot resolve one call to two different files.
|
|
54
91
|
*/
|
|
55
|
-
export interface
|
|
92
|
+
export interface ToolCallPathTarget {
|
|
56
93
|
param: string;
|
|
57
94
|
aliases?: readonly string[];
|
|
58
95
|
access: ToolPathAccess;
|
|
96
|
+
skillScopeEligible?: boolean;
|
|
97
|
+
/** How a RELATIVE spelling in `param` (or an alias) resolves. Absent ⇒ `cwd`. */
|
|
98
|
+
base?: ToolPathBase;
|
|
99
|
+
/** What the call targets when the slot is absent. Absent ⇒ `none`. */
|
|
100
|
+
absent?: ToolPathAbsence;
|
|
101
|
+
/**
|
|
102
|
+
* A top-level parameter whose ABSOLUTE glob pattern carries its own base directory (Glob's `pattern`:
|
|
103
|
+
* `/proj/secret/**` searches `/proj/secret` with no `path` at all). Consulted ONLY when the target slot
|
|
104
|
+
* is absent and `absent` is `base` — the tool's own precedence, in which an explicit `path` wins and a
|
|
105
|
+
* relative pattern leaves the base alone.
|
|
106
|
+
*/
|
|
107
|
+
patternParam?: string;
|
|
108
|
+
}
|
|
109
|
+
/** The DECLARATION spelling of {@link ToolCallPathTarget}: what a catalog row, a `ToolSpec` or an MCP
|
|
110
|
+
* overlay writes. `skillScopeEligible` is narrowed to `true` — a declaration says "eligible" or says
|
|
111
|
+
* nothing; "eligible: false" is the absence, and spelling it would be a second way to say one thing. */
|
|
112
|
+
export interface ToolPathTarget extends ToolCallPathTarget {
|
|
59
113
|
skillScopeEligible?: true;
|
|
60
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* The NORMALIZED spelling of {@link ToolCallPathTarget}: what the roster MINTS, what the wire carries, and
|
|
117
|
+
* what the gate stamps on a call. `aliases` and `skillScopeEligible` are always present because the mint
|
|
118
|
+
* fills them — a guarantee a consumer reading a stamped face has always had, and one the shared reader type
|
|
119
|
+
* deliberately does not weaken (an optional member here would break `face.pathTarget.aliases.includes(…)`
|
|
120
|
+
* at compile time for every downstream that already reads it).
|
|
121
|
+
*/
|
|
122
|
+
export interface ToolRosterPathTarget extends ToolCallPathTarget {
|
|
123
|
+
aliases: readonly string[];
|
|
124
|
+
skillScopeEligible: boolean;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The SLOT half of a target — which argument names the path — with the RESOLUTION half (`base` / `absent` /
|
|
128
|
+
* `patternParam`) dropped, so the reader falls back to the documented defaults.
|
|
129
|
+
*
|
|
130
|
+
* #635, from the adversarial round: the protective floor (design/388 B6 — a face that declares no target of
|
|
131
|
+
* its own is judged against the CATALOG's declaration for the name) rests on "naming a slot can only TIGHTEN
|
|
132
|
+
* a deny". Naming a slot does. Claiming how a FOREIGN tool of the same name RESOLVES that slot does not: a
|
|
133
|
+
* wrong claim moves the judged path to a different file, and the deny the floor exists to keep then misses.
|
|
134
|
+
* So the floor hands over the slot and keeps its mouth shut about the resolution.
|
|
135
|
+
*/
|
|
136
|
+
export declare function pathTargetSlotOnly(pt: ToolCallPathTarget): ToolCallPathTarget;
|
|
61
137
|
/**
|
|
62
138
|
* The parameter vocabulary a permission rule (`Tool(param:pattern)`) may name. DERIVED by default from
|
|
63
139
|
* the tool's schema: the SCALAR top-level parameters (string/number/integer/boolean and their enum/const/
|
package/dist/core/tool-face.js
CHANGED
|
@@ -2,6 +2,16 @@ export const TOOL_FAMILIES = ["shell", "file-read", "file-write", "search", "web
|
|
|
2
2
|
export const TOOL_MOUNT_TAGS = ["hands", "backgroundTasks", "workflow", "delegation", "hostInternals", "peerLane", "scheduler", "memory", "scenario", "always", "optional"];
|
|
3
3
|
export const TOOL_APPROVAL_CARDS = ["file-edit", "file-write", "notebook-edit", "shell", "fetch", "plan", "question", "generic"];
|
|
4
4
|
export const TOOL_PATH_ACCESSES = ["read", "create", "edit"];
|
|
5
|
+
export const TOOL_PATH_BASES = ["cwd", "root"];
|
|
6
|
+
export const TOOL_PATH_ABSENCES = ["none", "base"];
|
|
7
|
+
export function pathTargetSlotOnly(pt) {
|
|
8
|
+
return {
|
|
9
|
+
param: pt.param,
|
|
10
|
+
access: pt.access,
|
|
11
|
+
...(pt.aliases !== undefined ? { aliases: pt.aliases } : {}),
|
|
12
|
+
...(pt.skillScopeEligible !== undefined ? { skillScopeEligible: pt.skillScopeEligible } : {}),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
5
15
|
export const TOOL_WIRE_NAME_MAX_CHARS = 128;
|
|
6
16
|
export const TOOL_CONTRACT_MAX_CHARS = 64;
|
|
7
17
|
export const TOOL_KEY_MAX_CHARS = 256;
|
|
@@ -4,12 +4,7 @@ import type { Settlement } from "./gate-outcome.js";
|
|
|
4
4
|
/** design/388 B6 — the per-call face (see {@link ToolCallRequest.face}). */
|
|
5
5
|
export interface ToolCallFace {
|
|
6
6
|
family: import("./tool-face.js").ToolFamily;
|
|
7
|
-
pathTarget?:
|
|
8
|
-
param: string;
|
|
9
|
-
aliases: readonly string[];
|
|
10
|
-
access: "read" | "create" | "edit";
|
|
11
|
-
skillScopeEligible: boolean;
|
|
12
|
-
};
|
|
7
|
+
pathTarget?: import("./tool-face.js").ToolRosterPathTarget;
|
|
13
8
|
capabilityId: string;
|
|
14
9
|
contractId: string;
|
|
15
10
|
shapeDigest: string;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Layer-0 vocabulary: depends on the leaf catalog and the face vocabulary only.
|
|
12
12
|
*/
|
|
13
|
-
import { type ToolCatalogEntry, type ToolMountTag, type ToolPathAccess } from "./tool-face.js";
|
|
13
|
+
import { type ToolCallPathTarget, type ToolCatalogEntry, type ToolMountTag, type ToolPathAccess } from "./tool-face.js";
|
|
14
14
|
/** The whole static catalog, one frozen row per definition (design/388 §2.1 `describeToolCatalog()`).
|
|
15
15
|
* Replaces the retired name-keyed exports `HAND_TOOL_EFFECTS` / `DEFAULT_BUDGET_EXEMPT_TOOLS` /
|
|
16
16
|
* `COMPACTABLE_TOOLS`: filter this instead (`e.mountedBy.includes("hands")`, `e.face.budgetExempt`,
|
|
@@ -45,24 +45,21 @@ export interface ToolCallLike {
|
|
|
45
45
|
toolName: string;
|
|
46
46
|
args: unknown;
|
|
47
47
|
face?: {
|
|
48
|
-
pathTarget?:
|
|
49
|
-
param: string;
|
|
50
|
-
aliases?: readonly string[];
|
|
51
|
-
access: ToolPathAccess;
|
|
52
|
-
};
|
|
48
|
+
pathTarget?: ToolCallPathTarget;
|
|
53
49
|
} | undefined;
|
|
54
50
|
}
|
|
55
|
-
type CallPathTarget =
|
|
56
|
-
param: string;
|
|
57
|
-
aliases?: readonly string[];
|
|
58
|
-
access: ToolPathAccess;
|
|
59
|
-
};
|
|
51
|
+
type CallPathTarget = ToolCallPathTarget;
|
|
60
52
|
/**
|
|
61
53
|
* design/388 B6/B17 — the path target a PROTECTIVE fence reads (a deny-list judging a write's target: sensitive paths,
|
|
62
54
|
* frozen paths, write protection, the transcript gate; edit tracking): the object face's own declaration first, the
|
|
63
55
|
* catalog's declaration for the NAME as the FLOOR — for a bare request (a policy invoked outside a Runner) and for a
|
|
64
56
|
* face that declares none. Reading the catalog for an undeclared same-name tool can only TIGHTEN a deny-list (it adds
|
|
65
57
|
* a slot to judge — the pre-388 posture, never wider), which is exactly why this floor is wrong for a grant.
|
|
58
|
+
*
|
|
59
|
+
* #635: "can only tighten" is true of the SLOT and false of the RESOLUTION, so the floor hands over the first and
|
|
60
|
+
* defaults the second (`pathTargetSlotOnly`). Telling a fence that a FOREIGN tool of the same name resolves its slot
|
|
61
|
+
* against the project root is a claim about someone else's implementation: get it wrong and the judged path moves to
|
|
62
|
+
* a different file, and the deny this floor exists to preserve simply misses.
|
|
66
63
|
*/
|
|
67
64
|
export declare function protectivePathTargetOf(call: ToolCallLike): CallPathTarget | undefined;
|
|
68
65
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TOOL_MOUNT_TAGS } from "./tool-face.js";
|
|
1
|
+
import { TOOL_MOUNT_TAGS, pathTargetSlotOnly } from "./tool-face.js";
|
|
2
2
|
import { ENGINE_CARDS, TOOL_CATALOG_ENTRIES } from "./tool-catalog-entries.js";
|
|
3
3
|
export function describeToolCatalog() {
|
|
4
4
|
return TOOL_CATALOG_ENTRIES;
|
|
@@ -49,7 +49,10 @@ export function pathTargetValue(args, pt) {
|
|
|
49
49
|
return undefined;
|
|
50
50
|
}
|
|
51
51
|
export function protectivePathTargetOf(call) {
|
|
52
|
-
|
|
52
|
+
if (call.face?.pathTarget !== undefined)
|
|
53
|
+
return call.face.pathTarget;
|
|
54
|
+
const floor = pathTargetOf(call.toolName);
|
|
55
|
+
return floor === undefined || call.face === undefined ? floor : pathTargetSlotOnly(floor);
|
|
53
56
|
}
|
|
54
57
|
export function declaredPathTargetOf(call) {
|
|
55
58
|
return call.face !== undefined ? call.face.pathTarget : pathTargetOf(call.toolName);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Type, type Static, type TSchema } from "typebox";
|
|
2
2
|
import type { AgentTool } from "../internal/harness-types.js";
|
|
3
|
-
import { type ToolFamily, type ToolMountTag, type ToolPathTarget, type ToolRenderHints, type ToolRuleFace } from "./tool-face.js";
|
|
3
|
+
import { type ToolFamily, type ToolRosterPathTarget, type ToolMountTag, type ToolPathTarget, type ToolRenderHints, type ToolRuleFace } from "./tool-face.js";
|
|
4
4
|
import type { ToolContentOrigin, ToolEffect } from "./tool-spec.js";
|
|
5
5
|
export declare const ROSTER_SOURCES: readonly ["builtin", "caller", "host", "mcp", "a2a", "external", "synthetic"];
|
|
6
6
|
export type RosterSource = (typeof ROSTER_SOURCES)[number];
|
|
@@ -55,6 +55,9 @@ export declare const ToolRosterEntry: Type.TObject<{
|
|
|
55
55
|
aliases: Type.TArray<Type.TString>;
|
|
56
56
|
access: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"create">, Type.TLiteral<"edit">]>;
|
|
57
57
|
skillScopeEligible: Type.TBoolean;
|
|
58
|
+
base: Type.TOptional<Type.TUnion<[Type.TLiteral<"cwd">, Type.TLiteral<"root">]>>;
|
|
59
|
+
absent: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"base">]>>;
|
|
60
|
+
patternParam: Type.TOptional<Type.TString>;
|
|
58
61
|
}>>;
|
|
59
62
|
ruleFace: Type.TObject<{
|
|
60
63
|
primaryParams: Type.TArray<Type.TString>;
|
|
@@ -126,6 +129,9 @@ export declare const ToolRoster: Type.TObject<{
|
|
|
126
129
|
aliases: Type.TArray<Type.TString>;
|
|
127
130
|
access: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"create">, Type.TLiteral<"edit">]>;
|
|
128
131
|
skillScopeEligible: Type.TBoolean;
|
|
132
|
+
base: Type.TOptional<Type.TUnion<[Type.TLiteral<"cwd">, Type.TLiteral<"root">]>>;
|
|
133
|
+
absent: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"base">]>>;
|
|
134
|
+
patternParam: Type.TOptional<Type.TString>;
|
|
129
135
|
}>>;
|
|
130
136
|
ruleFace: Type.TObject<{
|
|
131
137
|
primaryParams: Type.TArray<Type.TString>;
|
|
@@ -205,6 +211,9 @@ export declare const ToolRosterDelta: Type.TObject<{
|
|
|
205
211
|
aliases: Type.TArray<Type.TString>;
|
|
206
212
|
access: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"create">, Type.TLiteral<"edit">]>;
|
|
207
213
|
skillScopeEligible: Type.TBoolean;
|
|
214
|
+
base: Type.TOptional<Type.TUnion<[Type.TLiteral<"cwd">, Type.TLiteral<"root">]>>;
|
|
215
|
+
absent: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"base">]>>;
|
|
216
|
+
patternParam: Type.TOptional<Type.TString>;
|
|
208
217
|
}>>;
|
|
209
218
|
ruleFace: Type.TObject<{
|
|
210
219
|
primaryParams: Type.TArray<Type.TString>;
|
|
@@ -265,7 +274,7 @@ export declare function parkedToolFace(roster: ToolRoster | undefined, toolName:
|
|
|
265
274
|
* partial face). This is the face every recheck of the row judges under, roster or no roster. */
|
|
266
275
|
export declare function parkedCallFaceOf(pending: {
|
|
267
276
|
family?: ToolFamily;
|
|
268
|
-
pathTarget?:
|
|
277
|
+
pathTarget?: ToolRosterPathTarget;
|
|
269
278
|
capabilityId?: string;
|
|
270
279
|
contractId?: string;
|
|
271
280
|
shapeDigest?: string;
|
package/dist/core/tool-roster.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { Type } from "typebox";
|
|
3
3
|
import { getToolContract } from "../prompt-assembly/tool-catalog.js";
|
|
4
4
|
import { protocolOf } from "./protocol-table.js";
|
|
5
|
-
import { RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_CHARS, RENDER_HINT_MAX_LIST, TOOL_APPROVAL_CARDS, TOOL_FAMILIES, TOOL_KEYS_MAX, TOOL_KEY_MAX_CHARS, TOOL_MOUNT_TAGS, } from "./tool-face.js";
|
|
5
|
+
import { RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_CHARS, RENDER_HINT_MAX_LIST, TOOL_APPROVAL_CARDS, TOOL_FAMILIES, TOOL_KEYS_MAX, TOOL_KEY_MAX_CHARS, TOOL_MOUNT_TAGS, TOOL_PATH_ABSENCES, TOOL_PATH_BASES, } from "./tool-face.js";
|
|
6
6
|
function lit(values) {
|
|
7
7
|
return Type.Union(values.map((v) => Type.Literal(v)));
|
|
8
8
|
}
|
|
@@ -42,7 +42,15 @@ export const ToolRosterEntry = Type.Object({
|
|
|
42
42
|
contentOrigin: lit(["local", "execution", "external"]),
|
|
43
43
|
contentOriginProvenance: lit(["declared", "server", "exempted", "default"]),
|
|
44
44
|
family: lit(TOOL_FAMILIES),
|
|
45
|
-
pathTarget: Type.Optional(Type.Object({
|
|
45
|
+
pathTarget: Type.Optional(Type.Object({
|
|
46
|
+
param: Key,
|
|
47
|
+
aliases: Type.Array(Key),
|
|
48
|
+
access: lit(["read", "create", "edit"]),
|
|
49
|
+
skillScopeEligible: Type.Boolean(),
|
|
50
|
+
base: Type.Optional(lit(TOOL_PATH_BASES)),
|
|
51
|
+
absent: Type.Optional(lit(TOOL_PATH_ABSENCES)),
|
|
52
|
+
patternParam: Type.Optional(Key),
|
|
53
|
+
}, { additionalProperties: false })),
|
|
46
54
|
ruleFace: Type.Object({ primaryParams: Type.Array(Key), params: Type.Array(Key) }, { additionalProperties: false }),
|
|
47
55
|
approvalPreview: Type.Boolean(),
|
|
48
56
|
validateInput: Type.Boolean(),
|
|
@@ -392,7 +400,17 @@ export function mintRosterEntry(tool, meta, facts) {
|
|
|
392
400
|
contentOriginProvenance,
|
|
393
401
|
family: face.family !== undefined && TOOL_FAMILIES.includes(face.family) ? face.family : "other",
|
|
394
402
|
...(pathTarget !== undefined
|
|
395
|
-
? {
|
|
403
|
+
? {
|
|
404
|
+
pathTarget: {
|
|
405
|
+
param: pathTarget.param,
|
|
406
|
+
aliases: [...(pathTarget.aliases ?? [])],
|
|
407
|
+
access: pathTarget.access,
|
|
408
|
+
skillScopeEligible: pathTarget.skillScopeEligible === true,
|
|
409
|
+
...(pathTarget.base !== undefined ? { base: pathTarget.base } : {}),
|
|
410
|
+
...(pathTarget.absent !== undefined ? { absent: pathTarget.absent } : {}),
|
|
411
|
+
...(pathTarget.patternParam !== undefined ? { patternParam: pathTarget.patternParam } : {}),
|
|
412
|
+
},
|
|
413
|
+
}
|
|
396
414
|
: {}),
|
|
397
415
|
ruleFace: rf,
|
|
398
416
|
approvalPreview: typeof tool.approvalPreview === "function",
|
package/dist/index.d.ts
CHANGED
|
@@ -53,6 +53,7 @@ export { runCascade, type CascadeRung, type CascadeConfig, type CascadeAttempt,
|
|
|
53
53
|
export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
|
|
54
54
|
export { materializeMcpTools, MCP_PREFIX, type MaterializedMcp, type McpServerStatus, type McpRefreshResult } from "./core/mcp.js";
|
|
55
55
|
export { MCP_FAILURE_KINDS, MCP_DELIVERY_VERDICTS, classifyMcpFailure, type McpFailure, type McpFailureKind, type McpDelivered } from "./core/mcp-failure.js";
|
|
56
|
+
export { MCP_INJECTION_DROP_REASONS, MCP_INJECTION_DROP_TEXT, mcpInjectionDroppedNotice, type McpInjectionDropReason, type McpInjectionDropFacts } from "./core/mcp-injection-drop.js";
|
|
56
57
|
export { materializeA2aTools, A2aRpcError, type MaterializedA2a, type A2aPeerStatus, type A2aRefreshResult, type A2aToolAxis } from "./core/a2a.js";
|
|
57
58
|
export { PROTOCOL_TABLE, MCP_NAMESPACE, A2A_NAMESPACE, protocolOf, type ProtocolNamespace, type ProtocolId } from "./core/protocol-table.js";
|
|
58
59
|
export { InMemorySessionPolicyStore, SessionPolicyError, loosenReasons, normalizeRules, stripRev, type SessionPolicyStore, type SessionPermissionRules, type StoredSessionRules, type SessionRulesRecord, type PutRulesOptions, } from "./core/session-policy-store.js";
|
|
@@ -124,10 +125,11 @@ export { createFsWriteGatePolicy, type FsWriteGatePolicyOptions } from "./core/f
|
|
|
124
125
|
export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
|
|
125
126
|
export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
|
|
126
127
|
export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, AGENT_MESSAGE_TAG, renderAgentMessageFrame, type SemaProvenance, } from "./core/task-notification.js";
|
|
127
|
-
export { TOOL_FAMILIES, TOOL_MOUNT_TAGS, TOOL_APPROVAL_CARDS, TOOL_PATH_ACCESSES, TOOL_WIRE_NAME_MAX_CHARS, TOOL_CONTRACT_MAX_CHARS, TOOL_KEY_MAX_CHARS, TOOL_KEYS_MAX, RENDER_HINT_MAX_CHARS, RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_LIST, type ToolFamily, type ToolMountTag, type ToolApprovalCard, type ToolPathAccess, type ToolPathTarget, type ToolRuleFace, type ToolRenderHints, type ToolFaceDeclaration, type ToolCatalogEntry, } from "./core/tool-face.js";
|
|
128
|
+
export { TOOL_FAMILIES, TOOL_MOUNT_TAGS, TOOL_APPROVAL_CARDS, TOOL_PATH_ACCESSES, TOOL_PATH_BASES, TOOL_PATH_ABSENCES, TOOL_WIRE_NAME_MAX_CHARS, TOOL_CONTRACT_MAX_CHARS, TOOL_KEY_MAX_CHARS, TOOL_KEYS_MAX, RENDER_HINT_MAX_CHARS, RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_LIST, type ToolFamily, type ToolMountTag, type ToolApprovalCard, type ToolPathAccess, type ToolPathBase, type ToolPathAbsence, type ToolPathTarget, type ToolCallPathTarget, type ToolRosterPathTarget, pathTargetSlotOnly, type ToolRuleFace, type ToolRenderHints, type ToolFaceDeclaration, type ToolCatalogEntry, } from "./core/tool-face.js";
|
|
128
129
|
export { describeToolCatalog, catalogEntriesNamed, catalogToolNames, catalogRuleFaceOf, pathTargetOf, pathTargetValue, protectivePathTargetOf, declaredPathTargetOf, isProtectedWrite, isDeclaredWrite, fileOpAccessOf, type ToolCallLike, pathConfinableWriteToolNames, skillScopeWriteToolNames, pathTargetingToolNames, compactableToolNames, budgetExemptToolNames, handBandEffects, engineCardTypes, predictMountedToolNames, HANDS_BAND_TAGS, MOUNT_TAG_IN_HANDS_BAND, } from "./core/tool-registry.js";
|
|
129
130
|
export { ToolRosterEntry, ToolRoster, ToolRosterDelta, ToolRosterRenderHints, ROSTER_SOURCES, type RosterSource, type ToolIdentity, toolIdentityOf, mintCapabilityId, diffToolRoster, judgeParkedToolIdentity, ruleFacesFromRoster, toolCallFaceOf, inputKeysOf, ruleFaceOfInstance, ToolRosterDeltaSeat, } from "./core/tool-roster.js";
|
|
130
131
|
export { type ToolCallFace } from "./core/tool-policy.js";
|
|
132
|
+
export { effectivePathTargetOf, pathTargetBaseOf, type ToolPathBases } from "./core/effective-path-target.js";
|
|
131
133
|
export { TOOL_CONFORMANCE_VECTORS, describeToolConformanceVectors, type ToolConformanceVector } from "./core/tool-conformance.js";
|
|
132
134
|
export { applyMcpToolFaces, toolFaceProblem, APPROVAL_CARD_REQUIRED_KEYS, type McpToolFace } from "./core/runner/tool-face-overlay.js";
|
|
133
135
|
export { createStructuredProjector } from "./core/runner/tool-output-projection.js";
|
|
@@ -186,12 +188,13 @@ export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRul
|
|
|
186
188
|
* and nothing more. Removal is exported without ceremony, because narrowing on a user's behalf is
|
|
187
189
|
* allowed and widening is not.
|
|
188
190
|
*/
|
|
189
|
-
export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, pathRuleReaches, ruleToolGrammarOf, COMMAND_RULE_TOOL, READ_RULE_TOOL, type PathRuleBases, type RuleBehavior, type PersistedRuleVerdict, parseRuleText, formatRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, type UncoveredSegmentDetail, type EditedRuleBreadthWarning, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, type PersistedRule, type RuleTombstone, type RuleScope, type RuleDot, type RuleAdd, type RuleAddOrigin, type RuleOffer, type RuleOfferBatchMember, type SegmentRuleSuggestion, type SegmentCoverage, type RuleReject, type RuleRejectCode, type ParsedRule, type PersistedRuleTool, type PersistedRuleMatch, } from "./core/permission-rule-model.js";
|
|
191
|
+
export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, programRunReachOf, PROGRAM_RUN_REACHES, type ProgramRunReach, type ProgramRunReachOutcome, pathRuleReaches, ruleToolGrammarOf, COMMAND_RULE_TOOL, READ_RULE_TOOL, type PathRuleBases, type RuleBehavior, type PersistedRuleVerdict, parseRuleText, formatRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, type UncoveredSegmentDetail, type EditedRuleBreadthWarning, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, type PersistedRule, type RuleTombstone, type RuleScope, type RuleDot, type RuleAdd, type RuleAddOrigin, type RuleOffer, type RuleOfferBatchMember, type SegmentRuleSuggestion, type SegmentCoverage, type RuleReject, type RuleRejectCode, type ParsedRule, type PersistedRuleTool, type PersistedRuleMatch, } from "./core/permission-rule-model.js";
|
|
190
192
|
export { removePersistedRule, applyTombstones, sameScope, sameRuleIdentity, isValidConsentScope, isValidDurableScope, InMemoryDurableRulePartition, EMPTY_DURABLE_RULE_PARTITION, type DurableRulePartition, type DurableRulePartitionProvider, type RuleWriteOutcome, type StoredRules, type RemoveResult, type PutResult, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, type RuleSyncState, type RuleSyncFrontier, type RuleSyncDrop, type RuleSyncLandingReport, type RuleOwner, type QuarantinedRuleAdd, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, type PermissionRuleWriter, type WritableDurableRulePartition, type RuleWriteDelta, type RuleAddDelta, type RuleDeleteDelta, type RuleSyncJoinDelta, type RawRuleSyncState, type RedemptionAuthorization, } from "./core/permission-rule-store.js";
|
|
191
193
|
export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, type PermissionRuleSyncTransport, type PermissionRuleSyncResult, type RuleSyncRequestBody, type RuleSyncResponseBody, } from "./core/permission-rule-sync.js";
|
|
192
194
|
export { createPermissionRuleStoreProvider, effectivePermissionRules, effectiveOrThrow, ruleSourceOf, type PermissionRuleStore, type PermissionRuleStoreProvider, type PermissionRuleStoreConfig, type EffectivePermissionRules, type EffectivePermissionRule, type RemovedPermissionRule, type RuleSource, } from "./core/permission-rule-provider.js";
|
|
193
195
|
export { InMemorySessionRulePartition, type SessionRulePartition, type SessionRuleAdd, type SessionRuleApplyResult, } from "./core/permission-rule-session.js";
|
|
194
|
-
export {
|
|
196
|
+
export { readShellCommand, isFullyReadable, MAX_SHELL_READ_CHARS, SHELL_WRAPPER_TABLE, type ShellCommandShape, type ShellSegment, type ShellWord, type ShellWrapperName, } from "./core/shell-lexer.js";
|
|
197
|
+
export { orgRuleVerdictFor, type OrgRuleVerdict, orgRuleShadows, unenforceableOrgRules, ORG_UNAVAILABLE_DECISION_REASON, ORG_RULE_DECISION_REASON, ORG_ADJUDICATION_TIMEOUT_MS, type OrgPermissionRule, type OrgRuleSnapshot, type OrgRuleSnapshotProvider, type OrgRuleStatePersistence, type PersistedOrgRuleState, type OrgRulePartitionConfig, type OrgRuleResolution, type OrgRuleStatus, } from "./core/permission-rule-org.js";
|
|
195
198
|
export { RULE_SYNC_DROP_CODES, type RuleSyncDropReason, type RuleQuarantineReason } from "./core/governance-codes.js";
|
|
196
199
|
export { prepareCardApproval, confirmRuleApproval, type ConfirmResult, type ConfirmRefusalReason, precheckEditedRuleText, type EditedRuleTextPrecheck, redeemRuleTicket, redeemRuleBatch, prepareCcImport, prepareStarterBatch, mintRuleTicket, STARTER_RULES, InMemoryRuleApprovalRecordStore, ruleOffersOfRecord, type RuleTicket, type RuleCandidate, type RuleApprovalKind, type RuleApprovalRecord, type RuleApprovalRecordStore, type RuleOffer2, type StaleRuleApprovalRecord, type RuleConsentDeps, type RedeemResult, type RedeemedBatchMember, type CcImportLayer, type ImportedSettingsLayer, type ImportPreview, } from "./core/permission-rule-consent.js";
|
|
197
200
|
export { FileDurableRulePartitionProvider, ORG_STATE_FILE } from "./stores/file/permission-rule-store.js";
|
package/dist/index.js
CHANGED
|
@@ -40,6 +40,7 @@ export { runCascade, } from "./agents/cascade.js";
|
|
|
40
40
|
export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
|
|
41
41
|
export { materializeMcpTools, MCP_PREFIX } from "./core/mcp.js";
|
|
42
42
|
export { MCP_FAILURE_KINDS, MCP_DELIVERY_VERDICTS, classifyMcpFailure } from "./core/mcp-failure.js";
|
|
43
|
+
export { MCP_INJECTION_DROP_REASONS, MCP_INJECTION_DROP_TEXT, mcpInjectionDroppedNotice } from "./core/mcp-injection-drop.js";
|
|
43
44
|
export { materializeA2aTools, A2aRpcError } from "./core/a2a.js";
|
|
44
45
|
export { PROTOCOL_TABLE, MCP_NAMESPACE, A2A_NAMESPACE, protocolOf } from "./core/protocol-table.js";
|
|
45
46
|
export { InMemorySessionPolicyStore, SessionPolicyError, loosenReasons, normalizeRules, stripRev, } from "./core/session-policy-store.js";
|
|
@@ -100,10 +101,11 @@ export { createFsWriteGatePolicy } from "./core/fs-write-gate-policy.js";
|
|
|
100
101
|
export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
|
|
101
102
|
export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
|
|
102
103
|
export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, AGENT_MESSAGE_TAG, renderAgentMessageFrame, } from "./core/task-notification.js";
|
|
103
|
-
export { TOOL_FAMILIES, TOOL_MOUNT_TAGS, TOOL_APPROVAL_CARDS, TOOL_PATH_ACCESSES, TOOL_WIRE_NAME_MAX_CHARS, TOOL_CONTRACT_MAX_CHARS, TOOL_KEY_MAX_CHARS, TOOL_KEYS_MAX, RENDER_HINT_MAX_CHARS, RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_LIST, } from "./core/tool-face.js";
|
|
104
|
+
export { TOOL_FAMILIES, TOOL_MOUNT_TAGS, TOOL_APPROVAL_CARDS, TOOL_PATH_ACCESSES, TOOL_PATH_BASES, TOOL_PATH_ABSENCES, TOOL_WIRE_NAME_MAX_CHARS, TOOL_CONTRACT_MAX_CHARS, TOOL_KEY_MAX_CHARS, TOOL_KEYS_MAX, RENDER_HINT_MAX_CHARS, RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_LIST, pathTargetSlotOnly, } from "./core/tool-face.js";
|
|
104
105
|
export { describeToolCatalog, catalogEntriesNamed, catalogToolNames, catalogRuleFaceOf, pathTargetOf, pathTargetValue, protectivePathTargetOf, declaredPathTargetOf, isProtectedWrite, isDeclaredWrite, fileOpAccessOf, pathConfinableWriteToolNames, skillScopeWriteToolNames, pathTargetingToolNames, compactableToolNames, budgetExemptToolNames, handBandEffects, engineCardTypes, predictMountedToolNames, HANDS_BAND_TAGS, MOUNT_TAG_IN_HANDS_BAND, } from "./core/tool-registry.js";
|
|
105
106
|
export { ToolRosterEntry, ToolRoster, ToolRosterDelta, ToolRosterRenderHints, ROSTER_SOURCES, toolIdentityOf, mintCapabilityId, diffToolRoster, judgeParkedToolIdentity, ruleFacesFromRoster, toolCallFaceOf, inputKeysOf, ruleFaceOfInstance, ToolRosterDeltaSeat, } from "./core/tool-roster.js";
|
|
106
107
|
export {} from "./core/tool-policy.js";
|
|
108
|
+
export { effectivePathTargetOf, pathTargetBaseOf } from "./core/effective-path-target.js";
|
|
107
109
|
export { TOOL_CONFORMANCE_VECTORS, describeToolConformanceVectors } from "./core/tool-conformance.js";
|
|
108
110
|
export { applyMcpToolFaces, toolFaceProblem, APPROVAL_CARD_REQUIRED_KEYS } from "./core/runner/tool-face-overlay.js";
|
|
109
111
|
export { createStructuredProjector } from "./core/runner/tool-output-projection.js";
|
|
@@ -145,11 +147,12 @@ export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/au
|
|
|
145
147
|
export { AUTO_MODE_ARMING_RECIPE_VERSION, autoModeArmingRecipeOf, sanitizeAutoModeArmingRecipe, foldAutoModeArming, } from "./core/auto-mode-arming.js";
|
|
146
148
|
export { rebuildAutoModeDecider, } from "./core/auto-mode-rebuild.js";
|
|
147
149
|
export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRule, wildcardMatch, isNamespacedCoveringRuleName, namespacedRuleNameCovers, } from "./core/permission-rules.js";
|
|
148
|
-
export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, pathRuleReaches, ruleToolGrammarOf, COMMAND_RULE_TOOL, READ_RULE_TOOL, parseRuleText, formatRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, } from "./core/permission-rule-model.js";
|
|
150
|
+
export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, programRunReachOf, PROGRAM_RUN_REACHES, pathRuleReaches, ruleToolGrammarOf, COMMAND_RULE_TOOL, READ_RULE_TOOL, parseRuleText, formatRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, } from "./core/permission-rule-model.js";
|
|
149
151
|
export { removePersistedRule, applyTombstones, sameScope, sameRuleIdentity, isValidConsentScope, isValidDurableScope, InMemoryDurableRulePartition, EMPTY_DURABLE_RULE_PARTITION, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, } from "./core/permission-rule-store.js";
|
|
150
152
|
export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, } from "./core/permission-rule-sync.js";
|
|
151
153
|
export { createPermissionRuleStoreProvider, effectivePermissionRules, effectiveOrThrow, ruleSourceOf, } from "./core/permission-rule-provider.js";
|
|
152
154
|
export { InMemorySessionRulePartition, } from "./core/permission-rule-session.js";
|
|
155
|
+
export { readShellCommand, isFullyReadable, MAX_SHELL_READ_CHARS, SHELL_WRAPPER_TABLE, } from "./core/shell-lexer.js";
|
|
153
156
|
export { orgRuleVerdictFor, orgRuleShadows, unenforceableOrgRules, ORG_UNAVAILABLE_DECISION_REASON, ORG_RULE_DECISION_REASON, ORG_ADJUDICATION_TIMEOUT_MS, } from "./core/permission-rule-org.js";
|
|
154
157
|
export { RULE_SYNC_DROP_CODES } from "./core/governance-codes.js";
|
|
155
158
|
export { prepareCardApproval, confirmRuleApproval, precheckEditedRuleText, redeemRuleTicket, redeemRuleBatch, prepareCcImport, prepareStarterBatch, mintRuleTicket, STARTER_RULES, InMemoryRuleApprovalRecordStore, ruleOffersOfRecord, } from "./core/permission-rule-consent.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentTool, ExecutionEnv } from "../../internal/harness-types.js";
|
|
2
2
|
import type { ReadDenyMatcher } from "./read-deny.js";
|
|
3
3
|
import type { ReadFace } from "./read-face.js";
|
|
4
|
+
import type { CwdRef } from "./fs-shared.js";
|
|
4
5
|
/**
|
|
5
6
|
* The Grep card's details assembly, PURE over the engine text ({mode, offset} from the request) —
|
|
6
7
|
* exported so the text→structured mapping is pinnable with synthetic texts (the byte-truncation and
|
|
@@ -10,5 +11,5 @@ import type { ReadFace } from "./read-face.js";
|
|
|
10
11
|
* this seam the honesty boundary.
|
|
11
12
|
*/
|
|
12
13
|
export declare function grepDetailFields(text: string, mode: "files_with_matches" | "content" | "count", offset?: number, structuredRows?: readonly import("./search.js").GrepRow[]): Record<string, unknown>;
|
|
13
|
-
export declare function createGrepTool(env: ExecutionEnv, rootCanonical: string, additionalRoots?: readonly string[], readDeny?: ReadDenyMatcher, readFace?: ReadFace): AgentTool;
|
|
14
|
-
export declare function createGlobTool(env: ExecutionEnv, rootCanonical: string, additionalRoots?: readonly string[], readDeny?: ReadDenyMatcher, readFace?: ReadFace): AgentTool;
|
|
14
|
+
export declare function createGrepTool(env: ExecutionEnv, rootCanonical: string, additionalRoots?: readonly string[], readDeny?: ReadDenyMatcher, readFace?: ReadFace, cwdRef?: CwdRef): AgentTool;
|
|
15
|
+
export declare function createGlobTool(env: ExecutionEnv, rootCanonical: string, additionalRoots?: readonly string[], readDeny?: ReadDenyMatcher, readFace?: ReadFace, cwdRef?: CwdRef): AgentTool;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import { defineTool, errorResult } from "../../core/tools.js";
|
|
3
3
|
import { resolveKey, violationText, violationDetails } from "./safety.js";
|
|
4
|
-
import { runGrepDetailed, runGlobDetailed,
|
|
4
|
+
import { runGrepDetailed, runGlobDetailed, invalidGlobTokens } from "./search.js";
|
|
5
5
|
import { toolFace } from "../../core/tool-catalog-entries.js";
|
|
6
|
+
import { pathTargetBaseOf, splitAbsoluteGlobPattern } from "../../core/effective-path-target.js";
|
|
7
|
+
import { pathTargetValue } from "../../core/tool-registry.js";
|
|
6
8
|
export function grepDetailFields(text, mode, offset, structuredRows) {
|
|
7
9
|
const structuredIdentityComplete = structuredRows !== undefined && structuredRows.every((r) => r.path !== undefined || r.text === "--");
|
|
8
10
|
const structuredPaths = structuredIdentityComplete && structuredRows !== undefined ? [...new Set(structuredRows.filter((r) => r.path !== undefined).map((r) => r.path))] : undefined;
|
|
@@ -72,7 +74,8 @@ export function grepDetailFields(text, mode, offset, structuredRows) {
|
|
|
72
74
|
}
|
|
73
75
|
return detailFields;
|
|
74
76
|
}
|
|
75
|
-
export function createGrepTool(env, rootCanonical, additionalRoots, readDeny, readFace) {
|
|
77
|
+
export function createGrepTool(env, rootCanonical, additionalRoots, readDeny, readFace, cwdRef) {
|
|
78
|
+
const declaredTarget = toolFace("grep").pathTarget;
|
|
76
79
|
return defineTool({
|
|
77
80
|
name: "Grep",
|
|
78
81
|
...toolFace("grep"),
|
|
@@ -136,9 +139,11 @@ export function createGrepTool(env, rootCanonical, additionalRoots, readDeny, re
|
|
|
136
139
|
`Close the bracket/brace, or drop \`glob\` and filter with \`path\`/\`type\` instead.`);
|
|
137
140
|
}
|
|
138
141
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
+
const baseCwd = pathTargetBaseOf(declaredTarget, { root: rootCanonical, cwd: cwdRef?.current });
|
|
143
|
+
const scopeSpelling = declaredTarget === undefined ? undefined : pathTargetValue(a, declaredTarget);
|
|
144
|
+
let scoped = scopeSpelling;
|
|
145
|
+
if (scopeSpelling !== undefined) {
|
|
146
|
+
const r = await resolveKey(env, rootCanonical, scopeSpelling, ctx.signal, baseCwd, additionalRoots, undefined, readDeny, readFace);
|
|
142
147
|
if (!r.ok)
|
|
143
148
|
return errorResult(violationText("Grep", r.violation), violationDetails(r.violation));
|
|
144
149
|
scoped = r.key;
|
|
@@ -146,7 +151,7 @@ export function createGrepTool(env, rootCanonical, additionalRoots, readDeny, re
|
|
|
146
151
|
if (!info.ok) {
|
|
147
152
|
const ex = await env.exists(scoped, ctx.signal);
|
|
148
153
|
if (!(ex.ok && !ex.value)) {
|
|
149
|
-
return errorResult(`Error (Grep): cannot determine the type of "${
|
|
154
|
+
return errorResult(`Error (Grep): cannot determine the type of "${scopeSpelling.slice(0, 300)}" (stat failed: ${info.error.message.slice(0, 200)}); refusing to search it — if it is a FIFO/socket/device, reading it would hang. Retry if this was transient.`);
|
|
150
155
|
}
|
|
151
156
|
}
|
|
152
157
|
}
|
|
@@ -172,7 +177,8 @@ export function createGrepTool(env, rootCanonical, additionalRoots, readDeny, re
|
|
|
172
177
|
},
|
|
173
178
|
});
|
|
174
179
|
}
|
|
175
|
-
export function createGlobTool(env, rootCanonical, additionalRoots, readDeny, readFace) {
|
|
180
|
+
export function createGlobTool(env, rootCanonical, additionalRoots, readDeny, readFace, cwdRef) {
|
|
181
|
+
const declaredTarget = toolFace("glob").pathTarget;
|
|
176
182
|
return defineTool({
|
|
177
183
|
name: "Glob",
|
|
178
184
|
...toolFace("glob"),
|
|
@@ -195,7 +201,8 @@ export function createGlobTool(env, rootCanonical, additionalRoots, readDeny, re
|
|
|
195
201
|
max_results: Type.Optional(Type.Number({ description: "Cap results (default 500)." })),
|
|
196
202
|
}),
|
|
197
203
|
execute: async (args, ctx) => {
|
|
198
|
-
let
|
|
204
|
+
let pattern = args.pattern;
|
|
205
|
+
let path = declaredTarget === undefined ? undefined : pathTargetValue(args, declaredTarget);
|
|
199
206
|
const { max_results } = args;
|
|
200
207
|
if (path === undefined) {
|
|
201
208
|
const split = splitAbsoluteGlobPattern(pattern);
|
|
@@ -204,9 +211,10 @@ export function createGlobTool(env, rootCanonical, additionalRoots, readDeny, re
|
|
|
204
211
|
pattern = split.relativePattern;
|
|
205
212
|
}
|
|
206
213
|
}
|
|
214
|
+
const baseCwd = pathTargetBaseOf(declaredTarget, { root: rootCanonical, cwd: cwdRef?.current });
|
|
207
215
|
let scoped = path;
|
|
208
216
|
if (path !== undefined) {
|
|
209
|
-
const r = await resolveKey(env, rootCanonical, path, ctx.signal,
|
|
217
|
+
const r = await resolveKey(env, rootCanonical, path, ctx.signal, baseCwd, additionalRoots, undefined, readDeny, readFace);
|
|
210
218
|
if (!r.ok)
|
|
211
219
|
return errorResult(violationText("Glob", r.violation), violationDetails(r.violation));
|
|
212
220
|
scoped = r.key;
|
package/dist/tools/fs/index.js
CHANGED
|
@@ -52,7 +52,7 @@ export function createHandsToolkit(env, readFileState, rootCanonical, opts = {})
|
|
|
52
52
|
if (!readOnly) {
|
|
53
53
|
tools.push(createEditFileTool(env, readFileState, rootCanonical, cwdRef, additionalRoots, opts.beforeWrite, opts.trackFileEdit, opts.onFileEdited), createWriteFileTool(env, readFileState, rootCanonical, cwdRef, additionalRoots, opts.beforeWrite, opts.trackFileEdit, opts.onFileEdited), createNotebookEditTool(env, readFileState, rootCanonical, cwdRef, additionalRoots, opts.beforeWrite, opts.trackFileEdit, opts.onFileEdited));
|
|
54
54
|
}
|
|
55
|
-
tools.push(createGrepTool(env, rootCanonical, readFaceRoots, readDeny, readFace), createGlobTool(env, rootCanonical, readFaceRoots, readDeny, readFace), createRepoMapTool(env, rootCanonical, readFaceRoots, readDeny, readFace));
|
|
55
|
+
tools.push(createGrepTool(env, rootCanonical, readFaceRoots, readDeny, readFace, cwdRef), createGlobTool(env, rootCanonical, readFaceRoots, readDeny, readFace, cwdRef), createRepoMapTool(env, rootCanonical, readFaceRoots, readDeny, readFace));
|
|
56
56
|
if (includeShell) {
|
|
57
57
|
tools.push(readOnly
|
|
58
58
|
? createBashReadonlyTool(env, rootCanonical, new Set(bashReadonlyAllow ?? BASH_READONLY_DEFAULT_ALLOW), {
|
|
@@ -51,14 +51,6 @@ export interface GrepParams {
|
|
|
51
51
|
* (`"*.ts,*.tsx"` → two globs), while a brace token (`*.{ts,tsx}`) is kept whole (its commas are
|
|
52
52
|
* alternation syntax, not separators). CC-verbatim splitting rules. */
|
|
53
53
|
export declare function splitGlobParam(glob: string): string[];
|
|
54
|
-
/** 批④ #8 (CC 2.1.198 RWp, bundle :332987): decompose an ABSOLUTE glob pattern into a base directory +
|
|
55
|
-
* relative pattern — cut at the last separator before the first glob metachar (`* ? [ {`); a pattern
|
|
56
|
-
* with no metachar splits dirname/basename. Returns undefined for a relative pattern (caller keeps it
|
|
57
|
-
* as-is) or when no usable base can be derived. */
|
|
58
|
-
export declare function splitAbsoluteGlobPattern(pattern: string): {
|
|
59
|
-
baseDir: string;
|
|
60
|
-
relativePattern: string;
|
|
61
|
-
} | undefined;
|
|
62
54
|
/**
|
|
63
55
|
* POSIX-safe single-quote so an arbitrary model-supplied string can't break out of the shell command that
|
|
64
56
|
* runs ripgrep. Wraps in single quotes (inside which the shell expands nothing — no `$()`, backtick, `;`, or
|
package/dist/tools/fs/search.js
CHANGED
|
@@ -71,29 +71,6 @@ export function splitGlobParam(glob) {
|
|
|
71
71
|
}
|
|
72
72
|
return out;
|
|
73
73
|
}
|
|
74
|
-
export function splitAbsoluteGlobPattern(pattern) {
|
|
75
|
-
if (!isAbsolutePathForm(pattern))
|
|
76
|
-
return undefined;
|
|
77
|
-
const m = /[*?[{]/.exec(pattern);
|
|
78
|
-
if (!m) {
|
|
79
|
-
const i = Math.max(pattern.lastIndexOf("/"), pattern.lastIndexOf("\\"));
|
|
80
|
-
if (i <= 0)
|
|
81
|
-
return undefined;
|
|
82
|
-
return { baseDir: pattern.slice(0, i), relativePattern: pattern.slice(i + 1) };
|
|
83
|
-
}
|
|
84
|
-
const prefix = pattern.slice(0, m.index);
|
|
85
|
-
const cut = Math.max(prefix.lastIndexOf("/"), prefix.lastIndexOf("\\"));
|
|
86
|
-
if (cut === -1)
|
|
87
|
-
return undefined;
|
|
88
|
-
let baseDir = pattern.slice(0, cut);
|
|
89
|
-
if (baseDir === "" && cut === 0)
|
|
90
|
-
baseDir = "/";
|
|
91
|
-
if (/^[A-Za-z]:$/.test(baseDir))
|
|
92
|
-
baseDir = baseDir + pattern[cut];
|
|
93
|
-
if (!baseDir)
|
|
94
|
-
return undefined;
|
|
95
|
-
return { baseDir, relativePattern: pattern.slice(cut + 1) };
|
|
96
|
-
}
|
|
97
74
|
export function shellQuote(s) {
|
|
98
75
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
99
76
|
}
|