@wrongstack/tools 0.297.0 → 0.298.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/dist/_spawn-stream.d.ts +2 -0
- package/dist/_util.d.ts +29 -1
- package/dist/audit.js +113 -65
- package/dist/bash.js +5 -4
- package/dist/batch-tool-use.js +70 -7
- package/dist/browser/index.js +31 -1
- package/dist/builtin.js +908 -390
- package/dist/codebase-index/index.js +68 -16
- package/dist/codebase-index/project-server-protocol.d.ts +26 -0
- package/dist/codebase-index/project-server.js +60 -16
- package/dist/codebase-index/worker.js +36 -13
- package/dist/codebase-index/writer-search-helpers.d.ts +16 -0
- package/dist/codebase-index/writer.d.ts +13 -1
- package/dist/design.d.ts +1 -1
- package/dist/design.js +4 -3
- package/dist/diff.js +11 -1
- package/dist/e2e.js +9 -6
- package/dist/edit.js +9 -6
- package/dist/exec-allowlist.d.ts +15 -0
- package/dist/exec.js +627 -568
- package/dist/format.js +116 -65
- package/dist/git.js +22 -2
- package/dist/glob.js +11 -5
- package/dist/grep.js +160 -104
- package/dist/index.js +859 -329
- package/dist/install.js +120 -68
- package/dist/json.js +64 -18
- package/dist/kanban-board-inputs.d.ts +21 -4
- package/dist/kanban.js +20 -5
- package/dist/languages/index.js +128 -71
- package/dist/lint.js +113 -65
- package/dist/outdated.js +86 -26
- package/dist/pack.js +908 -390
- package/dist/patch.js +11 -1
- package/dist/plan.js +32 -10
- package/dist/read.js +77 -23
- package/dist/replace.js +11 -3
- package/dist/scaffold.js +9 -6
- package/dist/session-kanban.js +21 -5
- package/dist/task.js +3 -1
- package/dist/test.js +113 -65
- package/dist/todo.js +3 -1
- package/dist/tool-tier.js +908 -390
- package/dist/tool-use.d.ts +1 -1
- package/dist/tool-use.js +28 -4
- package/dist/tree.d.ts +1 -0
- package/dist/tree.js +44 -8
- package/dist/typecheck.js +113 -65
- package/dist/write.js +9 -6
- package/package.json +7 -6
- package/dist/_concurrency.d.ts.map +0 -1
- package/dist/_danger-detect.d.ts.map +0 -1
- package/dist/_edit-match.d.ts.map +0 -1
- package/dist/_env.d.ts.map +0 -1
- package/dist/_fetch-guard.d.ts.map +0 -1
- package/dist/_output-spool.d.ts.map +0 -1
- package/dist/_redact-command.d.ts.map +0 -1
- package/dist/_regex.d.ts.map +0 -1
- package/dist/_session-shell.d.ts.map +0 -1
- package/dist/_shell-pick.d.ts.map +0 -1
- package/dist/_spawn-stream.d.ts.map +0 -1
- package/dist/_syntax-check.d.ts.map +0 -1
- package/dist/_util.d.ts.map +0 -1
- package/dist/_win32-resolve.d.ts.map +0 -1
- package/dist/audit.d.ts.map +0 -1
- package/dist/audit.js.map +0 -7
- package/dist/auto-proceed-loop-guard.d.ts.map +0 -1
- package/dist/auto-proceed-loop-guard.js.map +0 -7
- package/dist/bash-kill-guard.d.ts.map +0 -1
- package/dist/bash.d.ts.map +0 -1
- package/dist/bash.js.map +0 -7
- package/dist/batch-tool-use.d.ts.map +0 -1
- package/dist/batch-tool-use.js.map +0 -7
- package/dist/browser/artifacts.d.ts.map +0 -1
- package/dist/browser/index.d.ts.map +0 -1
- package/dist/browser/index.js.map +0 -7
- package/dist/browser/manager.d.ts.map +0 -1
- package/dist/browser/network-guard-proxy.d.ts.map +0 -1
- package/dist/browser/security.d.ts.map +0 -1
- package/dist/browser/tools.d.ts.map +0 -1
- package/dist/browser/types.d.ts.map +0 -1
- package/dist/builtin.d.ts.map +0 -1
- package/dist/builtin.js.map +0 -7
- package/dist/circuit-breaker.d.ts.map +0 -1
- package/dist/circuit-breaker.js.map +0 -7
- package/dist/codebase-index/background-indexer.d.ts.map +0 -1
- package/dist/codebase-index/bm25.d.ts.map +0 -1
- package/dist/codebase-index/circuit-breaker.d.ts.map +0 -1
- package/dist/codebase-index/codebase-index-tool.d.ts.map +0 -1
- package/dist/codebase-index/codebase-search-tool.d.ts.map +0 -1
- package/dist/codebase-index/codebase-stats-tool.d.ts.map +0 -1
- package/dist/codebase-index/dead-code-scan.d.ts.map +0 -1
- package/dist/codebase-index/generic-parser.d.ts.map +0 -1
- package/dist/codebase-index/gitignore.d.ts.map +0 -1
- package/dist/codebase-index/go-parser.d.ts.map +0 -1
- package/dist/codebase-index/index-service.d.ts.map +0 -1
- package/dist/codebase-index/index.d.ts.map +0 -1
- package/dist/codebase-index/index.js.map +0 -7
- package/dist/codebase-index/indexer.d.ts.map +0 -1
- package/dist/codebase-index/json-parser.d.ts.map +0 -1
- package/dist/codebase-index/languages.d.ts.map +0 -1
- package/dist/codebase-index/lsp-kind.d.ts.map +0 -1
- package/dist/codebase-index/parser-dispatch.d.ts.map +0 -1
- package/dist/codebase-index/project-server-cache.d.ts.map +0 -1
- package/dist/codebase-index/project-server-client.d.ts.map +0 -1
- package/dist/codebase-index/project-server-endpoint.d.ts.map +0 -1
- package/dist/codebase-index/project-server-protocol.d.ts.map +0 -1
- package/dist/codebase-index/project-server.d.ts.map +0 -1
- package/dist/codebase-index/project-server.js.map +0 -7
- package/dist/codebase-index/py-parser.d.ts.map +0 -1
- package/dist/codebase-index/refs-extractor.d.ts.map +0 -1
- package/dist/codebase-index/rs-parser.d.ts.map +0 -1
- package/dist/codebase-index/schema.d.ts.map +0 -1
- package/dist/codebase-index/spawn-gate.d.ts.map +0 -1
- package/dist/codebase-index/sqlite-runtime.d.ts.map +0 -1
- package/dist/codebase-index/ts-parser.d.ts.map +0 -1
- package/dist/codebase-index/worker-protocol.d.ts.map +0 -1
- package/dist/codebase-index/worker.d.ts.map +0 -1
- package/dist/codebase-index/worker.js.map +0 -7
- package/dist/codebase-index/writer-admin.d.ts.map +0 -1
- package/dist/codebase-index/writer-bulk-insert.d.ts.map +0 -1
- package/dist/codebase-index/writer-graph-helpers.d.ts.map +0 -1
- package/dist/codebase-index/writer-graph-reader.d.ts.map +0 -1
- package/dist/codebase-index/writer-helpers.d.ts.map +0 -1
- package/dist/codebase-index/writer-pragmas.d.ts.map +0 -1
- package/dist/codebase-index/writer-ref-mapper.d.ts.map +0 -1
- package/dist/codebase-index/writer-schema.d.ts.map +0 -1
- package/dist/codebase-index/writer-search-helpers.d.ts.map +0 -1
- package/dist/codebase-index/writer-store-pool.d.ts.map +0 -1
- package/dist/codebase-index/writer.d.ts.map +0 -1
- package/dist/codebase-index/yaml-parser.d.ts.map +0 -1
- package/dist/design.d.ts.map +0 -1
- package/dist/design.js.map +0 -7
- package/dist/diff.d.ts.map +0 -1
- package/dist/diff.js.map +0 -7
- package/dist/document.d.ts.map +0 -1
- package/dist/document.js.map +0 -7
- package/dist/e2e.d.ts.map +0 -1
- package/dist/e2e.js.map +0 -7
- package/dist/edit.d.ts.map +0 -1
- package/dist/edit.js.map +0 -7
- package/dist/exec-kill-guard.d.ts.map +0 -1
- package/dist/exec.d.ts.map +0 -1
- package/dist/exec.js.map +0 -7
- package/dist/fetch.d.ts.map +0 -1
- package/dist/fetch.js.map +0 -7
- package/dist/format.d.ts.map +0 -1
- package/dist/format.js.map +0 -7
- package/dist/git.d.ts.map +0 -1
- package/dist/git.js.map +0 -7
- package/dist/glob.d.ts.map +0 -1
- package/dist/glob.js.map +0 -7
- package/dist/grep.d.ts.map +0 -1
- package/dist/grep.js.map +0 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -7
- package/dist/install.d.ts.map +0 -1
- package/dist/install.js.map +0 -7
- package/dist/json.d.ts.map +0 -1
- package/dist/json.js.map +0 -7
- package/dist/kanban-board-inputs.d.ts.map +0 -1
- package/dist/kanban-decomposition-actions.d.ts.map +0 -1
- package/dist/kanban-detail-actions.d.ts.map +0 -1
- package/dist/kanban-evidence-bridge.d.ts.map +0 -1
- package/dist/kanban-presence.d.ts.map +0 -1
- package/dist/kanban-split-task-handler.d.ts.map +0 -1
- package/dist/kanban-task-inputs.d.ts.map +0 -1
- package/dist/kanban-tool-results.d.ts.map +0 -1
- package/dist/kanban-tool-schema.d.ts.map +0 -1
- package/dist/kanban-tool-types.d.ts.map +0 -1
- package/dist/kanban.d.ts.map +0 -1
- package/dist/kanban.js.map +0 -7
- package/dist/languages/detect.d.ts.map +0 -1
- package/dist/languages/diagnostics.d.ts.map +0 -1
- package/dist/languages/execute-tool.d.ts.map +0 -1
- package/dist/languages/execute.d.ts.map +0 -1
- package/dist/languages/index.d.ts.map +0 -1
- package/dist/languages/index.js.map +0 -7
- package/dist/languages/legacy-bridge.d.ts.map +0 -1
- package/dist/languages/package-tool.d.ts.map +0 -1
- package/dist/languages/plan.d.ts.map +0 -1
- package/dist/languages/profile-helpers.d.ts.map +0 -1
- package/dist/languages/profiles/additional.d.ts.map +0 -1
- package/dist/languages/profiles/primary.d.ts.map +0 -1
- package/dist/languages/registry.d.ts.map +0 -1
- package/dist/languages/tool.d.ts.map +0 -1
- package/dist/languages/types.d.ts.map +0 -1
- package/dist/lint.d.ts.map +0 -1
- package/dist/lint.js.map +0 -7
- package/dist/logs.d.ts.map +0 -1
- package/dist/logs.js.map +0 -7
- package/dist/memory.d.ts.map +0 -1
- package/dist/memory.js.map +0 -7
- package/dist/mode.d.ts.map +0 -1
- package/dist/mode.js.map +0 -7
- package/dist/next-steps.d.ts.map +0 -1
- package/dist/next-steps.js.map +0 -7
- package/dist/outdated.d.ts.map +0 -1
- package/dist/outdated.js.map +0 -7
- package/dist/pack.d.ts.map +0 -1
- package/dist/pack.js.map +0 -7
- package/dist/patch.d.ts.map +0 -1
- package/dist/patch.js.map +0 -7
- package/dist/plan.d.ts.map +0 -1
- package/dist/plan.js.map +0 -7
- package/dist/process-guardian.d.ts.map +0 -1
- package/dist/process-registry-persistent.d.ts.map +0 -1
- package/dist/process-registry.d.ts.map +0 -1
- package/dist/process-registry.js.map +0 -7
- package/dist/ps-slash.d.ts.map +0 -1
- package/dist/ps-slash.js.map +0 -7
- package/dist/read.d.ts.map +0 -1
- package/dist/read.js.map +0 -7
- package/dist/replace.d.ts.map +0 -1
- package/dist/replace.js.map +0 -7
- package/dist/scaffold.d.ts.map +0 -1
- package/dist/scaffold.js.map +0 -7
- package/dist/search.d.ts.map +0 -1
- package/dist/search.js.map +0 -7
- package/dist/session-kanban.d.ts.map +0 -1
- package/dist/session-kanban.js.map +0 -7
- package/dist/set-working-dir.d.ts.map +0 -1
- package/dist/skill.d.ts.map +0 -1
- package/dist/skill.js.map +0 -7
- package/dist/spawn-background.d.ts.map +0 -1
- package/dist/task.d.ts.map +0 -1
- package/dist/task.js.map +0 -7
- package/dist/test.d.ts.map +0 -1
- package/dist/test.js.map +0 -7
- package/dist/todo.d.ts.map +0 -1
- package/dist/todo.js.map +0 -7
- package/dist/tool-diff.d.ts.map +0 -1
- package/dist/tool-diff.js.map +0 -7
- package/dist/tool-help.d.ts.map +0 -1
- package/dist/tool-help.js.map +0 -7
- package/dist/tool-icon-map.d.ts.map +0 -1
- package/dist/tool-icons.d.ts.map +0 -1
- package/dist/tool-icons.js.map +0 -7
- package/dist/tool-search.d.ts.map +0 -1
- package/dist/tool-search.js.map +0 -7
- package/dist/tool-summary.d.ts.map +0 -1
- package/dist/tool-summary.js.map +0 -7
- package/dist/tool-tier.d.ts.map +0 -1
- package/dist/tool-tier.js.map +0 -7
- package/dist/tool-use.d.ts.map +0 -1
- package/dist/tool-use.js.map +0 -7
- package/dist/tree.d.ts.map +0 -1
- package/dist/tree.js.map +0 -7
- package/dist/typecheck.d.ts.map +0 -1
- package/dist/typecheck.js.map +0 -7
- package/dist/win32.d.ts.map +0 -1
- package/dist/win32.js.map +0 -7
- package/dist/write.d.ts.map +0 -1
- package/dist/write.js.map +0 -7
package/dist/format.js
CHANGED
|
@@ -78,11 +78,12 @@ function createOutputSpool(opts) {
|
|
|
78
78
|
return {
|
|
79
79
|
write(text) {
|
|
80
80
|
if (finalized || !text) return;
|
|
81
|
-
|
|
81
|
+
const textBytes = Buffer.byteLength(text, "utf8");
|
|
82
|
+
totalBytes += textBytes;
|
|
82
83
|
if (!stream && !failed) {
|
|
83
|
-
if (headBytes +
|
|
84
|
+
if (headBytes + textBytes <= threshold) {
|
|
84
85
|
head += text;
|
|
85
|
-
headBytes +=
|
|
86
|
+
headBytes += textBytes;
|
|
86
87
|
return;
|
|
87
88
|
}
|
|
88
89
|
head += text;
|
|
@@ -92,7 +93,7 @@ function createOutputSpool(opts) {
|
|
|
92
93
|
}
|
|
93
94
|
if (stream) {
|
|
94
95
|
if (stream.writableLength > SPOOL_WRITE_HWM_BYTES) {
|
|
95
|
-
droppedBytes +=
|
|
96
|
+
droppedBytes += textBytes;
|
|
96
97
|
return;
|
|
97
98
|
}
|
|
98
99
|
stream.write(text);
|
|
@@ -114,6 +115,52 @@ function createOutputSpool(opts) {
|
|
|
114
115
|
};
|
|
115
116
|
}
|
|
116
117
|
|
|
118
|
+
// src/_win32-resolve.ts
|
|
119
|
+
import * as fs from "node:fs";
|
|
120
|
+
import * as path2 from "node:path";
|
|
121
|
+
function resolveWin32Command(cmd) {
|
|
122
|
+
if (process.platform !== "win32") return cmd;
|
|
123
|
+
if (cmd.includes("/") || cmd.includes("\\") || path2.extname(cmd.replace(/\//g, "\\"))) {
|
|
124
|
+
return cmd;
|
|
125
|
+
}
|
|
126
|
+
const pathext = (process.env["PATHEXT"] ?? ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC").toLowerCase().split(";");
|
|
127
|
+
const pathDirs = (process.env["PATH"] ?? "").split(path2.delimiter);
|
|
128
|
+
for (const dir of pathDirs) {
|
|
129
|
+
const base = path2.join(dir, cmd);
|
|
130
|
+
for (const ext of pathext) {
|
|
131
|
+
const full = `${base}${ext}`;
|
|
132
|
+
try {
|
|
133
|
+
fs.accessSync(full, fs.constants.X_OK);
|
|
134
|
+
return full;
|
|
135
|
+
} catch {
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return cmd;
|
|
140
|
+
}
|
|
141
|
+
var WIN32_SHELL_META = /[&|<>"\r\n\0]/;
|
|
142
|
+
function assertSafeWin32ShellArgs(args) {
|
|
143
|
+
for (const arg of args) {
|
|
144
|
+
if (typeof arg === "string" && WIN32_SHELL_META.test(arg)) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
'win32 cmd shim spawn: argument contains a shell metacharacter (one of & | < > ", or a newline) that could enable command injection through the .cmd/.bat wrapper - refusing to run. Offending argument: ' + JSON.stringify(arg)
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function buildWin32CmdShimInvocation(command, args = []) {
|
|
152
|
+
assertSafeWin32ShellArgs([command, ...args]);
|
|
153
|
+
const line = ["call", quoteWin32CmdArg(command), ...args.map(quoteWin32CmdArg)].join(" ");
|
|
154
|
+
return {
|
|
155
|
+
command: process.env["COMSPEC"] ?? "cmd.exe",
|
|
156
|
+
args: ["/d", "/c", line],
|
|
157
|
+
windowsVerbatimArguments: true
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function quoteWin32CmdArg(arg) {
|
|
161
|
+
return `"${arg}"`;
|
|
162
|
+
}
|
|
163
|
+
|
|
117
164
|
// src/process-registry.ts
|
|
118
165
|
import { spawn } from "node:child_process";
|
|
119
166
|
import * as os from "node:os";
|
|
@@ -738,60 +785,17 @@ function getProcessRegistry() {
|
|
|
738
785
|
return _registry;
|
|
739
786
|
}
|
|
740
787
|
|
|
741
|
-
// src/_win32-resolve.ts
|
|
742
|
-
import * as fs from "node:fs";
|
|
743
|
-
import * as path2 from "node:path";
|
|
744
|
-
function resolveWin32Command(cmd) {
|
|
745
|
-
if (process.platform !== "win32") return cmd;
|
|
746
|
-
if (cmd.includes("/") || cmd.includes("\\") || path2.extname(cmd.replace(/\//g, "\\"))) {
|
|
747
|
-
return cmd;
|
|
748
|
-
}
|
|
749
|
-
const pathext = (process.env["PATHEXT"] ?? ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC").toLowerCase().split(";");
|
|
750
|
-
const pathDirs = (process.env["PATH"] ?? "").split(path2.delimiter);
|
|
751
|
-
for (const dir of pathDirs) {
|
|
752
|
-
const base = path2.join(dir, cmd);
|
|
753
|
-
for (const ext of pathext) {
|
|
754
|
-
const full = `${base}${ext}`;
|
|
755
|
-
try {
|
|
756
|
-
fs.accessSync(full, fs.constants.X_OK);
|
|
757
|
-
return full;
|
|
758
|
-
} catch {
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
return cmd;
|
|
763
|
-
}
|
|
764
|
-
var WIN32_SHELL_META = /[&|<>"\r\n\0]/;
|
|
765
|
-
function assertSafeWin32ShellArgs(args) {
|
|
766
|
-
for (const arg of args) {
|
|
767
|
-
if (typeof arg === "string" && WIN32_SHELL_META.test(arg)) {
|
|
768
|
-
throw new Error(
|
|
769
|
-
'win32 cmd shim spawn: argument contains a shell metacharacter (one of & | < > ", or a newline) that could enable command injection through the .cmd/.bat wrapper - refusing to run. Offending argument: ' + JSON.stringify(arg)
|
|
770
|
-
);
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
function buildWin32CmdShimInvocation(command, args = []) {
|
|
775
|
-
assertSafeWin32ShellArgs([command, ...args]);
|
|
776
|
-
const line = ["call", quoteWin32CmdArg(command), ...args.map(quoteWin32CmdArg)].join(" ");
|
|
777
|
-
return {
|
|
778
|
-
command: process.env["COMSPEC"] ?? "cmd.exe",
|
|
779
|
-
args: ["/d", "/c", line],
|
|
780
|
-
windowsVerbatimArguments: true
|
|
781
|
-
};
|
|
782
|
-
}
|
|
783
|
-
function quoteWin32CmdArg(arg) {
|
|
784
|
-
return `"${arg}"`;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
788
|
// src/_spawn-stream.ts
|
|
788
789
|
var isWin = process.platform === "win32";
|
|
789
790
|
async function* spawnStream(opts) {
|
|
790
791
|
const max = opts.maxBytes ?? 2e5;
|
|
791
792
|
const flushAt = opts.flushBytes ?? 4 * 1024;
|
|
792
793
|
const maxQueue = opts.maxQueueSize ?? 500;
|
|
794
|
+
const maxQueueBytes = opts.maxQueueBytes ?? 1024 * 1024;
|
|
793
795
|
let stdout = "";
|
|
794
796
|
let stderr = "";
|
|
797
|
+
let stdoutRetainedBytes = 0;
|
|
798
|
+
let stderrRetainedBytes = 0;
|
|
795
799
|
let pending = "";
|
|
796
800
|
let error;
|
|
797
801
|
const spool = createOutputSpool({ tool: opts.cmd, thresholdBytes: max });
|
|
@@ -833,6 +837,7 @@ async function* spawnStream(opts) {
|
|
|
833
837
|
});
|
|
834
838
|
}
|
|
835
839
|
const queue = [];
|
|
840
|
+
let queuedBytes = 0;
|
|
836
841
|
let waiter;
|
|
837
842
|
let paused = false;
|
|
838
843
|
const wake = () => {
|
|
@@ -843,7 +848,7 @@ async function* spawnStream(opts) {
|
|
|
843
848
|
}
|
|
844
849
|
};
|
|
845
850
|
const resume = () => {
|
|
846
|
-
if (paused && queue.length
|
|
851
|
+
if (paused && queue.length <= Math.floor(maxQueue / 2) && queuedBytes <= Math.floor(maxQueueBytes / 2)) {
|
|
847
852
|
paused = false;
|
|
848
853
|
child.stdout?.resume();
|
|
849
854
|
child.stderr?.resume();
|
|
@@ -853,11 +858,16 @@ async function* spawnStream(opts) {
|
|
|
853
858
|
const s = c.toString();
|
|
854
859
|
stdoutBytes += c.byteLength;
|
|
855
860
|
emitProcessOutput({ pid, stream: "stdout", chunk: c });
|
|
856
|
-
if (
|
|
861
|
+
if (stdoutRetainedBytes < max) {
|
|
862
|
+
const retained = utf8Prefix(s, max - stdoutRetainedBytes);
|
|
863
|
+
stdout += retained;
|
|
864
|
+
stdoutRetainedBytes += Buffer.byteLength(retained, "utf8");
|
|
865
|
+
}
|
|
857
866
|
spool.write(s);
|
|
858
|
-
queue.push({ kind: "out", data: s });
|
|
867
|
+
queue.push({ kind: "out", data: s, bytes: c.byteLength });
|
|
868
|
+
queuedBytes += c.byteLength;
|
|
859
869
|
wake();
|
|
860
|
-
if (!paused && queue.length >= maxQueue) {
|
|
870
|
+
if (!paused && (queue.length >= maxQueue || queuedBytes >= maxQueueBytes)) {
|
|
861
871
|
paused = true;
|
|
862
872
|
child.stdout?.pause();
|
|
863
873
|
child.stderr?.pause();
|
|
@@ -867,11 +877,16 @@ async function* spawnStream(opts) {
|
|
|
867
877
|
const s = c.toString();
|
|
868
878
|
stderrBytes += c.byteLength;
|
|
869
879
|
emitProcessOutput({ pid, stream: "stderr", chunk: c });
|
|
870
|
-
if (
|
|
880
|
+
if (stderrRetainedBytes < max) {
|
|
881
|
+
const retained = utf8Prefix(s, max - stderrRetainedBytes);
|
|
882
|
+
stderr += retained;
|
|
883
|
+
stderrRetainedBytes += Buffer.byteLength(retained, "utf8");
|
|
884
|
+
}
|
|
871
885
|
spool.write(s);
|
|
872
|
-
queue.push({ kind: "err", data: s });
|
|
886
|
+
queue.push({ kind: "err", data: s, bytes: c.byteLength });
|
|
887
|
+
queuedBytes += c.byteLength;
|
|
873
888
|
wake();
|
|
874
|
-
if (!paused && queue.length >= maxQueue) {
|
|
889
|
+
if (!paused && (queue.length >= maxQueue || queuedBytes >= maxQueueBytes)) {
|
|
875
890
|
paused = true;
|
|
876
891
|
child.stdout?.pause();
|
|
877
892
|
child.stderr?.pause();
|
|
@@ -881,7 +896,9 @@ async function* spawnStream(opts) {
|
|
|
881
896
|
child.stderr?.on("data", onErr);
|
|
882
897
|
child.on("error", (e) => {
|
|
883
898
|
error = e.message;
|
|
884
|
-
|
|
899
|
+
const bytes = Buffer.byteLength(e.message, "utf8");
|
|
900
|
+
queue.push({ kind: "error", data: e.message, bytes });
|
|
901
|
+
queuedBytes += bytes;
|
|
885
902
|
wake();
|
|
886
903
|
});
|
|
887
904
|
const completeTelemetry = (code, signal, timedOut = false) => {
|
|
@@ -902,7 +919,13 @@ async function* spawnStream(opts) {
|
|
|
902
919
|
if (typeof pid === "number") registry.unregister(pid);
|
|
903
920
|
const exitCode2 = code ?? (signal ? 1 : 0);
|
|
904
921
|
completeTelemetry(exitCode2, signal ?? void 0);
|
|
905
|
-
queue.push({
|
|
922
|
+
queue.push({
|
|
923
|
+
kind: "close",
|
|
924
|
+
data: "",
|
|
925
|
+
bytes: 0,
|
|
926
|
+
code: exitCode2,
|
|
927
|
+
...signal ? { signal } : {}
|
|
928
|
+
});
|
|
906
929
|
wake();
|
|
907
930
|
});
|
|
908
931
|
const onAbort = () => {
|
|
@@ -914,7 +937,7 @@ async function* spawnStream(opts) {
|
|
|
914
937
|
} catch {
|
|
915
938
|
}
|
|
916
939
|
}
|
|
917
|
-
queue.push({ kind: "close", data: "", code: 124 });
|
|
940
|
+
queue.push({ kind: "close", data: "", bytes: 0, code: 124 });
|
|
918
941
|
completeTelemetry(124, "SIGKILL", true);
|
|
919
942
|
wake();
|
|
920
943
|
};
|
|
@@ -932,6 +955,7 @@ async function* spawnStream(opts) {
|
|
|
932
955
|
});
|
|
933
956
|
}
|
|
934
957
|
const chunk = queue.shift();
|
|
958
|
+
queuedBytes -= chunk.bytes;
|
|
935
959
|
resume();
|
|
936
960
|
if (chunk.kind === "close") {
|
|
937
961
|
if (!spawnFailed) exitCode = chunk.code ?? 0;
|
|
@@ -958,7 +982,7 @@ async function* spawnStream(opts) {
|
|
|
958
982
|
stdout: spooled ? stdout + spoolNote(spooled) : stdout,
|
|
959
983
|
stderr,
|
|
960
984
|
exitCode,
|
|
961
|
-
truncated:
|
|
985
|
+
truncated: stdoutBytes > stdoutRetainedBytes || stderrBytes > stderrRetainedBytes,
|
|
962
986
|
error,
|
|
963
987
|
spoolPath: spooled?.path,
|
|
964
988
|
spoolBytes: spooled?.bytes
|
|
@@ -982,6 +1006,20 @@ async function* spawnStream(opts) {
|
|
|
982
1006
|
}
|
|
983
1007
|
}
|
|
984
1008
|
}
|
|
1009
|
+
function utf8Prefix(text, maxBytes) {
|
|
1010
|
+
if (maxBytes <= 0) return "";
|
|
1011
|
+
if (Buffer.byteLength(text, "utf8") <= maxBytes) return text;
|
|
1012
|
+
let low = 0;
|
|
1013
|
+
let high = text.length;
|
|
1014
|
+
while (low < high) {
|
|
1015
|
+
const mid = Math.ceil((low + high) / 2);
|
|
1016
|
+
if (Buffer.byteLength(text.slice(0, mid), "utf8") <= maxBytes) low = mid;
|
|
1017
|
+
else high = mid - 1;
|
|
1018
|
+
}
|
|
1019
|
+
let end = low;
|
|
1020
|
+
if (end > 0 && /[\uD800-\uDBFF]/.test(text[end - 1])) end--;
|
|
1021
|
+
return text.slice(0, end);
|
|
1022
|
+
}
|
|
985
1023
|
|
|
986
1024
|
// src/_util.ts
|
|
987
1025
|
import * as path3 from "node:path";
|
|
@@ -2549,8 +2587,8 @@ async function scanDirectory(directory, depth, profiles, limits, state, extraIgn
|
|
|
2549
2587
|
collectFileEvidence(directory, fullPath, entry.name, profiles, state);
|
|
2550
2588
|
}
|
|
2551
2589
|
}
|
|
2552
|
-
function collectFileEvidence(directory, fullPath,
|
|
2553
|
-
const lower =
|
|
2590
|
+
function collectFileEvidence(directory, fullPath, basename5, profiles, state) {
|
|
2591
|
+
const lower = basename5.toLowerCase();
|
|
2554
2592
|
const extension = path4.extname(lower);
|
|
2555
2593
|
for (const profile of profiles) {
|
|
2556
2594
|
const detector = profile.detectors.find(
|
|
@@ -2561,7 +2599,7 @@ function collectFileEvidence(directory, fullPath, basename4, profiles, state) {
|
|
|
2561
2599
|
candidate.evidence.push({
|
|
2562
2600
|
kind: detector.kind,
|
|
2563
2601
|
path: fullPath,
|
|
2564
|
-
value:
|
|
2602
|
+
value: basename5,
|
|
2565
2603
|
weight: detector.weight
|
|
2566
2604
|
});
|
|
2567
2605
|
if (detector.kind === "manifest" || detector.kind === "config") {
|
|
@@ -2981,10 +3019,11 @@ var MAX_ARGUMENTS = 128;
|
|
|
2981
3019
|
var MAX_ARGUMENT_LENGTH = 4096;
|
|
2982
3020
|
var PACKAGE_NAME_RE = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+(?:@[a-z0-9*+._~^<>=|-]+)?$/i;
|
|
2983
3021
|
var COMPOSER_PACKAGE_RE = /^[a-z0-9_.-]+\/[a-z0-9_.-]+(?::[a-z0-9*+._~^<>=|-]+)?$/i;
|
|
2984
|
-
var GO_MODULE_RE = /^(?:[a-z0-9
|
|
3022
|
+
var GO_MODULE_RE = /^(?:[a-z0-9-]+\.)+[a-z0-9-]+\/[a-z0-9._~+/@-]+$/i;
|
|
2985
3023
|
var PYTHON_PACKAGE_RE = /^[a-z0-9._-]+(?:\[[a-z0-9._,-]+\])?==[a-z0-9*+._!~-]+$/i;
|
|
2986
3024
|
async function planLanguageOperation(options) {
|
|
2987
3025
|
validateOperationOptions(options.operation, options.operationOptions?.packages);
|
|
3026
|
+
validateFilterOption(options.operationOptions?.filter);
|
|
2988
3027
|
const detection = await detectLanguageWorkspaces(options);
|
|
2989
3028
|
const candidates = detection.workspaces.filter(
|
|
2990
3029
|
(workspace) => workspace.capabilities.includes(options.operation)
|
|
@@ -3157,6 +3196,15 @@ function workspaceDepth(workspaceRoot, projectRoot) {
|
|
|
3157
3196
|
const relative5 = path6.relative(path6.resolve(projectRoot), path6.resolve(workspaceRoot));
|
|
3158
3197
|
return relative5 === "" ? 0 : relative5.split(path6.sep).length;
|
|
3159
3198
|
}
|
|
3199
|
+
function validateFilterOption(filter) {
|
|
3200
|
+
if (filter === void 0) return;
|
|
3201
|
+
if (filter.startsWith("-") || filter.includes(" --")) {
|
|
3202
|
+
throw new Error(`Invalid test filter (parsed as a runner option): "${filter}"`);
|
|
3203
|
+
}
|
|
3204
|
+
if (filter.length > MAX_ARGUMENT_LENGTH || /[\r\n\0]/.test(filter)) {
|
|
3205
|
+
throw new Error("Invalid test filter (oversized or contains a control character)");
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3160
3208
|
function validateOperationOptions(operation, packages) {
|
|
3161
3209
|
if (!operation.startsWith("package-") || !packages) return;
|
|
3162
3210
|
for (const value of packages) {
|
|
@@ -3486,6 +3534,9 @@ var formatTool = {
|
|
|
3486
3534
|
description: "Format source files according to project style (Biome). Can also run in check-only mode.",
|
|
3487
3535
|
usageHint: "RUN REGULARLY:\n\n- Use on changed files before committing.\n- `check: true` verifies formatting without making changes (useful in CI-like flows).\nThis project has very consistent formatting expectations. Always ensure your changes are formatted.",
|
|
3488
3536
|
permission: "confirm",
|
|
3537
|
+
// WS-046: gives permission decisions something to key on.
|
|
3538
|
+
// The files being rewritten are the subject; the fixer is how, not what.
|
|
3539
|
+
subjectKey: "files",
|
|
3489
3540
|
mutating: true,
|
|
3490
3541
|
capabilities: ["fs.write", "shell.restricted"],
|
|
3491
3542
|
icon: "code",
|
package/dist/git.js
CHANGED
|
@@ -91,6 +91,10 @@ var gitTool = {
|
|
|
91
91
|
// Conservative: any of these may mutate. The non-mutating commands
|
|
92
92
|
// (status/log/diff/branch/fetch) are still gated on `permission: 'confirm'`
|
|
93
93
|
// and `MUTATING_SUBCOMMANDS` is consulted at runtime for per-call checks.
|
|
94
|
+
// WS-046: gives permission decisions something to key on.
|
|
95
|
+
// The git subcommand (status/commit/push) is what a trust rule needs to
|
|
96
|
+
// distinguish; `git status` and `git push --force` must not share a subject.
|
|
97
|
+
subjectKey: "command",
|
|
94
98
|
mutating: true,
|
|
95
99
|
capabilities: ["fs.write", "shell.restricted"],
|
|
96
100
|
timeoutMs: TIMEOUT_MS,
|
|
@@ -159,6 +163,8 @@ var gitTool = {
|
|
|
159
163
|
truncated: false
|
|
160
164
|
};
|
|
161
165
|
}
|
|
166
|
+
const branchGuard = validateBranchInput(input);
|
|
167
|
+
if (branchGuard) return branchGuard;
|
|
162
168
|
if (input.command === "worktree") {
|
|
163
169
|
const guard = validateWorktreeInput(input, ctx.projectRoot);
|
|
164
170
|
if (guard) return guard;
|
|
@@ -207,6 +213,18 @@ var gitTool = {
|
|
|
207
213
|
return result;
|
|
208
214
|
}
|
|
209
215
|
};
|
|
216
|
+
function validateBranchInput(input) {
|
|
217
|
+
const branch = input.branch;
|
|
218
|
+
if (branch === void 0) return null;
|
|
219
|
+
if (!branch.startsWith("-") && !branch.includes(" --")) return null;
|
|
220
|
+
return {
|
|
221
|
+
command: input.command,
|
|
222
|
+
stdout: "",
|
|
223
|
+
stderr: `unsafe branch name (parsed as a git option): ${branch}`,
|
|
224
|
+
exitCode: 1,
|
|
225
|
+
truncated: false
|
|
226
|
+
};
|
|
227
|
+
}
|
|
210
228
|
function validateWorktreeInput(input, projectRoot) {
|
|
211
229
|
const reject = (stderr) => ({
|
|
212
230
|
command: "worktree",
|
|
@@ -215,7 +233,6 @@ function validateWorktreeInput(input, projectRoot) {
|
|
|
215
233
|
exitCode: 1,
|
|
216
234
|
truncated: false
|
|
217
235
|
});
|
|
218
|
-
if (input.branch?.startsWith("-")) return reject(`unsafe branch name: ${input.branch}`);
|
|
219
236
|
if (input.worktreePath?.startsWith("-")) {
|
|
220
237
|
return reject(`unsafe worktree path: ${input.worktreePath}`);
|
|
221
238
|
}
|
|
@@ -269,7 +286,10 @@ function buildArgs(input) {
|
|
|
269
286
|
...files.length ? ["--", ...files] : []
|
|
270
287
|
];
|
|
271
288
|
case "branch":
|
|
272
|
-
return input.branch ? [
|
|
289
|
+
return input.branch ? [
|
|
290
|
+
"branch",
|
|
291
|
+
...input.branch.startsWith("-") || input.branch.includes(" --") ? [] : [input.branch]
|
|
292
|
+
] : ["branch"];
|
|
273
293
|
case "checkout":
|
|
274
294
|
return [
|
|
275
295
|
"checkout",
|
package/dist/glob.js
CHANGED
|
@@ -101,11 +101,15 @@ function safeResolve(input, ctx) {
|
|
|
101
101
|
return ensureInsideRoot(resolvePath(input, ctx), ctx);
|
|
102
102
|
}
|
|
103
103
|
async function assertRealInsideRoot(absPath, ctx) {
|
|
104
|
-
|
|
104
|
+
await resolveRealInsideRoot(absPath, ctx);
|
|
105
|
+
}
|
|
106
|
+
async function resolveRealInsideRoot(absPath, ctx) {
|
|
107
|
+
if (ctx.allowOutsideProjectRoot) return absPath;
|
|
105
108
|
const realRoots = await Promise.all(
|
|
106
109
|
allowedRoots(ctx).map((r) => fsp.realpath(r).catch(() => path2.resolve(r)))
|
|
107
110
|
);
|
|
108
111
|
let probe = absPath;
|
|
112
|
+
const pendingTail = [];
|
|
109
113
|
for (; ; ) {
|
|
110
114
|
let real;
|
|
111
115
|
try {
|
|
@@ -113,13 +117,16 @@ async function assertRealInsideRoot(absPath, ctx) {
|
|
|
113
117
|
} catch (err) {
|
|
114
118
|
if (err.code === "ENOENT") {
|
|
115
119
|
const parent = path2.dirname(probe);
|
|
116
|
-
if (parent === probe) return;
|
|
120
|
+
if (parent === probe) return absPath;
|
|
121
|
+
pendingTail.unshift(path2.basename(probe));
|
|
117
122
|
probe = parent;
|
|
118
123
|
continue;
|
|
119
124
|
}
|
|
120
125
|
throw err;
|
|
121
126
|
}
|
|
122
|
-
if (isInsideAny(real, realRoots))
|
|
127
|
+
if (isInsideAny(real, realRoots)) {
|
|
128
|
+
return pendingTail.length > 0 ? path2.join(real, ...pendingTail) : real;
|
|
129
|
+
}
|
|
123
130
|
throw new Error(
|
|
124
131
|
`Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
|
|
125
132
|
);
|
|
@@ -127,8 +134,7 @@ async function assertRealInsideRoot(absPath, ctx) {
|
|
|
127
134
|
}
|
|
128
135
|
async function safeResolveReal(input, ctx) {
|
|
129
136
|
const abs = safeResolve(input, ctx);
|
|
130
|
-
await
|
|
131
|
-
return abs;
|
|
137
|
+
return await resolveRealInsideRoot(abs, ctx);
|
|
132
138
|
}
|
|
133
139
|
|
|
134
140
|
// src/glob.ts
|