@wrongstack/tools 0.320.1 → 1.0.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 (192) hide show
  1. package/dist/_danger-detect.d.ts +8 -0
  2. package/dist/_syntax-check.d.ts +1 -2
  3. package/dist/audit.d.ts +4 -5
  4. package/dist/audit.js +6 -6
  5. package/dist/auto-proceed-loop-guard.d.ts +1 -1
  6. package/dist/auto-proceed-loop-guard.js +9 -160
  7. package/dist/bash-kill-guard.d.ts +2 -3
  8. package/dist/bash.d.ts +2 -3
  9. package/dist/bash.js +4 -4
  10. package/dist/batch-tool-use.d.ts +2 -3
  11. package/dist/batch-tool-use.js +1 -1
  12. package/dist/browser/index.d.ts +1 -1
  13. package/dist/browser/index.js +1 -1
  14. package/dist/browser/tools.d.ts +56 -45
  15. package/dist/builtin.js +50 -50
  16. package/dist/{chunk-T77XOX7E.js → chunk-24T5XIJU.js} +1 -1
  17. package/dist/{chunk-DTQ75VBC.js → chunk-2CTZW6JQ.js} +2 -2
  18. package/dist/{chunk-KWXIKGE3.js → chunk-3D5DJWOE.js} +3 -3
  19. package/dist/{chunk-XSSFBS5I.js → chunk-4ERMPDHV.js} +11 -6
  20. package/dist/{chunk-QSNVDHOZ.js → chunk-4WPBS45A.js} +4 -5
  21. package/dist/{chunk-4CQWNZ62.js → chunk-5ITQPCLC.js} +2 -2
  22. package/dist/{chunk-B4HTSV6Z.js → chunk-5KS24LTS.js} +11 -11
  23. package/dist/{chunk-QPNYDH5B.js → chunk-62OAECEQ.js} +29 -7
  24. package/dist/{chunk-DFQDJT22.js → chunk-6GOZTS6F.js} +3 -3
  25. package/dist/{chunk-5UFVCIUB.js → chunk-6H4ERJP7.js} +140 -24
  26. package/dist/{chunk-34VLZ35Z.js → chunk-7HL23T3T.js} +63 -10
  27. package/dist/{chunk-HFXSNKCV.js → chunk-7JJFC6CT.js} +1 -1
  28. package/dist/{chunk-23EX5WDO.js → chunk-7LQCT3LT.js} +3 -3
  29. package/dist/{chunk-NDIT3SBZ.js → chunk-7N5U2RAU.js} +2 -2
  30. package/dist/{chunk-QBV725YG.js → chunk-7ODZTPCU.js} +2 -2
  31. package/dist/{chunk-6AAOT4PW.js → chunk-AQ5YBURX.js} +16 -4
  32. package/dist/{chunk-ZMW6WJFT.js → chunk-ASEXQRA7.js} +3 -3
  33. package/dist/{chunk-FRN7TIAA.js → chunk-B3MGJBFI.js} +1 -1
  34. package/dist/{chunk-JLYA4X7K.js → chunk-CGXTR34H.js} +21 -6
  35. package/dist/{chunk-IU4DV2PA.js → chunk-CHEK3ASV.js} +6 -3
  36. package/dist/{chunk-GOIZNNOA.js → chunk-DJYLI7EW.js} +1 -1
  37. package/dist/{chunk-Z6IHMJMC.js → chunk-DK4J2WMH.js} +11 -11
  38. package/dist/{chunk-OYP27E3I.js → chunk-DRRY6SCM.js} +47 -20
  39. package/dist/{chunk-JVRLTEO7.js → chunk-E7JE3UEX.js} +2 -2
  40. package/dist/{chunk-BK732J7I.js → chunk-FBUP524S.js} +4 -4
  41. package/dist/{chunk-NYRLWDT5.js → chunk-FVM3O4JQ.js} +1 -1
  42. package/dist/chunk-FYDBUVQD.js +244 -0
  43. package/dist/{chunk-PV6HIZQD.js → chunk-GDDXX27P.js} +50 -50
  44. package/dist/{chunk-3GIKYHLA.js → chunk-GKSG5CPH.js} +6 -6
  45. package/dist/{chunk-ESLPBT5A.js → chunk-HDYUBRMF.js} +4 -3
  46. package/dist/{chunk-4BABEJC2.js → chunk-IAYMTTR2.js} +236 -79
  47. package/dist/{chunk-ELRRTWNP.js → chunk-IXIS7RSG.js} +2 -2
  48. package/dist/{chunk-HR67OWEP.js → chunk-IYH4OHBP.js} +5 -5
  49. package/dist/{chunk-W232EFEM.js → chunk-JDOO4P6Z.js} +7 -4
  50. package/dist/{chunk-2OXHS3KZ.js → chunk-KLJZ4WV4.js} +4 -3
  51. package/dist/{chunk-3M7LLN7W.js → chunk-LQSOU63Z.js} +12 -11
  52. package/dist/{chunk-OTPTQBYE.js → chunk-MGPR7VG3.js} +279 -265
  53. package/dist/{chunk-C2DQKVLO.js → chunk-MJSJWXBF.js} +1 -1
  54. package/dist/{chunk-NSPNFOJ7.js → chunk-MK2JK35J.js} +25 -10
  55. package/dist/{chunk-JSNSMG5R.js → chunk-MSOAX3GC.js} +1 -1
  56. package/dist/{chunk-J43O3BOX.js → chunk-N3K2SFEI.js} +532 -492
  57. package/dist/{chunk-J74TMK4M.js → chunk-NJX2RXKJ.js} +50 -7
  58. package/dist/chunk-NL2S2CXD.js +171 -0
  59. package/dist/{chunk-WAQASTXB.js → chunk-O6BY43ZB.js} +29 -8
  60. package/dist/{chunk-QGF2C7TF.js → chunk-PVCB7RUZ.js} +2 -2
  61. package/dist/{chunk-YTKSNTT4.js → chunk-QA6IASYX.js} +8 -8
  62. package/dist/{chunk-VPALDFYM.js → chunk-RV7BVTDG.js} +1 -1
  63. package/dist/chunk-S57CDR2H.js +288 -0
  64. package/dist/{chunk-W2CECGTG.js → chunk-SMARDKAC.js} +1 -1
  65. package/dist/{chunk-QWKSKFKZ.js → chunk-SOR7OCYP.js} +1 -1
  66. package/dist/{chunk-I7FBZOEP.js → chunk-T3SMFF5Q.js} +11 -5
  67. package/dist/{chunk-4BHUSMNL.js → chunk-UI3ZJIG3.js} +1 -1
  68. package/dist/{chunk-WXJY3BKV.js → chunk-VBF2YXUW.js} +2 -2
  69. package/dist/{chunk-FQNXYA6W.js → chunk-VU3QBYL4.js} +36 -5
  70. package/dist/{chunk-VD2LV5WO.js → chunk-VZGPASGD.js} +37 -12
  71. package/dist/{chunk-UZFY3CKD.js → chunk-WEEVSWQB.js} +17 -6
  72. package/dist/chunk-XXRMF2BC.js +186 -0
  73. package/dist/{chunk-LRDIRJJL.js → chunk-YEISRT4S.js} +5 -11
  74. package/dist/{chunk-Q5JPPCZC.js → chunk-YJTXRH5Y.js} +3 -2
  75. package/dist/{chunk-Z5Q3TXRY.js → chunk-ZTCJCYLN.js} +3 -3
  76. package/dist/circuit-breaker.d.ts +1 -0
  77. package/dist/circuit-breaker.js +1 -1
  78. package/dist/clarify.d.ts +1 -0
  79. package/dist/codebase-index/codebase-ast-replace-tool.d.ts +2 -3
  80. package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +5 -4
  81. package/dist/codebase-index/codebase-incoming-calls-tool.d.ts +4 -3
  82. package/dist/codebase-index/codebase-index-tool.d.ts +2 -3
  83. package/dist/codebase-index/codebase-invariant-check-tool.d.ts +2 -3
  84. package/dist/codebase-index/codebase-outgoing-calls-tool.d.ts +4 -3
  85. package/dist/codebase-index/codebase-repo-map-tool.d.ts +2 -3
  86. package/dist/codebase-index/codebase-search-tool.d.ts +2 -3
  87. package/dist/codebase-index/codebase-skeleton-tool.d.ts +2 -3
  88. package/dist/codebase-index/codebase-stats-tool.d.ts +9 -3
  89. package/dist/codebase-index/codebase-targeted-test-tool.d.ts +4 -3
  90. package/dist/codebase-index/index.d.ts +11 -11
  91. package/dist/codebase-index/index.js +8 -8
  92. package/dist/codebase-index/project-server-framing.d.ts +29 -0
  93. package/dist/codebase-index/project-server-lifecycle.d.ts +20 -0
  94. package/dist/codebase-index/project-server-operations.d.ts +37 -0
  95. package/dist/codebase-index/project-server-types.d.ts +30 -0
  96. package/dist/codebase-index/project-server-watcher.d.ts +25 -0
  97. package/dist/codebase-index/project-server.js +448 -391
  98. package/dist/codebase-index/worker.js +2 -2
  99. package/dist/codebase-index/writer-init.d.ts +13 -0
  100. package/dist/codebase-index/writer-maintenance.d.ts +14 -0
  101. package/dist/codebase-index/writer.d.ts +0 -15
  102. package/dist/design.d.ts +2 -2
  103. package/dist/design.js +1 -1
  104. package/dist/diff.d.ts +4 -4
  105. package/dist/diff.js +1 -1
  106. package/dist/document.d.ts +3 -4
  107. package/dist/document.js +1 -1
  108. package/dist/e2e.d.ts +1 -1
  109. package/dist/e2e.js +1 -1
  110. package/dist/edit.d.ts +3 -3
  111. package/dist/edit.js +6 -6
  112. package/dist/exec.d.ts +2 -3
  113. package/dist/exec.js +4 -4
  114. package/dist/fetch.d.ts +4 -3
  115. package/dist/fetch.js +1 -1
  116. package/dist/format.d.ts +17 -45
  117. package/dist/format.js +12 -8
  118. package/dist/git.d.ts +3 -3
  119. package/dist/git.js +1 -1
  120. package/dist/glob.d.ts +2 -3
  121. package/dist/glob.js +2 -2
  122. package/dist/grep.d.ts +7 -5
  123. package/dist/grep.js +3 -3
  124. package/dist/index.d.ts +54 -45
  125. package/dist/index.js +118 -59
  126. package/dist/install.d.ts +7 -55
  127. package/dist/install.js +6 -6
  128. package/dist/json.d.ts +3 -4
  129. package/dist/json.js +2 -2
  130. package/dist/kanban-tool-types.d.ts +1 -2
  131. package/dist/kanban.d.ts +3 -19
  132. package/dist/kanban.js +1 -1
  133. package/dist/languages/execute-tool.d.ts +2 -3
  134. package/dist/languages/index.d.ts +2 -2
  135. package/dist/languages/index.js +4 -4
  136. package/dist/languages/tool.d.ts +3 -4
  137. package/dist/{legacy-bridge-FOV5ODDI.js → legacy-bridge-YXANP5QB.js} +6 -6
  138. package/dist/lint.d.ts +5 -4
  139. package/dist/lint.js +6 -6
  140. package/dist/logs.d.ts +3 -4
  141. package/dist/logs.js +2 -2
  142. package/dist/memory.d.ts +7 -8
  143. package/dist/memory.js +1 -1
  144. package/dist/mode.d.ts +3 -4
  145. package/dist/mode.js +1 -1
  146. package/dist/next-steps-tool.d.ts +2 -3
  147. package/dist/next-steps.d.ts +4 -0
  148. package/dist/next-steps.js +9 -175
  149. package/dist/outdated.d.ts +5 -29
  150. package/dist/outdated.js +3 -3
  151. package/dist/pack.js +51 -51
  152. package/dist/patch.d.ts +2 -3
  153. package/dist/patch.js +5 -5
  154. package/dist/plan.d.ts +4 -4
  155. package/dist/plan.js +3 -3
  156. package/dist/process-registry.js +2 -2
  157. package/dist/ps-slash.js +4 -4
  158. package/dist/pwsh.d.ts +1 -0
  159. package/dist/read.d.ts +5 -5
  160. package/dist/read.js +5 -5
  161. package/dist/replace.d.ts +2 -3
  162. package/dist/replace.js +6 -6
  163. package/dist/scaffold.d.ts +7 -3
  164. package/dist/scaffold.js +3 -1
  165. package/dist/search.d.ts +17 -3
  166. package/dist/search.js +5 -1
  167. package/dist/set-working-dir.d.ts +2 -3
  168. package/dist/skill.d.ts +4 -5
  169. package/dist/skill.js +1 -1
  170. package/dist/task.d.ts +6 -6
  171. package/dist/task.js +3 -3
  172. package/dist/test.d.ts +5 -4
  173. package/dist/test.js +6 -6
  174. package/dist/todo.d.ts +8 -8
  175. package/dist/todo.js +2 -2
  176. package/dist/tool-diff.js +11 -230
  177. package/dist/tool-help.d.ts +2 -3
  178. package/dist/tool-help.js +1 -1
  179. package/dist/tool-search.d.ts +2 -3
  180. package/dist/tool-search.js +1 -1
  181. package/dist/tool-summary.js +5 -281
  182. package/dist/tool-tier.js +52 -52
  183. package/dist/tool-use.d.ts +2 -3
  184. package/dist/tool-use.js +1 -1
  185. package/dist/tree.d.ts +5 -3
  186. package/dist/tree.js +5 -1
  187. package/dist/typecheck.d.ts +3 -3
  188. package/dist/typecheck.js +6 -6
  189. package/dist/write.d.ts +2 -3
  190. package/dist/write.js +6 -6
  191. package/package.json +5 -5
  192. package/dist/spawn-background.d.ts +0 -80
