@wrongstack/tools 0.310.1 → 0.313.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 (135) hide show
  1. package/dist/_shell-pick.d.ts +5 -10
  2. package/dist/audit.js +10 -4055
  3. package/dist/bash.js +9 -2332
  4. package/dist/batch-tool-use.js +2 -187
  5. package/dist/browser/index.js +25 -1339
  6. package/dist/builtin.js +69 -33985
  7. package/dist/chunk-2CTB3UK5.js +197 -0
  8. package/dist/chunk-2ME7ZWDD.js +1272 -0
  9. package/dist/chunk-2TFQDEPU.js +113 -0
  10. package/dist/chunk-2ZCJNKFE.js +315 -0
  11. package/dist/chunk-3PVYQFRQ.js +472 -0
  12. package/dist/chunk-3QMQBO5Z.js +89 -0
  13. package/dist/chunk-42AKKX7O.js +385 -0
  14. package/dist/chunk-42SKEETB.js +113 -0
  15. package/dist/chunk-4BHUSMNL.js +104 -0
  16. package/dist/chunk-4I4LWFOO.js +431 -0
  17. package/dist/chunk-553IQUMO.js +478 -0
  18. package/dist/chunk-55KF77OK.js +1944 -0
  19. package/dist/chunk-6HLZK37X.js +359 -0
  20. package/dist/chunk-6RNIFLG4.js +305 -0
  21. package/dist/chunk-A6BRWIXN.js +317 -0
  22. package/dist/chunk-AHHDWNXC.js +200 -0
  23. package/dist/chunk-B2CIOKWP.js +899 -0
  24. package/dist/chunk-BTSFTGIL.js +7 -0
  25. package/dist/chunk-D33S4RQG.js +222 -0
  26. package/dist/chunk-DIJKHSUO.js +134 -0
  27. package/dist/chunk-DPL47QGS.js +3515 -0
  28. package/dist/chunk-EMRGN4KM.js +170 -0
  29. package/dist/chunk-FGOABE4Z.js +955 -0
  30. package/dist/chunk-FW65TP4G.js +520 -0
  31. package/dist/chunk-GOIZNNOA.js +221 -0
  32. package/dist/chunk-H5MJUAA6.js +295 -0
  33. package/dist/chunk-H5OHH6F4.js +223 -0
  34. package/dist/chunk-HC5RM4WY.js +199 -0
  35. package/dist/chunk-HEQFMLZ7.js +190 -0
  36. package/dist/chunk-HFXSNKCV.js +196 -0
  37. package/dist/chunk-HXSBQ2SE.js +1723 -0
  38. package/dist/chunk-ILESNGNM.js +163 -0
  39. package/dist/chunk-INF5CGAO.js +137 -0
  40. package/dist/chunk-IWDFZ6XR.js +337 -0
  41. package/dist/chunk-IXMNTNW5.js +238 -0
  42. package/dist/chunk-J4SRJKBW.js +428 -0
  43. package/dist/chunk-J5SKD6LN.js +235 -0
  44. package/dist/chunk-JRJJX3L5.js +424 -0
  45. package/dist/chunk-KXNDHMUB.js +366 -0
  46. package/dist/chunk-LIJQMYYX.js +59 -0
  47. package/dist/chunk-MAN26PZ5.js +260 -0
  48. package/dist/chunk-MKRQMLZA.js +474 -0
  49. package/dist/chunk-NBDZMMG2.js +169 -0
  50. package/dist/chunk-NHA6BEIH.js +101 -0
  51. package/dist/chunk-OA6YJIWL.js +4412 -0
  52. package/dist/chunk-OZC255IC.js +2830 -0
  53. package/dist/chunk-PUR6WU2B.js +154 -0
  54. package/dist/chunk-Q5JPPCZC.js +12 -0
  55. package/dist/chunk-QBV725YG.js +128 -0
  56. package/dist/chunk-QHVW4AAM.js +892 -0
  57. package/dist/chunk-QNJ7AQ4B.js +1000 -0
  58. package/dist/chunk-RGISBZBD.js +231 -0
  59. package/dist/chunk-RJZQWEMS.js +84 -0
  60. package/dist/chunk-RP2ZA47V.js +15 -0
  61. package/dist/chunk-RXISBFR5.js +315 -0
  62. package/dist/chunk-S5CCLZL3.js +99 -0
  63. package/dist/chunk-TVTCSBJF.js +122 -0
  64. package/dist/chunk-U4D5S3VQ.js +21 -0
  65. package/dist/chunk-U4VAATKP.js +193 -0
  66. package/dist/chunk-UKU2ZX4C.js +203 -0
  67. package/dist/chunk-UNSKG6DC.js +159 -0
  68. package/dist/chunk-URFKEIHM.js +1091 -0
  69. package/dist/chunk-UTV7YAW7.js +178 -0
  70. package/dist/chunk-V43EQ6VR.js +68 -0
  71. package/dist/chunk-VB3MJGCV.js +610 -0
  72. package/dist/chunk-WHIIIREL.js +223 -0
  73. package/dist/chunk-XMIFYKUT.js +1371 -0
  74. package/dist/chunk-YF2RSV34.js +54 -0
  75. package/dist/chunk-Z6DAKQ3U.js +1 -0
  76. package/dist/chunk-ZIGAZFWE.js +522 -0
  77. package/dist/circuit-breaker.js +3 -191
  78. package/dist/codebase-index/index.js +84 -13688
  79. package/dist/codebase-index/parser-worker-script.js +8 -3995
  80. package/dist/codebase-index/project-server.js +60 -8548
  81. package/dist/codebase-index/worker.js +20 -8416
  82. package/dist/design.js +2 -299
  83. package/dist/diff.js +4 -256
  84. package/dist/document.js +4 -222
  85. package/dist/e2e.js +5 -476
  86. package/dist/edit.js +14 -10200
  87. package/dist/exec.js +16 -3131
  88. package/dist/fetch.js +8 -398
  89. package/dist/format.js +10 -3750
  90. package/dist/generic-parser-VUXDIAOZ.js +13 -0
  91. package/dist/git.js +4 -380
  92. package/dist/glob.js +6 -280
  93. package/dist/go-parser-6CA77WZ4.js +469 -0
  94. package/dist/grep.js +7 -604
  95. package/dist/index.js +318 -35423
  96. package/dist/install.js +10 -4091
  97. package/dist/json-parser-7YMDJSBJ.js +213 -0
  98. package/dist/json.js +4 -665
  99. package/dist/kanban.js +3 -2096
  100. package/dist/languages/index.js +23 -4664
  101. package/dist/legacy-bridge-7UKZT46G.js +18 -0
  102. package/dist/lint.js +10 -3706
  103. package/dist/logs.js +4 -287
  104. package/dist/memory.js +6 -215
  105. package/dist/mode.js +3 -99
  106. package/dist/outdated.js +4 -5170
  107. package/dist/pack.js +65 -33933
  108. package/dist/parser-dispatch-VPOFDO2U.js +14 -0
  109. package/dist/patch.js +13 -9935
  110. package/dist/plan.js +5 -3286
  111. package/dist/process-registry.js +8 -651
  112. package/dist/ps-slash.js +12 -1439
  113. package/dist/py-parser-GPM5VYRG.js +16 -0
  114. package/dist/read.js +13 -9816
  115. package/dist/replace.js +15 -10014
  116. package/dist/rs-parser-WVQ4KYCX.js +81 -0
  117. package/dist/scaffold.js +4 -253
  118. package/dist/search.js +5 -585
  119. package/dist/session-kanban.js +30 -972
  120. package/dist/skill.js +2 -215
  121. package/dist/task.js +5 -3410
  122. package/dist/test.js +10 -3773
  123. package/dist/todo.js +4 -2891
  124. package/dist/tool-help.js +3 -123
  125. package/dist/tool-search.js +3 -79
  126. package/dist/tool-tier.js +68 -34020
  127. package/dist/tool-use.js +2 -93
  128. package/dist/tree-sitter-parser-YCILHGZD.js +17 -0
  129. package/dist/tree.js +4 -288
  130. package/dist/ts-parser-YH4ZMWMH.js +232 -0
  131. package/dist/typecheck.js +10 -3753
  132. package/dist/win32.js +6 -60
  133. package/dist/write.js +14 -9882
  134. package/dist/yaml-parser-GFAOKV53.js +157 -0
  135. package/package.json +5 -5
