@wrongstack/tools 1.0.7 → 1.0.9

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 (135) hide show
  1. package/dist/_win32-resolve.d.ts +5 -0
  2. package/dist/audit.js +5 -5
  3. package/dist/bash.js +2 -2
  4. package/dist/browser/index.js +1 -1
  5. package/dist/builtin.js +41 -41
  6. package/dist/{chunk-N3OTTQNC.js → chunk-2OCAAFAT.js} +44 -25
  7. package/dist/{chunk-5MP76C72.js → chunk-2UVAIS5O.js} +24 -29
  8. package/dist/{chunk-SIIOHBNY.js → chunk-3RRK33YM.js} +2 -2
  9. package/dist/{chunk-M2W36JT7.js → chunk-4CE3RKEP.js} +6 -3
  10. package/dist/{chunk-QJARSK2G.js → chunk-4SUGLJLO.js} +11 -3
  11. package/dist/{chunk-AH7J5HWL.js → chunk-5RBUYFRV.js} +15 -7
  12. package/dist/{chunk-WKLUOXR4.js → chunk-7GOE2ZTZ.js} +2 -2
  13. package/dist/{chunk-O6AGFJBO.js → chunk-7V33PHT6.js} +49 -77
  14. package/dist/{chunk-CAF4L6KN.js → chunk-C3WP6ZOT.js} +36 -48
  15. package/dist/{chunk-KMXPP32M.js → chunk-C6ZOXNXV.js} +13 -3
  16. package/dist/{chunk-EGT5QLCB.js → chunk-D6RQZMZS.js} +123 -255
  17. package/dist/{chunk-S6CGSFLX.js → chunk-DBG7UQGK.js} +10 -3
  18. package/dist/{chunk-2W4XTULI.js → chunk-DLZCOEVG.js} +50 -8
  19. package/dist/{chunk-NL45OWEO.js → chunk-DOAHONOS.js} +7 -12
  20. package/dist/{chunk-3LQJXJDM.js → chunk-E7A4SLKR.js} +2 -2
  21. package/dist/{chunk-JB5JLY7V.js → chunk-ENE22I5W.js} +387 -394
  22. package/dist/{chunk-SEONDNLN.js → chunk-G7CYW5EP.js} +2 -2
  23. package/dist/{chunk-YPSIG23D.js → chunk-HV7RWDCL.js} +3 -3
  24. package/dist/{chunk-TU6UVATU.js → chunk-HYHE4VNA.js} +3 -3
  25. package/dist/{chunk-HIRVCXLP.js → chunk-IE4KDAOB.js} +3 -3
  26. package/dist/{chunk-YA2ZYCJY.js → chunk-JPK2HHBK.js} +1 -1
  27. package/dist/{chunk-7E55DAFW.js → chunk-KHUCKLOR.js} +12 -7
  28. package/dist/{chunk-R3HIZVFS.js → chunk-KPDCKSN5.js} +23 -3
  29. package/dist/{chunk-B3MGJBFI.js → chunk-KS2OEZWV.js} +23 -47
  30. package/dist/{chunk-UI3ZJIG3.js → chunk-LKLIQUCW.js} +14 -8
  31. package/dist/{chunk-62OAECEQ.js → chunk-LLSFOUZF.js} +8 -8
  32. package/dist/{chunk-YZQSUL5G.js → chunk-M4ZHHCCW.js} +14 -6
  33. package/dist/{chunk-IXIS7RSG.js → chunk-MRXWOOOR.js} +29 -47
  34. package/dist/{chunk-C4DSQBTT.js → chunk-NEYUPZL6.js} +3 -3
  35. package/dist/{chunk-6XYFYLN7.js → chunk-O2MHULBO.js} +13 -8
  36. package/dist/{chunk-B62LKMWQ.js → chunk-OKZJJDOG.js} +86 -188
  37. package/dist/{chunk-JKFIDWQG.js → chunk-ON6ET5ER.js} +52 -9
  38. package/dist/{chunk-KF7GMVNU.js → chunk-OUERRFEM.js} +32 -11
  39. package/dist/{chunk-4DK5WZGR.js → chunk-OXO773CW.js} +127 -196
  40. package/dist/{chunk-GF4JHLCO.js → chunk-PWZUHZP7.js} +2 -2
  41. package/dist/{chunk-CLJXKFVS.js → chunk-QA37PFYL.js} +29 -68
  42. package/dist/{chunk-A3LNNBYO.js → chunk-QAWI3RSK.js} +41 -83
  43. package/dist/{chunk-ZMCV3XOV.js → chunk-SPNXDTCJ.js} +29 -63
  44. package/dist/{chunk-H2VB7GCR.js → chunk-ULI2J6TX.js} +27 -14
  45. package/dist/{chunk-EMA2XENR.js → chunk-UVYRQKPZ.js} +4 -3
  46. package/dist/{chunk-2NTHMZV3.js → chunk-VMJY6FYJ.js} +693 -276
  47. package/dist/{chunk-KPR53VKZ.js → chunk-WEUEU53R.js} +2 -2
  48. package/dist/{chunk-ZOUG3KKS.js → chunk-XPVYZ2S6.js} +2 -2
  49. package/dist/{chunk-5U5ULQX2.js → chunk-XZLVJD56.js} +5 -1
  50. package/dist/{chunk-HCPSVK7J.js → chunk-YKSOSI2N.js} +47 -31
  51. package/dist/codebase-index/codebase-ast-replace-tool.d.ts +5 -6
  52. package/dist/codebase-index/codebase-context-tool.d.ts +4 -6
  53. package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +1 -2
  54. package/dist/codebase-index/codebase-incoming-calls-tool.d.ts +0 -2
  55. package/dist/codebase-index/codebase-index-tool.d.ts +0 -2
  56. package/dist/codebase-index/codebase-invariant-check-tool.d.ts +1 -2
  57. package/dist/codebase-index/codebase-outgoing-calls-tool.d.ts +0 -2
  58. package/dist/codebase-index/codebase-repo-map-tool.d.ts +1 -2
  59. package/dist/codebase-index/codebase-search-tool.d.ts +1 -1
  60. package/dist/codebase-index/codebase-targeted-test-tool.d.ts +1 -2
  61. package/dist/codebase-index/index.js +8 -8
  62. package/dist/codebase-index/parser-worker-script.js +3 -3
  63. package/dist/codebase-index/project-server.js +5 -5
  64. package/dist/codebase-index/worker.js +4 -4
  65. package/dist/design.js +1 -1
  66. package/dist/diff.js +1 -1
  67. package/dist/edit.js +7 -7
  68. package/dist/exec.d.ts +7 -7
  69. package/dist/exec.js +2 -2
  70. package/dist/format.js +5 -5
  71. package/dist/git.js +1 -1
  72. package/dist/glob.js +1 -1
  73. package/dist/{go-parser-VDPRQEGM.js → go-parser-Z4H6SR3R.js} +6 -3
  74. package/dist/grep.js +1 -1
  75. package/dist/index.js +45 -45
  76. package/dist/install.js +5 -5
  77. package/dist/json.d.ts +0 -1
  78. package/dist/json.js +1 -1
  79. package/dist/kanban-presence.d.ts +6 -0
  80. package/dist/kanban-serializer.d.ts +9 -1
  81. package/dist/kanban-split-task-handler.d.ts +1 -1
  82. package/dist/kanban-tool-results.d.ts +57 -2
  83. package/dist/kanban-tool-types.d.ts +16 -5
  84. package/dist/kanban.d.ts +14 -0
  85. package/dist/kanban.js +9 -1
  86. package/dist/languages/index.js +3 -3
  87. package/dist/{legacy-bridge-4T4OTSQP.js → legacy-bridge-BPT2S2F4.js} +5 -5
  88. package/dist/lint.js +5 -5
  89. package/dist/logs.js +1 -1
  90. package/dist/mode.d.ts +3 -2
  91. package/dist/mode.js +1 -1
  92. package/dist/outdated.js +2 -2
  93. package/dist/pack.js +42 -42
  94. package/dist/{parser-dispatch-4E2SDQUO.js → parser-dispatch-WG4DNBHH.js} +4 -4
  95. package/dist/patch.js +7 -7
  96. package/dist/plan.d.ts +2 -1
  97. package/dist/plan.js +3 -3
  98. package/dist/{py-parser-MAW6DHFE.js → py-parser-4PFZYAJ7.js} +3 -3
  99. package/dist/read.js +7 -7
  100. package/dist/replace.js +7 -7
  101. package/dist/search.d.ts +0 -6
  102. package/dist/search.js +1 -1
  103. package/dist/security-ast-scan-tool.d.ts +1 -2
  104. package/dist/session-shell.js +2 -2
  105. package/dist/task.d.ts +2 -1
  106. package/dist/task.js +3 -3
  107. package/dist/test.d.ts +8 -1
  108. package/dist/test.js +5 -5
  109. package/dist/todo.js +2 -2
  110. package/dist/tool-search.d.ts +2 -0
  111. package/dist/tool-search.js +1 -1
  112. package/dist/tool-tier.js +43 -43
  113. package/dist/tool-use.d.ts +2 -2
  114. package/dist/tool-use.js +1 -1
  115. package/dist/tree.js +1 -1
  116. package/dist/typecheck.js +5 -5
  117. package/dist/wasm/bash/tree-sitter-bash.wasm +0 -0
  118. package/dist/wasm/c/tree-sitter-c.wasm +0 -0
  119. package/dist/wasm/c_sharp/tree-sitter-c_sharp.wasm +0 -0
  120. package/dist/wasm/checksums.json +16 -0
  121. package/dist/wasm/cpp/tree-sitter-cpp.wasm +0 -0
  122. package/dist/wasm/elixir/tree-sitter-elixir.wasm +0 -0
  123. package/dist/wasm/go/tree-sitter-go.wasm +0 -0
  124. package/dist/wasm/java/tree-sitter-java.wasm +0 -0
  125. package/dist/wasm/kotlin/tree-sitter-kotlin.wasm +0 -0
  126. package/dist/wasm/php/tree-sitter-php.wasm +0 -0
  127. package/dist/wasm/python/tree-sitter-python.wasm +0 -0
  128. package/dist/wasm/ruby/tree-sitter-ruby.wasm +0 -0
  129. package/dist/wasm/rust/tree-sitter-rust.wasm +0 -0
  130. package/dist/wasm/swift/tree-sitter-swift.wasm +0 -0
  131. package/dist/wasm/tree-sitter-runtime.wasm +0 -0
  132. package/dist/win32.d.ts +1 -1
  133. package/dist/win32.js +3 -1
  134. package/dist/write.js +7 -7
  135. package/package.json +10 -10
