@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.
Files changed (182) hide show
  1. package/dist/_edit-match.d.ts +3 -2
  2. package/dist/_output-spool.d.ts +4 -3
  3. package/dist/_shell-pick.d.ts +2 -1
  4. package/dist/_spawn-stream.d.ts +2 -1
  5. package/dist/_syntax-check.d.ts +2 -1
  6. package/dist/audit.js +10 -4055
  7. package/dist/bash-kill-guard.d.ts +3 -6
  8. package/dist/bash.js +9 -2308
  9. package/dist/batch-tool-use.js +2 -187
  10. package/dist/browser/index.js +25 -1339
  11. package/dist/browser/network-guard-proxy.d.ts +2 -1
  12. package/dist/builtin.js +69 -33949
  13. package/dist/chunk-22B7GE5T.js +260 -0
  14. package/dist/chunk-2VSZC6QM.js +113 -0
  15. package/dist/chunk-3PVYQFRQ.js +472 -0
  16. package/dist/chunk-42BHI7TN.js +337 -0
  17. package/dist/chunk-4BHUSMNL.js +104 -0
  18. package/dist/chunk-4I4LWFOO.js +431 -0
  19. package/dist/chunk-4UESMQDP.js +122 -0
  20. package/dist/chunk-553IQUMO.js +478 -0
  21. package/dist/chunk-5H4GSJAI.js +223 -0
  22. package/dist/chunk-6RNIFLG4.js +305 -0
  23. package/dist/chunk-7EY5DCRO.js +434 -0
  24. package/dist/chunk-A6BRWIXN.js +317 -0
  25. package/dist/chunk-AHHDWNXC.js +200 -0
  26. package/dist/chunk-BSLVR56S.js +199 -0
  27. package/dist/chunk-BTSFTGIL.js +7 -0
  28. package/dist/chunk-D33S4RQG.js +222 -0
  29. package/dist/chunk-DA4KNE2H.js +4412 -0
  30. package/dist/chunk-DR7JOQTC.js +520 -0
  31. package/dist/chunk-EEOFQDT6.js +898 -0
  32. package/dist/chunk-EJWSCQ6D.js +137 -0
  33. package/dist/chunk-EMRGN4KM.js +170 -0
  34. package/dist/chunk-FQZOHLG3.js +89 -0
  35. package/dist/chunk-GOIZNNOA.js +221 -0
  36. package/dist/chunk-HFXSNKCV.js +196 -0
  37. package/dist/chunk-HYX2TZ7O.js +1272 -0
  38. package/dist/chunk-I64BS3VC.js +15 -0
  39. package/dist/chunk-IVWV2UM6.js +955 -0
  40. package/dist/chunk-IXMNTNW5.js +238 -0
  41. package/dist/chunk-IYK7XGDZ.js +892 -0
  42. package/dist/chunk-J5SKD6LN.js +235 -0
  43. package/dist/chunk-JNNVRHMV.js +2111 -0
  44. package/dist/chunk-JOHXDF3D.js +295 -0
  45. package/dist/chunk-JRJJX3L5.js +424 -0
  46. package/dist/chunk-K3WNSHUF.js +1371 -0
  47. package/dist/chunk-L25CVUVR.js +2830 -0
  48. package/dist/chunk-LIJQMYYX.js +59 -0
  49. package/dist/chunk-LWKUTMD5.js +197 -0
  50. package/dist/chunk-MQX2KXVW.js +54 -0
  51. package/dist/chunk-MZZN7VCD.js +359 -0
  52. package/dist/chunk-NBDZMMG2.js +169 -0
  53. package/dist/chunk-NKJW5GFO.js +366 -0
  54. package/dist/chunk-NKNOBUBU.js +522 -0
  55. package/dist/chunk-O4MBV4AX.js +134 -0
  56. package/dist/chunk-OUBDL3WH.js +3515 -0
  57. package/dist/chunk-PQKK5JH7.js +101 -0
  58. package/dist/chunk-PY2IOS7C.js +1000 -0
  59. package/dist/chunk-Q5JPPCZC.js +12 -0
  60. package/dist/chunk-QBV725YG.js +128 -0
  61. package/dist/chunk-QZQSPUBF.js +315 -0
  62. package/dist/chunk-RGISBZBD.js +231 -0
  63. package/dist/chunk-RJZQWEMS.js +84 -0
  64. package/dist/chunk-RXISBFR5.js +315 -0
  65. package/dist/chunk-S5CCLZL3.js +99 -0
  66. package/dist/chunk-SDLVH5RZ.js +178 -0
  67. package/dist/chunk-T2F4S7U4.js +1723 -0
  68. package/dist/chunk-TEBQ4VPZ.js +163 -0
  69. package/dist/chunk-U4D5S3VQ.js +21 -0
  70. package/dist/chunk-U4VAATKP.js +193 -0
  71. package/dist/chunk-UCYQTZ7F.js +113 -0
  72. package/dist/chunk-UKU2ZX4C.js +203 -0
  73. package/dist/chunk-UNSKG6DC.js +159 -0
  74. package/dist/chunk-V43EQ6VR.js +68 -0
  75. package/dist/chunk-VB3MJGCV.js +610 -0
  76. package/dist/chunk-VFKPWSOX.js +154 -0
  77. package/dist/chunk-VJNHFZ7J.js +190 -0
  78. package/dist/chunk-VXECAJJ7.js +1091 -0
  79. package/dist/chunk-WHIIIREL.js +223 -0
  80. package/dist/chunk-Z6DAKQ3U.js +1 -0
  81. package/dist/chunk-ZJQ4IGXK.js +474 -0
  82. package/dist/chunk-ZLTFLC25.js +385 -0
  83. package/dist/circuit-breaker.js +3 -191
  84. package/dist/codebase-index/ast-invariant-engine.d.ts +5 -4
  85. package/dist/codebase-index/binary-frame.d.ts +0 -2
  86. package/dist/codebase-index/bm25.d.ts +1 -1
  87. package/dist/codebase-index/circuit-breaker.d.ts +2 -1
  88. package/dist/codebase-index/codebase-ast-replace-tool.d.ts +3 -2
  89. package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +4 -3
  90. package/dist/codebase-index/codebase-invariant-check-tool.d.ts +3 -2
  91. package/dist/codebase-index/codebase-repo-map-tool.d.ts +3 -2
  92. package/dist/codebase-index/codebase-skeleton-tool.d.ts +3 -2
  93. package/dist/codebase-index/codebase-targeted-test-tool.d.ts +3 -2
  94. package/dist/codebase-index/content-hash.d.ts +0 -2
  95. package/dist/codebase-index/import-extractor.d.ts +0 -13
  96. package/dist/codebase-index/index-service.d.ts +1 -1
  97. package/dist/codebase-index/index.js +84 -13688
  98. package/dist/codebase-index/languages.d.ts +2 -1
  99. package/dist/codebase-index/module-roots.d.ts +3 -2
  100. package/dist/codebase-index/parser-batch.d.ts +0 -5
  101. package/dist/codebase-index/parser-dispatch.d.ts +2 -1
  102. package/dist/codebase-index/parser-output.d.ts +4 -3
  103. package/dist/codebase-index/parser-worker-pool.d.ts +0 -2
  104. package/dist/codebase-index/parser-worker-script.d.ts +1 -16
  105. package/dist/codebase-index/parser-worker-script.js +8 -3995
  106. package/dist/codebase-index/project-server-client-state.d.ts +2 -2
  107. package/dist/codebase-index/project-server-endpoint.d.ts +0 -15
  108. package/dist/codebase-index/project-server.js +60 -8548
  109. package/dist/codebase-index/tree-sitter/visitor.d.ts +2 -1
  110. package/dist/codebase-index/tree-sitter-parser.d.ts +0 -2
  111. package/dist/codebase-index/ts-parser.d.ts +1 -1
  112. package/dist/codebase-index/vector-search.d.ts +2 -1
  113. package/dist/codebase-index/wal-maintenance.d.ts +3 -2
  114. package/dist/codebase-index/worker.js +20 -8416
  115. package/dist/codebase-index/writer-admin.d.ts +0 -1
  116. package/dist/codebase-index/writer-search.d.ts +0 -9
  117. package/dist/design.js +2 -299
  118. package/dist/diff.js +4 -256
  119. package/dist/document.js +4 -222
  120. package/dist/e2e.js +5 -476
  121. package/dist/edit.js +14 -10200
  122. package/dist/exec.js +16 -3131
  123. package/dist/fetch.js +8 -398
  124. package/dist/format.js +10 -3750
  125. package/dist/generic-parser-VUXDIAOZ.js +13 -0
  126. package/dist/git.js +4 -380
  127. package/dist/glob.js +6 -280
  128. package/dist/go-parser-JXYKJHRC.js +469 -0
  129. package/dist/grep.js +7 -604
  130. package/dist/index.js +318 -35387
  131. package/dist/install.js +10 -4091
  132. package/dist/json-parser-IBHZ4BZC.js +213 -0
  133. package/dist/json.js +4 -665
  134. package/dist/kanban-contract-actions.d.ts +1 -1
  135. package/dist/kanban-detail-actions.d.ts +2 -1
  136. package/dist/kanban-presence.d.ts +2 -1
  137. package/dist/kanban-serializer.d.ts +0 -8
  138. package/dist/kanban-split-task-handler.d.ts +2 -2
  139. package/dist/kanban-tool-types.d.ts +2 -1
  140. package/dist/kanban.js +3 -2096
  141. package/dist/languages/diagnostics.d.ts +2 -1
  142. package/dist/languages/index.js +23 -4664
  143. package/dist/languages/legacy-bridge.d.ts +3 -2
  144. package/dist/languages/types.d.ts +2 -1
  145. package/dist/legacy-bridge-7M6QLUQN.js +18 -0
  146. package/dist/lint.js +10 -3706
  147. package/dist/logs.js +4 -287
  148. package/dist/memory.js +6 -215
  149. package/dist/mode.js +3 -99
  150. package/dist/outdated.js +4 -5170
  151. package/dist/pack.js +65 -33897
  152. package/dist/parser-dispatch-QH4XPGG6.js +14 -0
  153. package/dist/patch.js +13 -9935
  154. package/dist/plan.js +5 -3286
  155. package/dist/process-registry.js +8 -651
  156. package/dist/ps-slash.js +12 -1439
  157. package/dist/pwsh.d.ts +0 -1
  158. package/dist/py-parser-IS4HKYMF.js +16 -0
  159. package/dist/read.js +13 -9816
  160. package/dist/replace.js +15 -10014
  161. package/dist/rs-parser-XHUUO2KZ.js +81 -0
  162. package/dist/scaffold.js +4 -253
  163. package/dist/search.js +5 -585
  164. package/dist/session-kanban-sync.d.ts +0 -6
  165. package/dist/session-kanban.js +30 -972
  166. package/dist/skill.js +2 -215
  167. package/dist/spawn-background.d.ts +1 -1
  168. package/dist/task.js +5 -3410
  169. package/dist/test.js +10 -3773
  170. package/dist/todo.js +4 -2891
  171. package/dist/tool-help.js +3 -123
  172. package/dist/tool-search.js +3 -79
  173. package/dist/tool-tier.js +68 -33984
  174. package/dist/tool-use.js +2 -93
  175. package/dist/tree-sitter-parser-AIERW3YI.js +15 -0
  176. package/dist/tree.js +4 -288
  177. package/dist/ts-parser-RCTYKSVI.js +232 -0
  178. package/dist/typecheck.js +10 -3753
  179. package/dist/win32.js +6 -60
  180. package/dist/write.js +14 -9882
  181. package/dist/yaml-parser-4SAXV3PL.js +157 -0
  182. 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,7 @@
1
+ // src/_env.ts
2
+ import { buildChildEnv } from "@wrongstack/core/utils";
3
+
4
+ export {
5
+ buildChildEnv
6
+ };
7
+ //# sourceMappingURL=chunk-BTSFTGIL.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