@wrongstack/tools 0.296.4 → 0.298.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/dist/_spawn-stream.d.ts +2 -0
- package/dist/_util.d.ts +29 -1
- package/dist/audit.js +128 -65
- package/dist/bash.js +20 -4
- package/dist/batch-tool-use.js +70 -7
- package/dist/browser/index.js +31 -1
- package/dist/builtin.js +883 -351
- package/dist/codebase-index/index.js +95 -16
- package/dist/codebase-index/project-server-protocol.d.ts +26 -0
- package/dist/codebase-index/project-server.js +76 -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.js +562 -516
- package/dist/format.js +131 -65
- package/dist/git.js +22 -2
- package/dist/glob.js +11 -5
- package/dist/grep.js +160 -104
- package/dist/index.js +834 -290
- package/dist/install.js +135 -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 +143 -71
- package/dist/lint.js +128 -65
- package/dist/next-steps.d.ts +23 -0
- package/dist/next-steps.js +4 -0
- package/dist/outdated.js +101 -26
- package/dist/pack.js +883 -351
- package/dist/patch.js +11 -1
- package/dist/plan.js +32 -10
- package/dist/process-registry.d.ts +9 -0
- package/dist/process-registry.js +15 -0
- package/dist/ps-slash.js +15 -0
- package/dist/read.js +104 -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 +128 -65
- package/dist/todo.js +3 -1
- package/dist/tool-tier.js +883 -351
- 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 +128 -65
- package/dist/write.js +9 -6
- package/package.json +5 -4
- 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/outdated.js
CHANGED
|
@@ -52,12 +52,13 @@ function ensureInsideRoot(absPath, ctx) {
|
|
|
52
52
|
function safeResolve(input, ctx) {
|
|
53
53
|
return ensureInsideRoot(resolvePath(input, ctx), ctx);
|
|
54
54
|
}
|
|
55
|
-
async function
|
|
56
|
-
if (ctx.allowOutsideProjectRoot) return;
|
|
55
|
+
async function resolveRealInsideRoot(absPath, ctx) {
|
|
56
|
+
if (ctx.allowOutsideProjectRoot) return absPath;
|
|
57
57
|
const realRoots = await Promise.all(
|
|
58
58
|
allowedRoots(ctx).map((r) => fsp.realpath(r).catch(() => path.resolve(r)))
|
|
59
59
|
);
|
|
60
60
|
let probe = absPath;
|
|
61
|
+
const pendingTail = [];
|
|
61
62
|
for (; ; ) {
|
|
62
63
|
let real;
|
|
63
64
|
try {
|
|
@@ -65,13 +66,16 @@ async function assertRealInsideRoot(absPath, ctx) {
|
|
|
65
66
|
} catch (err) {
|
|
66
67
|
if (err.code === "ENOENT") {
|
|
67
68
|
const parent = path.dirname(probe);
|
|
68
|
-
if (parent === probe) return;
|
|
69
|
+
if (parent === probe) return absPath;
|
|
70
|
+
pendingTail.unshift(path.basename(probe));
|
|
69
71
|
probe = parent;
|
|
70
72
|
continue;
|
|
71
73
|
}
|
|
72
74
|
throw err;
|
|
73
75
|
}
|
|
74
|
-
if (isInsideAny(real, realRoots))
|
|
76
|
+
if (isInsideAny(real, realRoots)) {
|
|
77
|
+
return pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
|
|
78
|
+
}
|
|
75
79
|
throw new Error(
|
|
76
80
|
`Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
|
|
77
81
|
);
|
|
@@ -79,8 +83,7 @@ async function assertRealInsideRoot(absPath, ctx) {
|
|
|
79
83
|
}
|
|
80
84
|
async function safeResolveReal(input, ctx) {
|
|
81
85
|
const abs = safeResolve(input, ctx);
|
|
82
|
-
await
|
|
83
|
-
return abs;
|
|
86
|
+
return await resolveRealInsideRoot(abs, ctx);
|
|
84
87
|
}
|
|
85
88
|
function collapseCarriageReturns(text) {
|
|
86
89
|
const lf = text.replace(/\r\n/g, "\n");
|
|
@@ -1682,8 +1685,8 @@ async function scanDirectory(directory, depth, profiles, limits, state, extraIgn
|
|
|
1682
1685
|
collectFileEvidence(directory, fullPath, entry.name, profiles, state);
|
|
1683
1686
|
}
|
|
1684
1687
|
}
|
|
1685
|
-
function collectFileEvidence(directory, fullPath,
|
|
1686
|
-
const lower =
|
|
1688
|
+
function collectFileEvidence(directory, fullPath, basename5, profiles, state) {
|
|
1689
|
+
const lower = basename5.toLowerCase();
|
|
1687
1690
|
const extension = path3.extname(lower);
|
|
1688
1691
|
for (const profile of profiles) {
|
|
1689
1692
|
const detector = profile.detectors.find(
|
|
@@ -1694,7 +1697,7 @@ function collectFileEvidence(directory, fullPath, basename4, profiles, state) {
|
|
|
1694
1697
|
candidate.evidence.push({
|
|
1695
1698
|
kind: detector.kind,
|
|
1696
1699
|
path: fullPath,
|
|
1697
|
-
value:
|
|
1700
|
+
value: basename5,
|
|
1698
1701
|
weight: detector.weight
|
|
1699
1702
|
});
|
|
1700
1703
|
if (detector.kind === "manifest" || detector.kind === "config") {
|
|
@@ -2442,11 +2445,12 @@ function createOutputSpool(opts) {
|
|
|
2442
2445
|
return {
|
|
2443
2446
|
write(text) {
|
|
2444
2447
|
if (finalized || !text) return;
|
|
2445
|
-
|
|
2448
|
+
const textBytes = Buffer.byteLength(text, "utf8");
|
|
2449
|
+
totalBytes += textBytes;
|
|
2446
2450
|
if (!stream && !failed) {
|
|
2447
|
-
if (headBytes +
|
|
2451
|
+
if (headBytes + textBytes <= threshold) {
|
|
2448
2452
|
head += text;
|
|
2449
|
-
headBytes +=
|
|
2453
|
+
headBytes += textBytes;
|
|
2450
2454
|
return;
|
|
2451
2455
|
}
|
|
2452
2456
|
head += text;
|
|
@@ -2456,7 +2460,7 @@ function createOutputSpool(opts) {
|
|
|
2456
2460
|
}
|
|
2457
2461
|
if (stream) {
|
|
2458
2462
|
if (stream.writableLength > SPOOL_WRITE_HWM_BYTES) {
|
|
2459
|
-
droppedBytes +=
|
|
2463
|
+
droppedBytes += textBytes;
|
|
2460
2464
|
return;
|
|
2461
2465
|
}
|
|
2462
2466
|
stream.write(text);
|
|
@@ -2840,6 +2844,7 @@ var init_process_registry = __esm({
|
|
|
2840
2844
|
}
|
|
2841
2845
|
/** Get all tracked processes. */
|
|
2842
2846
|
list() {
|
|
2847
|
+
this._pruneAllStale();
|
|
2843
2848
|
return Array.from(this.processes.values());
|
|
2844
2849
|
}
|
|
2845
2850
|
/** Get processes filtered by name (e.g. 'bash', 'exec'). */
|
|
@@ -2870,6 +2875,7 @@ var init_process_registry = __esm({
|
|
|
2870
2875
|
* Combined stats for observability — used by /ps and the TUI status bar.
|
|
2871
2876
|
*/
|
|
2872
2877
|
stats() {
|
|
2878
|
+
this._pruneAllStale();
|
|
2873
2879
|
return {
|
|
2874
2880
|
activeCount: this.activeCount,
|
|
2875
2881
|
backgroundCount: this.activeBackgroundCount,
|
|
@@ -3109,6 +3115,19 @@ var init_process_registry = __esm({
|
|
|
3109
3115
|
this.processes.delete(pid);
|
|
3110
3116
|
}
|
|
3111
3117
|
}
|
|
3118
|
+
/**
|
|
3119
|
+
* Remove every stale entry, not just one PID. `list()`/`stats()` — the
|
|
3120
|
+
* surfaces the TUI status bar and `/ps` poll — must prune too: a child
|
|
3121
|
+
* whose 'close' event never fires (e.g. Windows grandchildren holding stdio
|
|
3122
|
+
* open) would otherwise linger in the registry until someone looks up its
|
|
3123
|
+
* exact PID, and PID reuse meanwhile makes `get()`/`kill()` target the
|
|
3124
|
+
* wrong process. RAM-leak audit 2026-07-31, MEDIUM.
|
|
3125
|
+
*/
|
|
3126
|
+
_pruneAllStale() {
|
|
3127
|
+
for (const [pid, entry] of this.processes) {
|
|
3128
|
+
if (this._isStaleEntry(entry)) this.processes.delete(pid);
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3112
3131
|
};
|
|
3113
3132
|
}
|
|
3114
3133
|
});
|
|
@@ -3125,8 +3144,11 @@ async function* spawnStream(opts) {
|
|
|
3125
3144
|
const max = opts.maxBytes ?? 2e5;
|
|
3126
3145
|
const flushAt = opts.flushBytes ?? 4 * 1024;
|
|
3127
3146
|
const maxQueue = opts.maxQueueSize ?? 500;
|
|
3147
|
+
const maxQueueBytes = opts.maxQueueBytes ?? 1024 * 1024;
|
|
3128
3148
|
let stdout = "";
|
|
3129
3149
|
let stderr = "";
|
|
3150
|
+
let stdoutRetainedBytes = 0;
|
|
3151
|
+
let stderrRetainedBytes = 0;
|
|
3130
3152
|
let pending = "";
|
|
3131
3153
|
let error;
|
|
3132
3154
|
const spool = createOutputSpool({ tool: opts.cmd, thresholdBytes: max });
|
|
@@ -3168,6 +3190,7 @@ async function* spawnStream(opts) {
|
|
|
3168
3190
|
});
|
|
3169
3191
|
}
|
|
3170
3192
|
const queue = [];
|
|
3193
|
+
let queuedBytes = 0;
|
|
3171
3194
|
let waiter;
|
|
3172
3195
|
let paused = false;
|
|
3173
3196
|
const wake = () => {
|
|
@@ -3178,7 +3201,7 @@ async function* spawnStream(opts) {
|
|
|
3178
3201
|
}
|
|
3179
3202
|
};
|
|
3180
3203
|
const resume = () => {
|
|
3181
|
-
if (paused && queue.length
|
|
3204
|
+
if (paused && queue.length <= Math.floor(maxQueue / 2) && queuedBytes <= Math.floor(maxQueueBytes / 2)) {
|
|
3182
3205
|
paused = false;
|
|
3183
3206
|
child.stdout?.resume();
|
|
3184
3207
|
child.stderr?.resume();
|
|
@@ -3188,11 +3211,16 @@ async function* spawnStream(opts) {
|
|
|
3188
3211
|
const s = c.toString();
|
|
3189
3212
|
stdoutBytes += c.byteLength;
|
|
3190
3213
|
emitProcessOutput({ pid, stream: "stdout", chunk: c });
|
|
3191
|
-
if (
|
|
3214
|
+
if (stdoutRetainedBytes < max) {
|
|
3215
|
+
const retained = utf8Prefix(s, max - stdoutRetainedBytes);
|
|
3216
|
+
stdout += retained;
|
|
3217
|
+
stdoutRetainedBytes += Buffer.byteLength(retained, "utf8");
|
|
3218
|
+
}
|
|
3192
3219
|
spool.write(s);
|
|
3193
|
-
queue.push({ kind: "out", data: s });
|
|
3220
|
+
queue.push({ kind: "out", data: s, bytes: c.byteLength });
|
|
3221
|
+
queuedBytes += c.byteLength;
|
|
3194
3222
|
wake();
|
|
3195
|
-
if (!paused && queue.length >= maxQueue) {
|
|
3223
|
+
if (!paused && (queue.length >= maxQueue || queuedBytes >= maxQueueBytes)) {
|
|
3196
3224
|
paused = true;
|
|
3197
3225
|
child.stdout?.pause();
|
|
3198
3226
|
child.stderr?.pause();
|
|
@@ -3202,11 +3230,16 @@ async function* spawnStream(opts) {
|
|
|
3202
3230
|
const s = c.toString();
|
|
3203
3231
|
stderrBytes += c.byteLength;
|
|
3204
3232
|
emitProcessOutput({ pid, stream: "stderr", chunk: c });
|
|
3205
|
-
if (
|
|
3233
|
+
if (stderrRetainedBytes < max) {
|
|
3234
|
+
const retained = utf8Prefix(s, max - stderrRetainedBytes);
|
|
3235
|
+
stderr += retained;
|
|
3236
|
+
stderrRetainedBytes += Buffer.byteLength(retained, "utf8");
|
|
3237
|
+
}
|
|
3206
3238
|
spool.write(s);
|
|
3207
|
-
queue.push({ kind: "err", data: s });
|
|
3239
|
+
queue.push({ kind: "err", data: s, bytes: c.byteLength });
|
|
3240
|
+
queuedBytes += c.byteLength;
|
|
3208
3241
|
wake();
|
|
3209
|
-
if (!paused && queue.length >= maxQueue) {
|
|
3242
|
+
if (!paused && (queue.length >= maxQueue || queuedBytes >= maxQueueBytes)) {
|
|
3210
3243
|
paused = true;
|
|
3211
3244
|
child.stdout?.pause();
|
|
3212
3245
|
child.stderr?.pause();
|
|
@@ -3216,7 +3249,9 @@ async function* spawnStream(opts) {
|
|
|
3216
3249
|
child.stderr?.on("data", onErr);
|
|
3217
3250
|
child.on("error", (e) => {
|
|
3218
3251
|
error = e.message;
|
|
3219
|
-
|
|
3252
|
+
const bytes = Buffer.byteLength(e.message, "utf8");
|
|
3253
|
+
queue.push({ kind: "error", data: e.message, bytes });
|
|
3254
|
+
queuedBytes += bytes;
|
|
3220
3255
|
wake();
|
|
3221
3256
|
});
|
|
3222
3257
|
const completeTelemetry = (code, signal, timedOut = false) => {
|
|
@@ -3237,7 +3272,13 @@ async function* spawnStream(opts) {
|
|
|
3237
3272
|
if (typeof pid === "number") registry.unregister(pid);
|
|
3238
3273
|
const exitCode2 = code ?? (signal ? 1 : 0);
|
|
3239
3274
|
completeTelemetry(exitCode2, signal ?? void 0);
|
|
3240
|
-
queue.push({
|
|
3275
|
+
queue.push({
|
|
3276
|
+
kind: "close",
|
|
3277
|
+
data: "",
|
|
3278
|
+
bytes: 0,
|
|
3279
|
+
code: exitCode2,
|
|
3280
|
+
...signal ? { signal } : {}
|
|
3281
|
+
});
|
|
3241
3282
|
wake();
|
|
3242
3283
|
});
|
|
3243
3284
|
const onAbort = () => {
|
|
@@ -3249,7 +3290,7 @@ async function* spawnStream(opts) {
|
|
|
3249
3290
|
} catch {
|
|
3250
3291
|
}
|
|
3251
3292
|
}
|
|
3252
|
-
queue.push({ kind: "close", data: "", code: 124 });
|
|
3293
|
+
queue.push({ kind: "close", data: "", bytes: 0, code: 124 });
|
|
3253
3294
|
completeTelemetry(124, "SIGKILL", true);
|
|
3254
3295
|
wake();
|
|
3255
3296
|
};
|
|
@@ -3267,6 +3308,7 @@ async function* spawnStream(opts) {
|
|
|
3267
3308
|
});
|
|
3268
3309
|
}
|
|
3269
3310
|
const chunk = queue.shift();
|
|
3311
|
+
queuedBytes -= chunk.bytes;
|
|
3270
3312
|
resume();
|
|
3271
3313
|
if (chunk.kind === "close") {
|
|
3272
3314
|
if (!spawnFailed) exitCode = chunk.code ?? 0;
|
|
@@ -3293,7 +3335,7 @@ async function* spawnStream(opts) {
|
|
|
3293
3335
|
stdout: spooled ? stdout + spoolNote(spooled) : stdout,
|
|
3294
3336
|
stderr,
|
|
3295
3337
|
exitCode,
|
|
3296
|
-
truncated:
|
|
3338
|
+
truncated: stdoutBytes > stdoutRetainedBytes || stderrBytes > stderrRetainedBytes,
|
|
3297
3339
|
error,
|
|
3298
3340
|
spoolPath: spooled?.path,
|
|
3299
3341
|
spoolBytes: spooled?.bytes
|
|
@@ -3317,13 +3359,27 @@ async function* spawnStream(opts) {
|
|
|
3317
3359
|
}
|
|
3318
3360
|
}
|
|
3319
3361
|
}
|
|
3362
|
+
function utf8Prefix(text, maxBytes) {
|
|
3363
|
+
if (maxBytes <= 0) return "";
|
|
3364
|
+
if (Buffer.byteLength(text, "utf8") <= maxBytes) return text;
|
|
3365
|
+
let low = 0;
|
|
3366
|
+
let high = text.length;
|
|
3367
|
+
while (low < high) {
|
|
3368
|
+
const mid = Math.ceil((low + high) / 2);
|
|
3369
|
+
if (Buffer.byteLength(text.slice(0, mid), "utf8") <= maxBytes) low = mid;
|
|
3370
|
+
else high = mid - 1;
|
|
3371
|
+
}
|
|
3372
|
+
let end = low;
|
|
3373
|
+
if (end > 0 && /[\uD800-\uDBFF]/.test(text[end - 1])) end--;
|
|
3374
|
+
return text.slice(0, end);
|
|
3375
|
+
}
|
|
3320
3376
|
var isWin;
|
|
3321
3377
|
var init_spawn_stream = __esm({
|
|
3322
3378
|
"src/_spawn-stream.ts"() {
|
|
3323
3379
|
"use strict";
|
|
3324
3380
|
init_output_spool();
|
|
3325
|
-
init_process_registry();
|
|
3326
3381
|
init_win32_resolve();
|
|
3382
|
+
init_process_registry();
|
|
3327
3383
|
isWin = process.platform === "win32";
|
|
3328
3384
|
}
|
|
3329
3385
|
});
|
|
@@ -3333,6 +3389,7 @@ import * as fs3 from "node:fs/promises";
|
|
|
3333
3389
|
import * as path6 from "node:path";
|
|
3334
3390
|
async function planLanguageOperation(options) {
|
|
3335
3391
|
validateOperationOptions(options.operation, options.operationOptions?.packages);
|
|
3392
|
+
validateFilterOption(options.operationOptions?.filter);
|
|
3336
3393
|
const detection = await detectLanguageWorkspaces(options);
|
|
3337
3394
|
const candidates = detection.workspaces.filter(
|
|
3338
3395
|
(workspace) => workspace.capabilities.includes(options.operation)
|
|
@@ -3505,6 +3562,15 @@ function workspaceDepth(workspaceRoot, projectRoot) {
|
|
|
3505
3562
|
const relative5 = path6.relative(path6.resolve(projectRoot), path6.resolve(workspaceRoot));
|
|
3506
3563
|
return relative5 === "" ? 0 : relative5.split(path6.sep).length;
|
|
3507
3564
|
}
|
|
3565
|
+
function validateFilterOption(filter) {
|
|
3566
|
+
if (filter === void 0) return;
|
|
3567
|
+
if (filter.startsWith("-") || filter.includes(" --")) {
|
|
3568
|
+
throw new Error(`Invalid test filter (parsed as a runner option): "${filter}"`);
|
|
3569
|
+
}
|
|
3570
|
+
if (filter.length > MAX_ARGUMENT_LENGTH || /[\r\n\0]/.test(filter)) {
|
|
3571
|
+
throw new Error("Invalid test filter (oversized or contains a control character)");
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3508
3574
|
function validateOperationOptions(operation, packages) {
|
|
3509
3575
|
if (!operation.startsWith("package-") || !packages) return;
|
|
3510
3576
|
for (const value of packages) {
|
|
@@ -3546,7 +3612,7 @@ var init_plan = __esm({
|
|
|
3546
3612
|
MAX_ARGUMENT_LENGTH = 4096;
|
|
3547
3613
|
PACKAGE_NAME_RE = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+(?:@[a-z0-9*+._~^<>=|-]+)?$/i;
|
|
3548
3614
|
COMPOSER_PACKAGE_RE = /^[a-z0-9_.-]+\/[a-z0-9_.-]+(?::[a-z0-9*+._~^<>=|-]+)?$/i;
|
|
3549
|
-
GO_MODULE_RE = /^(?:[a-z0-9
|
|
3615
|
+
GO_MODULE_RE = /^(?:[a-z0-9-]+\.)+[a-z0-9-]+\/[a-z0-9._~+/@-]+$/i;
|
|
3550
3616
|
PYTHON_PACKAGE_RE = /^[a-z0-9._-]+(?:\[[a-z0-9._,-]+\])?==[a-z0-9*+._!~-]+$/i;
|
|
3551
3617
|
}
|
|
3552
3618
|
});
|
|
@@ -4144,6 +4210,9 @@ var init_execute_tool = __esm({
|
|
|
4144
4210
|
useInstead: ["language_info", "install", "audit", "outdated"]
|
|
4145
4211
|
},
|
|
4146
4212
|
permission: "confirm",
|
|
4213
|
+
// WS-046: gives permission decisions something to key on.
|
|
4214
|
+
// The action performed (build/test/lint); the cwd is where, not what.
|
|
4215
|
+
subjectKey: "action",
|
|
4147
4216
|
mutating: true,
|
|
4148
4217
|
riskTier: "standard",
|
|
4149
4218
|
capabilities: ["shell.restricted", "fs.write"],
|
|
@@ -4376,6 +4445,9 @@ var init_package_tool = __esm({
|
|
|
4376
4445
|
useInstead: ["language_info", "language", "install", "audit", "outdated"]
|
|
4377
4446
|
},
|
|
4378
4447
|
permission: "confirm",
|
|
4448
|
+
// WS-046: gives permission decisions something to key on.
|
|
4449
|
+
// The package operation performed — install/remove are not interchangeable.
|
|
4450
|
+
subjectKey: "operation",
|
|
4379
4451
|
mutating: true,
|
|
4380
4452
|
riskTier: "destructive",
|
|
4381
4453
|
capabilities: ["shell.restricted", "fs.write", "net.outbound", "package.install"],
|
|
@@ -4879,6 +4951,9 @@ var outdatedTool = {
|
|
|
4879
4951
|
// tool.confirm_needed flow on every invocation. M-1 originally
|
|
4880
4952
|
// fixed four sibling tools (mcp_control, shellcheck, shellcheck (scan mode),
|
|
4881
4953
|
// search) but missed this one; applying the same contract here.
|
|
4954
|
+
// WS-046: gives permission decisions something to key on.
|
|
4955
|
+
// The working directory scanned.
|
|
4956
|
+
subjectKey: "cwd",
|
|
4882
4957
|
mutating: true,
|
|
4883
4958
|
// Capability is outbound network — the tool only hits the package
|
|
4884
4959
|
// registry over HTTP, never touches the filesystem or runs shell.
|