@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
package/dist/json.js CHANGED
@@ -1,669 +1,8 @@
1
- // src/json.ts
2
- import * as fs from "node:fs/promises";
3
- import { deepMerge as deepMergeCore } from "@wrongstack/core/utils";
4
-
5
- // src/_regex.ts
6
1
  import {
7
- capSubject,
8
- compileUserRegex,
9
- MAX_SUBJECT_LEN
10
- } from "@wrongstack/primitives";
11
-
12
- // src/_util.ts
13
- import * as fsp from "node:fs/promises";
14
- import * as path from "node:path";
15
- import * as Core from "@wrongstack/core/utils";
16
- function resolvePath(input, ctx) {
17
- return path.isAbsolute(input) ? path.normalize(input) : path.resolve(ctx.workingDir ?? ctx.cwd, input);
18
- }
19
- function allowedRoots(ctx) {
20
- return [path.resolve(ctx.projectRoot), path.resolve(Core.wstackGlobalRoot())];
21
- }
22
- function isInsideAny(target, roots) {
23
- return roots.some((root) => {
24
- const rel = path.relative(root, target);
25
- return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
26
- });
27
- }
28
- function ensureInsideRoot(absPath, ctx) {
29
- const target = path.resolve(absPath);
30
- if (ctx.allowOutsideProjectRoot) return target;
31
- if (isInsideAny(target, allowedRoots(ctx))) return target;
32
- throw new Error(`Path "${absPath}" is outside project root "${path.resolve(ctx.projectRoot)}"`);
33
- }
34
- function safeResolve(input, ctx) {
35
- return ensureInsideRoot(resolvePath(input, ctx), ctx);
36
- }
37
- async function resolveRealInsideRoot(absPath, ctx) {
38
- if (ctx.allowOutsideProjectRoot) return absPath;
39
- const realRoots = await Promise.all(
40
- allowedRoots(ctx).map((r) => fsp.realpath(r).catch(() => path.resolve(r)))
41
- );
42
- let probe = absPath;
43
- const pendingTail = [];
44
- for (; ; ) {
45
- let real;
46
- try {
47
- real = await fsp.realpath(probe);
48
- } catch (err) {
49
- if (err.code === "ENOENT") {
50
- const parent = path.dirname(probe);
51
- if (parent === probe) return absPath;
52
- pendingTail.unshift(path.basename(probe));
53
- probe = parent;
54
- continue;
55
- }
56
- throw err;
57
- }
58
- const candidate = pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
59
- if (isInsideAny(candidate, realRoots)) {
60
- return candidate;
61
- }
62
- throw new Error(
63
- `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
64
- );
65
- }
66
- }
67
- async function safeResolveReal(input, ctx) {
68
- const abs = safeResolve(input, ctx);
69
- return await resolveRealInsideRoot(abs, ctx);
70
- }
71
-
72
- // src/json.ts
73
- var MAX_JSON_FILE_BYTES = 16 * 1024 * 1024;
74
- var MAX_JSON_FILE_BYTES_HUMAN = "16 MiB";
75
- var JsonFileTooLargeError = class extends Error {
76
- constructor(filePath, size) {
77
- super(
78
- `json: "${filePath}" is ${size} bytes \u2014 exceeds the ${MAX_JSON_FILE_BYTES_HUMAN} file-size limit. Extract the relevant portion into a smaller file first, or use a shell tool to query it directly.`
79
- );
80
- this.name = "JsonFileTooLargeError";
81
- }
82
- };
83
- async function readJsonFileBounded(filePath, ctx) {
84
- const resolved = await safeResolveReal(filePath, ctx);
85
- const stat2 = await fs.stat(resolved);
86
- if (stat2.size > MAX_JSON_FILE_BYTES) {
87
- throw new JsonFileTooLargeError(filePath, stat2.size);
88
- }
89
- return fs.readFile(resolved, "utf8");
90
- }
91
- var jsonTool = {
92
- name: "json",
93
- category: "Data",
94
- description: "Parse, pretty-print, query, validate, transform, and merge JSON/JSON5/YAML. Use `action` to select the operation: parse (default), query, validate, transform, or merge.",
95
- usageHint: 'VERY USEFUL FOR DATA INSPECTION:\n\n- `action: "parse"` (default): read/pretty-print/convert JSON, JSON5, or YAML from `file` or `data`.\n- `action: "query"`: JMESPath-like query (`a.b[0].c`, `items[*].name`, filters, functions).\n- `action: "validate"`: validate data against a JSON Schema (`schema` param).\n- `action: "transform"`: chain multiple JMESPath transforms (`transforms` param).\n- `action: "merge"`: deep merge `base` and `patch` objects (`conflictResolution` param).\nPrefer this over raw `read` + manual parsing when dealing with configuration or data files.',
96
- permission: "auto",
97
- mutating: false,
98
- maxOutputBytes: 262144,
99
- timeoutMs: 5e3,
100
- capabilities: ["fs.read"],
101
- icon: "json",
102
- inputSchema: {
103
- type: "object",
104
- properties: {
105
- action: {
106
- type: "string",
107
- enum: ["parse", "query", "validate", "transform", "merge"],
108
- description: "Operation (default: parse). parse=read/pretty-print, query=JMESPath, validate=schema, transform=chained queries, merge=deep merge."
109
- },
110
- file: { type: "string", description: "Path to JSON/JSON5/YAML file (parse/query/validate)" },
111
- data: {
112
- type: "string",
113
- description: "JSON/JSON5/YAML string (parse/query/validate, alternative to file)"
114
- },
115
- format: {
116
- type: "string",
117
- enum: ["json", "json5", "yaml"],
118
- description: "Output format for parse/query/transform (default: json)"
119
- },
120
- query: {
121
- type: "string",
122
- description: "JMESPath-like query expression (query action)"
123
- },
124
- transforms: {
125
- type: "array",
126
- items: { type: "string" },
127
- description: "Ordered JMESPath query strings (transform action)"
128
- },
129
- schema: {
130
- type: "object",
131
- description: "JSON Schema to validate against (validate action)"
132
- },
133
- base: { description: "Base JSON object (merge action)" },
134
- patch: { description: "Patch JSON object to merge in (merge action)" },
135
- conflictResolution: {
136
- type: "string",
137
- enum: ["prefer-base", "prefer-patch"],
138
- description: "Merge conflict resolution (default: prefer-patch)"
139
- },
140
- validate: {
141
- type: "boolean",
142
- description: "Validate syntax only, no output (parse action, default: false)"
143
- }
144
- }
145
- },
146
- async execute(input, ctx) {
147
- const action = input.action ?? "parse";
148
- switch (action) {
149
- case "query":
150
- return executeQuery(input, ctx);
151
- case "validate":
152
- return executeValidate(input, ctx);
153
- case "transform":
154
- return executeTransform(input, ctx);
155
- case "merge":
156
- return executeMerge(input);
157
- default:
158
- return executeParse(input, ctx);
159
- }
160
- }
161
- };
162
- async function executeParse(input, ctx) {
163
- const format = input.format ?? "json";
164
- let parsed;
165
- let raw;
166
- if (input.file) {
167
- try {
168
- raw = await readJsonFileBounded(input.file, ctx);
169
- } catch (error) {
170
- return {
171
- data: null,
172
- formatted: "",
173
- type: "unknown",
174
- action: "parse",
175
- error: error instanceof JsonFileTooLargeError ? error.message : "Could not read file"
176
- };
177
- }
178
- } else if (input.data) {
179
- raw = input.data;
180
- } else {
181
- return {
182
- data: null,
183
- formatted: "",
184
- type: "unknown",
185
- action: "parse",
186
- error: "Provide file or data"
187
- };
188
- }
189
- try {
190
- parsed = JSON.parse(raw);
191
- } catch (e) {
192
- return {
193
- data: null,
194
- formatted: "",
195
- type: "unknown",
196
- action: "parse",
197
- /* v8 ignore next -- JSON.parse only throws SyntaxError (an Error); the String(e) side is defensive. */
198
- error: `Parse failed: ${e instanceof Error ? e.message : String(e)}`
199
- };
200
- }
201
- if (input.validate) {
202
- return {
203
- data: parsed,
204
- formatted: "valid",
205
- type: Array.isArray(parsed) ? "array" : typeof parsed,
206
- action: "parse",
207
- keys: typeof parsed === "object" && parsed !== null ? Object.keys(parsed) : void 0
208
- };
209
- }
210
- if (input.query) {
211
- const queryResult = simpleQuery(parsed, input.query);
212
- const formatted2 = formatOutput(queryResult, format);
213
- return {
214
- data: parsed,
215
- formatted: formatted2,
216
- type: Array.isArray(parsed) ? "array" : typeof parsed,
217
- action: "parse",
218
- keys: typeof parsed === "object" && parsed !== null ? Object.keys(parsed) : void 0,
219
- query_result: queryResult
220
- };
221
- }
222
- const formatted = formatOutput(parsed, format);
223
- return {
224
- data: parsed,
225
- formatted,
226
- type: Array.isArray(parsed) ? "array" : typeof parsed,
227
- action: "parse",
228
- keys: typeof parsed === "object" && parsed !== null ? Object.keys(parsed) : void 0
229
- };
230
- }
231
- async function executeQuery(input, ctx) {
232
- if (!input.query) {
233
- return {
234
- data: null,
235
- formatted: "",
236
- type: "unknown",
237
- action: "query",
238
- error: "query is required for action: query"
239
- };
240
- }
241
- let parsed;
242
- if (input.file) {
243
- try {
244
- const raw = await readJsonFileBounded(input.file, ctx);
245
- parsed = JSON.parse(raw);
246
- } catch (error) {
247
- return {
248
- data: null,
249
- formatted: "",
250
- type: "unknown",
251
- action: "query",
252
- error: error instanceof JsonFileTooLargeError ? error.message : "Could not read/parse file"
253
- };
254
- }
255
- } else if (input.data) {
256
- try {
257
- parsed = JSON.parse(input.data);
258
- } catch {
259
- return {
260
- data: null,
261
- formatted: "",
262
- type: "unknown",
263
- action: "query",
264
- error: "Could not parse data string"
265
- };
266
- }
267
- } else {
268
- return {
269
- data: null,
270
- formatted: "",
271
- type: "unknown",
272
- action: "query",
273
- error: "Provide file or data"
274
- };
275
- }
276
- try {
277
- const result = jmespathSearch(parsed, input.query);
278
- const format = input.format ?? "json";
279
- return {
280
- data: parsed,
281
- formatted: formatOutput(result, format),
282
- type: result === null ? "null" : Array.isArray(result) ? "array" : typeof result,
283
- action: "query",
284
- query_result: result
285
- };
286
- } catch (e) {
287
- return {
288
- data: null,
289
- formatted: "",
290
- type: "unknown",
291
- action: "query",
292
- /* v8 ignore next -- defensive String(e) */
293
- error: `Query failed: ${e instanceof Error ? e.message : String(e)}`
294
- };
295
- }
296
- }
297
- async function executeValidate(input, ctx) {
298
- if (!input.schema) {
299
- return {
300
- data: null,
301
- formatted: "",
302
- type: "unknown",
303
- action: "validate",
304
- error: "schema is required for action: validate"
305
- };
306
- }
307
- let parsed;
308
- if (input.file) {
309
- try {
310
- const raw = await readJsonFileBounded(input.file, ctx);
311
- parsed = JSON.parse(raw);
312
- } catch (error) {
313
- return {
314
- data: null,
315
- formatted: "",
316
- type: "unknown",
317
- action: "validate",
318
- error: error instanceof JsonFileTooLargeError ? error.message : "Could not read/parse file"
319
- };
320
- }
321
- } else if (input.data) {
322
- try {
323
- parsed = JSON.parse(input.data);
324
- } catch {
325
- return {
326
- data: null,
327
- formatted: "",
328
- type: "unknown",
329
- action: "validate",
330
- error: "Could not parse data string"
331
- };
332
- }
333
- } else {
334
- return {
335
- data: null,
336
- formatted: "",
337
- type: "unknown",
338
- action: "validate",
339
- error: "Provide file or data"
340
- };
341
- }
342
- try {
343
- const { valid, errors } = validateJsonSchema(parsed, input.schema);
344
- return {
345
- data: parsed,
346
- formatted: valid ? "valid" : "invalid",
347
- type: Array.isArray(parsed) ? "array" : typeof parsed,
348
- action: "validate",
349
- valid,
350
- errors
351
- };
352
- } catch (e) {
353
- return {
354
- data: null,
355
- formatted: "",
356
- type: "unknown",
357
- action: "validate",
358
- /* v8 ignore next -- defensive String(e) */
359
- error: `Validation failed: ${e instanceof Error ? e.message : String(e)}`
360
- };
361
- }
362
- }
363
- async function executeTransform(input, ctx) {
364
- if (!input.transforms || input.transforms.length === 0) {
365
- return {
366
- data: null,
367
- formatted: "",
368
- type: "unknown",
369
- action: "transform",
370
- error: "transforms array is required for action: transform"
371
- };
372
- }
373
- let parsed;
374
- if (input.file) {
375
- try {
376
- const raw = await readJsonFileBounded(input.file, ctx);
377
- parsed = JSON.parse(raw);
378
- } catch (error) {
379
- return {
380
- data: null,
381
- formatted: "",
382
- type: "unknown",
383
- action: "transform",
384
- error: error instanceof JsonFileTooLargeError ? error.message : "Could not read/parse file"
385
- };
386
- }
387
- } else if (input.data) {
388
- try {
389
- parsed = JSON.parse(input.data);
390
- } catch {
391
- return {
392
- data: null,
393
- formatted: "",
394
- type: "unknown",
395
- action: "transform",
396
- error: "Could not parse data string"
397
- };
398
- }
399
- } else {
400
- return {
401
- data: null,
402
- formatted: "",
403
- type: "unknown",
404
- action: "transform",
405
- error: "Provide file or data"
406
- };
407
- }
408
- try {
409
- let current = parsed;
410
- const steps = [];
411
- for (const t of input.transforms) {
412
- current = jmespathSearch(current, t);
413
- steps.push({ transform: t, result: current });
414
- }
415
- const format = input.format ?? "json";
416
- return {
417
- data: parsed,
418
- formatted: formatOutput(current, format),
419
- type: current === null ? "null" : Array.isArray(current) ? "array" : typeof current,
420
- action: "transform",
421
- result: current,
422
- steps
423
- };
424
- } catch (e) {
425
- return {
426
- data: null,
427
- formatted: "",
428
- type: "unknown",
429
- action: "transform",
430
- /* v8 ignore next -- defensive String(e) */
431
- error: `Transform failed: ${e instanceof Error ? e.message : String(e)}`
432
- };
433
- }
434
- }
435
- async function executeMerge(input) {
436
- if (input.base === void 0 || input.patch === void 0) {
437
- return {
438
- data: null,
439
- formatted: "",
440
- type: "unknown",
441
- action: "merge",
442
- error: "base and patch are required for action: merge"
443
- };
444
- }
445
- const conflictResolution = input.conflictResolution ?? "prefer-patch";
446
- try {
447
- const result = deepMergeCore(input.base, input.patch, { conflictResolution });
448
- const format = input.format ?? "json";
449
- return {
450
- data: result,
451
- formatted: formatOutput(result, format),
452
- type: result === null ? "null" : Array.isArray(result) ? "array" : typeof result,
453
- action: "merge",
454
- result
455
- };
456
- } catch (e) {
457
- return {
458
- data: null,
459
- formatted: "",
460
- type: "unknown",
461
- action: "merge",
462
- /* v8 ignore next -- defensive String(e) */
463
- error: `Merge failed: ${e instanceof Error ? e.message : String(e)}`
464
- };
465
- }
466
- }
467
- function jmespathSearch(data, query) {
468
- if (!query || query === "@") return data;
469
- if (query === "$") return data;
470
- const dotMatch = query.match(/^([a-zA-Z_][a-zA-Z0-9_]*)(?:\.(.+))?$/);
471
- if (dotMatch) {
472
- const key = dotMatch[1];
473
- const rest = dotMatch[2];
474
- const val = data?.[key];
475
- if (rest === void 0) return val;
476
- return jmespathSearch(val, rest);
477
- }
478
- const arrMatch = query.match(/^\[(\d+)\](?:\.(.+))?$/);
479
- if (arrMatch) {
480
- const idx = Number.parseInt(arrMatch[1], 10);
481
- const rest = arrMatch[2];
482
- const arr = data;
483
- const val = arr?.[idx];
484
- if (rest === void 0) return val;
485
- return jmespathSearch(val, rest);
486
- }
487
- if (query === "[*]") {
488
- if (Array.isArray(data)) {
489
- return data;
490
- }
491
- return data;
492
- }
493
- const multiMatch = query.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\[\*\](?:\.(.+))?$/);
494
- if (multiMatch) {
495
- const key = multiMatch[1];
496
- const rest = multiMatch[2];
497
- const arr = data?.[key];
498
- if (!Array.isArray(arr)) return [];
499
- if (rest === void 0) return arr;
500
- return arr.map((item) => jmespathSearch(item, rest));
501
- }
502
- const filterMatch = query.match(
503
- /^\[\\?([a-zA-Z_][a-zA-Z0-9_]*)(==|!=|<|>|<=|>=)(`[^`]+`|'[^']*')\](?:\.(.+))?$/
504
- );
505
- if (filterMatch) {
506
- const field = filterMatch[1];
507
- const op = filterMatch[2];
508
- const rawVal = filterMatch[3];
509
- const rest = filterMatch[4];
510
- const cmpVal = JSON.parse(rawVal.slice(1, -1));
511
- const arr = data;
512
- if (!Array.isArray(arr)) return [];
513
- const filtered = arr.filter((item) => {
514
- const itemVal = item[field];
515
- switch (op) {
516
- case "==":
517
- return itemVal === cmpVal;
518
- case "!=":
519
- return itemVal !== cmpVal;
520
- case ">":
521
- return Number(itemVal) > Number(cmpVal);
522
- case "<":
523
- return Number(itemVal) < Number(cmpVal);
524
- case ">=":
525
- return Number(itemVal) >= Number(cmpVal);
526
- case "<=":
527
- return Number(itemVal) <= Number(cmpVal);
528
- /* v8 ignore next -- op is constrained to the six operators by the filter regex; default is unreachable. */
529
- default:
530
- return true;
531
- }
532
- });
533
- if (rest === void 0) return filtered;
534
- return filtered.map((item) => jmespathSearch(item, rest));
535
- }
536
- const fnMatch = query.match(/^(length|keys|values|type)\(@\)$/);
537
- if (fnMatch) {
538
- const fn = fnMatch[1];
539
- switch (fn) {
540
- case "length":
541
- if (Array.isArray(data)) return data.length;
542
- if (typeof data === "string") return data.length;
543
- if (typeof data === "object" && data !== null) return Object.keys(data).length;
544
- return 0;
545
- case "keys":
546
- if (typeof data === "object" && data !== null && !Array.isArray(data))
547
- return Object.keys(data);
548
- return [];
549
- case "values":
550
- if (typeof data === "object" && data !== null && !Array.isArray(data))
551
- return Object.values(data);
552
- return [];
553
- case "type":
554
- if (data === null) return "null";
555
- if (Array.isArray(data)) return "array";
556
- return typeof data;
557
- /* v8 ignore next 2 -- fn is constrained to the four names by the function regex; default is unreachable. */
558
- default:
559
- return null;
560
- }
561
- }
562
- return null;
563
- }
564
- function validateJsonSchema(data, schema) {
565
- const errors = [];
566
- function check(value, s, path2) {
567
- if (s["type"]) {
568
- const expectedType = s["type"];
569
- const actualType = Array.isArray(value) ? "array" : value === null ? "null" : typeof value;
570
- if (expectedType === "integer") {
571
- if (!Number.isInteger(value)) errors.push(`${path2}: expected integer, got ${actualType}`);
572
- } else if (expectedType !== actualType) {
573
- errors.push(`${path2}: expected ${expectedType}, got ${actualType}`);
574
- }
575
- }
576
- if (typeof value === "string" && s["format"] === "uri" && value) {
577
- try {
578
- new URL(value);
579
- } catch {
580
- errors.push(`${path2}: not a valid URI`);
581
- }
582
- }
583
- if (typeof value === "string" && s["pattern"]) {
584
- const compiled = compileUserRegex(s["pattern"], "");
585
- if (!compiled.ok) {
586
- errors.push(`${path2}: invalid schema pattern \u2014 ${compiled.reason}`);
587
- } else if (!compiled.regex.test(capSubject(value))) {
588
- errors.push(`${path2}: does not match pattern ${s["pattern"]}`);
589
- }
590
- }
591
- if (typeof value === "string" && s["minLength"] !== void 0 && value.length < s["minLength"]) {
592
- errors.push(`${path2}: string too short (min ${s["minLength"]})`);
593
- }
594
- if (typeof value === "string" && s["maxLength"] !== void 0 && value.length > s["maxLength"]) {
595
- errors.push(`${path2}: string too long (max ${s["maxLength"]})`);
596
- }
597
- if (typeof value === "number" && s["minimum"] !== void 0 && value < s["minimum"]) {
598
- errors.push(`${path2}: below minimum ${s["minimum"]}`);
599
- }
600
- if (typeof value === "number" && s["maximum"] !== void 0 && value > s["maximum"]) {
601
- errors.push(`${path2}: above maximum ${s["maximum"]}`);
602
- }
603
- if (Array.isArray(value) && s["items"] && Array.isArray(s["items"])) {
604
- for (let i = 0; i < value.length; i++) {
605
- check(value[i], s["items"], `${path2}[${i}]`);
606
- }
607
- }
608
- if (typeof value === "object" && value !== null && !Array.isArray(value) && s["properties"]) {
609
- const props = s["properties"];
610
- for (const [k, propSchema] of Object.entries(props)) {
611
- check(value[k], propSchema, `${path2}.${k}`);
612
- }
613
- }
614
- }
615
- check(data, schema, "$");
616
- return { valid: errors.length === 0, errors };
617
- }
618
- function simpleQuery(data, path2) {
619
- const parts = path2.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
620
- let current = data;
621
- for (const part of parts) {
622
- if (current === null || current === void 0) return void 0;
623
- const idx = Number(part);
624
- if (!Number.isNaN(idx) && Array.isArray(current)) {
625
- current = current[idx];
626
- } else if (typeof current === "object" && current !== null) {
627
- current = current[part];
628
- } else {
629
- return void 0;
630
- }
631
- }
632
- return current;
633
- }
634
- function formatOutput(data, format) {
635
- if (format === "json5") {
636
- return JSON.stringify(data, null, 2).replace(/,\s*}/g, "}").replace(/,\s*\]/g, "]");
637
- }
638
- if (format === "yaml") {
639
- return toYaml(data);
640
- }
641
- return JSON.stringify(data, null, 2);
642
- }
643
- function toYaml(data, indent = 0) {
644
- if (data === null) return "null\n";
645
- if (data === void 0) return "";
646
- if (typeof data === "boolean") return String(data) + "\n";
647
- if (typeof data === "number") return String(data) + "\n";
648
- if (typeof data === "string") {
649
- if (data.includes("\n") || data.includes(":") || data.includes("#")) {
650
- return `"${data.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"
651
- `;
652
- }
653
- return data + "\n";
654
- }
655
- if (Array.isArray(data)) {
656
- if (data.length === 0) return "[]\n";
657
- const prefix = " ".repeat(indent);
658
- return data.map((item) => `${prefix}- ${toYaml(item, indent + 1).trimStart()}`).join("");
659
- }
660
- if (typeof data === "object") {
661
- const prefix = " ".repeat(indent);
662
- const entries = Object.entries(data);
663
- return entries.map(([k, v]) => `${prefix}${k}: ${toYaml(v, indent + 1)}`).join("");
664
- }
665
- return String(data) + "\n";
666
- }
2
+ jsonTool
3
+ } from "./chunk-VB3MJGCV.js";
4
+ import "./chunk-Q5JPPCZC.js";
5
+ import "./chunk-D33S4RQG.js";
667
6
  export {
668
7
  jsonTool
669
8
  };