@@ -1,15 +1,17 @@
1
1
  import {
2
2
  tryLegacyCodeOperation
3
- } from "./chunk-I7FBZOEP.js";
3
+ } from "./chunk-T3SMFF5Q.js";
4
4
  import {
5
5
  spawnStream
6
- } from "./chunk-OYP27E3I.js";
6
+ } from "./chunk-DRRY6SCM.js";
7
7
  import {
8
+ ensureInsideRoot,
8
9
  normalizeCommandOutput,
9
10
  safeResolveReal
10
11
  } from "./chunk-ZUFHAHTE.js";
11
12
 
12
13
  // src/format.ts
14
+ import * as path from "node:path";
13
15
  import { ToolValidationError } from "@wrongstack/core/types";
14
16
  var formatTool = {
15
17
  name: "format",
@@ -43,18 +45,43 @@ var formatTool = {
43
45
  cwd: { type: "string", description: "Working directory (default: cwd)" }
44
46
  }
45
47
  },
48
+ writeTargets(input) {
49
+ if (input?.check) return [];
50
+ if (!input?.files) return [];
51
+ const rawFiles = Array.isArray(input.files) ? input.files : input.files.split(",");
52
+ return [
53
+ ...new Set(
54
+ rawFiles.filter((f) => typeof f === "string").map((f) => f.trim().replace(/\\/g, "/")).filter(Boolean)
55
+ )
56
+ ];
57
+ },
46
58
  async execute(input, ctx, opts) {
47
59
  let final;
48
60
  const executeStream = formatTool.executeStream;
49
61
  if (!executeStream) throw new Error("formatTool: stream execution unavailable");
50
- for await (const ev of executeStream(input, ctx, opts)) {
62
+ const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
63
+ for await (const ev of executeStream(input, ctx, { signal })) {
51
64
  if (ev.type === "final") final = ev.output;
52
65
  }
53
66
  if (!final) throw new Error("format: stream ended without final event");
54
67
  return final;
55
68
  },
56
69
  async *executeStream(input, ctx, opts) {
57
- const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
70
+ if (input.cwd !== void 0 && (typeof input.cwd !== "string" || !input.cwd.trim())) {
71
+ throw new ToolValidationError({
72
+ message: "format: cwd must be a non-empty string when provided.",
73
+ field: "cwd"
74
+ });
75
+ }
76
+ let cwd;
77
+ try {
78
+ cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
79
+ } catch (err) {
80
+ throw new ToolValidationError({
81
+ message: `format: ${err.message}`,
82
+ field: "cwd"
83
+ });
84
+ }
58
85
  const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
59
86
  signal.throwIfAborted();
60
87
  const VALID_FIXERS = /* @__PURE__ */ new Set(["biome", "prettier", "auto"]);
@@ -107,7 +134,21 @@ var formatTool = {
107
134
  text: `Running ${detected}\u2026`,
108
135
  data: { fixer: detected, check: !!input.check }
109
136
  };
110
- const fileList = input.files ? (Array.isArray(input.files) ? input.files : input.files.split(",")).map((f) => f.trim().replace(/\\/g, "/")).filter(Boolean) : [];
137
+ const fileList = input.files ? [
138
+ ...new Set(
139
+ (Array.isArray(input.files) ? input.files : input.files.split(",")).filter((f) => typeof f === "string").map((f) => f.trim().replace(/\\/g, "/")).filter(Boolean)
140
+ )
141
+ ] : [];
142
+ for (const f of fileList) {
143
+ try {
144
+ ensureInsideRoot(path.resolve(cwd, f), ctx);
145
+ } catch (err) {
146
+ throw new ToolValidationError({
147
+ message: `format: file "${f}" ${err.message}`,
148
+ field: "files"
149
+ });
150
+ }
151
+ }
111
152
  let args;
112
153
  if (detected === "prettier") {
113
154
  args = [input.check ? "--check" : "--write"];
@@ -198,6 +239,8 @@ async function detectFixer(cwd) {
198
239
  }
199
240
 
200
241
  export {
201
- formatTool
242
+ formatTool,
243
+ parseFormatterCounts,
244
+ detectFixer
202
245
  };
203
- //# sourceMappingURL=chunk-J74TMK4M.js.map
246
+ //# sourceMappingURL=chunk-NJX2RXKJ.js.map
@@ -0,0 +1,171 @@
1
+ // src/auto-proceed-loop-guard.ts
2
+ function normalizeForRepetition(prompt) {
3
+ return prompt.replace(/\s+/g, " ").trim().toLowerCase();
4
+ }
5
+ var GROUNDED_NO_PROGRESS_STEER = [
6
+ "NOTE: The todo board has not changed since the previous automatic continuation \u2014 this exact instruction is being repeated.",
7
+ "Before anything else, bring the board up to date so the loop stays grounded:",
8
+ "- mark work that is actually finished as completed,",
9
+ "- split the current item into smaller concrete sub-items if it needs more than one turn,",
10
+ "- remove or reword items that no longer apply.",
11
+ "Then continue the work. If you are blocked, state exactly what is blocking you instead of repeating the same turn."
12
+ ].join("\n");
13
+ function createContinuationAttemptTracker() {
14
+ const attempts = /* @__PURE__ */ new Map();
15
+ const skipped = /* @__PURE__ */ new Set();
16
+ return {
17
+ recordAttempt(todoId) {
18
+ const count = (attempts.get(todoId) ?? 0) + 1;
19
+ attempts.set(todoId, count);
20
+ return count;
21
+ },
22
+ getAttempts(todoId) {
23
+ return attempts.get(todoId) ?? 0;
24
+ },
25
+ markSkipped(todoId) {
26
+ skipped.add(todoId);
27
+ },
28
+ isSkipped(todoId) {
29
+ return skipped.has(todoId);
30
+ },
31
+ reset() {
32
+ attempts.clear();
33
+ skipped.clear();
34
+ },
35
+ snapshot() {
36
+ const result = {};
37
+ const allIds = /* @__PURE__ */ new Set([...attempts.keys(), ...skipped]);
38
+ for (const id of allIds) {
39
+ result[id] = { attempts: attempts.get(id) ?? 0, skipped: skipped.has(id) };
40
+ }
41
+ return result;
42
+ }
43
+ };
44
+ }
45
+ var ADVANCE_PREAMBLES = [
46
+ "Pivoting to the next open item \u2014 previous todo still pending after {attempts} attempt(s).",
47
+ "Shifting focus to a different task while the previous item ({label}) remains open after {attempts} attempt(s).",
48
+ "No board progress on the current item after {attempts} attempt(s). Continuing with the next todo.",
49
+ "The previous item is still unresolved after {attempts} try(ies). Moving on down the list.",
50
+ "Advancing to the next piece of work after {attempts} unproductive attempt(s) on the prior one.",
51
+ "Taking a different angle \u2014 the stalled item ({label}) stays open after {attempts} attempt(s). Pressing ahead.",
52
+ "The todo board shows no movement on the current task after {attempts} attempt(s). Switching gears.",
53
+ "No change on the board from the last {attempts} continuation(s). Proceeding to the next open item."
54
+ ];
55
+ function generateAdvancementPrompt(stalledTodo, nextTodo, attemptCount, todos) {
56
+ const idx = Math.max(0, Math.min(attemptCount - 1, ADVANCE_PREAMBLES.length - 1));
57
+ const preamble = ADVANCE_PREAMBLES[idx].replace(
58
+ /\{attempts\}/g,
59
+ () => String(attemptCount)
60
+ ).replace(/\{label\}/g, () => stalledTodo.content.slice(0, 72));
61
+ if (!nextTodo) {
62
+ return [
63
+ preamble,
64
+ "",
65
+ "No more open items remain on the todo list. What has been accomplished and what should I do next?"
66
+ ].join("\n");
67
+ }
68
+ const itemLabel = nextTodo.status === "in_progress" && nextTodo.activeForm ? nextTodo.activeForm : nextTodo.content;
69
+ const done = todos.filter((t) => t.status === "completed").length;
70
+ const total = todos.length;
71
+ const lines = [preamble, "", `Proceed with: ${itemLabel}`];
72
+ if (total > 0) {
73
+ lines.push("", `Todo board (${done}/${total} done):`);
74
+ lines.push(
75
+ ...todos.slice(0, 20).map((t) => {
76
+ const mark = t.status === "completed" ? "[x]" : t.status === "in_progress" ? "[~]" : "[ ]";
77
+ const flat = t.content.replace(/\n|\r/g, " ");
78
+ return ` ${mark} ${flat}`;
79
+ })
80
+ );
81
+ }
82
+ lines.push(
83
+ "",
84
+ "If this item is already done, mark it complete and move to the next open todo. Keep the board honest as you work."
85
+ );
86
+ return lines.join("\n");
87
+ }
88
+ function matchTodoIdFromPrompt(todos, prompt) {
89
+ if (todos.length === 0 || !prompt) return null;
90
+ const lowerPrompt = prompt.toLowerCase();
91
+ const inProgress = todos.find((t) => t.status === "in_progress");
92
+ if (inProgress) {
93
+ const label = (inProgress.activeForm ?? inProgress.content).toLowerCase();
94
+ if (label.length > 5 && lowerPrompt.includes(label)) {
95
+ return { id: inProgress.id, content: inProgress.activeForm ?? inProgress.content };
96
+ }
97
+ }
98
+ for (const t of todos) {
99
+ if (t.status === "completed") continue;
100
+ if (inProgress && t.id === inProgress.id) continue;
101
+ const label = (t.activeForm ?? t.content).toLowerCase();
102
+ if (label.length > 5 && lowerPrompt.includes(label)) {
103
+ return { id: t.id, content: t.activeForm ?? t.content };
104
+ }
105
+ }
106
+ const firstOpen = todos.find((t) => t.status !== "completed");
107
+ return firstOpen ? { id: firstOpen.id, content: firstOpen.activeForm ?? firstOpen.content } : null;
108
+ }
109
+ var MAX_ADVANCEMENT_ATTEMPTS = 9;
110
+ function createAutoProceedLoopGuard(options = {}) {
111
+ const safeIntegerOption = (value, fallback) => {
112
+ if (value === void 0) return fallback;
113
+ if (!Number.isFinite(value)) return fallback;
114
+ return Math.floor(value);
115
+ };
116
+ const repeatThreshold = Math.max(2, safeIntegerOption(options.repeatThreshold, 2));
117
+ const windowSize = Math.max(repeatThreshold, safeIntegerOption(options.windowSize, 3));
118
+ let buffer = [];
119
+ let steeredFor = null;
120
+ function record(prompt) {
121
+ const normalized = normalizeForRepetition(prompt);
122
+ buffer.push(normalized);
123
+ if (buffer.length > windowSize) {
124
+ buffer = buffer.slice(buffer.length - windowSize);
125
+ }
126
+ let runLength = 0;
127
+ for (let i = buffer.length - 1; i >= 0; i--) {
128
+ if (buffer[i] === normalized) runLength++;
129
+ else break;
130
+ }
131
+ return {
132
+ normalized,
133
+ runLength,
134
+ shouldHalt: runLength >= repeatThreshold
135
+ };
136
+ }
137
+ function recordGrounded(prompt) {
138
+ const signal = record(prompt);
139
+ if (!signal.shouldHalt) {
140
+ steeredFor = null;
141
+ return { ...signal, shouldHalt: false, action: "feed" };
142
+ }
143
+ if (steeredFor === signal.normalized) {
144
+ return { ...signal, action: "halt" };
145
+ }
146
+ steeredFor = signal.normalized;
147
+ return { ...signal, shouldHalt: false, action: "steer" };
148
+ }
149
+ function reset() {
150
+ buffer = [];
151
+ steeredFor = null;
152
+ }
153
+ function history() {
154
+ return buffer.slice();
155
+ }
156
+ function size() {
157
+ return buffer.length;
158
+ }
159
+ return { record, recordGrounded, reset, history, size };
160
+ }
161
+
162
+ export {
163
+ normalizeForRepetition,
164
+ GROUNDED_NO_PROGRESS_STEER,
165
+ createContinuationAttemptTracker,
166
+ generateAdvancementPrompt,
167
+ matchTodoIdFromPrompt,
168
+ MAX_ADVANCEMENT_ATTEMPTS,
169
+ createAutoProceedLoopGuard
170
+ };
171
+ //# sourceMappingURL=chunk-NL2S2CXD.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  tryLegacyPackageOperation
3
- } from "./chunk-I7FBZOEP.js";
3
+ } from "./chunk-T3SMFF5Q.js";
4
4
  import {
5
5
  spawnStream
6
- } from "./chunk-OYP27E3I.js";
6
+ } from "./chunk-DRRY6SCM.js";
7
7
  import {
8
8
  detectPackageManager,
9
9
  normalizeCommandOutput,
@@ -66,16 +66,37 @@ var installTool = {
66
66
  let final;
67
67
  const executeStream = installTool.executeStream;
68
68
  if (!executeStream) throw new Error("installTool: stream execution unavailable");
69
- for await (const ev of executeStream(input, ctx, opts)) {
69
+ const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
70
+ for await (const ev of executeStream(input, ctx, { signal })) {
70
71
  if (ev.type === "final") final = ev.output;
71
72
  }
72
73
  if (!final) throw new Error("install: stream ended without final event");
73
74
  return final;
74
75
  },
75
76
  async *executeStream(input, ctx, opts) {
76
- const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
77
+ if (input.cwd !== void 0 && (typeof input.cwd !== "string" || !input.cwd.trim())) {
78
+ throw new ToolValidationError({
79
+ message: "install: cwd must be a non-empty string when provided.",
80
+ field: "cwd"
81
+ });
82
+ }
83
+ let cwd;
84
+ try {
85
+ cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
86
+ } catch (err) {
87
+ throw new ToolValidationError({
88
+ message: `install: ${err.message}`,
89
+ field: "cwd"
90
+ });
91
+ }
77
92
  const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
78
93
  signal.throwIfAborted();
94
+ if (input.packages !== void 0 && typeof input.packages !== "string" && !Array.isArray(input.packages)) {
95
+ throw new ToolValidationError({
96
+ message: "install: packages must be a string or array of strings",
97
+ field: "packages"
98
+ });
99
+ }
79
100
  const VALID_SAVES = /* @__PURE__ */ new Set(["dependency", "dev", "optional"]);
80
101
  if (input.save !== void 0 && !VALID_SAVES.has(input.save)) {
81
102
  throw new ToolValidationError({
@@ -84,7 +105,7 @@ var installTool = {
84
105
  });
85
106
  }
86
107
  if (!input.global) {
87
- const rawList2 = input.packages ? (Array.isArray(input.packages) ? input.packages : input.packages.split(",")).map((p) => p.trim()).filter(Boolean) : [];
108
+ const rawList2 = input.packages ? (Array.isArray(input.packages) ? input.packages : input.packages.split(",")).filter((p) => typeof p === "string").map((p) => p.trim()).filter(Boolean) : [];
88
109
  const pkgList2 = Array.from(new Set(rawList2));
89
110
  const bridge = await tryLegacyPackageOperation(
90
111
  "package-install",
@@ -102,7 +123,7 @@ var installTool = {
102
123
  type: "final",
103
124
  output: {
104
125
  exit_code: run?.exitCode ?? 0,
105
- packages: [],
126
+ packages: pkgList2,
106
127
  output: normalizeCommandOutput(
107
128
  run?.output || outcome.manifestsChanged.join(", ") || "ok"
108
129
  ),
@@ -117,7 +138,7 @@ var installTool = {
117
138
  yield { type: "log", text: `Resolving with ${pkgManager}\u2026`, data: { phase: "resolve" } };
118
139
  const globalFlag = input.global ? ["-g"] : [];
119
140
  const ignoreScripts = input.lifecycleScripts !== true;
120
- const rawList = input.packages ? (Array.isArray(input.packages) ? input.packages : input.packages.split(",")).map((p) => p.trim()).filter(Boolean) : [];
141
+ const rawList = input.packages ? (Array.isArray(input.packages) ? input.packages : input.packages.split(",")).filter((p) => typeof p === "string").map((p) => p.trim()).filter(Boolean) : [];
121
142
  const pkgList = Array.from(new Set(rawList));
122
143
  const PKG_NAME_RE = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+(?:@[a-z0-9^~><=*.+-]+)?$/i;
123
144
  for (const pkg of pkgList) {
@@ -232,4 +253,4 @@ function resolveManifestPath(cwd, pkgManager) {
232
253
  export {
233
254
  installTool
234
255
  };
235
- //# sourceMappingURL=chunk-WAQASTXB.js.map
256
+ //# sourceMappingURL=chunk-O6BY43ZB.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getProcessRegistry
3
- } from "./chunk-ESLPBT5A.js";
3
+ } from "./chunk-HDYUBRMF.js";
4
4
 
5
5
  // src/process-registry-persistent.ts
6
6
  import * as fs from "node:fs/promises";
@@ -519,4 +519,4 @@ export {
519
519
  getPersistentProcessRegistry,
520
520
  resetPersistentProcessRegistry
521
521
  };
522
- //# sourceMappingURL=chunk-QGF2C7TF.js.map
522
+ //# sourceMappingURL=chunk-PVCB7RUZ.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  tryLegacyCodeOperation
3
- } from "./chunk-I7FBZOEP.js";
3
+ } from "./chunk-T3SMFF5Q.js";
4
4
  import {
5
5
  spawnStream
6
- } from "./chunk-OYP27E3I.js";
6
+ } from "./chunk-DRRY6SCM.js";
7
7
  import {
8
8
  normalizeCommandOutput,
9
9
  safeResolveReal
@@ -166,7 +166,7 @@ function buildArgs(runner, input) {
166
166
  if (input.verbose) args.push("--verbose");
167
167
  if (input.watch) args.push("--watch");
168
168
  if (input.coverage) args.push("--coverage");
169
- if (input.grep) args.push("--testPathPattern", input.grep);
169
+ if (input.grep) args.push("--testNamePattern", input.grep);
170
170
  args.push("--testTimeout", String(timeout));
171
171
  break;
172
172
  case "mocha":
@@ -195,12 +195,12 @@ function parseResult(runner, result, duration) {
195
195
  if (failedMatch?.[1]) failed = Number.parseInt(failedMatch[1], 10);
196
196
  tests_run = passed + failed;
197
197
  } else if (runner === "jest") {
198
- const suitesMatch = out.match(/Test Suites:\s+(\d+)\s+total/);
199
- const passedMatch = out.match(/Tests:\s+(\d+)\s+passed/);
200
- const failedMatch = out.match(/Tests:\s+(\d+)\s+failed/);
201
- tests_run = Number.parseInt(suitesMatch?.[1] ?? "0", 10);
198
+ const totalMatch = out.match(/Tests:\s+(?:.*,\s+)?(\d+)\s+total/);
199
+ const passedMatch = out.match(/Tests:\s+.*?(\d+)\s+passed/);
200
+ const failedMatch = out.match(/Tests:\s+.*?(\d+)\s+failed/);
202
201
  passed = Number.parseInt(passedMatch?.[1] ?? "0", 10);
203
202
  failed = Number.parseInt(failedMatch?.[1] ?? "0", 10);
203
+ tests_run = totalMatch?.[1] ? Number.parseInt(totalMatch[1], 10) : passed + failed;
204
204
  } else if (runner === "mocha") {
205
205
  const passedMatch = out.match(/(\d+)\s+passing/);
206
206
  const failedMatch = out.match(/(\d+)\s+failing/);
@@ -231,4 +231,4 @@ ${result.stderr}` : result.stdout || result.stderr || result.error || "";
231
231
  export {
232
232
  testTool
233
233
  };
234
- //# sourceMappingURL=chunk-YTKSNTT4.js.map
234
+ //# sourceMappingURL=chunk-QA6IASYX.js.map
@@ -422,4 +422,4 @@ export {
422
422
  discoverE2EProjects,
423
423
  e2ePlanTool
424
424
  };
425
- //# sourceMappingURL=chunk-VPALDFYM.js.map
425
+ //# sourceMappingURL=chunk-RV7BVTDG.js.map