@@ -14,8 +14,9 @@ import {
14
14
  } from "./chunk-HDYUBRMF.js";
15
15
  import {
16
16
  buildWin32CmdShimInvocation,
17
+ isWinCmdShim,
17
18
  resolveWin32Command
18
- } from "./chunk-5U5ULQX2.js";
19
+ } from "./chunk-XZLVJD56.js";
19
20
  import {
20
21
  COMMAND_OUTPUT_MAX_BYTES,
21
22
  normalizeCommandOutput,
@@ -272,8 +273,10 @@ var RULES = [
272
273
  if (cmd !== "git") return false;
273
274
  const cleanIdx = args.indexOf("clean");
274
275
  if (cleanIdx < 0) return false;
275
- return args.slice(cleanIdx + 1).some(
276
- (a) => a === "-f" || a === "--force" || a.startsWith("-f") || a.startsWith("--force=")
276
+ const after = args.slice(cleanIdx + 1);
277
+ if (after.some((a) => a === "--dry-run" || /^-[a-z]*n[a-z]*$/i.test(a))) return false;
278
+ return after.some(
279
+ (a) => a === "--force" || a.startsWith("--force=") || /^-[a-z]+$/i.test(a) && a.toLowerCase().includes("f")
277
280
  );
278
281
  },
279
282
  reason: "git clean -f (deletes untracked files)"
@@ -1471,7 +1474,6 @@ function validateArgs(cmd, args) {
1471
1474
  }
1472
1475
  return null;
1473
1476
  }
1474
- var SAFE_DANGER = { level: "safe", reasons: [] };
1475
1477
  var execTool = {
1476
1478
  name: "exec",
1477
1479
  category: "Shell",
@@ -1524,43 +1526,23 @@ var execTool = {
1524
1526
  },
1525
1527
  required: ["command"]
1526
1528
  },
1529
+ // Refusals (breaker, allowlist, blocked args, kill guard, cwd containment)
1530
+ // and launch failures THROW: a returned `allowed: false` / `exitCode: 1`
1531
+ // payload was recorded by the executor as a successful call. Non-zero
1532
+ // exits, timeouts and aborts remain data (the command did run).
1527
1533
  async execute(input, ctx, opts) {
1528
1534
  const registry = getProcessRegistry();
1529
1535
  if (!registry.canProceed) {
1530
- return {
1531
- command: input.command,
1532
- args: input.args ?? [],
1533
- stdout: "",
1534
- stderr: "Circuit breaker is open \u2014 too many consecutive failures. Use /kill reset to recover.",
1535
- exitCode: 1,
1536
- truncated: false,
1537
- allowed: false,
1538
- danger: SAFE_DANGER
1539
- };
1536
+ throw new Error(
1537
+ "exec: circuit breaker is open \u2014 too many consecutive failures. Use /kill reset to recover."
1538
+ );
1540
1539
  }
1541
- const cmd = input.command.trim();
1542
- if (!cmd)
1543
- return {
1544
- command: cmd,
1545
- args: [],
1546
- stdout: "",
1547
- stderr: "Empty command",
1548
- exitCode: 1,
1549
- truncated: false,
1550
- allowed: false,
1551
- danger: SAFE_DANGER
1552
- };
1540
+ const cmd = (input.command ?? "").trim();
1541
+ if (!cmd) throw new Error("exec: empty command");
1553
1542
  if (!isExecCommandAllowed(cmd)) {
1554
- return {
1555
- command: cmd,
1556
- args: input.args ?? [],
1557
- stdout: "",
1558
- stderr: `Command "${cmd}" not in allowlist. Add it to your active profile config (~/.wrongstack/profiles/<name>/config.json) under "tools": { "exec": { "allow": ["${cmd}"] } }, or use the bash tool for one-off arbitrary commands.`,
1559
- exitCode: 1,
1560
- truncated: false,
1561
- allowed: false,
1562
- danger: SAFE_DANGER
1563
- };
1543
+ throw new Error(
1544
+ `exec: command "${cmd}" not in allowlist. Add it to your active profile config (~/.wrongstack/profiles/<name>/config.json) under "tools": { "exec": { "allow": ["${cmd}"] } }, or use the bash tool for one-off arbitrary commands.`
1545
+ );
1564
1546
  }
1565
1547
  const args = (input.args ?? []).slice(0, MAX_ARGS);
1566
1548
  const rawTimeout = typeof input.timeout === "number" && !Number.isNaN(input.timeout) ? input.timeout : DEFAULT_TIMEOUT_MS;
@@ -1568,45 +1550,22 @@ var execTool = {
1568
1550
  const danger = detectDanger(cmd, args, dangerBypass);
1569
1551
  const killCheck = await checkExecKillCommand(cmd, args);
1570
1552
  if (killCheck.blocked) {
1571
- return {
1572
- command: cmd,
1573
- args,
1574
- stdout: "",
1575
- stderr: killCheck.reason ?? "Kill command blocked: targets a protected WrongStack process.",
1576
- exitCode: 1,
1577
- truncated: false,
1578
- allowed: false,
1579
- danger
1580
- };
1553
+ throw new Error(
1554
+ `exec: ${killCheck.reason ?? "Kill command blocked: targets a protected WrongStack process."}`
1555
+ );
1581
1556
  }
1582
1557
  const argError = validateArgs(cmd, args);
1583
1558
  if (argError) {
1584
- return {
1585
- command: cmd,
1586
- args,
1587
- stdout: "",
1588
- stderr: argError,
1589
- exitCode: 1,
1590
- truncated: false,
1591
- allowed: false,
1592
- danger
1593
- };
1559
+ throw new Error(`exec: ${argError}`);
1594
1560
  }
1595
1561
  const defaultCwd = ctx.workingDir ?? ctx.cwd;
1596
1562
  let cwd;
1597
1563
  try {
1598
1564
  cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : await safeResolveReal(defaultCwd, ctx);
1599
- } catch {
1600
- return {
1601
- command: cmd,
1602
- args,
1603
- stdout: "",
1604
- stderr: `cwd "${input.cwd ?? defaultCwd}" resolves outside project root`,
1605
- exitCode: 1,
1606
- truncated: false,
1607
- allowed: false,
1608
- danger
1609
- };
1565
+ } catch (err) {
1566
+ throw new Error(`exec: cwd "${input.cwd ?? defaultCwd}" resolves outside project root`, {
1567
+ cause: err
1568
+ });
1610
1569
  }
1611
1570
  const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
1612
1571
  if (signal.aborted) {
@@ -1636,7 +1595,7 @@ var execTool = {
1636
1595
  }
1637
1596
  };
1638
1597
  function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1639
- return new Promise((resolve) => {
1598
+ return new Promise((resolve, reject) => {
1640
1599
  let stdout = "";
1641
1600
  let stderr = "";
1642
1601
  let killed = false;
@@ -1646,6 +1605,11 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1646
1605
  resolvedOnce.value = true;
1647
1606
  resolve(result);
1648
1607
  };
1608
+ const fail = (err) => {
1609
+ if (resolvedOnce.value) return;
1610
+ resolvedOnce.value = true;
1611
+ reject(err);
1612
+ };
1649
1613
  const startedAt = Date.now();
1650
1614
  let stdoutBytes = 0;
1651
1615
  let stderrBytes = 0;
@@ -1683,7 +1647,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1683
1647
  let child;
1684
1648
  try {
1685
1649
  const resolved = resolveWin32Command(cmd);
1686
- const needsShell = isWin2 && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
1650
+ const needsShell = isWin2 && isWinCmdShim(resolved);
1687
1651
  const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;
1688
1652
  const spawnCmd = shim?.command ?? resolved;
1689
1653
  const spawnArgs = shim?.args ?? args;
@@ -1707,16 +1671,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1707
1671
  startedAt: new Date(startedAt).toISOString()
1708
1672
  });
1709
1673
  emitCompletedOnce(1, void 0);
1710
- finish({
1711
- command: cmd,
1712
- args,
1713
- stdout: "",
1714
- stderr: `spawn failed: ${toErrorMessage(err)}`,
1715
- exitCode: 1,
1716
- truncated: false,
1717
- allowed: true,
1718
- danger
1719
- });
1674
+ fail(new Error(`exec: spawn failed: ${toErrorMessage(err)}`, { cause: err }));
1720
1675
  return;
1721
1676
  }
1722
1677
  emitProcessStarted({
@@ -1738,19 +1693,22 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1738
1693
  };
1739
1694
  child.on("error", (err) => {
1740
1695
  const isAbort = err && err.code === "ABORT_ERR";
1741
- const stderrText = isAbort ? `Aborted: ${err.message}` : err.message;
1742
1696
  if (timer !== void 0) clearTimeout(timer);
1743
1697
  if (isWin2) signal.removeEventListener("abort", onAbort);
1744
1698
  if (typeof pid === "number") registry.unregister(pid);
1745
1699
  registry.afterCall(Date.now() - startedAt, true);
1746
1700
  spool.finalize();
1747
1701
  emitCompletedOnce(isAbort ? 124 : 1, child.pid, isAbort ? "ABORT" : void 0);
1702
+ if (!isAbort) {
1703
+ fail(new Error(`exec: process error: ${err.message}`, { cause: err }));
1704
+ return;
1705
+ }
1748
1706
  finish({
1749
1707
  command: cmd,
1750
1708
  args,
1751
1709
  stdout: normalizeCommandOutput(stdout),
1752
- stderr: stderrText,
1753
- exitCode: isAbort ? 124 : 1,
1710
+ stderr: `Aborted: ${err.message}`,
1711
+ exitCode: 124,
1754
1712
  truncated: Buffer.byteLength(stdout, "utf8") > COMMAND_OUTPUT_MAX_BYTES,
1755
1713
  allowed: true,
1756
1714
  danger
@@ -1844,4 +1802,4 @@ export {
1844
1802
  getExecAllowlist,
1845
1803
  execTool
1846
1804
  };
1847
- //# sourceMappingURL=chunk-A3LNNBYO.js.map
1805
+ //# sourceMappingURL=chunk-QAWI3RSK.js.map
@@ -110,29 +110,18 @@ var gitTool = {
110
110
  });
111
111
  }
112
112
  if (input.command === "commit" && !input.message) {
113
- return {
114
- command: "commit",
115
- stdout: "",
116
- stderr: "git commit requires a message (-m flag)",
117
- exitCode: 1,
118
- truncated: false
119
- };
113
+ throw new ToolValidationError({
114
+ message: "git: commit requires a message",
115
+ field: "message"
116
+ });
120
117
  }
121
- const branchGuard = validateBranchInput(input);
122
- if (branchGuard) return branchGuard;
118
+ assertSafeBranch(input);
123
119
  if (input.command === "worktree") {
124
- const guard = validateWorktreeInput(input, ctx.projectRoot);
125
- if (guard) return guard;
120
+ assertSafeWorktreeInput(input, ctx.projectRoot);
126
121
  }
127
122
  const gitDir = findGitDir(ctx.cwd, ctx.projectRoot);
128
123
  if (!gitDir) {
129
- return {
130
- command: input.command,
131
- stdout: "",
132
- stderr: "Not in a git repository (within project root)",
133
- exitCode: 128,
134
- truncated: false
135
- };
124
+ throw new Error(`git: Not in a git repository (within project root ${ctx.projectRoot})`);
136
125
  }
137
126
  const args = buildArgs(input);
138
127
  const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
@@ -169,37 +158,32 @@ var gitTool = {
169
158
  return result;
170
159
  }
171
160
  };
172
- function validateBranchInput(input) {
161
+ function assertSafeBranch(input) {
173
162
  const branch = input.branch;
174
- if (branch === void 0) return null;
175
- if (!branch.startsWith("-") && !branch.includes(" --")) return null;
176
- return {
177
- command: input.command,
178
- stdout: "",
179
- stderr: `unsafe branch name (parsed as a git option): ${branch}`,
180
- exitCode: 1,
181
- truncated: false
182
- };
183
- }
184
- function validateWorktreeInput(input, projectRoot) {
185
- const reject = (stderr) => ({
186
- command: "worktree",
187
- stdout: "",
188
- stderr,
189
- exitCode: 1,
190
- truncated: false
163
+ if (branch === void 0) return;
164
+ if (!branch.startsWith("-") && !branch.includes(" --")) return;
165
+ throw new ToolValidationError({
166
+ message: `git: unsafe branch name (parsed as a git option): ${branch}`,
167
+ field: "branch"
191
168
  });
169
+ }
170
+ function assertSafeWorktreeInput(input, projectRoot) {
171
+ const reject = (message) => {
172
+ throw new ToolValidationError({ message: `git: ${message}`, field: "worktreePath" });
173
+ };
192
174
  if (input.worktreePath?.startsWith("-")) {
193
- return reject(`unsafe worktree path: ${input.worktreePath}`);
175
+ reject(`unsafe worktree path: ${input.worktreePath}`);
176
+ }
177
+ if (input.worktreeAction === "add" && !input.worktreePath) {
178
+ reject("worktree add requires worktreePath");
194
179
  }
195
180
  if ((input.worktreeAction === "add" || input.worktreeAction === "remove") && input.worktreePath) {
196
181
  const root = resolve(projectRoot);
197
182
  const abs = resolve(root, input.worktreePath);
198
183
  if (abs !== root && !abs.startsWith(root + sep)) {
199
- return reject(`unsafe worktree path (escapes project root): ${input.worktreePath}`);
184
+ reject(`unsafe worktree path (escapes project root): ${input.worktreePath}`);
200
185
  }
201
186
  }
202
- return null;
203
187
  }
204
188
  function findGitDir(cwd, projectRoot) {
205
189
  const root = projectRoot;
@@ -296,15 +280,9 @@ function buildArgs(input) {
296
280
  }
297
281
  function runGit(args, cwd, signal) {
298
282
  if (signal.aborted) {
299
- return Promise.resolve({
300
- command: args[0],
301
- stdout: "",
302
- stderr: "Aborted",
303
- exitCode: 124,
304
- truncated: false
305
- });
283
+ return Promise.reject(signal.reason ?? new Error("git: aborted"));
306
284
  }
307
- return new Promise((resolve2) => {
285
+ return new Promise((resolve2, reject) => {
308
286
  let stdout = "";
309
287
  let stderr = "";
310
288
  let stdoutBytes = 0;
@@ -333,21 +311,9 @@ function runGit(args, cwd, signal) {
333
311
  }
334
312
  });
335
313
  child.on("error", (err) => {
336
- const stdoutTail = stdoutDecoder.end();
337
- if (stdoutTail && stdout.length < MAX_OUTPUT) {
338
- stdout += stdoutTail.slice(0, MAX_OUTPUT - stdout.length);
339
- }
340
- const stderrTail = stderrDecoder.end();
341
- if (stderrTail && stderr.length < MAX_OUTPUT) {
342
- stderr += stderrTail.slice(0, MAX_OUTPUT - stderr.length);
343
- }
344
- resolve2({
345
- command: args[0],
346
- stdout: normalizeCommandOutput(stdout),
347
- stderr: err.message,
348
- exitCode: 1,
349
- truncated: stdoutBytes > MAX_OUTPUT || Buffer.byteLength(stdout, "utf8") > COMMAND_OUTPUT_MAX_BYTES
350
- });
314
+ reject(
315
+ err.code === "ABORT_ERR" ? err : new Error(`git: could not run git ${args[0] ?? ""}: ${err.message}`, { cause: err })
316
+ );
351
317
  });
352
318
  child.on("close", (code) => {
353
319
  const stdoutTail = stdoutDecoder.end();
@@ -373,4 +339,4 @@ function runGit(args, cwd, signal) {
373
339
  export {
374
340
  gitTool
375
341
  };
376
- //# sourceMappingURL=chunk-ZMCV3XOV.js.map
342
+ //# sourceMappingURL=chunk-SPNXDTCJ.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  tryLegacyPackageOperation
3
- } from "./chunk-3LQJXJDM.js";
3
+ } from "./chunk-E7A4SLKR.js";
4
4
  import {
5
5
  spawnStream
6
- } from "./chunk-EMA2XENR.js";
6
+ } from "./chunk-UVYRQKPZ.js";
7
7
  import {
8
8
  detectPackageManager,
9
9
  normalizeCommandOutput,
@@ -119,6 +119,11 @@ var installTool = {
119
119
  if (bridge?.outcome) {
120
120
  const outcome = bridge.outcome;
121
121
  const run = outcome.run;
122
+ if (outcome.status !== "passed") {
123
+ throw new Error(
124
+ `install: ${bridge.language} package install ${outcome.status}${run?.exitCode != null ? ` (exit ${run.exitCode})` : ""}${run?.error ? `: ${run.error}` : ""}${failureTail(run?.output ?? "")}`
125
+ );
126
+ }
122
127
  yield {
123
128
  type: "final",
124
129
  output: {
@@ -143,17 +148,10 @@ var installTool = {
143
148
  const PKG_NAME_RE = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+(?:@[a-z0-9^~><=*.+-]+)?$/i;
144
149
  for (const pkg of pkgList) {
145
150
  if (!PKG_NAME_RE.test(pkg) || pkg.startsWith("-") || pkg.length > 200) {
146
- yield {
147
- type: "final",
148
- output: {
149
- packages: pkgList,
150
- exit_code: 1,
151
- output: `Invalid package name "${pkg}". Names must match ${PKG_NAME_RE} and not start with "-".`,
152
- dry_run: Boolean(input.dry_run),
153
- truncated: false
154
- }
155
- };
156
- return;
151
+ throw new ToolValidationError({
152
+ message: `install: Invalid package name "${pkg}". Names must match ${PKG_NAME_RE} and not start with "-".`,
153
+ field: "packages"
154
+ });
157
155
  }
158
156
  }
159
157
  const hasPkgs = pkgList.length > 0;
@@ -196,6 +194,9 @@ var installTool = {
196
194
  signal,
197
195
  maxBytes: 1e5
198
196
  });
197
+ if (result.error) {
198
+ throw new Error(`install: could not run ${pkgManager}: ${result.error}`);
199
+ }
199
200
  const rawOutput = result.stdout && result.stderr ? `${result.stdout}
200
201
  ${result.stderr}` : result.stdout || result.stderr || result.error || "";
201
202
  const output = {
@@ -235,9 +236,21 @@ ${result.stderr}` : result.stdout || result.stderr || result.error || "";
235
236
  outcome: output.dry_run ? "dry run" : result.exitCode === 0 ? `installed ${pkgList.length || "all"} packages` : `failed (exit ${result.exitCode})`,
236
237
  risk: "package"
237
238
  });
239
+ if (result.exitCode !== 0) {
240
+ throw new Error(
241
+ `install: ${pkgManager} ${args.filter((a) => !a.startsWith("-")).join(" ")} failed (exit ${result.exitCode})${failureTail(output.output)}`
242
+ );
243
+ }
238
244
  yield { type: "final", output };
239
245
  }
240
246
  };
247
+ function failureTail(output) {
248
+ const trimmed = output.trim();
249
+ if (!trimmed) return "";
250
+ const MAX = 4e3;
251
+ return `:
252
+ ${trimmed.length > MAX ? `\u2026${trimmed.slice(-MAX)}` : trimmed}`;
253
+ }
241
254
  function resolveManifestPath(cwd, pkgManager) {
242
255
  switch (pkgManager) {
243
256
  case "pnpm":
@@ -253,4 +266,4 @@ function resolveManifestPath(cwd, pkgManager) {
253
266
  export {
254
267
  installTool
255
268
  };
256
- //# sourceMappingURL=chunk-H2VB7GCR.js.map
269
+ //# sourceMappingURL=chunk-ULI2J6TX.js.map
@@ -8,8 +8,9 @@ import {
8
8
  } from "./chunk-HDYUBRMF.js";
9
9
  import {
10
10
  buildWin32CmdShimInvocation,
11
+ isWinCmdShim,
11
12
  resolveWin32Command
12
- } from "./chunk-5U5ULQX2.js";
13
+ } from "./chunk-XZLVJD56.js";
13
14
 
14
15
  // src/_spawn-stream.ts
15
16
  import { spawn } from "node:child_process";
@@ -35,7 +36,7 @@ async function* spawnStream(opts) {
35
36
  let error;
36
37
  const spool = createOutputSpool({ tool: opts.cmd, thresholdBytes: max });
37
38
  const resolved = resolveWin32Command(opts.cmd);
38
- const needsShell = isWin && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
39
+ const needsShell = isWin && isWinCmdShim(resolved);
39
40
  const shim = needsShell ? buildWin32CmdShimInvocation(resolved, opts.args) : null;
40
41
  const cmd = shim?.command ?? resolved;
41
42
  const args = shim?.args ?? opts.args;
@@ -285,4 +286,4 @@ function utf8Prefix(text, maxBytes) {
285
286
  export {
286
287
  spawnStream
287
288
  };
288
- //# sourceMappingURL=chunk-EMA2XENR.js.map
289
+ //# sourceMappingURL=chunk-UVYRQKPZ.js.map