@@ -3,5 +3,5 @@ import type { KanbanToolInput, KanbanToolOutput } from './kanban-tool-types.js';
3
3
  * Handle a contract-map action, or return `undefined` when the action belongs
4
4
  * to another handler. Mirrors the shape of `handleKanbanDetailAction`.
5
5
  */
6
- export declare function handleKanbanContractAction(projectRoot: string, input: KanbanToolInput, actor: string | undefined): Promise<KanbanToolOutput | undefined>;
6
+ export declare function handleKanbanContractAction(projectRoot: string, input: KanbanToolInput, actor: string | undefined, sessionId: string): Promise<KanbanToolOutput | undefined>;
7
7
  //# sourceMappingURL=kanban-contract-actions.d.ts.map
@@ -1,3 +1,4 @@
1
+ import type { Context } from '@wrongstack/core/agent';
1
2
  import type { KanbanToolInput, KanbanToolOutput } from './kanban-tool-types.js';
2
- export declare function handleKanbanDetailAction(projectRoot: string, input: KanbanToolInput): Promise<KanbanToolOutput | undefined>;
3
+ export declare function handleKanbanDetailAction(projectRoot: string, input: KanbanToolInput, ctx: Context): Promise<KanbanToolOutput | undefined>;
3
4
  //# sourceMappingURL=kanban-detail-actions.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import type { KanbanToolInput, KanbanToolOutput } from './kanban-tool-types.js';
2
- export interface KanbanPresenceContext {
2
+ interface KanbanPresenceContext {
3
3
  session?: {
4
4
  id?: string | undefined;
5
5
  } | undefined;
@@ -7,4 +7,5 @@ export interface KanbanPresenceContext {
7
7
  agentName?: string | undefined;
8
8
  }
9
9
  export declare function createKanbanPresenceWrapper(projectRoot: string, input: KanbanToolInput, ctx: KanbanPresenceContext): (result: KanbanToolOutput) => Promise<KanbanToolOutput>;
10
+ export {};
10
11
  //# sourceMappingURL=kanban-presence.d.ts.map