@@ -0,0 +1,385 @@
1
+ import {
2
+ parseGeneric
3
+ } from "./chunk-A6BRWIXN.js";
4
+ import {
5
+ parseParserOutput,
6
+ withSpawnGate
7
+ } from "./chunk-42SKEETB.js";
8
+ import {
9
+ resolveWin32Command
10
+ } from "./chunk-V43EQ6VR.js";
11
+
12
+ // src/codebase-index/py-parser.ts
13
+ import { spawn } from "node:child_process";
14
+ import * as fs from "node:fs/promises";
15
+ import * as os from "node:os";
16
+ import * as path from "node:path";
17
+ async function parseSymbols(opts) {
18
+ const { file, content, lang } = opts;
19
+ try {
20
+ const native = await withSpawnGate(() => syncPyParse(file, content, lang));
21
+ if (native !== null) return native;
22
+ } catch {
23
+ }
24
+ return parseGeneric({ file, content, lang: lang === "py" ? "py" : lang });
25
+ }
26
+ var PY_PARSE_SCRIPT = `import ast, json, sys, os
27
+
28
+ def get_name(node):
29
+ if isinstance(node, ast.Name):
30
+ return node.id
31
+ elif isinstance(node, ast.Attribute):
32
+ return get_name(node.value) + "." + node.attr
33
+ elif isinstance(node, ast.Subscript):
34
+ return get_name(node.value)
35
+ elif isinstance(node, ast.Call):
36
+ return get_name(node.func)
37
+ elif isinstance(node, ast.Constant):
38
+ return str(node.value)
39
+ return ""
40
+
41
+ def get_decorators(node):
42
+ decs = []
43
+ for dec in node.decorator_list:
44
+ decs.append(get_name(dec))
45
+ return decs
46
+
47
+ def get_bases(node):
48
+ bases = []
49
+ for base in node.bases:
50
+ bases.append(get_name(base))
51
+ return bases
52
+
53
+ def get_args(args):
54
+ parts = []
55
+ for arg in args.args:
56
+ parts.append(arg.arg)
57
+ return ", ".join(parts)
58
+
59
+ def get_returns(node):
60
+ if node.returns is None:
61
+ return ""
62
+ return get_name(node.returns)
63
+
64
+ class Sym:
65
+ def __init__(self, name, kind, line, col, signature, scope):
66
+ self.name = name
67
+ self.kind = kind
68
+ self.line = line
69
+ self.col = col
70
+ self.signature = signature
71
+ self.scope = scope
72
+ def to_dict(self):
73
+ return {
74
+ "name": self.name,
75
+ "kind": self.kind,
76
+ "line": self.line,
77
+ "col": self.col,
78
+ "signature": self.signature,
79
+ "scope": self.scope,
80
+ }
81
+
82
+ def is_private(name):
83
+ return name.startswith("__") and not name.endswith("__")
84
+
85
+ def leaf_name(node):
86
+ # Declared name of the callee: \`join\` of \`os.path.join\`. Matches how the
87
+ # TypeScript and Go extractors record call refs, so resolution behaves the
88
+ # same across languages.
89
+ if isinstance(node, ast.Attribute):
90
+ return node.attr
91
+ if isinstance(node, ast.Name):
92
+ return node.id
93
+ return get_name(node).split(".")[-1]
94
+
95
+ syms = []
96
+ refs = []
97
+ errors = []
98
+
99
+ try:
100
+ source = sys.stdin.read()
101
+ tree = ast.parse(source, filename=sys.argv[1])
102
+ except Exception as e:
103
+ errors.append(str(e))
104
+ print(json.dumps({"symbols": [], "refs": []}))
105
+ sys.exit(0)
106
+
107
+ # Module-level scope
108
+ module_scope = os.path.basename(sys.argv[1])[:-3] # strip .py
109
+
110
+ class ModuleVisitor(ast.NodeVisitor):
111
+ def __init__(self):
112
+ self.scope_stack = [module_scope]
113
+
114
+ def visit_ClassDef(self, node):
115
+ bases = get_bases(node)
116
+ decs = get_decorators(node)
117
+ sig = "class " + node.name
118
+ if bases:
119
+ sig += "(" + ", ".join(bases) + ")"
120
+ sig += ": ..."
121
+ syms.append(Sym(
122
+ name=node.name,
123
+ kind="class",
124
+ line=node.lineno,
125
+ col=node.col_offset,
126
+ signature=sig,
127
+ scope=".".join(self.scope_stack) + "." + node.name,
128
+ ))
129
+ self.scope_stack.append(node.name)
130
+ self.generic_visit(node)
131
+ self.scope_stack.pop()
132
+
133
+ def visit_FunctionDef(self, node):
134
+ decs = get_decorators(node)
135
+ args = get_args(node.args)
136
+ returns = get_returns(node)
137
+ is_async = isinstance(node, ast.AsyncFunctionDef)
138
+
139
+ kind = "function"
140
+ prefix = "def "
141
+ if decs:
142
+ for d in decs:
143
+ if d.endswith(".staticmethod"):
144
+ kind = "staticmethod"
145
+ elif d.endswith(".classmethod"):
146
+ kind = "classmethod"
147
+ elif d == "property":
148
+ kind = "property"
149
+
150
+ if is_async:
151
+ kind = "async_" + kind
152
+
153
+ sig = f"{prefix}{node.name}({args})"
154
+ if returns:
155
+ sig += f" -> {returns}"
156
+ scope = ".".join(self.scope_stack) + "." + node.name
157
+
158
+ syms.append(Sym(
159
+ name=node.name,
160
+ kind=kind,
161
+ line=node.lineno,
162
+ col=node.col_offset,
163
+ signature=sig,
164
+ scope=scope,
165
+ ))
166
+ # Don't descend into function bodies to avoid local symbols
167
+ # self.generic_visit(node)
168
+
169
+ def visit_AsyncFunctionDef(self, node):
170
+ # Treat as function
171
+ self.visit_FunctionDef(node)
172
+
173
+ def visit_Assign(self, node):
174
+ for target in node.targets:
175
+ if isinstance(target, ast.Name):
176
+ name = target.id
177
+ if is_private(name):
178
+ continue
179
+ # Infer constness from UPPER_CASE naming
180
+ kind = "const" if name.isupper() else "var"
181
+ col = target.col_offset if hasattr(target, 'col_offset') else 0
182
+ syms.append(Sym(
183
+ name=name,
184
+ kind=kind,
185
+ line=node.lineno,
186
+ col=col,
187
+ signature=f"{name} = ...",
188
+ scope=".".join(self.scope_stack),
189
+ ))
190
+
191
+ def visit_AnnAssign(self, node):
192
+ if isinstance(node.target, ast.Name):
193
+ name = node.target.id
194
+ if is_private(name):
195
+ return
196
+ kind = "const" if name.isupper() else "var"
197
+ col = node.target.col_offset if hasattr(node.target, 'col_offset') else 0
198
+ sig = f"{name}: {get_name(node.annotation)}"
199
+ if node.value:
200
+ sig += " = ..."
201
+ syms.append(Sym(
202
+ name=name,
203
+ kind=kind,
204
+ line=node.lineno,
205
+ col=col,
206
+ signature=sig,
207
+ scope=".".join(self.scope_stack),
208
+ ))
209
+
210
+ def visit_Import(self, node):
211
+ for alias in node.names:
212
+ name = alias.asname or alias.name
213
+ syms.append(Sym(
214
+ name=name,
215
+ kind="import",
216
+ line=node.lineno,
217
+ col=node.col_offset,
218
+ signature=f"import {alias.name}",
219
+ scope=".".join(self.scope_stack),
220
+ ))
221
+
222
+ def visit_ImportFrom(self, node):
223
+ module = node.module or ""
224
+ for alias in node.names:
225
+ name = alias.asname or alias.name
226
+ syms.append(Sym(
227
+ name=name,
228
+ kind="import",
229
+ line=node.lineno,
230
+ col=node.col_offset,
231
+ signature=f"from {module} import {alias.name}",
232
+ scope=".".join(self.scope_stack),
233
+ ))
234
+
235
+ visitor = ModuleVisitor()
236
+ visitor.visit(tree)
237
+
238
+ # Refs need a separate full walk: ModuleVisitor deliberately does not descend
239
+ # into function bodies (it would index locals as symbols), but that is exactly
240
+ # where the calls are.
241
+ for node in ast.walk(tree):
242
+ if isinstance(node, ast.Call):
243
+ name = leaf_name(node.func)
244
+ if name:
245
+ refs.append({"toName": name, "callType": "call", "line": node.lineno})
246
+ elif isinstance(node, ast.Import):
247
+ for alias in node.names:
248
+ refs.append({
249
+ "toName": alias.name.split(".")[-1],
250
+ "callType": "import",
251
+ "line": node.lineno,
252
+ "module": alias.name,
253
+ })
254
+ elif isinstance(node, ast.ImportFrom):
255
+ # PEP 328: node.level is the number of leading dots. Preserving them is
256
+ # what lets the resolver walk up from the importing file's package \u2014
257
+ # dropping them made \`from .foo import X\` indistinguishable from an
258
+ # absolute \`foo\`.
259
+ module = ("." * (node.level or 0)) + (node.module or "")
260
+ for alias in node.names:
261
+ refs.append({
262
+ "toName": alias.name,
263
+ "callType": "import",
264
+ "line": node.lineno,
265
+ "module": module,
266
+ })
267
+ elif isinstance(node, ast.ClassDef):
268
+ for base in node.bases:
269
+ name = leaf_name(base)
270
+ if name:
271
+ refs.append({"toName": name, "callType": "inherit", "line": node.lineno})
272
+
273
+ print(json.dumps({"symbols": [s.to_dict() for s in syms], "refs": refs}))
274
+ `;
275
+ async function resolvePython() {
276
+ const candidates = process.platform === "win32" ? ["python3", "python", "py"] : ["python3", "python"];
277
+ for (const name of candidates) {
278
+ const resolved = resolveWin32Command(name);
279
+ if (!await commandIsAvailable(resolved)) continue;
280
+ return resolved;
281
+ }
282
+ return null;
283
+ }
284
+ function commandIsAvailable(command) {
285
+ return new Promise((resolve) => {
286
+ let settled = false;
287
+ const proc = spawn(command, ["--version"], {
288
+ stdio: "ignore",
289
+ windowsHide: true
290
+ });
291
+ const finish = (available) => {
292
+ if (settled) return;
293
+ settled = true;
294
+ clearTimeout(timer);
295
+ resolve(available);
296
+ };
297
+ const timer = setTimeout(() => {
298
+ proc.kill("SIGKILL");
299
+ finish(false);
300
+ }, 5e3);
301
+ timer.unref?.();
302
+ proc.once("error", () => finish(false));
303
+ proc.once("close", (code) => finish(code === 0));
304
+ });
305
+ }
306
+ function spawnPyParser(pyBinary, scriptPath, filePath, content) {
307
+ return new Promise((resolve, reject) => {
308
+ let settled = false;
309
+ const proc = spawn(pyBinary, [scriptPath, filePath], {
310
+ stdio: ["pipe", "pipe", "pipe"],
311
+ windowsHide: true
312
+ });
313
+ proc.on("error", (err) => {
314
+ if (settled) return;
315
+ settled = true;
316
+ reject(err);
317
+ });
318
+ proc.stdin?.write(content);
319
+ proc.stdin?.end();
320
+ let stdout = "";
321
+ proc.stdout?.on("data", (chunk) => {
322
+ stdout += chunk.toString();
323
+ });
324
+ proc.stderr?.resume();
325
+ const timer = setTimeout(() => {
326
+ if (settled) return;
327
+ settled = true;
328
+ proc.kill("SIGKILL");
329
+ reject(new Error("timeout"));
330
+ }, 15e3);
331
+ timer.unref?.();
332
+ proc.on("close", (code) => {
333
+ if (settled) return;
334
+ settled = true;
335
+ clearTimeout(timer);
336
+ resolve({ code, stdout });
337
+ });
338
+ });
339
+ }
340
+ var _cachedScriptPath = null;
341
+ var cachedPyBinary;
342
+ function resolvePythonBinary() {
343
+ cachedPyBinary ??= resolvePython();
344
+ return cachedPyBinary;
345
+ }
346
+ async function syncPyParse(filePath, content, lang) {
347
+ try {
348
+ if (!_cachedScriptPath) {
349
+ const tmpDir = path.join(os.tmpdir(), "ws-py-parse");
350
+ await fs.mkdir(tmpDir, { recursive: true });
351
+ _cachedScriptPath = path.join(tmpDir, "parse.py");
352
+ await fs.writeFile(_cachedScriptPath, PY_PARSE_SCRIPT, "utf8");
353
+ }
354
+ cachedPyBinary ??= resolvePython();
355
+ const pyBinary = await cachedPyBinary;
356
+ if (!pyBinary) return null;
357
+ const { code, stdout } = await spawnPyParser(pyBinary, _cachedScriptPath, filePath, content);
358
+ if (code !== 0 || !stdout.trim()) {
359
+ return { file: filePath, lang, symbols: [], mtimeMs: Date.now() };
360
+ }
361
+ const { symbols: raw, refs } = parseParserOutput(stdout, lang);
362
+ const symbols = raw.map((s) => ({
363
+ id: 0,
364
+ lang,
365
+ kind: s.kind,
366
+ name: s.name,
367
+ file: filePath,
368
+ line: s.line,
369
+ col: s.col,
370
+ signature: s.signature ?? "",
371
+ docComment: "",
372
+ scope: s.scope ?? "",
373
+ text: `${s.name} ${s.signature ?? ""}`.trim()
374
+ }));
375
+ return { file: filePath, lang, symbols, refs, mtimeMs: Date.now() };
376
+ } catch {
377
+ return null;
378
+ }
379
+ }
380
+
381
+ export {
382
+ parseSymbols,
383
+ resolvePythonBinary
384
+ };
385
+ //# sourceMappingURL=chunk-42AKKX7O.js.map
@@ -0,0 +1,113 @@
1
+ // src/codebase-index/parser-output.ts
2
+ var CALL_TYPES = /* @__PURE__ */ new Set([
3
+ "call",
4
+ "type_ref",
5
+ "inherit",
6
+ "implement",
7
+ "import"
8
+ ]);
9
+ function coerceSymbols(value) {
10
+ if (!Array.isArray(value)) return [];
11
+ return value.flatMap((entry) => {
12
+ const candidate = entry;
13
+ if (typeof candidate.name !== "string" || typeof candidate.kind !== "string") return [];
14
+ return [
15
+ {
16
+ name: candidate.name,
17
+ kind: candidate.kind,
18
+ line: typeof candidate.line === "number" ? candidate.line : 1,
19
+ col: typeof candidate.col === "number" ? candidate.col : 0,
20
+ signature: typeof candidate.signature === "string" ? candidate.signature : "",
21
+ scope: typeof candidate.scope === "string" ? candidate.scope : ""
22
+ }
23
+ ];
24
+ });
25
+ }
26
+ function coerceRefs(value, lang) {
27
+ if (!Array.isArray(value)) return [];
28
+ return value.flatMap((entry) => {
29
+ const candidate = entry;
30
+ if (typeof candidate.toName !== "string" || !candidate.toName) return [];
31
+ if (typeof candidate.callType !== "string" || !CALL_TYPES.has(candidate.callType)) return [];
32
+ const module = typeof candidate.module === "string" && candidate.module ? candidate.module : void 0;
33
+ return [
34
+ {
35
+ fromId: 0,
36
+ toName: candidate.toName,
37
+ callType: candidate.callType,
38
+ line: typeof candidate.line === "number" ? candidate.line : 1,
39
+ lang,
40
+ module
41
+ }
42
+ ];
43
+ });
44
+ }
45
+ function parseParserOutput(stdout, lang) {
46
+ const trimmed = stdout.trim();
47
+ if (!trimmed) return { symbols: [], refs: [] };
48
+ let parsed;
49
+ try {
50
+ parsed = JSON.parse(trimmed);
51
+ } catch {
52
+ return { symbols: [], refs: [] };
53
+ }
54
+ if (Array.isArray(parsed)) return { symbols: coerceSymbols(parsed), refs: [] };
55
+ const record = parsed;
56
+ return {
57
+ symbols: coerceSymbols(record.symbols),
58
+ refs: dedupeRefs(coerceRefs(record.refs, lang))
59
+ };
60
+ }
61
+ function parseParserBatchOutput(stdout, lang) {
62
+ const trimmed = stdout.trim();
63
+ if (!trimmed) return [];
64
+ let parsed;
65
+ try {
66
+ parsed = JSON.parse(trimmed);
67
+ } catch {
68
+ return [];
69
+ }
70
+ if (!parsed || typeof parsed !== "object") return [];
71
+ const results = parsed.results;
72
+ if (!Array.isArray(results)) return [];
73
+ return results.flatMap((entry) => {
74
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return [];
75
+ const candidate = entry;
76
+ if (typeof candidate.file !== "string" || !candidate.file) return [];
77
+ return [
78
+ {
79
+ file: candidate.file,
80
+ error: typeof candidate.error === "string" && candidate.error ? candidate.error : void 0,
81
+ symbols: coerceSymbols(candidate.symbols),
82
+ refs: dedupeRefs(coerceRefs(candidate.refs, lang))
83
+ }
84
+ ];
85
+ });
86
+ }
87
+ function dedupeRefs(refs) {
88
+ const seen = /* @__PURE__ */ new Set();
89
+ return refs.filter((ref) => {
90
+ const key = `${ref.toName}:${ref.callType}:${ref.line}:${ref.module ?? ""}`;
91
+ if (seen.has(key)) return false;
92
+ seen.add(key);
93
+ return true;
94
+ });
95
+ }
96
+
97
+ // src/codebase-index/spawn-gate.ts
98
+ var chain = Promise.resolve();
99
+ function withSpawnGate(fn) {
100
+ const run = chain.then(fn, fn);
101
+ chain = run.then(
102
+ () => void 0,
103
+ () => void 0
104
+ );
105
+ return run;
106
+ }
107
+
108
+ export {
109
+ parseParserOutput,
110
+ parseParserBatchOutput,
111
+ withSpawnGate
112
+ };
113
+ //# sourceMappingURL=chunk-42SKEETB.js.map
@@ -0,0 +1,104 @@
1
+ // src/mode.ts
2
+ function modeFamily(mode) {
3
+ if (mode.tags?.includes("lite")) return "lite";
4
+ if (mode.tags?.includes("deep")) return "deep";
5
+ if (mode.tags?.includes("balanced") || mode.id === "default") return "balanced";
6
+ return "custom";
7
+ }
8
+ function createModeTool(modeStore) {
9
+ return {
10
+ name: "mode",
11
+ category: "Session",
12
+ description: "Manage agent operating modes. Modes change the agent's behavior, personality, and system prompt for different workflows (e.g. coding, security review, planning).",
13
+ usageHint: "POWERFUL BEHAVIOR CONTROL TOOL:\n\n- Use `list` to see available modes.\n- Use `set <modeId>` to switch the agent into a specific role/mode.\n- Use `get` to check current mode.\n- Use `clear` to return to default behavior.\nSwitching modes is very effective for specialized tasks. The mode change affects how the agent reasons and which guidelines it follows.",
14
+ permission: "confirm",
15
+ // WS-046: gives permission decisions something to key on — the mode being
16
+ // activated. Permission semantics are unchanged.
17
+ subjectKey: "mode",
18
+ mutating: true,
19
+ timeoutMs: 5e3,
20
+ capabilities: ["session.mode"],
21
+ icon: "settings",
22
+ inputSchema: {
23
+ type: "object",
24
+ properties: {
25
+ action: {
26
+ type: "string",
27
+ enum: ["get", "list", "set", "clear"],
28
+ description: "The mode operation to perform."
29
+ },
30
+ mode: {
31
+ type: "string",
32
+ description: "The mode identifier to activate (only required when action=set)."
33
+ }
34
+ },
35
+ required: ["action"]
36
+ },
37
+ async execute(input) {
38
+ switch (input.action) {
39
+ case "get": {
40
+ const mode = await modeStore.getActiveMode();
41
+ return {
42
+ action: "get",
43
+ currentMode: mode?.id,
44
+ success: true,
45
+ message: mode ? `Current mode: ${mode.name} \u2014 ${mode.description}` : "No mode set (using default)"
46
+ };
47
+ }
48
+ case "list": {
49
+ const modes = await modeStore.listModes();
50
+ const lines = modes.map((m) => ` ${m.id.padEnd(20)} [${modeFamily(m)}] ${m.name} \u2014 ${m.description}`).join("\n");
51
+ return {
52
+ action: "list",
53
+ modes: modes.map((m) => ({
54
+ id: m.id,
55
+ name: m.name,
56
+ description: m.description,
57
+ family: modeFamily(m),
58
+ tags: m.tags ?? []
59
+ })),
60
+ success: true,
61
+ message: lines
62
+ };
63
+ }
64
+ case "set": {
65
+ if (!input.mode) {
66
+ return { action: "set", success: false, message: "mode is required for action=set" };
67
+ }
68
+ const mode = await modeStore.getMode(input.mode);
69
+ if (!mode) {
70
+ return { action: "set", success: false, message: `Mode "${input.mode}" not found` };
71
+ }
72
+ await modeStore.setActiveMode(input.mode);
73
+ return {
74
+ action: "set",
75
+ currentMode: mode.id,
76
+ success: true,
77
+ message: `Switched to mode: ${mode.name}
78
+
79
+ ${mode.description}`
80
+ };
81
+ }
82
+ case "clear": {
83
+ await modeStore.setActiveMode(null);
84
+ return {
85
+ action: "clear",
86
+ success: true,
87
+ message: "Mode cleared \u2014 using default mode"
88
+ };
89
+ }
90
+ default:
91
+ return {
92
+ action: input.action,
93
+ success: false,
94
+ message: `Unknown action "${input.action}"`
95
+ };
96
+ }
97
+ }
98
+ };
99
+ }
100
+
101
+ export {
102
+ createModeTool
103
+ };
104
+ //# sourceMappingURL=chunk-4BHUSMNL.js.map