@warlock.js/ai-workspace 5.30.0 → 5.31.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 +46 -2
- package/README.md +34 -21
- package/cjs/index.cjs +3116 -309
- package/cjs/index.cjs.map +1 -1
- package/esm/backends/local.d.mts.map +1 -1
- package/esm/backends/local.mjs +165 -27
- package/esm/backends/local.mjs.map +1 -1
- package/esm/backends/mock.d.mts +11 -5
- package/esm/backends/mock.d.mts.map +1 -1
- package/esm/backends/mock.mjs +34 -0
- package/esm/backends/mock.mjs.map +1 -1
- package/esm/contracts/index.d.mts +3 -3
- package/esm/contracts/tool-io.type.d.mts +202 -4
- package/esm/contracts/tool-io.type.d.mts.map +1 -1
- package/esm/contracts/workspace-backend.contract.d.mts +61 -1
- package/esm/contracts/workspace-backend.contract.d.mts.map +1 -1
- package/esm/contracts/workspace-ops.contract.d.mts +32 -3
- package/esm/contracts/workspace-ops.contract.d.mts.map +1 -1
- package/esm/contracts/workspace-policy.type.d.mts +133 -12
- package/esm/contracts/workspace-policy.type.d.mts.map +1 -1
- package/esm/contracts/workspace.contract.d.mts +63 -9
- package/esm/contracts/workspace.contract.d.mts.map +1 -1
- package/esm/errors.d.mts +79 -5
- package/esm/errors.d.mts.map +1 -1
- package/esm/errors.mjs +22 -1
- package/esm/errors.mjs.map +1 -1
- package/esm/index.d.mts +13 -5
- package/esm/index.mjs +10 -2
- package/esm/ops.d.mts +21 -2
- package/esm/ops.d.mts.map +1 -1
- package/esm/ops.mjs +230 -64
- package/esm/ops.mjs.map +1 -1
- package/esm/policy/jail.mjs +73 -0
- package/esm/policy/jail.mjs.map +1 -0
- package/esm/policy/policy.d.mts +25 -15
- package/esm/policy/policy.d.mts.map +1 -1
- package/esm/policy/policy.mjs +61 -85
- package/esm/policy/policy.mjs.map +1 -1
- package/esm/policy/shell-check.d.mts +64 -0
- package/esm/policy/shell-check.d.mts.map +1 -0
- package/esm/policy/shell-check.mjs +627 -0
- package/esm/policy/shell-check.mjs.map +1 -0
- package/esm/policy/shell-parser.mjs +802 -0
- package/esm/policy/shell-parser.mjs.map +1 -0
- package/esm/policy/tokenize-command.d.mts +63 -0
- package/esm/policy/tokenize-command.d.mts.map +1 -0
- package/esm/policy/tokenize-command.mjs +75 -23
- package/esm/policy/tokenize-command.mjs.map +1 -1
- package/esm/shell-jobs.d.mts +45 -0
- package/esm/shell-jobs.d.mts.map +1 -0
- package/esm/shell-jobs.mjs +247 -0
- package/esm/shell-jobs.mjs.map +1 -0
- package/esm/todos.d.mts +22 -0
- package/esm/todos.d.mts.map +1 -0
- package/esm/todos.mjs +73 -0
- package/esm/todos.mjs.map +1 -0
- package/esm/tools/edit-file.d.mts.map +1 -1
- package/esm/tools/edit-file.mjs +2 -1
- package/esm/tools/edit-file.mjs.map +1 -1
- package/esm/tools/glob.d.mts.map +1 -1
- package/esm/tools/glob.mjs +2 -1
- package/esm/tools/glob.mjs.map +1 -1
- package/esm/tools/grep.d.mts.map +1 -1
- package/esm/tools/grep.mjs +2 -1
- package/esm/tools/grep.mjs.map +1 -1
- package/esm/tools/json-schemas.mjs +175 -0
- package/esm/tools/json-schemas.mjs.map +1 -0
- package/esm/tools/list-dir.d.mts +32 -0
- package/esm/tools/list-dir.d.mts.map +1 -0
- package/esm/tools/list-dir.mjs +50 -0
- package/esm/tools/list-dir.mjs.map +1 -0
- package/esm/tools/multi-edit.d.mts +38 -0
- package/esm/tools/multi-edit.d.mts.map +1 -0
- package/esm/tools/multi-edit.mjs +121 -0
- package/esm/tools/multi-edit.mjs.map +1 -0
- package/esm/tools/read-file.d.mts.map +1 -1
- package/esm/tools/read-file.mjs +2 -1
- package/esm/tools/read-file.mjs.map +1 -1
- package/esm/tools/run-shell.d.mts +34 -12
- package/esm/tools/run-shell.d.mts.map +1 -1
- package/esm/tools/run-shell.mjs +59 -53
- package/esm/tools/run-shell.mjs.map +1 -1
- package/esm/tools/run-tests.d.mts +8 -0
- package/esm/tools/run-tests.d.mts.map +1 -1
- package/esm/tools/run-tests.mjs +10 -3
- package/esm/tools/run-tests.mjs.map +1 -1
- package/esm/tools/schema.mjs +23 -18
- package/esm/tools/schema.mjs.map +1 -1
- package/esm/tools/shell-kill.d.mts +25 -0
- package/esm/tools/shell-kill.d.mts.map +1 -0
- package/esm/tools/shell-kill.mjs +36 -0
- package/esm/tools/shell-kill.mjs.map +1 -0
- package/esm/tools/shell-output.d.mts +30 -0
- package/esm/tools/shell-output.d.mts.map +1 -0
- package/esm/tools/shell-output.mjs +49 -0
- package/esm/tools/shell-output.mjs.map +1 -0
- package/esm/tools/todo.d.mts +43 -0
- package/esm/tools/todo.d.mts.map +1 -0
- package/esm/tools/todo.mjs +126 -0
- package/esm/tools/todo.mjs.map +1 -0
- package/esm/tools/write-file.d.mts.map +1 -1
- package/esm/tools/write-file.mjs +2 -1
- package/esm/tools/write-file.mjs.map +1 -1
- package/esm/workspace.d.mts +11 -8
- package/esm/workspace.d.mts.map +1 -1
- package/esm/workspace.mjs +108 -27
- package/esm/workspace.mjs.map +1 -1
- package/llms-full.txt +155 -34
- package/llms.txt +1 -1
- package/package.json +3 -3
- package/skills/README.md +2 -2
- package/skills/build-loop-agent/SKILL.md +7 -7
- package/skills/index.md +6 -1
- package/skills/use-a-workspace/SKILL.md +148 -27
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region ../../packages/ai-workspace/src/contracts/tool-io.type.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* Input/output shapes for the
|
|
3
|
+
* Input/output shapes for the workspace tools and the direct
|
|
4
4
|
* methods that back them. These are the wire contracts the agent sees
|
|
5
5
|
* (via each tool's schema) and the values the policy-enforced ops layer
|
|
6
6
|
* returns. Paths in every `*Input` are workspace-relative; the policy
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* The discriminating set of tool names a workspace can vend, used by
|
|
11
11
|
* `tools.pick(...)` to select a least-privilege subset.
|
|
12
12
|
*/
|
|
13
|
-
type WorkspaceToolName = "readFile" | "editFile" | "writeFile" | "runShell" | "runTests" | "grep" | "glob";
|
|
13
|
+
type WorkspaceToolName = "readFile" | "editFile" | "multiEdit" | "writeFile" | "listDir" | "runShell" | "shellOutput" | "shellKill" | "runTests" | "grep" | "glob" | "todoWrite" | "todoRead";
|
|
14
14
|
/** Input to the `read_file` tool / `readFile()` direct method. */
|
|
15
15
|
interface ReadFileInput {
|
|
16
16
|
/** Workspace-relative path to read. */
|
|
@@ -86,6 +86,40 @@ interface EditFileResult {
|
|
|
86
86
|
/** SHA-256 of the file content after the edit. */
|
|
87
87
|
hash: string;
|
|
88
88
|
}
|
|
89
|
+
/** One replacement inside a {@link MultiEditInput}. */
|
|
90
|
+
interface MultiEditOperation {
|
|
91
|
+
/** Exact substring to replace; must be unique unless `replaceAll`. */
|
|
92
|
+
oldString: string;
|
|
93
|
+
/** Replacement text. */
|
|
94
|
+
newString: string;
|
|
95
|
+
/** Replace every occurrence instead of requiring a single unique match. */
|
|
96
|
+
replaceAll?: boolean;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Input to the `multi_edit` tool / `multiEdit()` direct method — several
|
|
100
|
+
* exact-string replacements in one file, applied in order (each edit sees
|
|
101
|
+
* the result of the previous ones) and written once. All of them apply or
|
|
102
|
+
* none do.
|
|
103
|
+
*/
|
|
104
|
+
interface MultiEditInput {
|
|
105
|
+
/** Workspace-relative path to edit. */
|
|
106
|
+
path: string;
|
|
107
|
+
/** The replacements, applied in order. At least one. */
|
|
108
|
+
edits: MultiEditOperation[];
|
|
109
|
+
/** Expected current SHA-256 of the file; a mismatch rejects every edit as stale. */
|
|
110
|
+
expectHash?: string;
|
|
111
|
+
}
|
|
112
|
+
/** Result of a successful multi-edit. */
|
|
113
|
+
interface MultiEditResult {
|
|
114
|
+
/** Workspace-relative path that was edited. */
|
|
115
|
+
path: string;
|
|
116
|
+
/** Number of edits applied (always `edits.length`). */
|
|
117
|
+
edits: number;
|
|
118
|
+
/** Total occurrences replaced across every edit. */
|
|
119
|
+
replacements: number;
|
|
120
|
+
/** SHA-256 of the file content after all edits. */
|
|
121
|
+
hash: string;
|
|
122
|
+
}
|
|
89
123
|
/** Input to the `write_file` tool / `writeFile()` direct method. */
|
|
90
124
|
interface WriteFileInput {
|
|
91
125
|
/** Workspace-relative path to write (created if absent). */
|
|
@@ -115,10 +149,104 @@ interface ExecOptions {
|
|
|
115
149
|
}
|
|
116
150
|
/** Input to the `run_shell` tool / `exec()` direct method. */
|
|
117
151
|
interface RunShellInput {
|
|
118
|
-
/** The command line to run;
|
|
152
|
+
/** The command line to run; every command in it is policy-checked. */
|
|
119
153
|
command: string;
|
|
120
154
|
/** Per-call wall-clock cap (overrides the policy default if lower). */
|
|
121
155
|
timeoutMs?: number;
|
|
156
|
+
/**
|
|
157
|
+
* Start the command as a background job and return its id at once,
|
|
158
|
+
* instead of waiting for it. Needs `shell.background` in the policy.
|
|
159
|
+
*/
|
|
160
|
+
background?: boolean;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Lifecycle state of a background command.
|
|
164
|
+
*
|
|
165
|
+
* - `"running"` — still running.
|
|
166
|
+
* - `"exited"` — finished on its own; `exitCode` holds its exit code.
|
|
167
|
+
* - `"killed"` — stopped by `shell_kill` / `shellKill()` or `dispose()`.
|
|
168
|
+
* - `"timed-out"` — killed for exceeding `shell.background.timeoutMs` (or
|
|
169
|
+
* the per-call `timeoutMs`).
|
|
170
|
+
*/
|
|
171
|
+
type ShellJobStatus = "running" | "exited" | "killed" | "timed-out";
|
|
172
|
+
/** A background command owned by the workspace. */
|
|
173
|
+
interface ShellJobInfo {
|
|
174
|
+
/** Workspace-unique id (`"job-1"`, `"job-2"`, …) for `shell_output` / `shell_kill`. */
|
|
175
|
+
id: string;
|
|
176
|
+
/** The command line it runs. */
|
|
177
|
+
command: string;
|
|
178
|
+
/** Lifecycle state. */
|
|
179
|
+
status: ShellJobStatus;
|
|
180
|
+
/** Exit code once it has stopped; `null` while running. */
|
|
181
|
+
exitCode: number | null;
|
|
182
|
+
/** OS process id of the direct child, when the backend has one. */
|
|
183
|
+
pid?: number;
|
|
184
|
+
/** ISO timestamp it was started. */
|
|
185
|
+
startedAt: string;
|
|
186
|
+
/** ISO timestamp it stopped, once it has. */
|
|
187
|
+
endedAt?: string;
|
|
188
|
+
}
|
|
189
|
+
/** What `run_shell` returns when called with `background: true`. */
|
|
190
|
+
interface RunShellBackgroundResult extends ShellJobInfo {
|
|
191
|
+
/** Always `true` — tells this result apart from a foreground {@link RunShellResult}. */
|
|
192
|
+
background: true;
|
|
193
|
+
}
|
|
194
|
+
/** Options for `startShell()`. */
|
|
195
|
+
interface StartShellOptions {
|
|
196
|
+
/**
|
|
197
|
+
* Wall-clock cap for this background command, in ms. Lowers
|
|
198
|
+
* `shell.background.timeoutMs` (never raises it); absent ⇒ the policy
|
|
199
|
+
* value, or no cap.
|
|
200
|
+
*/
|
|
201
|
+
timeoutMs?: number;
|
|
202
|
+
}
|
|
203
|
+
/** Input to the `shell_output` tool. */
|
|
204
|
+
interface ShellOutputInput {
|
|
205
|
+
/** The background command id `run_shell` returned. */
|
|
206
|
+
id: string;
|
|
207
|
+
/**
|
|
208
|
+
* Return only output produced after this `cursor` (from an earlier
|
|
209
|
+
* result). Omit to get everything since the previous read.
|
|
210
|
+
*/
|
|
211
|
+
since?: number;
|
|
212
|
+
/**
|
|
213
|
+
* Wait up to this many ms (capped at 30 000) for new output or for the
|
|
214
|
+
* command to stop, when there is nothing new yet.
|
|
215
|
+
*/
|
|
216
|
+
waitMs?: number;
|
|
217
|
+
}
|
|
218
|
+
/** Options for `shellOutput()`. */
|
|
219
|
+
interface ShellOutputOptions {
|
|
220
|
+
/** See {@link ShellOutputInput.since}. */
|
|
221
|
+
since?: number;
|
|
222
|
+
/** See {@link ShellOutputInput.waitMs}. */
|
|
223
|
+
waitMs?: number;
|
|
224
|
+
/** Stops a `waitMs` wait early. */
|
|
225
|
+
signal?: AbortSignal;
|
|
226
|
+
}
|
|
227
|
+
/** New output of a background command plus its current state. */
|
|
228
|
+
interface ShellOutputResult extends ShellJobInfo {
|
|
229
|
+
/** Standard output produced after `since`. */
|
|
230
|
+
stdout: string;
|
|
231
|
+
/** Standard error produced after `since`. */
|
|
232
|
+
stderr: string;
|
|
233
|
+
/**
|
|
234
|
+
* Total bytes the command has produced so far (both streams). Pass it as
|
|
235
|
+
* `since` to read only what comes next.
|
|
236
|
+
*/
|
|
237
|
+
cursor: number;
|
|
238
|
+
/**
|
|
239
|
+
* Bytes produced after `since` that are no longer kept (the per-command
|
|
240
|
+
* buffer holds the newest `shell.maxOutputBytes`).
|
|
241
|
+
*/
|
|
242
|
+
droppedBytes: number;
|
|
243
|
+
/** True when `droppedBytes > 0`. */
|
|
244
|
+
truncated: boolean;
|
|
245
|
+
}
|
|
246
|
+
/** Input to the `shell_kill` tool. */
|
|
247
|
+
interface ShellKillInput {
|
|
248
|
+
/** The background command id to stop. */
|
|
249
|
+
id: string;
|
|
122
250
|
}
|
|
123
251
|
/** Result of a shell command — captured streams plus how it terminated. */
|
|
124
252
|
interface RunShellResult {
|
|
@@ -173,6 +301,44 @@ interface GrepResult {
|
|
|
173
301
|
/** Total number of matches (== `matches.length` unless capped). */
|
|
174
302
|
total: number;
|
|
175
303
|
}
|
|
304
|
+
/** Input to the `list_dir` tool. */
|
|
305
|
+
interface ListDirInput {
|
|
306
|
+
/** Workspace-relative directory to list. Default `"."` (the root). */
|
|
307
|
+
path?: string;
|
|
308
|
+
/** How many levels deep to list (1 = direct children). Default `1`. */
|
|
309
|
+
depth?: number;
|
|
310
|
+
/** Extra globs to leave out, on top of `list.ignore` and `denyPaths`. */
|
|
311
|
+
ignore?: string[];
|
|
312
|
+
}
|
|
313
|
+
/** Options for `listDir()`. */
|
|
314
|
+
interface ListDirOptions {
|
|
315
|
+
/** See {@link ListDirInput.depth}. */
|
|
316
|
+
depth?: number;
|
|
317
|
+
/** See {@link ListDirInput.ignore}. */
|
|
318
|
+
ignore?: string[];
|
|
319
|
+
}
|
|
320
|
+
/** Kind of a listed entry. A symlink is reported, never followed. */
|
|
321
|
+
type ListDirEntryType = "file" | "directory" | "symlink" | "other";
|
|
322
|
+
/** One entry of a directory listing. */
|
|
323
|
+
interface ListDirEntry {
|
|
324
|
+
/** Workspace-relative path (absolute for a directory outside `cwd` in `allowPaths`). */
|
|
325
|
+
path: string;
|
|
326
|
+
/** Entry kind. */
|
|
327
|
+
type: ListDirEntryType;
|
|
328
|
+
/** Size in bytes, for files (when the backend reports it). */
|
|
329
|
+
size?: number;
|
|
330
|
+
/** 1 for a direct child of the listed directory, 2 for a grandchild, … */
|
|
331
|
+
depth: number;
|
|
332
|
+
}
|
|
333
|
+
/** Result of a directory listing. */
|
|
334
|
+
interface ListDirResult {
|
|
335
|
+
/** The listed directory, workspace-relative (`"."` for the root). */
|
|
336
|
+
path: string;
|
|
337
|
+
/** Entries, breadth-first, each level sorted by name. */
|
|
338
|
+
entries: ListDirEntry[];
|
|
339
|
+
/** True when `list.maxEntries` cut the listing short. */
|
|
340
|
+
truncated: boolean;
|
|
341
|
+
}
|
|
176
342
|
/** Input to the `glob` tool / `glob()` direct method. */
|
|
177
343
|
interface GlobInput {
|
|
178
344
|
/** Glob pattern resolved relative to `cwd` (e.g. `"src/api/*.ts"`). */
|
|
@@ -183,6 +349,38 @@ interface GlobResult {
|
|
|
183
349
|
/** Workspace-relative paths matching the pattern, sorted. */
|
|
184
350
|
paths: string[];
|
|
185
351
|
}
|
|
352
|
+
/** State of one todo item. */
|
|
353
|
+
type WorkspaceTodoStatus = "pending" | "in_progress" | "completed";
|
|
354
|
+
/** One item of the workspace's todo list. */
|
|
355
|
+
interface WorkspaceTodo {
|
|
356
|
+
/** Stable id (assigned `"1"`, `"2"`, … when the writer omits it). */
|
|
357
|
+
id: string;
|
|
358
|
+
/** What the step is. */
|
|
359
|
+
content: string;
|
|
360
|
+
/** Its state. */
|
|
361
|
+
status: WorkspaceTodoStatus;
|
|
362
|
+
}
|
|
363
|
+
/** One item as written by `todo_write` / `writeTodos()` — `id` is optional. */
|
|
364
|
+
interface WorkspaceTodoInput {
|
|
365
|
+
/** Stable id; omit to have one assigned from the item's position. */
|
|
366
|
+
id?: string;
|
|
367
|
+
/** What the step is (non-empty, at most 1 000 characters). */
|
|
368
|
+
content: string;
|
|
369
|
+
/** Its state. */
|
|
370
|
+
status: WorkspaceTodoStatus;
|
|
371
|
+
}
|
|
372
|
+
/** Input to the `todo_write` tool — the whole new list, replacing the old one. */
|
|
373
|
+
interface TodoWriteInput {
|
|
374
|
+
/** The complete list (at most 100 items). An empty list clears it. */
|
|
375
|
+
todos: WorkspaceTodoInput[];
|
|
376
|
+
}
|
|
377
|
+
/** The todo list plus a count per status. */
|
|
378
|
+
interface TodoListResult {
|
|
379
|
+
/** Every item, in order. */
|
|
380
|
+
todos: WorkspaceTodo[];
|
|
381
|
+
/** How many items are in each status. */
|
|
382
|
+
counts: Record<WorkspaceTodoStatus, number>;
|
|
383
|
+
}
|
|
186
384
|
//#endregion
|
|
187
|
-
export { EditFileInput, EditFileResult, ExecOptions, GlobInput, GlobResult, GrepInput, GrepMatch, GrepResult, ReadFileInput, ReadFileResult, RunShellInput, RunShellResult, RunTestsInput, WorkspaceToolName, WriteFileInput, WriteFileResult };
|
|
385
|
+
export { EditFileInput, EditFileResult, ExecOptions, GlobInput, GlobResult, GrepInput, GrepMatch, GrepResult, ListDirEntry, ListDirEntryType, ListDirInput, ListDirOptions, ListDirResult, MultiEditInput, MultiEditOperation, MultiEditResult, ReadFileInput, ReadFileResult, RunShellBackgroundResult, RunShellInput, RunShellResult, RunTestsInput, ShellJobInfo, ShellJobStatus, ShellKillInput, ShellOutputInput, ShellOutputOptions, ShellOutputResult, StartShellOptions, TodoListResult, TodoWriteInput, WorkspaceTodo, WorkspaceTodoInput, WorkspaceTodoStatus, WorkspaceToolName, WriteFileInput, WriteFileResult };
|
|
188
386
|
//# sourceMappingURL=tool-io.type.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-io.type.d.mts","names":[],"sources":["../../../../../../../../packages/ai-workspace/src/contracts/tool-io.type.ts"],"mappings":";;AAYA;;;;AAA6B;
|
|
1
|
+
{"version":3,"file":"tool-io.type.d.mts","names":[],"sources":["../../../../../../../../packages/ai-workspace/src/contracts/tool-io.type.ts"],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { WorkspaceShellInterpreter } from "./workspace-policy.type.mjs";
|
|
2
|
+
|
|
1
3
|
//#region ../../packages/ai-workspace/src/contracts/workspace-backend.contract.d.ts
|
|
2
4
|
/**
|
|
3
5
|
* Low-level result of a backend command execution. Mirrors the shape the
|
|
@@ -43,6 +45,52 @@ interface WorkspaceBackendExecOptions {
|
|
|
43
45
|
* backend.
|
|
44
46
|
*/
|
|
45
47
|
signal?: AbortSignal;
|
|
48
|
+
/**
|
|
49
|
+
* How to run `command`: `"none"` (default) tokenizes it into an argv and
|
|
50
|
+
* spawns it without a shell; `"sh"` hands the whole line to `/bin/sh -c`
|
|
51
|
+
* (`cmd.exe /d /v:off /s /c` on Windows). The ops layer has already
|
|
52
|
+
* checked every command in the line against the policy; a backend that
|
|
53
|
+
* does not support `"sh"` must refuse the command rather than run it
|
|
54
|
+
* another way.
|
|
55
|
+
*/
|
|
56
|
+
interpreter?: WorkspaceShellInterpreter;
|
|
57
|
+
}
|
|
58
|
+
/** Which stream a background command's output chunk came from. */
|
|
59
|
+
type WorkspaceOutputStream = "stdout" | "stderr";
|
|
60
|
+
/** Options for {@link WorkspaceBackend.start}. */
|
|
61
|
+
interface WorkspaceBackendStartOptions {
|
|
62
|
+
/** Working directory for the spawned process (already jail-resolved). */
|
|
63
|
+
cwd?: string;
|
|
64
|
+
/** Exact environment for the spawned process (NOT merged with process.env). */
|
|
65
|
+
env?: Record<string, string>;
|
|
66
|
+
/** See {@link WorkspaceBackendExecOptions.interpreter}. */
|
|
67
|
+
interpreter?: WorkspaceShellInterpreter;
|
|
68
|
+
/**
|
|
69
|
+
* Receives output as it arrives, decoded as UTF-8 and never split inside a
|
|
70
|
+
* character. Called synchronously or later — never after `done` settles.
|
|
71
|
+
*/
|
|
72
|
+
onOutput(stream: WorkspaceOutputStream, chunk: string): void;
|
|
73
|
+
}
|
|
74
|
+
/** A running background command, as a backend hands it to the ops layer. */
|
|
75
|
+
interface WorkspaceBackendProcess {
|
|
76
|
+
/** OS process id of the direct child, when there is one. */
|
|
77
|
+
readonly pid?: number;
|
|
78
|
+
/**
|
|
79
|
+
* Settles once the process has exited and its output has been delivered.
|
|
80
|
+
* Never rejects: a spawn failure resolves with exit code `127`.
|
|
81
|
+
*/
|
|
82
|
+
readonly done: Promise<{
|
|
83
|
+
exitCode: number;
|
|
84
|
+
}>;
|
|
85
|
+
/** Kill the whole process tree. Idempotent; safe after it has exited. */
|
|
86
|
+
kill(): void;
|
|
87
|
+
}
|
|
88
|
+
/** What {@link WorkspaceBackend.stat} reports about a path (symlinks are not followed). */
|
|
89
|
+
interface WorkspaceBackendStat {
|
|
90
|
+
/** Entry kind. */
|
|
91
|
+
type: "file" | "directory" | "symlink" | "other";
|
|
92
|
+
/** Size in bytes. */
|
|
93
|
+
size: number;
|
|
46
94
|
}
|
|
47
95
|
/**
|
|
48
96
|
* The swappable executor a workspace runs on — the thin, **policy-agnostic**
|
|
@@ -79,7 +127,19 @@ interface WorkspaceBackend {
|
|
|
79
127
|
realpath(absPath: string): Promise<string>;
|
|
80
128
|
/** Run a command and capture its outcome. */
|
|
81
129
|
exec(command: string, opts?: WorkspaceBackendExecOptions): Promise<WorkspaceBackendExecResult>;
|
|
130
|
+
/**
|
|
131
|
+
* Describe an absolute path without following a final symlink. Optional:
|
|
132
|
+
* without it, `list_dir` tells files from directories by trying to list
|
|
133
|
+
* them and reports no sizes.
|
|
134
|
+
*/
|
|
135
|
+
stat?(absPath: string): Promise<WorkspaceBackendStat>;
|
|
136
|
+
/**
|
|
137
|
+
* Start a long-running command and return at once. Optional: without it,
|
|
138
|
+
* background commands are refused. The process must be its own process
|
|
139
|
+
* group (or equivalent) so `kill()` reaches every descendant.
|
|
140
|
+
*/
|
|
141
|
+
start?(command: string, opts: WorkspaceBackendStartOptions): WorkspaceBackendProcess;
|
|
82
142
|
}
|
|
83
143
|
//#endregion
|
|
84
|
-
export { WorkspaceBackend, WorkspaceBackendExecOptions, WorkspaceBackendExecResult };
|
|
144
|
+
export { WorkspaceBackend, WorkspaceBackendExecOptions, WorkspaceBackendExecResult, WorkspaceBackendProcess, WorkspaceBackendStartOptions, WorkspaceBackendStat, WorkspaceOutputStream };
|
|
85
145
|
//# sourceMappingURL=workspace-backend.contract.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-backend.contract.d.mts","names":[],"sources":["../../../../../../../../packages/ai-workspace/src/contracts/workspace-backend.contract.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"workspace-backend.contract.d.mts","names":[],"sources":["../../../../../../../../packages/ai-workspace/src/contracts/workspace-backend.contract.ts"],"mappings":";;;;;AAQA;;;;UAAiB,0BAAA;EAIf;EAFA,QAAA;EAMA;EAJA,MAAA;EAWS;EATT,MAAA;EAiBe;EAff,QAAA;;;;;;;EAOA,SAAA;AAAA;;;;;;UAQe,2BAAA;EAwBwB;EAtBvC,GAAA;EA0BU;EAxBV,SAAA;;EAEA,GAAA,GAAM,MAAA;EAsByB;AAGjC;;;;;;;EAhBE,MAAA,GAAS,WAAA;EAkBT;;;;;;;;EATA,WAAA,GAAc,yBAAA;AAAA;AAkBuC;AAAA,KAd3C,qBAAA;;UAGK,4BAAA;EAsBO;EApBtB,GAAA;EAoBS;EAlBT,GAAA,GAAM,MAAA;EAkBmB;EAhBzB,WAAA,GAAc,yBAAA;EAkBV;AAAA;AAIN;;EAjBE,QAAA,CAAS,MAAA,EAAQ,qBAAA,EAAuB,KAAA;AAAA;AAqBpC;AAAA,UAjBW,uBAAA;EAsCgB;EAAA,SApCtB,GAAA;EAsCkB;;;;EAAA,SAjClB,IAAA,EAAM,OAAO;IAAG,QAAA;EAAA;EA+CI;EA7C7B,IAAA;AAAA;;UAIe,oBAAA;EAqDe;EAnD9B,IAAA;EAmDoF;EAjDpF,IAAI;AAAA;;;;;;;;;;;;;;;;;;;UAqBW,gBAAA;EAcN;EAZT,QAAA,CAAS,OAAA,WAAkB,OAAA;EAc3B;EAZA,SAAA,CAAU,OAAA,UAAiB,OAAA,WAAkB,OAAA;EAYhB;EAV7B,MAAA,CAAO,OAAA,WAAkB,OAAA;EAUkC;EAR3D,KAAA,CAAM,OAAA,WAAkB,OAAA;EAcxB;EAZA,MAAA,CAAO,OAAA,WAAkB,OAAA;EAYD;EAVxB,IAAA,CAAK,MAAA,WAAiB,OAAA;EAgBtB;EAdA,QAAA,CAAS,OAAA,WAAkB,OAAA;EAcG;EAZ9B,IAAA,CAAK,OAAA,UAAiB,IAAA,GAAO,2BAAA,GAA8B,OAAA,CAAQ,0BAAA;EAYN;;AAAuB;;;EANpF,IAAA,EAAM,OAAA,WAAkB,OAAA,CAAQ,oBAAA;;;;;;EAMhC,KAAA,EAAO,OAAA,UAAiB,IAAA,EAAM,4BAAA,GAA+B,uBAAA;AAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EditFileInput, EditFileResult, ExecOptions, GrepResult, ReadFileResult, RunShellResult } from "./tool-io.type.mjs";
|
|
1
|
+
import { EditFileInput, EditFileResult, ExecOptions, GrepResult, ListDirOptions, ListDirResult, MultiEditInput, MultiEditResult, ReadFileResult, RunShellResult, ShellJobInfo, ShellOutputOptions, ShellOutputResult, StartShellOptions } from "./tool-io.type.mjs";
|
|
2
2
|
|
|
3
3
|
//#region ../../packages/ai-workspace/src/contracts/workspace-ops.contract.d.ts
|
|
4
4
|
/**
|
|
@@ -43,12 +43,35 @@ interface WorkspaceOps {
|
|
|
43
43
|
*/
|
|
44
44
|
editFile(input: EditFileInput): Promise<EditFileResult>;
|
|
45
45
|
/**
|
|
46
|
-
*
|
|
47
|
-
* against the
|
|
46
|
+
* Apply several exact-string edits to one file atomically: each edit runs
|
|
47
|
+
* against the result of the previous ones, under the same uniqueness rules
|
|
48
|
+
* as `editFile`, and the file is written once — or, when any edit fails,
|
|
49
|
+
* not at all (`WorkspaceEditError` with `editIndex`).
|
|
50
|
+
*/
|
|
51
|
+
multiEdit(input: MultiEditInput): Promise<MultiEditResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Run a command line after checking every command in it against the
|
|
54
|
+
* shell policy (see `WorkspaceShellPolicy`), with the policy environment,
|
|
48
55
|
* timeout, and output byte cap applied. `signal` cancels this one call
|
|
49
56
|
* (see {@link ExecOptions}).
|
|
50
57
|
*/
|
|
51
58
|
exec(command: string, opts?: ExecOptions): Promise<RunShellResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Start a policy-checked command as a background job owned by the
|
|
61
|
+
* workspace and return at once. Needs `shell.background`.
|
|
62
|
+
*/
|
|
63
|
+
startShell(command: string, opts?: StartShellOptions): Promise<ShellJobInfo>;
|
|
64
|
+
/** New output of a background command since `since` (default: the last read). */
|
|
65
|
+
shellOutput(id: string, opts?: ShellOutputOptions): Promise<ShellOutputResult>;
|
|
66
|
+
/** Kill a background command's whole process tree and report its final state. */
|
|
67
|
+
shellKill(id: string): Promise<ShellJobInfo>;
|
|
68
|
+
/** Every background command this workspace knows, oldest first. */
|
|
69
|
+
listShells(): ShellJobInfo[];
|
|
70
|
+
/**
|
|
71
|
+
* List a jailed directory — bounded by depth and `list.maxEntries`, with
|
|
72
|
+
* `denyPaths` and `list.ignore` left out and symlinks never followed.
|
|
73
|
+
*/
|
|
74
|
+
listDir(path?: string, opts?: ListDirOptions): Promise<ListDirResult>;
|
|
52
75
|
/** Search jailed file contents for a regex pattern. */
|
|
53
76
|
grep(pattern: string, opts?: {
|
|
54
77
|
glob?: string;
|
|
@@ -62,6 +85,12 @@ interface WorkspaceOps {
|
|
|
62
85
|
mkdir(path: string): Promise<void>;
|
|
63
86
|
/** Remove a file or directory tree at a jailed path. */
|
|
64
87
|
remove(path: string): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Kill every background command (whole process trees) and refuse new
|
|
90
|
+
* commands. A foreground command already running finishes on its own (or
|
|
91
|
+
* by its timeout / signal). Idempotent.
|
|
92
|
+
*/
|
|
93
|
+
dispose(): Promise<void>;
|
|
65
94
|
}
|
|
66
95
|
//#endregion
|
|
67
96
|
export { WorkspaceOps };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-ops.contract.d.mts","names":[],"sources":["../../../../../../../../packages/ai-workspace/src/contracts/workspace-ops.contract.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"workspace-ops.contract.d.mts","names":[],"sources":["../../../../../../../../packages/ai-workspace/src/contracts/workspace-ops.contract.ts"],"mappings":";;;;;AAoCA;;;;;;;;;;;;;;;;;UAAiB,YAAA;EA0CgB;;;;;;EAnC/B,QAAA,CAAS,IAAA,UAAc,IAAA;IAAS,MAAA;IAAiB,KAAA;EAAA,IAAmB,OAAA,CAAQ,cAAA;EAkDL;EA/CvE,SAAA,CAAU,IAAA,UAAc,OAAA,WAAkB,OAAA;IAAU,IAAA;IAAc,YAAA;EAAA;EAkEvD;;;;;EA3DX,QAAA,CAAS,KAAA,EAAO,aAAA,GAAgB,OAAA,CAAQ,cAAA;EAVS;;;;;;EAkBjD,SAAA,CAAU,KAAA,EAAO,cAAA,GAAiB,OAAA,CAAQ,eAAA;EAfA;;;;;;EAuB1C,IAAA,CAAK,OAAA,UAAiB,IAAA,GAAO,WAAA,GAAc,OAAA,CAAQ,cAAA;EAhBX;;;;EAsBxC,UAAA,CAAW,OAAA,UAAiB,IAAA,GAAO,iBAAA,GAAoB,OAAA,CAAQ,YAAA;EAdrB;EAiB1C,WAAA,CAAY,EAAA,UAAY,IAAA,GAAO,kBAAA,GAAqB,OAAA,CAAQ,iBAAA;EATvD;EAYL,SAAA,CAAU,EAAA,WAAa,OAAA,CAAQ,YAAA;EAZT;EAetB,UAAA,IAAc,YAAA;EAfqC;;;;EAqBnD,OAAA,CAAQ,IAAA,WAAe,IAAA,GAAO,cAAA,GAAiB,OAAA,CAAQ,aAAA;EAfA;EAkBvD,IAAA,CAAK,OAAA,UAAiB,IAAA;IAAS,IAAA;IAAe,UAAA;EAAA,IAAyB,OAAA,CAAQ,UAAA;EAfvD;EAkBxB,IAAA,CAAK,OAAA,WAAkB,OAAA;EAlBqC;EAqB5D,MAAA,CAAO,IAAA,WAAe,OAAA;EAlBZ;EAqBV,KAAA,CAAM,IAAA,WAAe,OAAA;EArBU;EAwB/B,MAAA,CAAO,IAAA,WAAe,OAAA;EArBR;;;;;EA4Bd,OAAA,IAAW,OAAA;AAAA"}
|
|
@@ -8,33 +8,130 @@
|
|
|
8
8
|
* past the W1 surface and intentionally absent from this union.
|
|
9
9
|
*/
|
|
10
10
|
type WorkspaceBackendType = "local" | "mock";
|
|
11
|
+
/**
|
|
12
|
+
* How `run_shell` / `exec()` interpret a command line.
|
|
13
|
+
*
|
|
14
|
+
* - `"none"` (default) — **argv mode**: the line is tokenized into one argv
|
|
15
|
+
* (quotes respected, no shell semantics) and spawned without a shell. Any
|
|
16
|
+
* unquoted shell operator is refused with a message that says how to split
|
|
17
|
+
* the line.
|
|
18
|
+
* - `"sh"` — **shell mode** (explicit opt-in): the line runs through
|
|
19
|
+
* `/bin/sh -c` (`cmd.exe /d /v:off /s /c` on Windows). Before it runs, the
|
|
20
|
+
* line is parsed and every simple command in it — inside `;`, `&&`, `||`,
|
|
21
|
+
* pipes, subshells, `$( )` and backticks — is checked against the same
|
|
22
|
+
* `deny` / `allow` / `denyPatterns` / `allowCommand` rules, and every
|
|
23
|
+
* redirection target and `cd` directory against the path jail. Syntax the
|
|
24
|
+
* parser cannot read with confidence is refused, never guessed at.
|
|
25
|
+
*/
|
|
26
|
+
type WorkspaceShellInterpreter = "none" | "sh";
|
|
27
|
+
/**
|
|
28
|
+
* A command pattern in `shell.denyPatterns`.
|
|
29
|
+
*
|
|
30
|
+
* - A **string** is tokenized like a command and matches a command whose
|
|
31
|
+
* argv **starts with** those tokens — the executable compared by basename,
|
|
32
|
+
* case-insensitively. `"git push --force"` matches
|
|
33
|
+
* `git push --force origin main` but not `git push origin --force`.
|
|
34
|
+
* - A **RegExp** is tested against the command's argv joined with single
|
|
35
|
+
* spaces, the executable reduced to its basename (`/usr/bin/git push`
|
|
36
|
+
* is tested as `"git push"`). Use it for option orders and spellings:
|
|
37
|
+
* `/^git push\b.*(--force|-f\b)/`. A `g`/`y` flag is ignored.
|
|
38
|
+
*/
|
|
39
|
+
type WorkspaceCommandPattern = string | RegExp;
|
|
40
|
+
/** What {@link WorkspaceAllowCommand} is told about the command it checks. */
|
|
41
|
+
interface WorkspaceCommandCheckContext {
|
|
42
|
+
/** The full command line the checked command is part of. */
|
|
43
|
+
command: string;
|
|
44
|
+
/** The interpreter the line runs under. */
|
|
45
|
+
interpreter: WorkspaceShellInterpreter;
|
|
46
|
+
/**
|
|
47
|
+
* True when the argv is a command run through a wrapper the policy
|
|
48
|
+
* unwrapped (`time npm test` is checked as `["time", "npm", "test"]` and
|
|
49
|
+
* then as the nested `["npm", "test"]`) or by `find -exec`.
|
|
50
|
+
*/
|
|
51
|
+
nested: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A host predicate over every simple command's argv. Return `true` to let
|
|
55
|
+
* the command through, `false` to refuse it, or a string to refuse it with
|
|
56
|
+
* that explanation (shown to the model). A throw refuses the command too —
|
|
57
|
+
* the hook fails closed. It can only narrow what `allow` / `deny` permit,
|
|
58
|
+
* never widen it, and it must be synchronous.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* allowCommand: (argv) =>
|
|
62
|
+
* argv[0] === "git" && argv[1] === "push" ? "Pushing is done by the release job." : true
|
|
63
|
+
*/
|
|
64
|
+
type WorkspaceAllowCommand = (argv: readonly string[], context: WorkspaceCommandCheckContext) => boolean | string;
|
|
65
|
+
/**
|
|
66
|
+
* Background-command sub-policy. Present ⇒ `run_shell({ background: true })`
|
|
67
|
+
* and `startShell()` may start long-running commands (dev servers,
|
|
68
|
+
* watchers) that belong to the workspace; absent ⇒ background commands are
|
|
69
|
+
* refused. Every background command is killed — its whole process tree —
|
|
70
|
+
* by `workspace.dispose()`, and when the Node process exits.
|
|
71
|
+
*/
|
|
72
|
+
interface WorkspaceBackgroundPolicy {
|
|
73
|
+
/** Most background commands running at once. Default `4`. */
|
|
74
|
+
maxJobs?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Wall-clock cap for one background command, after which its process tree
|
|
77
|
+
* is killed (`status: "timed-out"`). Default: none — it runs until killed
|
|
78
|
+
* or disposed. A model-supplied `timeoutMs` can only lower it.
|
|
79
|
+
*/
|
|
80
|
+
timeoutMs?: number;
|
|
81
|
+
}
|
|
11
82
|
/**
|
|
12
83
|
* Shell-execution sub-policy for `run_shell` / `run_tests` and the
|
|
13
84
|
* `exec()` direct method.
|
|
14
85
|
*
|
|
15
|
-
* **Command gating.**
|
|
16
|
-
* respected, NO shell semantics) and executed
|
|
17
|
-
* containing unquoted shell metacharacters (`;`,
|
|
18
|
-
* `$`, redirection, parentheses) is
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
86
|
+
* **Command gating.** By default (`interpreter: "none"`) each command is
|
|
87
|
+
* tokenized into an argv (quotes respected, NO shell semantics) and executed
|
|
88
|
+
* without a shell; a command containing unquoted shell metacharacters (`;`,
|
|
89
|
+
* `&`, `|`, backticks, `$`, redirection, parentheses) is refused with a
|
|
90
|
+
* message that names the operator and suggests the split. With
|
|
91
|
+
* `interpreter: "sh"` the line runs through a shell, and every simple
|
|
92
|
+
* command in it is checked. Each command's executable basename is matched
|
|
93
|
+
* against `allow` / `deny`; **deny wins** (and matches case-insensitively).
|
|
94
|
+
* A non-empty `allow` is exhaustive. `denyPatterns` and `allowCommand`
|
|
95
|
+
* then refine the decision per argv. A command that would run another
|
|
96
|
+
* command out of the policy's sight (`bash -c`, `eval`, `xargs`, `sudo`, …)
|
|
97
|
+
* is refused when the policy has deny rules, unless it is named in `allow`.
|
|
24
98
|
*
|
|
25
99
|
* **Environment.** The spawned process does NOT inherit `process.env`.
|
|
26
100
|
* The effective environment is `{ ...pick(process.env, inheritEnv), ...env }`
|
|
27
101
|
* — so `run_shell` cannot find `node`/`npm` unless `inheritEnv` includes
|
|
28
|
-
* `"PATH"`. This is deliberate isolation, documented loudly.
|
|
102
|
+
* `"PATH"`. This is deliberate isolation, documented loudly. Shell mode also
|
|
103
|
+
* drops the variables that change how a shell parses or starts (`ENV`,
|
|
104
|
+
* `BASH_ENV`, `SHELLOPTS`, `BASHOPTS`, `CDPATH`, `IFS`, `PS4`, `BASH_FUNC_*`).
|
|
29
105
|
*/
|
|
30
106
|
interface WorkspaceShellPolicy {
|
|
31
107
|
/** Allowed executable basenames (e.g. `["npm", "node"]`). */
|
|
32
108
|
allow?: string[];
|
|
33
109
|
/** Denied executable basenames — wins over `allow`. */
|
|
34
110
|
deny?: string[];
|
|
111
|
+
/**
|
|
112
|
+
* Argument-level denials checked against every simple command (see
|
|
113
|
+
* {@link WorkspaceCommandPattern}), e.g. `["rm -rf /", "git push --force"]`.
|
|
114
|
+
*/
|
|
115
|
+
denyPatterns?: WorkspaceCommandPattern[];
|
|
116
|
+
/**
|
|
117
|
+
* Host predicate over every simple command's argv (see
|
|
118
|
+
* {@link WorkspaceAllowCommand}).
|
|
119
|
+
*/
|
|
120
|
+
allowCommand?: WorkspaceAllowCommand;
|
|
121
|
+
/**
|
|
122
|
+
* How the command line is interpreted. Default `"none"` (argv mode, no
|
|
123
|
+
* shell). `"sh"` is an explicit opt-in to shell syntax — pipes, `&&`,
|
|
124
|
+
* redirections — still checked per simple command (see
|
|
125
|
+
* {@link WorkspaceShellInterpreter}).
|
|
126
|
+
*/
|
|
127
|
+
interpreter?: WorkspaceShellInterpreter;
|
|
35
128
|
/** Per-command wall-clock cap; on expiry the process is SIGKILLed. */
|
|
36
129
|
timeoutMs?: number;
|
|
37
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* Max bytes captured from stdout/stderr before output is truncated. For a
|
|
132
|
+
* background command it is the most output kept per command; older output
|
|
133
|
+
* is dropped first.
|
|
134
|
+
*/
|
|
38
135
|
maxOutputBytes?: number;
|
|
39
136
|
/** Explicit environment variables injected into every spawned process. */
|
|
40
137
|
env?: Record<string, string>;
|
|
@@ -43,6 +140,11 @@ interface WorkspaceShellPolicy {
|
|
|
43
140
|
* Nothing from `process.env` leaks in unless listed here.
|
|
44
141
|
*/
|
|
45
142
|
inheritEnv?: string[];
|
|
143
|
+
/**
|
|
144
|
+
* Enables background commands (see {@link WorkspaceBackgroundPolicy}).
|
|
145
|
+
* Absent ⇒ `run_shell({ background: true })` is refused.
|
|
146
|
+
*/
|
|
147
|
+
background?: WorkspaceBackgroundPolicy;
|
|
46
148
|
}
|
|
47
149
|
/**
|
|
48
150
|
* Read sub-policy controlling how much of a file a single read returns.
|
|
@@ -60,6 +162,23 @@ interface WorkspaceReadPolicy {
|
|
|
60
162
|
/** Default number of lines a read returns when no explicit limit is given. */
|
|
61
163
|
defaultLines?: number;
|
|
62
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Directory-listing sub-policy for the `list_dir` tool and `listDir()`.
|
|
167
|
+
* `denyPaths` are always hidden from listings; `ignore` hides more without
|
|
168
|
+
* blocking access (an ignored file can still be read).
|
|
169
|
+
*/
|
|
170
|
+
interface WorkspaceListPolicy {
|
|
171
|
+
/**
|
|
172
|
+
* Globs (`*`, `**`, `?`; a bare name also hides its contents) left out of
|
|
173
|
+
* listings. Default `["node_modules", ".git"]`; setting it replaces the
|
|
174
|
+
* default.
|
|
175
|
+
*/
|
|
176
|
+
ignore?: string[];
|
|
177
|
+
/** Deepest `depth` a listing may ask for. Default `5`. */
|
|
178
|
+
maxDepth?: number;
|
|
179
|
+
/** Most entries one listing returns; the rest set `truncated`. Default `500`. */
|
|
180
|
+
maxEntries?: number;
|
|
181
|
+
}
|
|
63
182
|
/**
|
|
64
183
|
* The full policy that bounds a workspace — the single source of truth
|
|
65
184
|
* the policy engine enforces for both `.tools.*` and the direct methods.
|
|
@@ -90,9 +209,11 @@ interface WorkspacePolicy {
|
|
|
90
209
|
shell?: WorkspaceShellPolicy;
|
|
91
210
|
/** Read sub-policy (byte cap + default line window). */
|
|
92
211
|
read?: WorkspaceReadPolicy;
|
|
212
|
+
/** Directory-listing sub-policy (ignore globs + bounds). */
|
|
213
|
+
list?: WorkspaceListPolicy;
|
|
93
214
|
/** Executor the workspace runs on. Defaults to `"local"`. */
|
|
94
215
|
backend?: WorkspaceBackendType;
|
|
95
216
|
}
|
|
96
217
|
//#endregion
|
|
97
|
-
export { WorkspaceBackendType, WorkspacePolicy, WorkspaceReadPolicy, WorkspaceShellPolicy };
|
|
218
|
+
export { WorkspaceAllowCommand, WorkspaceBackendType, WorkspaceBackgroundPolicy, WorkspaceCommandCheckContext, WorkspaceCommandPattern, WorkspaceListPolicy, WorkspacePolicy, WorkspaceReadPolicy, WorkspaceShellInterpreter, WorkspaceShellPolicy };
|
|
98
219
|
//# sourceMappingURL=workspace-policy.type.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-policy.type.d.mts","names":[],"sources":["../../../../../../../../packages/ai-workspace/src/contracts/workspace-policy.type.ts"],"mappings":";;AAQA;;;;AAAgC;
|
|
1
|
+
{"version":3,"file":"workspace-policy.type.d.mts","names":[],"sources":["../../../../../../../../packages/ai-workspace/src/contracts/workspace-policy.type.ts"],"mappings":";;AAQA;;;;AAAgC;AAiBhC;;KAjBY,oBAAA;;AAiByB;AAcrC;;;;AAAqD;AAGrD;;;;;;;;KAjBY,yBAAA;AA2BJ;AAcR;;;;;;;;AAEuC;AAUvC;;AA1BQ,KAbI,uBAAA,YAAmC,MAAM;;UAGpC,4BAAA;EAuEA;EArEf,OAAA;;EAEA,WAAA,EAAa,yBAAyB;EAiFvB;;;;;EA3Ef,MAAA;AAAA;;;;;;;;;;;;KAcU,qBAAA,IACV,IAAA,qBACA,OAAA,EAAS,4BAA4B;;;;AAsFC;AAOxC;;;UAnFiB,yBAAA;EA6FH;EA3FZ,OAAA;EAmGkC;;;;;EA7FlC,SAAS;AAAA;AAuGC;AAsBZ;;;;;;;;;;;;;;;;;;;;;AAcgC;;AApCpB,UA5EK,oBAAA;;EAEf,KAAA;;EAEA,IAAA;;;;;EAKA,YAAA,GAAe,uBAAA;;;;;EAKf,YAAA,GAAe,qBAAA;;;;;;;EAOf,WAAA,GAAc,yBAAA;;EAEd,SAAA;;;;;;EAMA,cAAA;;EAEA,GAAA,GAAM,MAAA;;;;;EAKN,UAAA;;;;;EAKA,UAAA,GAAa,yBAAA;AAAA;;;;;UAOE,mBAAA;;;;;;;;EAQf,QAAA;;EAEA,YAAY;AAAA;;;;;;UAQG,mBAAA;;;;;;EAMf,MAAA;;EAEA,QAAA;;EAEA,UAAA;AAAA;;;;;;;;;;;;;;;;;;;;UAsBe,eAAA;;EAEf,GAAA;;EAEA,UAAA;;EAEA,SAAA;;EAEA,KAAA,GAAQ,oBAAA;;EAER,IAAA,GAAO,mBAAA;;EAEP,IAAA,GAAO,mBAAA;;EAEP,OAAA,GAAU,oBAAA;AAAA"}
|