@wrongstack/tools 0.313.0 → 0.316.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/_edit-match.d.ts +3 -2
- package/dist/_output-spool.d.ts +4 -3
- package/dist/_shell-pick.d.ts +2 -1
- package/dist/_spawn-stream.d.ts +2 -1
- package/dist/_syntax-check.d.ts +2 -1
- package/dist/audit.js +10 -4055
- package/dist/bash-kill-guard.d.ts +3 -6
- package/dist/bash.js +9 -2308
- package/dist/batch-tool-use.js +2 -187
- package/dist/browser/index.js +25 -1339
- package/dist/browser/network-guard-proxy.d.ts +2 -1
- package/dist/builtin.js +69 -33949
- package/dist/chunk-22B7GE5T.js +260 -0
- package/dist/chunk-2VSZC6QM.js +113 -0
- package/dist/chunk-3PVYQFRQ.js +472 -0
- package/dist/chunk-42BHI7TN.js +337 -0
- package/dist/chunk-4BHUSMNL.js +104 -0
- package/dist/chunk-4I4LWFOO.js +431 -0
- package/dist/chunk-4UESMQDP.js +122 -0
- package/dist/chunk-553IQUMO.js +478 -0
- package/dist/chunk-5H4GSJAI.js +223 -0
- package/dist/chunk-6RNIFLG4.js +305 -0
- package/dist/chunk-7EY5DCRO.js +434 -0
- package/dist/chunk-A6BRWIXN.js +317 -0
- package/dist/chunk-AHHDWNXC.js +200 -0
- package/dist/chunk-BSLVR56S.js +199 -0
- package/dist/chunk-BTSFTGIL.js +7 -0
- package/dist/chunk-D33S4RQG.js +222 -0
- package/dist/chunk-DA4KNE2H.js +4412 -0
- package/dist/chunk-DR7JOQTC.js +520 -0
- package/dist/chunk-EEOFQDT6.js +898 -0
- package/dist/chunk-EJWSCQ6D.js +137 -0
- package/dist/chunk-EMRGN4KM.js +170 -0
- package/dist/chunk-FQZOHLG3.js +89 -0
- package/dist/chunk-GOIZNNOA.js +221 -0
- package/dist/chunk-HFXSNKCV.js +196 -0
- package/dist/chunk-HYX2TZ7O.js +1272 -0
- package/dist/chunk-I64BS3VC.js +15 -0
- package/dist/chunk-IVWV2UM6.js +955 -0
- package/dist/chunk-IXMNTNW5.js +238 -0
- package/dist/chunk-IYK7XGDZ.js +892 -0
- package/dist/chunk-J5SKD6LN.js +235 -0
- package/dist/chunk-JNNVRHMV.js +2111 -0
- package/dist/chunk-JOHXDF3D.js +295 -0
- package/dist/chunk-JRJJX3L5.js +424 -0
- package/dist/chunk-K3WNSHUF.js +1371 -0
- package/dist/chunk-L25CVUVR.js +2830 -0
- package/dist/chunk-LIJQMYYX.js +59 -0
- package/dist/chunk-LWKUTMD5.js +197 -0
- package/dist/chunk-MQX2KXVW.js +54 -0
- package/dist/chunk-MZZN7VCD.js +359 -0
- package/dist/chunk-NBDZMMG2.js +169 -0
- package/dist/chunk-NKJW5GFO.js +366 -0
- package/dist/chunk-NKNOBUBU.js +522 -0
- package/dist/chunk-O4MBV4AX.js +134 -0
- package/dist/chunk-OUBDL3WH.js +3515 -0
- package/dist/chunk-PQKK5JH7.js +101 -0
- package/dist/chunk-PY2IOS7C.js +1000 -0
- package/dist/chunk-Q5JPPCZC.js +12 -0
- package/dist/chunk-QBV725YG.js +128 -0
- package/dist/chunk-QZQSPUBF.js +315 -0
- package/dist/chunk-RGISBZBD.js +231 -0
- package/dist/chunk-RJZQWEMS.js +84 -0
- package/dist/chunk-RXISBFR5.js +315 -0
- package/dist/chunk-S5CCLZL3.js +99 -0
- package/dist/chunk-SDLVH5RZ.js +178 -0
- package/dist/chunk-T2F4S7U4.js +1723 -0
- package/dist/chunk-TEBQ4VPZ.js +163 -0
- package/dist/chunk-U4D5S3VQ.js +21 -0
- package/dist/chunk-U4VAATKP.js +193 -0
- package/dist/chunk-UCYQTZ7F.js +113 -0
- package/dist/chunk-UKU2ZX4C.js +203 -0
- package/dist/chunk-UNSKG6DC.js +159 -0
- package/dist/chunk-V43EQ6VR.js +68 -0
- package/dist/chunk-VB3MJGCV.js +610 -0
- package/dist/chunk-VFKPWSOX.js +154 -0
- package/dist/chunk-VJNHFZ7J.js +190 -0
- package/dist/chunk-VXECAJJ7.js +1091 -0
- package/dist/chunk-WHIIIREL.js +223 -0
- package/dist/chunk-Z6DAKQ3U.js +1 -0
- package/dist/chunk-ZJQ4IGXK.js +474 -0
- package/dist/chunk-ZLTFLC25.js +385 -0
- package/dist/circuit-breaker.js +3 -191
- package/dist/codebase-index/ast-invariant-engine.d.ts +5 -4
- package/dist/codebase-index/binary-frame.d.ts +0 -2
- package/dist/codebase-index/bm25.d.ts +1 -1
- package/dist/codebase-index/circuit-breaker.d.ts +2 -1
- package/dist/codebase-index/codebase-ast-replace-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +4 -3
- package/dist/codebase-index/codebase-invariant-check-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-repo-map-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-skeleton-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-targeted-test-tool.d.ts +3 -2
- package/dist/codebase-index/content-hash.d.ts +0 -2
- package/dist/codebase-index/import-extractor.d.ts +0 -13
- package/dist/codebase-index/index-service.d.ts +1 -1
- package/dist/codebase-index/index.js +84 -13688
- package/dist/codebase-index/languages.d.ts +2 -1
- package/dist/codebase-index/module-roots.d.ts +3 -2
- package/dist/codebase-index/parser-batch.d.ts +0 -5
- package/dist/codebase-index/parser-dispatch.d.ts +2 -1
- package/dist/codebase-index/parser-output.d.ts +4 -3
- package/dist/codebase-index/parser-worker-pool.d.ts +0 -2
- package/dist/codebase-index/parser-worker-script.d.ts +1 -16
- package/dist/codebase-index/parser-worker-script.js +8 -3995
- package/dist/codebase-index/project-server-client-state.d.ts +2 -2
- package/dist/codebase-index/project-server-endpoint.d.ts +0 -15
- package/dist/codebase-index/project-server.js +60 -8548
- package/dist/codebase-index/tree-sitter/visitor.d.ts +2 -1
- package/dist/codebase-index/tree-sitter-parser.d.ts +0 -2
- package/dist/codebase-index/ts-parser.d.ts +1 -1
- package/dist/codebase-index/vector-search.d.ts +2 -1
- package/dist/codebase-index/wal-maintenance.d.ts +3 -2
- package/dist/codebase-index/worker.js +20 -8416
- package/dist/codebase-index/writer-admin.d.ts +0 -1
- package/dist/codebase-index/writer-search.d.ts +0 -9
- package/dist/design.js +2 -299
- package/dist/diff.js +4 -256
- package/dist/document.js +4 -222
- package/dist/e2e.js +5 -476
- package/dist/edit.js +14 -10200
- package/dist/exec.js +16 -3131
- package/dist/fetch.js +8 -398
- package/dist/format.js +10 -3750
- package/dist/generic-parser-VUXDIAOZ.js +13 -0
- package/dist/git.js +4 -380
- package/dist/glob.js +6 -280
- package/dist/go-parser-JXYKJHRC.js +469 -0
- package/dist/grep.js +7 -604
- package/dist/index.js +318 -35387
- package/dist/install.js +10 -4091
- package/dist/json-parser-IBHZ4BZC.js +213 -0
- package/dist/json.js +4 -665
- package/dist/kanban-contract-actions.d.ts +1 -1
- package/dist/kanban-detail-actions.d.ts +2 -1
- package/dist/kanban-presence.d.ts +2 -1
- package/dist/kanban-serializer.d.ts +0 -8
- package/dist/kanban-split-task-handler.d.ts +2 -2
- package/dist/kanban-tool-types.d.ts +2 -1
- package/dist/kanban.js +3 -2096
- package/dist/languages/diagnostics.d.ts +2 -1
- package/dist/languages/index.js +23 -4664
- package/dist/languages/legacy-bridge.d.ts +3 -2
- package/dist/languages/types.d.ts +2 -1
- package/dist/legacy-bridge-7M6QLUQN.js +18 -0
- package/dist/lint.js +10 -3706
- package/dist/logs.js +4 -287
- package/dist/memory.js +6 -215
- package/dist/mode.js +3 -99
- package/dist/outdated.js +4 -5170
- package/dist/pack.js +65 -33897
- package/dist/parser-dispatch-QH4XPGG6.js +14 -0
- package/dist/patch.js +13 -9935
- package/dist/plan.js +5 -3286
- package/dist/process-registry.js +8 -651
- package/dist/ps-slash.js +12 -1439
- package/dist/pwsh.d.ts +0 -1
- package/dist/py-parser-IS4HKYMF.js +16 -0
- package/dist/read.js +13 -9816
- package/dist/replace.js +15 -10014
- package/dist/rs-parser-XHUUO2KZ.js +81 -0
- package/dist/scaffold.js +4 -253
- package/dist/search.js +5 -585
- package/dist/session-kanban-sync.d.ts +0 -6
- package/dist/session-kanban.js +30 -972
- package/dist/skill.js +2 -215
- package/dist/spawn-background.d.ts +1 -1
- package/dist/task.js +5 -3410
- package/dist/test.js +10 -3773
- package/dist/todo.js +4 -2891
- package/dist/tool-help.js +3 -123
- package/dist/tool-search.js +3 -79
- package/dist/tool-tier.js +68 -33984
- package/dist/tool-use.js +2 -93
- package/dist/tree-sitter-parser-AIERW3YI.js +15 -0
- package/dist/tree.js +4 -288
- package/dist/ts-parser-RCTYKSVI.js +232 -0
- package/dist/typecheck.js +10 -3753
- package/dist/win32.js +6 -60
- package/dist/write.js +14 -9882
- package/dist/yaml-parser-4SAXV3PL.js +157 -0
- package/package.json +5 -5
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import {
|
|
2
|
+
tryLegacyCodeOperation
|
|
3
|
+
} from "./chunk-PQKK5JH7.js";
|
|
4
|
+
import {
|
|
5
|
+
spawnStream
|
|
6
|
+
} from "./chunk-22B7GE5T.js";
|
|
7
|
+
import {
|
|
8
|
+
normalizeCommandOutput,
|
|
9
|
+
safeResolveReal
|
|
10
|
+
} from "./chunk-D33S4RQG.js";
|
|
11
|
+
|
|
12
|
+
// src/test.ts
|
|
13
|
+
import * as path from "node:path";
|
|
14
|
+
var testTool = {
|
|
15
|
+
name: "test",
|
|
16
|
+
category: "Code Quality",
|
|
17
|
+
description: "Execute the project's test suite. This is one of the most critical tools for validating that your changes are correct.",
|
|
18
|
+
usageHint: "ESSENTIAL BEFORE CONSIDERING WORK DONE:\n\n- Use `files` or `grep` to run only relevant tests during development.\n- `coverage: true` is useful when working on critical paths.\nRun tests frequently. A clean test run is usually required before the task can be considered complete.",
|
|
19
|
+
permission: "confirm",
|
|
20
|
+
mutating: false,
|
|
21
|
+
icon: "test",
|
|
22
|
+
timeoutMs: 12e4,
|
|
23
|
+
capabilities: ["shell.restricted"],
|
|
24
|
+
inputSchema: {
|
|
25
|
+
type: "object",
|
|
26
|
+
properties: {
|
|
27
|
+
files: {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: 'Test files: single path, comma-separated list, or glob (e.g. "**/*.test.ts")'
|
|
30
|
+
},
|
|
31
|
+
runner: {
|
|
32
|
+
type: "string",
|
|
33
|
+
enum: ["vitest", "jest", "mocha", "auto"],
|
|
34
|
+
description: "Test runner (default: auto-detect)"
|
|
35
|
+
},
|
|
36
|
+
watch: { type: "boolean", description: "Run in watch mode (default: false)" },
|
|
37
|
+
coverage: { type: "boolean", description: "Generate coverage report (default: false)" },
|
|
38
|
+
cwd: { type: "string", description: "Working directory (default: cwd)" },
|
|
39
|
+
grep: { type: "string", description: "Filter tests by name pattern (default: none)" },
|
|
40
|
+
timeout: { type: "integer", description: "Test timeout in ms (default: 30000)" },
|
|
41
|
+
verbose: {
|
|
42
|
+
type: "boolean",
|
|
43
|
+
description: "Per-test verbose reporter output (default: false \u2014 the summary reporter is used; full output is always saved to a log file referenced in the result)"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
async execute(input, ctx, opts) {
|
|
48
|
+
let final;
|
|
49
|
+
const executeStream = testTool.executeStream;
|
|
50
|
+
if (!executeStream) throw new Error("testTool: stream execution unavailable");
|
|
51
|
+
for await (const ev of executeStream(input, ctx, opts)) {
|
|
52
|
+
if (ev.type === "final") final = ev.output;
|
|
53
|
+
}
|
|
54
|
+
if (!final) throw new Error("test: stream ended without final event");
|
|
55
|
+
return final;
|
|
56
|
+
},
|
|
57
|
+
async *executeStream(input, ctx, opts) {
|
|
58
|
+
const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
|
|
59
|
+
const runner = input.runner ?? "auto";
|
|
60
|
+
if (runner === "auto") {
|
|
61
|
+
const bridge = await tryLegacyCodeOperation("test", {
|
|
62
|
+
cwd,
|
|
63
|
+
projectRoot: ctx.projectRoot,
|
|
64
|
+
signal: opts.signal
|
|
65
|
+
});
|
|
66
|
+
if (bridge?.run) {
|
|
67
|
+
const run = bridge.run;
|
|
68
|
+
yield {
|
|
69
|
+
type: "final",
|
|
70
|
+
output: {
|
|
71
|
+
runner: bridge.language,
|
|
72
|
+
exit_code: run.exitCode ?? 0,
|
|
73
|
+
tests_run: (run.summary.passed ?? 0) + (run.summary.failed ?? 0),
|
|
74
|
+
passed: run.summary.passed ?? 0,
|
|
75
|
+
failed: run.summary.failed ?? 0,
|
|
76
|
+
duration_ms: run.durationMs,
|
|
77
|
+
output: normalizeCommandOutput(run.output || run.error || ""),
|
|
78
|
+
truncated: run.truncated
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const detected = runner === "auto" ? await detectRunner(cwd) : runner;
|
|
85
|
+
if (!detected) {
|
|
86
|
+
yield {
|
|
87
|
+
type: "final",
|
|
88
|
+
output: {
|
|
89
|
+
runner: "none",
|
|
90
|
+
exit_code: 0,
|
|
91
|
+
tests_run: 0,
|
|
92
|
+
passed: 0,
|
|
93
|
+
failed: 0,
|
|
94
|
+
duration_ms: 0,
|
|
95
|
+
output: "No test runner found (vitest.config.ts, jest.config.js, .mocharc.json)",
|
|
96
|
+
truncated: false
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
yield { type: "log", text: `Running ${detected}\u2026`, data: { runner: detected } };
|
|
102
|
+
const start = Date.now();
|
|
103
|
+
const args = buildArgs(detected, input);
|
|
104
|
+
const result = yield* spawnStream({
|
|
105
|
+
cmd: detected,
|
|
106
|
+
args,
|
|
107
|
+
cwd,
|
|
108
|
+
signal: opts.signal,
|
|
109
|
+
maxBytes: 2e5
|
|
110
|
+
});
|
|
111
|
+
const duration = Date.now() - start;
|
|
112
|
+
yield { type: "final", output: parseResult(detected, result, duration) };
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
async function detectRunner(cwd) {
|
|
116
|
+
const { stat } = await import("node:fs/promises");
|
|
117
|
+
const candidates = ["vitest.config.ts", "jest.config.js", ".mocharc.json"];
|
|
118
|
+
for (const f of candidates) {
|
|
119
|
+
try {
|
|
120
|
+
await stat(path.join(cwd, f));
|
|
121
|
+
if (f.includes("vitest")) return "vitest";
|
|
122
|
+
if (f.includes("jest")) return "jest";
|
|
123
|
+
if (f.includes("mocha")) return "mocha";
|
|
124
|
+
} catch {
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
function buildArgs(runner, input) {
|
|
130
|
+
const args = [];
|
|
131
|
+
const timeout = input.timeout ?? 3e4;
|
|
132
|
+
switch (runner) {
|
|
133
|
+
case "vitest":
|
|
134
|
+
args.push(input.watch ? "watch" : "run");
|
|
135
|
+
if (input.verbose) args.push("--reporter=verbose");
|
|
136
|
+
if (input.coverage) args.push("--coverage");
|
|
137
|
+
if (input.grep) args.push("--testNamePattern", input.grep);
|
|
138
|
+
args.push("--testTimeout", String(timeout));
|
|
139
|
+
break;
|
|
140
|
+
case "jest":
|
|
141
|
+
if (input.verbose) args.push("--verbose");
|
|
142
|
+
if (input.watch) args.push("--watch");
|
|
143
|
+
if (input.coverage) args.push("--coverage");
|
|
144
|
+
if (input.grep) args.push("--testPathPattern", input.grep);
|
|
145
|
+
args.push("--testTimeout", String(timeout));
|
|
146
|
+
break;
|
|
147
|
+
case "mocha":
|
|
148
|
+
args.push("--reporter", "spec");
|
|
149
|
+
if (input.grep) args.push("--grep", input.grep);
|
|
150
|
+
args.push("--timeout", String(timeout));
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
if (input.files) {
|
|
154
|
+
const files = Array.isArray(input.files) ? input.files : input.files.split(",");
|
|
155
|
+
args.push("--", ...files.map((f) => f.trim()));
|
|
156
|
+
}
|
|
157
|
+
return args;
|
|
158
|
+
}
|
|
159
|
+
function parseResult(runner, result, duration) {
|
|
160
|
+
const out = result.stdout + result.stderr;
|
|
161
|
+
let tests_run = 0;
|
|
162
|
+
let passed = 0;
|
|
163
|
+
let failed = 0;
|
|
164
|
+
if (runner === "vitest") {
|
|
165
|
+
const passedMatch = out.match(/(\d+) passed/);
|
|
166
|
+
const failedMatch = out.match(/(\d+) failed/);
|
|
167
|
+
if (passedMatch?.[1]) passed = Number.parseInt(passedMatch[1], 10);
|
|
168
|
+
if (failedMatch?.[1]) failed = Number.parseInt(failedMatch[1], 10);
|
|
169
|
+
tests_run = passed + failed;
|
|
170
|
+
} else if (runner === "jest") {
|
|
171
|
+
const suitesMatch = out.match(/Test Suites:\s+(\d+)\s+total/);
|
|
172
|
+
const passedMatch = out.match(/Tests:\s+(\d+)\s+passed/);
|
|
173
|
+
const failedMatch = out.match(/Tests:\s+(\d+)\s+failed/);
|
|
174
|
+
tests_run = Number.parseInt(suitesMatch?.[1] ?? "0", 10);
|
|
175
|
+
passed = Number.parseInt(passedMatch?.[1] ?? "0", 10);
|
|
176
|
+
failed = Number.parseInt(failedMatch?.[1] ?? "0", 10);
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
runner,
|
|
180
|
+
exit_code: result.exitCode,
|
|
181
|
+
tests_run,
|
|
182
|
+
passed,
|
|
183
|
+
failed,
|
|
184
|
+
duration_ms: duration,
|
|
185
|
+
// A passing run only needs the tail summary in chat history — counts are
|
|
186
|
+
// already parsed above and the FULL log is on disk (spool marker rides
|
|
187
|
+
// the stdout tail). Failures keep the standard command-output cap so
|
|
188
|
+
// the agent sees the failure details inline.
|
|
189
|
+
output: normalizeCommandOutput(result.stdout || result.error || "", {
|
|
190
|
+
maxBytes: result.exitCode === 0 ? 4096 : void 0
|
|
191
|
+
}),
|
|
192
|
+
truncated: result.truncated
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export {
|
|
197
|
+
testTool
|
|
198
|
+
};
|
|
199
|
+
//# sourceMappingURL=chunk-BSLVR56S.js.map
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// src/_util.ts
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import * as fsp from "node:fs/promises";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import * as Core from "@wrongstack/core/utils";
|
|
6
|
+
function sha256hex(content) {
|
|
7
|
+
return createHash("sha256").update(content, "utf8").digest("hex");
|
|
8
|
+
}
|
|
9
|
+
async function detectPackageManager(cwd, stopAt) {
|
|
10
|
+
let dir = path.resolve(cwd);
|
|
11
|
+
const stop = stopAt ? path.resolve(stopAt) : dir;
|
|
12
|
+
for (; ; ) {
|
|
13
|
+
const found = await detectPackageManagerInDir(dir);
|
|
14
|
+
if (found) return found;
|
|
15
|
+
if (dir === stop) break;
|
|
16
|
+
const parent = path.dirname(dir);
|
|
17
|
+
const relParent = path.relative(stop, parent);
|
|
18
|
+
if (parent === dir || relParent.startsWith("..") || path.isAbsolute(relParent)) break;
|
|
19
|
+
dir = parent;
|
|
20
|
+
}
|
|
21
|
+
return "npm";
|
|
22
|
+
}
|
|
23
|
+
async function detectPackageManagerInDir(dir) {
|
|
24
|
+
const fs = await import("node:fs/promises");
|
|
25
|
+
try {
|
|
26
|
+
const raw = await fs.readFile(path.join(dir, "package.json"), "utf8");
|
|
27
|
+
const declared = JSON.parse(raw).packageManager;
|
|
28
|
+
if (typeof declared === "string") {
|
|
29
|
+
const name = declared.split("@")[0] ?? "";
|
|
30
|
+
if (name === "pnpm" || name === "yarn") return name;
|
|
31
|
+
if (name === "npm" || name === "bun") return "npm";
|
|
32
|
+
}
|
|
33
|
+
} catch {
|
|
34
|
+
}
|
|
35
|
+
const lockfiles = [
|
|
36
|
+
["pnpm-lock.yaml", "pnpm"],
|
|
37
|
+
["yarn.lock", "yarn"],
|
|
38
|
+
["bun.lockb", "npm"],
|
|
39
|
+
["bun.lock", "npm"],
|
|
40
|
+
["package-lock.json", "npm"],
|
|
41
|
+
["npm-shrinkwrap.json", "npm"]
|
|
42
|
+
];
|
|
43
|
+
for (const [file, manager] of lockfiles) {
|
|
44
|
+
try {
|
|
45
|
+
await fs.stat(`${dir}/${file}`);
|
|
46
|
+
return manager;
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function resolvePath(input, ctx) {
|
|
53
|
+
return path.isAbsolute(input) ? path.normalize(input) : path.resolve(ctx.workingDir ?? ctx.cwd, input);
|
|
54
|
+
}
|
|
55
|
+
function allowedRoots(ctx) {
|
|
56
|
+
return [path.resolve(ctx.projectRoot), path.resolve(Core.wstackGlobalRoot())];
|
|
57
|
+
}
|
|
58
|
+
function isInsideAny(target, roots) {
|
|
59
|
+
return roots.some((root) => {
|
|
60
|
+
const rel = path.relative(root, target);
|
|
61
|
+
return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function ensureInsideRoot(absPath, ctx) {
|
|
65
|
+
const target = path.resolve(absPath);
|
|
66
|
+
if (ctx.allowOutsideProjectRoot) return target;
|
|
67
|
+
if (isInsideAny(target, allowedRoots(ctx))) return target;
|
|
68
|
+
throw new Error(`Path "${absPath}" is outside project root "${path.resolve(ctx.projectRoot)}"`);
|
|
69
|
+
}
|
|
70
|
+
function safeResolve(input, ctx) {
|
|
71
|
+
return ensureInsideRoot(resolvePath(input, ctx), ctx);
|
|
72
|
+
}
|
|
73
|
+
async function assertRealInsideRoot(absPath, ctx) {
|
|
74
|
+
await resolveRealInsideRoot(absPath, ctx);
|
|
75
|
+
}
|
|
76
|
+
async function resolveRealInsideRoot(absPath, ctx) {
|
|
77
|
+
if (ctx.allowOutsideProjectRoot) return absPath;
|
|
78
|
+
const realRoots = await Promise.all(
|
|
79
|
+
allowedRoots(ctx).map((r) => fsp.realpath(r).catch(() => path.resolve(r)))
|
|
80
|
+
);
|
|
81
|
+
let probe = absPath;
|
|
82
|
+
const pendingTail = [];
|
|
83
|
+
for (; ; ) {
|
|
84
|
+
let real;
|
|
85
|
+
try {
|
|
86
|
+
real = await fsp.realpath(probe);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
if (err.code === "ENOENT") {
|
|
89
|
+
const parent = path.dirname(probe);
|
|
90
|
+
if (parent === probe) return absPath;
|
|
91
|
+
pendingTail.unshift(path.basename(probe));
|
|
92
|
+
probe = parent;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
97
|
+
const candidate = pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
|
|
98
|
+
if (isInsideAny(candidate, realRoots)) {
|
|
99
|
+
return candidate;
|
|
100
|
+
}
|
|
101
|
+
throw new Error(
|
|
102
|
+
`Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async function safeResolveReal(input, ctx) {
|
|
107
|
+
const abs = safeResolve(input, ctx);
|
|
108
|
+
return await resolveRealInsideRoot(abs, ctx);
|
|
109
|
+
}
|
|
110
|
+
function truncateDiffPayload(diff, maxBytes) {
|
|
111
|
+
const total = Buffer.byteLength(diff, "utf8");
|
|
112
|
+
if (total <= maxBytes) return { text: diff, truncated: false };
|
|
113
|
+
const MARKER_RESERVE = 96;
|
|
114
|
+
let head = takeHeadBytes(diff, Math.max(0, maxBytes - MARKER_RESERVE));
|
|
115
|
+
const nl = head.lastIndexOf("\n");
|
|
116
|
+
if (nl > 0) head = head.slice(0, nl);
|
|
117
|
+
const kept = Buffer.byteLength(head, "utf8");
|
|
118
|
+
return {
|
|
119
|
+
text: `${head}
|
|
120
|
+
\u2026[diff truncated: ${total - kept} of ${total} bytes omitted]`,
|
|
121
|
+
truncated: true
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function truncateMiddle(s, max) {
|
|
125
|
+
if (Buffer.byteLength(s, "utf8") <= max) return s;
|
|
126
|
+
const half = Math.floor(max / 2);
|
|
127
|
+
return s.slice(0, half) + `
|
|
128
|
+
\u2026[truncated ${Buffer.byteLength(s, "utf8") - max} bytes from middle]\u2026
|
|
129
|
+
` + s.slice(-half);
|
|
130
|
+
}
|
|
131
|
+
function isBinaryBuffer(buf) {
|
|
132
|
+
const len = Math.min(buf.length, 8192);
|
|
133
|
+
for (let i = 0; i < len; i++) {
|
|
134
|
+
if (buf[i] === 0) return true;
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
var COMMAND_OUTPUT_MAX_BYTES = 32768;
|
|
139
|
+
var REPEAT_RUN_THRESHOLD = 3;
|
|
140
|
+
function collapseCarriageReturns(text) {
|
|
141
|
+
const lf = text.replace(/\r\n/g, "\n");
|
|
142
|
+
if (!lf.includes("\r")) return lf;
|
|
143
|
+
return lf.split("\n").map((line) => line.includes("\r") ? line.slice(line.lastIndexOf("\r") + 1) : line).join("\n");
|
|
144
|
+
}
|
|
145
|
+
function collapseConsecutiveDuplicates(text, minRun = REPEAT_RUN_THRESHOLD) {
|
|
146
|
+
const lines = text.split("\n");
|
|
147
|
+
const out = [];
|
|
148
|
+
let i = 0;
|
|
149
|
+
while (i < lines.length) {
|
|
150
|
+
let j = i + 1;
|
|
151
|
+
while (j < lines.length && lines[j] === lines[i]) j++;
|
|
152
|
+
const run = j - i;
|
|
153
|
+
if (run >= minRun) {
|
|
154
|
+
out.push(lines[i], `\u2026 \u27E8repeated ${run}\xD7\u27E9`);
|
|
155
|
+
} else {
|
|
156
|
+
for (let k = i; k < j; k++) out.push(lines[k]);
|
|
157
|
+
}
|
|
158
|
+
i = j;
|
|
159
|
+
}
|
|
160
|
+
return out.join("\n");
|
|
161
|
+
}
|
|
162
|
+
function takeHeadBytes(s, maxBytes) {
|
|
163
|
+
if (maxBytes <= 0) return "";
|
|
164
|
+
if (Buffer.byteLength(s, "utf8") <= maxBytes) return s;
|
|
165
|
+
let lo = 0;
|
|
166
|
+
let hi = s.length;
|
|
167
|
+
while (lo < hi) {
|
|
168
|
+
const mid = Math.ceil((lo + hi) / 2);
|
|
169
|
+
if (Buffer.byteLength(s.slice(0, mid), "utf8") <= maxBytes) lo = mid;
|
|
170
|
+
else hi = mid - 1;
|
|
171
|
+
}
|
|
172
|
+
return s.slice(0, lo);
|
|
173
|
+
}
|
|
174
|
+
function takeTailBytes(s, maxBytes) {
|
|
175
|
+
if (maxBytes <= 0) return "";
|
|
176
|
+
if (Buffer.byteLength(s, "utf8") <= maxBytes) return s;
|
|
177
|
+
let lo = 0;
|
|
178
|
+
let hi = s.length;
|
|
179
|
+
while (lo < hi) {
|
|
180
|
+
const mid = Math.ceil((lo + hi) / 2);
|
|
181
|
+
if (Buffer.byteLength(s.slice(s.length - mid), "utf8") <= maxBytes) lo = mid;
|
|
182
|
+
else hi = mid - 1;
|
|
183
|
+
}
|
|
184
|
+
return s.slice(s.length - lo);
|
|
185
|
+
}
|
|
186
|
+
function truncateHeadTail(s, maxBytes) {
|
|
187
|
+
const total = Buffer.byteLength(s, "utf8");
|
|
188
|
+
if (total <= maxBytes) return s;
|
|
189
|
+
const MARKER_RESERVE = 64;
|
|
190
|
+
const avail = Math.max(0, maxBytes - MARKER_RESERVE);
|
|
191
|
+
const headBudget = Math.floor(avail * 0.45);
|
|
192
|
+
const head = takeHeadBytes(s, headBudget);
|
|
193
|
+
const tail = takeTailBytes(s, avail - Buffer.byteLength(head, "utf8"));
|
|
194
|
+
const kept = Buffer.byteLength(head, "utf8") + Buffer.byteLength(tail, "utf8");
|
|
195
|
+
return `${head}
|
|
196
|
+
\u2026[truncated ${total - kept} bytes]\u2026
|
|
197
|
+
${tail}`;
|
|
198
|
+
}
|
|
199
|
+
function normalizeCommandOutput(raw, opts = {}) {
|
|
200
|
+
if (!raw) return raw;
|
|
201
|
+
let text = Core.stripAnsi(raw);
|
|
202
|
+
text = collapseCarriageReturns(text);
|
|
203
|
+
text = text.replace(/[ \t]+$/gm, "");
|
|
204
|
+
text = collapseConsecutiveDuplicates(text);
|
|
205
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
206
|
+
return truncateHeadTail(text, opts.maxBytes ?? COMMAND_OUTPUT_MAX_BYTES);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export {
|
|
210
|
+
sha256hex,
|
|
211
|
+
detectPackageManager,
|
|
212
|
+
ensureInsideRoot,
|
|
213
|
+
assertRealInsideRoot,
|
|
214
|
+
resolveRealInsideRoot,
|
|
215
|
+
safeResolveReal,
|
|
216
|
+
truncateDiffPayload,
|
|
217
|
+
truncateMiddle,
|
|
218
|
+
isBinaryBuffer,
|
|
219
|
+
COMMAND_OUTPUT_MAX_BYTES,
|
|
220
|
+
normalizeCommandOutput
|
|
221
|
+
};
|
|
222
|
+
//# sourceMappingURL=chunk-D33S4RQG.js.map
|