@warlock.js/ai-workspace 5.31.0 → 5.32.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 +6 -0
- package/cjs/index.cjs +34 -22
- package/cjs/index.cjs.map +1 -1
- package/esm/backends/local.d.mts +1 -3
- package/esm/backends/local.d.mts.map +1 -1
- package/esm/backends/local.mjs +1 -1
- package/esm/backends/local.mjs.map +1 -1
- package/esm/backends/mock.d.mts +5 -6
- package/esm/backends/mock.d.mts.map +1 -1
- package/esm/contracts/index.d.mts +2 -1
- package/esm/contracts/tool-io.type.d.mts +37 -38
- package/esm/contracts/tool-io.type.d.mts.map +1 -1
- package/esm/contracts/workspace-backend.contract.d.mts +7 -9
- package/esm/contracts/workspace-backend.contract.d.mts.map +1 -1
- package/esm/contracts/workspace-ops.contract.d.mts +1 -3
- package/esm/contracts/workspace-ops.contract.d.mts.map +1 -1
- package/esm/contracts/workspace-policy.type.d.mts +10 -11
- package/esm/contracts/workspace-policy.type.d.mts.map +1 -1
- package/esm/contracts/workspace.contract.d.mts +2 -4
- package/esm/contracts/workspace.contract.d.mts.map +1 -1
- package/esm/errors.d.mts +35 -23
- package/esm/errors.d.mts.map +1 -1
- package/esm/index.d.mts +1 -0
- package/esm/ops.d.mts +3 -4
- package/esm/ops.d.mts.map +1 -1
- package/esm/policy/policy.d.mts +5 -5
- package/esm/policy/policy.d.mts.map +1 -1
- package/esm/policy/policy.mjs +4 -3
- package/esm/policy/policy.mjs.map +1 -1
- package/esm/policy/shell-check.d.mts +5 -6
- package/esm/policy/shell-check.d.mts.map +1 -1
- package/esm/policy/shell-check.mjs +24 -13
- package/esm/policy/shell-check.mjs.map +1 -1
- package/esm/policy/shell-parser.mjs +2 -2
- package/esm/policy/shell-parser.mjs.map +1 -1
- package/esm/policy/tokenize-command.d.mts +3 -4
- package/esm/policy/tokenize-command.d.mts.map +1 -1
- package/esm/policy/tokenize-command.mjs +2 -2
- package/esm/policy/tokenize-command.mjs.map +1 -1
- package/esm/shell-jobs.d.mts +3 -3
- package/esm/shell-jobs.d.mts.map +1 -1
- package/esm/shell-jobs.mjs +1 -1
- package/esm/todos.d.mts +2 -2
- package/esm/todos.d.mts.map +1 -1
- package/esm/todos.mjs +1 -1
- package/esm/tools/edit-file.d.mts +2 -3
- package/esm/tools/edit-file.d.mts.map +1 -1
- package/esm/tools/glob.d.mts +3 -4
- package/esm/tools/glob.d.mts.map +1 -1
- package/esm/tools/grep.d.mts +3 -4
- package/esm/tools/grep.d.mts.map +1 -1
- package/esm/tools/list-dir.d.mts +2 -3
- package/esm/tools/list-dir.d.mts.map +1 -1
- package/esm/tools/multi-edit.d.mts +2 -3
- package/esm/tools/multi-edit.d.mts.map +1 -1
- package/esm/tools/read-file.d.mts +2 -3
- package/esm/tools/read-file.d.mts.map +1 -1
- package/esm/tools/run-shell.d.mts +5 -6
- package/esm/tools/run-shell.d.mts.map +1 -1
- package/esm/tools/run-tests.d.mts +3 -4
- package/esm/tools/run-tests.d.mts.map +1 -1
- package/esm/tools/shell-kill.d.mts +2 -3
- package/esm/tools/shell-kill.d.mts.map +1 -1
- package/esm/tools/shell-output.d.mts +2 -3
- package/esm/tools/shell-output.d.mts.map +1 -1
- package/esm/tools/todo.d.mts +3 -4
- package/esm/tools/todo.d.mts.map +1 -1
- package/esm/tools/write-file.d.mts +2 -3
- package/esm/tools/write-file.d.mts.map +1 -1
- package/esm/workspace.d.mts +3 -3
- package/esm/workspace.d.mts.map +1 -1
- package/esm/workspace.mjs +1 -1
- package/esm/workspace.mjs.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to `@warlock.js/ai-workspace` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
|
|
6
6
|
|
|
7
|
+
## 5.32.0 - 2026-10-18
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Pin the package development compiler to TypeScript 7.0.2 and use explicit Node types and source roots with supported module resolution.
|
|
12
|
+
|
|
7
13
|
## 5.31.0 - 2026-10-18
|
|
8
14
|
|
|
9
15
|
### Upgrading
|
package/cjs/index.cjs
CHANGED
|
@@ -20,7 +20,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
20
20
|
}
|
|
21
21
|
return to;
|
|
22
22
|
};
|
|
23
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
24
24
|
value: mod,
|
|
25
25
|
enumerable: true
|
|
26
26
|
}) : target, mod));
|
|
@@ -188,7 +188,7 @@ const MAX_NESTING = 16;
|
|
|
188
188
|
* appear unquoted in command position. The parser does not read compound
|
|
189
189
|
* commands, so a line using one is refused.
|
|
190
190
|
*/
|
|
191
|
-
const RESERVED_WORDS = new Set([
|
|
191
|
+
const RESERVED_WORDS = /* @__PURE__ */ new Set([
|
|
192
192
|
"!",
|
|
193
193
|
"{",
|
|
194
194
|
"}",
|
|
@@ -212,7 +212,7 @@ const RESERVED_WORDS = new Set([
|
|
|
212
212
|
"while"
|
|
213
213
|
]);
|
|
214
214
|
/** cmd.exe keywords the `"cmd"` dialect refuses in command position. */
|
|
215
|
-
const CMD_RESERVED_WORDS = new Set([
|
|
215
|
+
const CMD_RESERVED_WORDS = /* @__PURE__ */ new Set([
|
|
216
216
|
"if",
|
|
217
217
|
"for",
|
|
218
218
|
"goto",
|
|
@@ -990,7 +990,7 @@ function parseShellLine(line, dialect) {
|
|
|
990
990
|
* rejected instead of silently running commands past the allowlist. Inside
|
|
991
991
|
* quotes they are ordinary literal bytes and pass through as argument data.
|
|
992
992
|
*/
|
|
993
|
-
const UNQUOTED_METACHARACTERS = new Set([
|
|
993
|
+
const UNQUOTED_METACHARACTERS = /* @__PURE__ */ new Set([
|
|
994
994
|
";",
|
|
995
995
|
"&",
|
|
996
996
|
"|",
|
|
@@ -1002,7 +1002,7 @@ const UNQUOTED_METACHARACTERS = new Set([
|
|
|
1002
1002
|
")"
|
|
1003
1003
|
]);
|
|
1004
1004
|
/** Two-character operators reported as one token in a refusal. */
|
|
1005
|
-
const TWO_CHARACTER_OPERATORS = new Set([
|
|
1005
|
+
const TWO_CHARACTER_OPERATORS = /* @__PURE__ */ new Set([
|
|
1006
1006
|
"&&",
|
|
1007
1007
|
"||",
|
|
1008
1008
|
">>",
|
|
@@ -1115,7 +1115,7 @@ function tokenizeCommand(command) {
|
|
|
1115
1115
|
* With deny rules in force they would hide a denied command, so they are
|
|
1116
1116
|
* refused unless the policy names them in `allow`.
|
|
1117
1117
|
*/
|
|
1118
|
-
const OPAQUE_RUNNERS = new Set([
|
|
1118
|
+
const OPAQUE_RUNNERS = /* @__PURE__ */ new Set([
|
|
1119
1119
|
"sh",
|
|
1120
1120
|
"bash",
|
|
1121
1121
|
"dash",
|
|
@@ -1159,7 +1159,7 @@ const OPAQUE_RUNNERS = new Set([
|
|
|
1159
1159
|
"flock"
|
|
1160
1160
|
]);
|
|
1161
1161
|
/** POSIX shell builtins that evaluate code or change how later names resolve. */
|
|
1162
|
-
const SHELL_OPAQUE_BUILTINS = new Set([
|
|
1162
|
+
const SHELL_OPAQUE_BUILTINS = /* @__PURE__ */ new Set([
|
|
1163
1163
|
"eval",
|
|
1164
1164
|
".",
|
|
1165
1165
|
"source",
|
|
@@ -1183,7 +1183,7 @@ const SHELL_OPAQUE_BUILTINS = new Set([
|
|
|
1183
1183
|
"readarray"
|
|
1184
1184
|
]);
|
|
1185
1185
|
/** cmd.exe builtins that run commands or change the environment. */
|
|
1186
|
-
const CMD_OPAQUE_BUILTINS = new Set([
|
|
1186
|
+
const CMD_OPAQUE_BUILTINS = /* @__PURE__ */ new Set([
|
|
1187
1187
|
"call",
|
|
1188
1188
|
"start",
|
|
1189
1189
|
"set",
|
|
@@ -1195,7 +1195,7 @@ const CMD_OPAQUE_BUILTINS = new Set([
|
|
|
1195
1195
|
* subscripts such as `a[$(cmd)]`): their arguments must be literal and free
|
|
1196
1196
|
* of `[`.
|
|
1197
1197
|
*/
|
|
1198
|
-
const ARITHMETIC_SENSITIVE_BUILTINS = new Set([
|
|
1198
|
+
const ARITHMETIC_SENSITIVE_BUILTINS = /* @__PURE__ */ new Set([
|
|
1199
1199
|
"test",
|
|
1200
1200
|
"[",
|
|
1201
1201
|
"printf",
|
|
@@ -1219,7 +1219,7 @@ const ARITHMETIC_SENSITIVE_BUILTINS = new Set([
|
|
|
1219
1219
|
* the jail's sight, `PS4` is expanded — command substitutions included —
|
|
1220
1220
|
* on every traced line, `IFS` re-splits expansions).
|
|
1221
1221
|
*/
|
|
1222
|
-
const SENSITIVE_VARIABLES = new Set([
|
|
1222
|
+
const SENSITIVE_VARIABLES = /* @__PURE__ */ new Set([
|
|
1223
1223
|
"CDPATH",
|
|
1224
1224
|
"ENV",
|
|
1225
1225
|
"BASH_ENV",
|
|
@@ -1237,13 +1237,13 @@ const SENSITIVE_VARIABLES = new Set([
|
|
|
1237
1237
|
"BASH_LOADABLES_PATH"
|
|
1238
1238
|
]);
|
|
1239
1239
|
/** Redirection targets that are always fine even though they sit outside the jail. */
|
|
1240
|
-
const DEVICE_TARGETS = new Set([
|
|
1240
|
+
const DEVICE_TARGETS = /* @__PURE__ */ new Set([
|
|
1241
1241
|
"/dev/null",
|
|
1242
1242
|
"/dev/stdout",
|
|
1243
1243
|
"/dev/stderr"
|
|
1244
1244
|
]);
|
|
1245
1245
|
/** cmd.exe's null device. */
|
|
1246
|
-
const CMD_DEVICE_TARGETS = new Set(["nul"]);
|
|
1246
|
+
const CMD_DEVICE_TARGETS = /* @__PURE__ */ new Set(["nul"]);
|
|
1247
1247
|
/** Deepest chain of wrappers (`env time nice …`) the policy unwraps. */
|
|
1248
1248
|
const MAX_WRAPPER_DEPTH = 8;
|
|
1249
1249
|
/** Most distinct directories a line may `cd` between. */
|
|
@@ -1342,7 +1342,8 @@ var LineChecker = class {
|
|
|
1342
1342
|
verdict = false;
|
|
1343
1343
|
}
|
|
1344
1344
|
if (verdict === true) return;
|
|
1345
|
-
|
|
1345
|
+
const explanation = typeof verdict === "string" && verdict.trim() !== "" ? ` ${verdict.trim()}` : "";
|
|
1346
|
+
throw new Refusal("not-allowed", `${shown} was refused by the workspace shell policy.${explanation}`, executableBasename(argv[0] ?? "", this.dialect));
|
|
1346
1347
|
}
|
|
1347
1348
|
/** Whether the policy names `executable` in a non-empty `allow` list. */
|
|
1348
1349
|
explicitlyAllowed(executable) {
|
|
@@ -1365,7 +1366,10 @@ var LineChecker = class {
|
|
|
1365
1366
|
if (executable === "") throw new Refusal("not-allowed", "The command has no executable name.");
|
|
1366
1367
|
if (dynamic[0] === true) throw new Refusal("unsupported-syntax", `The command name \`${first}\` is decided when the line runs, so the workspace shell policy cannot check it. Write the command name literally.`);
|
|
1367
1368
|
if (this.deny.has(key)) throw new Refusal("denied-executable", `\`${executable}\` is denied by the workspace shell policy (in ${show(argv.join(" "))}).`, executable);
|
|
1368
|
-
if (this.allow.length > 0 && !this.allow.includes(executable))
|
|
1369
|
+
if (this.allow.length > 0 && !this.allow.includes(executable)) {
|
|
1370
|
+
const listed = this.allow.slice(0, 20).join(", ");
|
|
1371
|
+
throw new Refusal("not-allowed", `\`${executable}\` is not in the workspace shell allowlist. Allowed commands: ${listed}${this.allow.length > 20 ? ", …" : ""}.`, executable);
|
|
1372
|
+
}
|
|
1369
1373
|
this.checkHooks(argv, depth > 0);
|
|
1370
1374
|
this.commands.push([...argv]);
|
|
1371
1375
|
if (OPAQUE_RUNNERS.has(key) || this.shellMode && this.dialect === "posix" && SHELL_OPAQUE_BUILTINS.has(key) || this.shellMode && this.dialect === "cmd" && CMD_OPAQUE_BUILTINS.has(key)) {
|
|
@@ -1609,16 +1613,23 @@ function argvModeRefusal(command) {
|
|
|
1609
1613
|
const segments = parsed.ok ? parsed.segments : [];
|
|
1610
1614
|
if ((token === "&&" || token === "||" || token === ";" || token === "\n") && segments.length >= 2) {
|
|
1611
1615
|
const shownOperator = token === "\n" ? "A line break" : `\`${token}\``;
|
|
1612
|
-
if ((segments[0]?.source ?? "").trim().split(/\s+/)[0] === "cd")
|
|
1616
|
+
if ((segments[0]?.source ?? "").trim().split(/\s+/)[0] === "cd") {
|
|
1617
|
+
const rest = segments.slice(1).map((segment) => show(segment.source));
|
|
1618
|
+
return new Refusal("metacharacter", `${shownOperator} is not supported in argv mode, and \`cd\` does not carry over: every command starts in the workspace root. Run ${rest.join(", then ")} on its own, with paths relative to the root.${suffix}`);
|
|
1619
|
+
}
|
|
1613
1620
|
const steps = segments.map((segment) => show(segment.source));
|
|
1614
1621
|
const joiner = token === "||" ? ", and if it fails, " : ", then ";
|
|
1615
1622
|
return new Refusal("metacharacter", `${shownOperator} is not supported in argv mode: run ${steps.join(joiner)}, as separate commands.${suffix}`);
|
|
1616
1623
|
}
|
|
1617
1624
|
if (token === "&" && segments.length >= 1) {
|
|
1618
1625
|
const steps = segments.map((segment) => show(segment.source));
|
|
1619
|
-
|
|
1626
|
+
const run = steps.length === 1 ? `run ${steps[0] ?? ""} without it` : `run ${steps.join(", then ")} as separate commands`;
|
|
1627
|
+
return new Refusal("metacharacter", `\`&\` is not supported in argv mode: ${run}; start a long-running command with background: true.${suffix}`);
|
|
1628
|
+
}
|
|
1629
|
+
if (token === "|") {
|
|
1630
|
+
const pipeline = command.split("|").map((part) => part.trim()).filter(Boolean);
|
|
1631
|
+
return new Refusal("metacharacter", `\`|\` (a pipe) is not supported in argv mode: run ${show(pipeline[0] ?? command)} on its own and read its output yourself.${suffix}`);
|
|
1620
1632
|
}
|
|
1621
|
-
if (token === "|") return new Refusal("metacharacter", `\`|\` (a pipe) is not supported in argv mode: run ${show(command.split("|").map((part) => part.trim()).filter(Boolean)[0] ?? command)} on its own and read its output yourself.${suffix}`);
|
|
1622
1633
|
if (token === ">" || token === ">>" || token === ">&") return new Refusal("metacharacter", `\`${token}\` (redirection) is not supported in argv mode: run the command without it and save the output with write_file if you need it.${suffix}`);
|
|
1623
1634
|
if (token === "<" || token === "<<" || token === "<&") return new Refusal("metacharacter", `\`${token}\` (input redirection) is not supported in argv mode: pass the file path to the command as an argument.${suffix}`);
|
|
1624
1635
|
if (token === "$(" || token === "`") return new Refusal("metacharacter", `Command substitution (${token === "$(" ? "`$(…)`" : "backticks"}) is not supported in argv mode: run the inner command first, then pass its output literally.${suffix}`);
|
|
@@ -1785,8 +1796,9 @@ async function resolveInJail(policy, inputPath) {
|
|
|
1785
1796
|
const insideCwd = isInside(absolutePath, jailRoot);
|
|
1786
1797
|
const allowRoots = policy.allowPaths ?? [];
|
|
1787
1798
|
let insideAllow = false;
|
|
1788
|
-
if (!insideCwd) {
|
|
1789
|
-
|
|
1799
|
+
if (!insideCwd) for (const root of allowRoots) {
|
|
1800
|
+
const canonicalRoot = await canonicalize$1(root);
|
|
1801
|
+
if (isInside(absolutePath, canonicalRoot)) {
|
|
1790
1802
|
insideAllow = true;
|
|
1791
1803
|
break;
|
|
1792
1804
|
}
|
|
@@ -1863,7 +1875,7 @@ function buildEnv(policy) {
|
|
|
1863
1875
|
* `PS4` can run command substitutions, `BASH_FUNC_*` imports functions that
|
|
1864
1876
|
* shadow commands, `CDPATH` moves `cd`, `IFS` re-splits words).
|
|
1865
1877
|
*/
|
|
1866
|
-
const SHELL_STARTUP_VARIABLES = new Set([
|
|
1878
|
+
const SHELL_STARTUP_VARIABLES = /* @__PURE__ */ new Set([
|
|
1867
1879
|
"ENV",
|
|
1868
1880
|
"BASH_ENV",
|
|
1869
1881
|
"SHELLOPTS",
|
|
@@ -2727,7 +2739,7 @@ function createOps(backend, policy, runtime) {
|
|
|
2727
2739
|
* policy-driven cap (and the `truncated` flag) on top. Generous enough that
|
|
2728
2740
|
* ordinary command output is never clipped here.
|
|
2729
2741
|
*/
|
|
2730
|
-
const MAX_STREAM_BYTES =
|
|
2742
|
+
const MAX_STREAM_BYTES = 10485760;
|
|
2731
2743
|
/**
|
|
2732
2744
|
* Append a chunk to a capped list of buffers, tracking the running byte
|
|
2733
2745
|
* total and stopping once {@link MAX_STREAM_BYTES} is reached. Trailing bytes
|
|
@@ -4485,7 +4497,7 @@ const READONLY_TOOL_NAMES = [
|
|
|
4485
4497
|
"todoRead"
|
|
4486
4498
|
];
|
|
4487
4499
|
/** Tools vended only when the policy enables background commands. */
|
|
4488
|
-
const BACKGROUND_TOOL_NAMES = new Set(["shellOutput", "shellKill"]);
|
|
4500
|
+
const BACKGROUND_TOOL_NAMES = /* @__PURE__ */ new Set(["shellOutput", "shellKill"]);
|
|
4489
4501
|
/**
|
|
4490
4502
|
* Choose the dumb IO executor for a policy. `"mock"` selects the
|
|
4491
4503
|
* in-memory backend (hermetic tests); anything else — including the
|