@zaly/agent 0.0.3

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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -0
  3. package/dist/agent-BaD2kax9.mjs +68 -0
  4. package/dist/agent-BaD2kax9.mjs.map +1 -0
  5. package/dist/agent-GDLdDc2w.mjs +902 -0
  6. package/dist/agent-GDLdDc2w.mjs.map +1 -0
  7. package/dist/bash-QNMTQ1PD.mjs +142 -0
  8. package/dist/bash-QNMTQ1PD.mjs.map +1 -0
  9. package/dist/compactions-3AjPqjeZ.mjs +190 -0
  10. package/dist/compactions-3AjPqjeZ.mjs.map +1 -0
  11. package/dist/edit-Qxl4w1C2.mjs +170 -0
  12. package/dist/edit-Qxl4w1C2.mjs.map +1 -0
  13. package/dist/env-UUFv5Mye.mjs +30 -0
  14. package/dist/env-UUFv5Mye.mjs.map +1 -0
  15. package/dist/fetch-D8cmmA3E.mjs +111 -0
  16. package/dist/fetch-D8cmmA3E.mjs.map +1 -0
  17. package/dist/find-Bah9SKWX.mjs +87 -0
  18. package/dist/find-Bah9SKWX.mjs.map +1 -0
  19. package/dist/grep-B2Ax7ewy.mjs +244 -0
  20. package/dist/grep-B2Ax7ewy.mjs.map +1 -0
  21. package/dist/index-node-esm-D6YQRKEz.mjs +1537 -0
  22. package/dist/index-node-esm-D6YQRKEz.mjs.map +1 -0
  23. package/dist/index.d.mts +1605 -0
  24. package/dist/index.d.mts.map +1 -0
  25. package/dist/index.mjs +948 -0
  26. package/dist/index.mjs.map +1 -0
  27. package/dist/jsonl-Dw_VBp46.mjs +134 -0
  28. package/dist/jsonl-Dw_VBp46.mjs.map +1 -0
  29. package/dist/manager-D-lWBTHG.mjs +271 -0
  30. package/dist/manager-D-lWBTHG.mjs.map +1 -0
  31. package/dist/markdown-Bv4J8cg3.mjs +53 -0
  32. package/dist/markdown-Bv4J8cg3.mjs.map +1 -0
  33. package/dist/masker-Bv9KjkDF.mjs +396 -0
  34. package/dist/masker-Bv9KjkDF.mjs.map +1 -0
  35. package/dist/model-_3ZA2xqm.mjs +27 -0
  36. package/dist/model-_3ZA2xqm.mjs.map +1 -0
  37. package/dist/notify-DpG_m9iP.mjs +96 -0
  38. package/dist/notify-DpG_m9iP.mjs.map +1 -0
  39. package/dist/read-Djsx2NZl.mjs +205 -0
  40. package/dist/read-Djsx2NZl.mjs.map +1 -0
  41. package/dist/registry-CFmR5G3J.mjs +564 -0
  42. package/dist/registry-CFmR5G3J.mjs.map +1 -0
  43. package/dist/search-CRw247ES.mjs +121 -0
  44. package/dist/search-CRw247ES.mjs.map +1 -0
  45. package/dist/session/claude.d.mts +59 -0
  46. package/dist/session/claude.d.mts.map +1 -0
  47. package/dist/session/claude.mjs +455 -0
  48. package/dist/session/claude.mjs.map +1 -0
  49. package/dist/session-CUUdWFC5.mjs +450 -0
  50. package/dist/session-CUUdWFC5.mjs.map +1 -0
  51. package/dist/session-Ds5nJz5A.d.mts +346 -0
  52. package/dist/session-Ds5nJz5A.d.mts.map +1 -0
  53. package/dist/session.d.mts +37 -0
  54. package/dist/session.d.mts.map +1 -0
  55. package/dist/session.mjs +106 -0
  56. package/dist/session.mjs.map +1 -0
  57. package/dist/subagent-baqzjRMc.mjs +136 -0
  58. package/dist/subagent-baqzjRMc.mjs.map +1 -0
  59. package/dist/swarm-BJ3gQA1Z.mjs +194 -0
  60. package/dist/swarm-BJ3gQA1Z.mjs.map +1 -0
  61. package/dist/swarm-BuFx_xeY.mjs +109 -0
  62. package/dist/swarm-BuFx_xeY.mjs.map +1 -0
  63. package/dist/tasks-D8rARHZ1.mjs +65 -0
  64. package/dist/tasks-D8rARHZ1.mjs.map +1 -0
  65. package/dist/tasks-WmC270X2.mjs +615 -0
  66. package/dist/tasks-WmC270X2.mjs.map +1 -0
  67. package/dist/tools-DW1dbcCz.mjs +695 -0
  68. package/dist/tools-DW1dbcCz.mjs.map +1 -0
  69. package/dist/truncate-BSMXgiXj.mjs +102 -0
  70. package/dist/truncate-BSMXgiXj.mjs.map +1 -0
  71. package/dist/uuid-ByXP5SO5.mjs +59 -0
  72. package/dist/uuid-ByXP5SO5.mjs.map +1 -0
  73. package/dist/wakeup-BYqTnfSp.mjs +29 -0
  74. package/dist/wakeup-BYqTnfSp.mjs.map +1 -0
  75. package/dist/write-D3L-92vj.mjs +89 -0
  76. package/dist/write-D3L-92vj.mjs.map +1 -0
  77. package/package.json +63 -0
@@ -0,0 +1,695 @@
1
+ import { safeStringify } from "@zaly/shared";
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
10
+ var __exportAll = (all, no_symbols) => {
11
+ let target = {};
12
+ for (var name in all) __defProp(target, name, {
13
+ get: all[name],
14
+ enumerable: true
15
+ });
16
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
17
+ return target;
18
+ };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
21
+ key = keys[i];
22
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
23
+ get: ((k) => from[k]).bind(null, key),
24
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
25
+ });
26
+ }
27
+ return to;
28
+ };
29
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
30
+ value: mod,
31
+ enumerable: true
32
+ }) : target, mod));
33
+ //#endregion
34
+ //#region ../../node_modules/.bun/shell-quote@1.9.0/node_modules/shell-quote/quote.js
35
+ var require_quote = /* @__PURE__ */ __commonJSMin(((exports, module) => {
36
+ /** @import { ControlOperator } from './parse' */
37
+ /** @type {ControlOperator['op'][]} */
38
+ var OPS = [
39
+ "||",
40
+ "&&",
41
+ ";;",
42
+ "|&",
43
+ "<(",
44
+ "<<<",
45
+ ">>",
46
+ ">&",
47
+ "<&",
48
+ "&",
49
+ ";",
50
+ "(",
51
+ ")",
52
+ "|",
53
+ "<",
54
+ ">"
55
+ ];
56
+ var LINE_TERMINATORS = /[\n\r\u2028\u2029]/;
57
+ var GLOB_SHELL_SPECIAL = /[\s#!"$&'():;<=>@\\^`|]/g;
58
+ /** @type {import('./quote')} */
59
+ module.exports = function quote(xs) {
60
+ return xs.map(function(s) {
61
+ if (s === "") return "''";
62
+ if (s && typeof s === "object") {
63
+ if ("op" in s && s.op === "glob") {
64
+ if (typeof s.pattern !== "string") throw new TypeError("glob token requires a string `pattern`");
65
+ if (LINE_TERMINATORS.test(s.pattern)) throw new TypeError("glob `pattern` must not contain line terminators");
66
+ return s.pattern.replace(GLOB_SHELL_SPECIAL, "\\$&");
67
+ }
68
+ if ("op" in s && typeof s.op === "string") {
69
+ if (OPS.indexOf(s.op) < 0) throw new TypeError("invalid `op` value: " + JSON.stringify(s.op));
70
+ return s.op.replace(/[\s\S]/g, "\\$&");
71
+ }
72
+ if ("comment" in s && typeof s.comment === "string") {
73
+ if (LINE_TERMINATORS.test(s.comment)) throw new TypeError("`comment` must not contain line terminators");
74
+ return "#" + s.comment;
75
+ }
76
+ throw new TypeError("unrecognized object token shape");
77
+ }
78
+ if (/["\s\\]/.test(s) && !/'/.test(s)) return "'" + s.replace(/(['])/g, "\\$1") + "'";
79
+ if (/["'\s]/.test(s)) return "\"" + s.replace(/(["\\$`!])/g, "\\$1") + "\"";
80
+ return String(s).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}~])/g, "$1\\$2");
81
+ }).join(" ");
82
+ };
83
+ }));
84
+ //#endregion
85
+ //#region ../../node_modules/.bun/shell-quote@1.9.0/node_modules/shell-quote/parse.js
86
+ var require_parse = /* @__PURE__ */ __commonJSMin(((exports, module) => {
87
+ /**
88
+ * @import {
89
+ * ControlOperator,
90
+ * Env,
91
+ * GlobPattern,
92
+ * ParseEntry,
93
+ * } from './parse' */
94
+ var CONTROL = "(?:" + [
95
+ "\\|\\|",
96
+ "\\&\\&",
97
+ ";;",
98
+ "\\|\\&",
99
+ "\\<\\(",
100
+ "\\<\\<\\<",
101
+ ">>",
102
+ ">\\&",
103
+ "<\\&",
104
+ "[&;()|<>]"
105
+ ].join("|") + ")";
106
+ var controlRE = new RegExp("^" + CONTROL + "$");
107
+ var META = "|&;()<> \\t";
108
+ var SINGLE_QUOTE = "\"((\\\\\"|[^\"])*?)\"";
109
+ var DOUBLE_QUOTE = "'((\\\\'|[^'])*?)'";
110
+ var hash = /^#$/;
111
+ var SQ = "'";
112
+ var DQ = "\"";
113
+ var DS = "$";
114
+ var TOKEN = "";
115
+ var mult = 4294967296;
116
+ for (var i = 0; i < 4; i++) TOKEN += (mult * Math.random()).toString(16);
117
+ var startsWithToken = new RegExp("^" + TOKEN);
118
+ /**
119
+ * @param {string} s
120
+ * @param {RegExp} r
121
+ */
122
+ function matchAll(s, r) {
123
+ var origIndex = r.lastIndex;
124
+ var matches = [];
125
+ var matchObj;
126
+ while (matchObj = r.exec(s)) {
127
+ matches[matches.length] = matchObj;
128
+ if (r.lastIndex === matchObj.index) r.lastIndex += 1;
129
+ }
130
+ r.lastIndex = origIndex;
131
+ return matches;
132
+ }
133
+ /**
134
+ * @param {Env} env
135
+ * @param {string} pre
136
+ * @param {string} key
137
+ */
138
+ function getVar(env, pre, key) {
139
+ var r = typeof env === "function" ? env(key) : env[key];
140
+ if (typeof r === "undefined" && key != "") r = "";
141
+ else if (typeof r === "undefined") r = "$";
142
+ if (typeof r === "object") return pre + TOKEN + JSON.stringify(r) + TOKEN;
143
+ return pre + r;
144
+ }
145
+ /**
146
+ * @param {string} string
147
+ * @param {Env} [env]
148
+ * @param {{ escape?: string }} [opts]
149
+ * @returns {ParseEntry[]}
150
+ */
151
+ function parseInternal(string, env, opts) {
152
+ if (!opts) opts = {};
153
+ var BS = opts.escape || "\\";
154
+ var BAREWORD = "(\\" + BS + "['\"" + META + "]|[^\\s'\"" + META + "])+";
155
+ var matches = matchAll(string, new RegExp(["(" + CONTROL + ")", "(" + BAREWORD + "|" + SINGLE_QUOTE + "|" + DOUBLE_QUOTE + ")+"].join("|"), "g"));
156
+ if (matches.length === 0) return [];
157
+ if (!env) env = {};
158
+ var commented = false;
159
+ return matches.map(function(match) {
160
+ var s = match[0];
161
+ if (!s || commented) return;
162
+ if (controlRE.test(s)) return { op: s };
163
+ /** @type {string | boolean} */
164
+ var quote = false;
165
+ var esc = false;
166
+ var out = "";
167
+ var isGlob = false;
168
+ /** @type {number} */
169
+ var i;
170
+ function parseEnvVar() {
171
+ i += 1;
172
+ /** @type {number | RegExpMatchArray | null} */
173
+ var varend;
174
+ /** @type {string} */
175
+ var varname;
176
+ var char = s.charAt(i);
177
+ if (char === "{") {
178
+ i += 1;
179
+ if (s.charAt(i) === "}") throw new Error("Bad substitution: " + s.slice(i - 2, i + 1));
180
+ varend = s.indexOf("}", i);
181
+ if (varend < 0) throw new Error("Bad substitution: " + s.slice(i));
182
+ varname = s.slice(i, varend);
183
+ i = varend;
184
+ } else if (/[*@#?$!_-]/.test(char)) {
185
+ varname = char;
186
+ i += 1;
187
+ } else {
188
+ var slicedFromI = s.slice(i);
189
+ varend = slicedFromI.match(/[^\w\d_]/);
190
+ if (!varend) {
191
+ varname = slicedFromI;
192
+ i = s.length;
193
+ } else {
194
+ varname = slicedFromI.slice(0, varend.index);
195
+ i += varend.index - 1;
196
+ }
197
+ }
198
+ return getVar(env, "", varname);
199
+ }
200
+ for (i = 0; i < s.length; i++) {
201
+ var c = s.charAt(i);
202
+ isGlob = isGlob || !quote && (c === "*" || c === "?");
203
+ if (esc) {
204
+ out += c;
205
+ esc = false;
206
+ } else if (quote) if (c === quote) quote = false;
207
+ else if (quote == SQ) out += c;
208
+ else if (c === BS) {
209
+ i += 1;
210
+ c = s.charAt(i);
211
+ if (c === DQ || c === BS || c === DS) out += c;
212
+ else out += BS + c;
213
+ } else if (c === DS) out += parseEnvVar();
214
+ else out += c;
215
+ else if (c === DQ || c === SQ) quote = c;
216
+ else if (controlRE.test(c)) return { op: s };
217
+ else if (hash.test(c)) {
218
+ commented = true;
219
+ var commentObj = { comment: string.slice(match.index + i + 1) };
220
+ if (out.length) return [out, commentObj];
221
+ return [commentObj];
222
+ } else if (c === BS) esc = true;
223
+ else if (c === DS) out += parseEnvVar();
224
+ else out += c;
225
+ }
226
+ if (isGlob) return {
227
+ op: "glob",
228
+ pattern: out
229
+ };
230
+ return out;
231
+ }).reduce(function(prev, arg) {
232
+ if (typeof arg === "undefined") return prev;
233
+ /** @type {ParseEntry[]} */ [].concat(arg).forEach(function(entry) {
234
+ prev[prev.length] = entry;
235
+ });
236
+ return prev;
237
+ }, []);
238
+ }
239
+ /** @type {import('./parse')} */
240
+ module.exports = function parse(s, env, opts) {
241
+ var mapped = parseInternal(s, env, opts);
242
+ if (typeof env !== "function") return mapped;
243
+ return mapped.reduce(function(acc, s) {
244
+ if (typeof s === "object") {
245
+ acc[acc.length] = s;
246
+ return acc;
247
+ }
248
+ var xs = s.split(RegExp("(" + TOKEN + ".*?" + TOKEN + ")", "g"));
249
+ if (xs.length === 1) {
250
+ acc[acc.length] = xs[0];
251
+ return acc;
252
+ }
253
+ xs.filter(Boolean).forEach(function(x) {
254
+ acc[acc.length] = startsWithToken.test(x) ? JSON.parse(x.split(TOKEN)[1]) : x;
255
+ });
256
+ return acc;
257
+ }, []);
258
+ };
259
+ }));
260
+ //#endregion
261
+ //#region src/utils/bash/parser.ts
262
+ var import_shell_quote = (/* @__PURE__ */ __commonJSMin(((exports) => {
263
+ exports.quote = require_quote();
264
+ exports.parse = require_parse();
265
+ })))();
266
+ /** Targets a redirect can write to without filesystem implications.
267
+ * Anything else is treated as a file write and goes through fileWrite
268
+ * policy. */
269
+ const SAFE_REDIRECT_TARGETS = /* @__PURE__ */ new Set([
270
+ "/dev/null",
271
+ "/dev/stderr",
272
+ "/dev/stdout"
273
+ ]);
274
+ /** A redirect target like `&1`, `&2`, `&-` — duplicates an existing fd,
275
+ * no filesystem effect. */
276
+ function isFdRedirect(target) {
277
+ return /^&(?:\d+|-)$/.test(target);
278
+ }
279
+ const COMMAND_SEPS = /* @__PURE__ */ new Set([
280
+ "|",
281
+ "&&",
282
+ "||",
283
+ ";"
284
+ ]);
285
+ const REDIRECT_OPS = /* @__PURE__ */ new Set([
286
+ ">",
287
+ ">>",
288
+ "<",
289
+ ">&",
290
+ "<&"
291
+ ]);
292
+ const DYN_SENTINEL = "";
293
+ /** Parse a bash command line. Returns segments with a flag for
294
+ * unsupported constructs that force "ask" downstream. Heredocs,
295
+ * subshells, command substitution, and backticks all surface as
296
+ * `hasCommandSubst: true` (the umbrella "we can't reason about this"
297
+ * signal) rather than parse failures, so the policy can still decide. */
298
+ function parseBash(input) {
299
+ if (/<<-?\s*['"]?\w+/.test(input)) return {
300
+ ok: false,
301
+ reason: "heredoc not supported"
302
+ };
303
+ const hasBackticks = hasUnquotedBacktick(input);
304
+ let rawTokens;
305
+ try {
306
+ rawTokens = (0, import_shell_quote.parse)(input, (e) => e === "" ? void 0 : `${DYN_SENTINEL}\${${e}}`);
307
+ } catch (error) {
308
+ return {
309
+ ok: false,
310
+ reason: `tokenize: ${error.message}`
311
+ };
312
+ }
313
+ const flat = flattenParens(rawTokens);
314
+ const hasCommandSubst = hasBackticks || flat.hasCommandSubst;
315
+ const segmentTokens = [[]];
316
+ for (const t of flat.tokens) {
317
+ if (typeof t === "object" && "comment" in t) continue;
318
+ if (typeof t === "object" && "op" in t && COMMAND_SEPS.has(t.op)) {
319
+ if (segmentTokens.at(-1).length > 0) segmentTokens.push([]);
320
+ continue;
321
+ }
322
+ segmentTokens.at(-1).push(t);
323
+ }
324
+ if (segmentTokens.at(-1).length === 0) segmentTokens.pop();
325
+ const segments = [];
326
+ for (const segToks of segmentTokens) {
327
+ const seg = parseSegment(segToks);
328
+ if (!seg.ok) return seg;
329
+ if (seg.segment) segments.push({
330
+ ...seg.segment,
331
+ hasCommandSubst
332
+ });
333
+ }
334
+ if (segments.length === 0) return {
335
+ ok: false,
336
+ reason: "empty input"
337
+ };
338
+ return {
339
+ ok: true,
340
+ segments
341
+ };
342
+ }
343
+ function parseSegment(tokens) {
344
+ let args = [];
345
+ let reads = [];
346
+ let writes = [];
347
+ const dyn = /* @__PURE__ */ new Set();
348
+ for (let i = 0; i < tokens.length; i++) {
349
+ const t = tokens[i];
350
+ if (typeof t === "string") {
351
+ if (/^\d+$/.test(t)) {
352
+ const next = tokens[i + 1];
353
+ if (typeof next === "object" && "op" in next && REDIRECT_OPS.has(next.op)) continue;
354
+ }
355
+ args.push(t);
356
+ continue;
357
+ }
358
+ if ("comment" in t) continue;
359
+ if ("pattern" in t) {
360
+ args.push(t.pattern);
361
+ dyn.add(t.pattern);
362
+ continue;
363
+ }
364
+ if (!("op" in t)) return {
365
+ ok: false,
366
+ reason: `unsupported token: ${safeStringify(t)}`
367
+ };
368
+ if (REDIRECT_OPS.has(t.op)) {
369
+ const next = tokens[i + 1];
370
+ if (typeof next !== "string") return {
371
+ ok: false,
372
+ reason: `redirect target missing after ${t.op}`
373
+ };
374
+ i++;
375
+ if (t.op === ">" || t.op === ">>") {
376
+ if (SAFE_REDIRECT_TARGETS.has(next) || isFdRedirect(next)) continue;
377
+ writes.push({
378
+ mode: t.op === ">>" ? "append" : "trunc",
379
+ path: next
380
+ });
381
+ } else if (t.op === "<") {
382
+ if (SAFE_REDIRECT_TARGETS.has(next) || isFdRedirect(next)) continue;
383
+ reads.push(next);
384
+ }
385
+ continue;
386
+ }
387
+ return {
388
+ ok: false,
389
+ reason: `unsupported op: ${t.op}`
390
+ };
391
+ }
392
+ const dynPath = (p) => {
393
+ if (!p.includes(DYN_SENTINEL)) return p;
394
+ p = p.replaceAll(DYN_SENTINEL, "");
395
+ dyn.add(p);
396
+ return p;
397
+ };
398
+ args = args.map((a) => dynPath(a));
399
+ writes = writes.map((w) => ({
400
+ ...w,
401
+ path: dynPath(w.path)
402
+ }));
403
+ reads = reads.map(dynPath);
404
+ const unwrapped = unwrapWrappers(args);
405
+ if (unwrapped.length === 0) return {
406
+ ok: true,
407
+ segment: void 0
408
+ };
409
+ return {
410
+ ok: true,
411
+ segment: {
412
+ args: unwrapped.slice(1),
413
+ cmd: unwrapped[0],
414
+ dyn,
415
+ reads,
416
+ writes
417
+ }
418
+ };
419
+ }
420
+ /** Commands that wrap another command — they're transparent for
421
+ * permission purposes, since the security-relevant action is whatever
422
+ * they run. `sudo` is intentionally absent: it changes the effective
423
+ * user and must always be flagged. */
424
+ const WRAPPERS = {
425
+ command: {},
426
+ ionice: { valueFlags: /* @__PURE__ */ new Set([
427
+ "-c",
428
+ "-n",
429
+ "-p",
430
+ "-P",
431
+ "-u"
432
+ ]) },
433
+ nice: { valueFlags: /* @__PURE__ */ new Set(["-n", "--adjustment"]) },
434
+ nohup: {},
435
+ time: {}
436
+ };
437
+ /** Detect backticks outside single-quoted regions. Single quotes in
438
+ * bash can't be escaped from within, so the toggle is a simple state
439
+ * flip on every `'`. Double quotes do not suppress backtick
440
+ * substitution and are ignored here. */
441
+ function hasUnquotedBacktick(input) {
442
+ let inSingle = false;
443
+ for (const c of input) {
444
+ if (c === "'") {
445
+ inSingle = !inSingle;
446
+ continue;
447
+ }
448
+ if (c === "`" && !inSingle) return true;
449
+ }
450
+ return false;
451
+ }
452
+ /** Strip leading wrapper-command prefixes from an arg list. Repeats
453
+ * while the head is a wrapper (so `time nice -n 5 cmd` → `cmd`).
454
+ * Wrapper-flags (and their values, where applicable) are consumed
455
+ * along with the wrapper itself. */
456
+ function unwrapWrappers(args) {
457
+ let current = args;
458
+ while (current.length > 0) {
459
+ const spec = WRAPPERS[current[0]];
460
+ if (!spec) break;
461
+ const valueFlags = spec.valueFlags ?? /* @__PURE__ */ new Set();
462
+ let i = 1;
463
+ while (i < current.length && current[i].startsWith("-")) {
464
+ const flag = current[i];
465
+ i++;
466
+ if (valueFlags.has(flag) && i < current.length) i++;
467
+ }
468
+ current = current.slice(i);
469
+ }
470
+ return current;
471
+ }
472
+ /** Walk a token list and resolve paren constructs:
473
+ * - Plain `(subshell)` → tokens inlined with `;` boundaries on each
474
+ * side, so the contents become independent segments evaluated by
475
+ * the same policy. The subshell's own scope (cwd changes etc.) is
476
+ * irrelevant to permissions — each command is checked individually.
477
+ * - `$(...)` (command substitution) → stripped entirely, with the
478
+ * `hasCommandSubst` flag raised. The dynamic value can't be
479
+ * statically reasoned about. Detected by the leading `$` token
480
+ * that shell-quote emits before the `(`.
481
+ *
482
+ * Recurses into subshell contents to handle nesting and to catch
483
+ * `$(...)` constructs nested inside subshells. */
484
+ function flattenParens(tokens) {
485
+ const out = [];
486
+ let hasCommandSubst = false;
487
+ let i = 0;
488
+ while (i < tokens.length) {
489
+ const t = tokens[i];
490
+ if (typeof t === "object" && "op" in t && t.op === "(") {
491
+ const isSubst = out.at(-1) === "$";
492
+ if (isSubst) out.pop();
493
+ let depth = 1;
494
+ let j = i + 1;
495
+ while (j < tokens.length && depth > 0) {
496
+ const tj = tokens[j];
497
+ if (typeof tj === "object" && "op" in tj) {
498
+ if (tj.op === "(") depth++;
499
+ else if (tj.op === ")") depth--;
500
+ }
501
+ if (depth > 0) j++;
502
+ }
503
+ const inner = tokens.slice(i + 1, j);
504
+ if (isSubst) hasCommandSubst = true;
505
+ else {
506
+ const sub = flattenParens(inner);
507
+ if (sub.hasCommandSubst) hasCommandSubst = true;
508
+ out.push({ op: ";" }, ...sub.tokens, { op: ";" });
509
+ }
510
+ i = j + 1;
511
+ continue;
512
+ }
513
+ if (typeof t === "object" && "op" in t && t.op === ")") {
514
+ i++;
515
+ continue;
516
+ }
517
+ out.push(t);
518
+ i++;
519
+ }
520
+ return {
521
+ hasCommandSubst,
522
+ tokens: out
523
+ };
524
+ }
525
+ //#endregion
526
+ //#region src/utils/bash/tools.ts
527
+ /** All bare positional args (no leading dash). Default for many
528
+ * read-only utilities. */
529
+ function positionals(args) {
530
+ return args.filter((a) => !a.startsWith("-") && a !== "");
531
+ }
532
+ /** All positionals after the first one (e.g. `grep PATTERN file...`). */
533
+ function positionalsAfterFirst(args) {
534
+ const out = [];
535
+ let seenFirst = false;
536
+ for (const a of args) {
537
+ if (a.startsWith("-") || a === "") continue;
538
+ if (!seenFirst) {
539
+ seenFirst = true;
540
+ continue;
541
+ }
542
+ out.push(a);
543
+ }
544
+ return out;
545
+ }
546
+ /** Flags whose value is the *next* arg, not part of the script. */
547
+ const SED_VALUE_FLAGS = /* @__PURE__ */ new Set([
548
+ "-e",
549
+ "--expression",
550
+ "-f",
551
+ "--file"
552
+ ]);
553
+ /** Walk sed args, returning [scripts, positionalsAfterScript]. The
554
+ * "script" is everything passed via `-e` plus the first bare arg
555
+ * (the implicit script when no `-e` is given). Positionals after
556
+ * that are input files. */
557
+ function sedSplit(args) {
558
+ const scripts = [];
559
+ const files = [];
560
+ let needsImplicitScript = !args.some((a) => a === "-e" || a === "--expression" || a === "-f" || a === "--file");
561
+ for (let i = 0; i < args.length; i++) {
562
+ const a = args[i];
563
+ if (a.startsWith("-")) {
564
+ if (SED_VALUE_FLAGS.has(a) && i + 1 < args.length) {
565
+ if (a === "-e" || a === "--expression") scripts.push(args[i + 1]);
566
+ i++;
567
+ }
568
+ continue;
569
+ }
570
+ if (needsImplicitScript) {
571
+ scripts.push(a);
572
+ needsImplicitScript = false;
573
+ continue;
574
+ }
575
+ files.push(a);
576
+ }
577
+ return {
578
+ files,
579
+ scripts
580
+ };
581
+ }
582
+ const SED_INPLACE = /* @__PURE__ */ new Set(["-i", "--in-place"]);
583
+ function sedReads(args) {
584
+ return sedSplit(args).files;
585
+ }
586
+ function sedWrites(args) {
587
+ return args.some((a) => SED_INPLACE.has(a) || a.startsWith("-i.")) ? sedSplit(args).files : [];
588
+ }
589
+ function sedUnsafe(args) {
590
+ for (const script of sedSplit(args).scripts) if (/(?:^|;|\n)\s*[wWrR]\s+\S/.test(script)) return true;
591
+ return false;
592
+ }
593
+ function awkReads(args) {
594
+ let sawScript = false;
595
+ let usingFFlag = false;
596
+ const files = [];
597
+ for (let i = 0; i < args.length; i++) {
598
+ const a = args[i];
599
+ if (a === "-f" || a === "--file") {
600
+ if (i + 1 < args.length) files.push(args[i + 1]);
601
+ i++;
602
+ sawScript = true;
603
+ usingFFlag = true;
604
+ continue;
605
+ }
606
+ if (a.startsWith("-")) {
607
+ if (a === "-v" || a === "-F") i++;
608
+ continue;
609
+ }
610
+ if (!sawScript) {
611
+ sawScript = true;
612
+ continue;
613
+ }
614
+ files.push(a);
615
+ }
616
+ return usingFFlag ? files : files;
617
+ }
618
+ function awkUnsafe(args) {
619
+ let sawScript = false;
620
+ for (let i = 0; i < args.length; i++) {
621
+ const a = args[i];
622
+ if (a === "-f" || a === "--file" || a === "-v" || a === "-F") {
623
+ i++;
624
+ continue;
625
+ }
626
+ if (a.startsWith("-")) continue;
627
+ if (!sawScript) {
628
+ sawScript = true;
629
+ if (/[>|]/.test(a)) return true;
630
+ }
631
+ }
632
+ return false;
633
+ }
634
+ function findReads(args) {
635
+ const out = [];
636
+ for (const a of args) {
637
+ if (a.startsWith("-")) break;
638
+ out.push(a);
639
+ }
640
+ return out.length > 0 ? out : ["."];
641
+ }
642
+ function findUnsafe(args) {
643
+ return args.some((a) => a === "-delete" || a === "-exec" || a === "-execdir" || a === "-ok" || a === "-okdir");
644
+ }
645
+ const dynamicExec = () => true;
646
+ const TOOLS = {
647
+ ".": { unsafe: dynamicExec },
648
+ awk: {
649
+ reads: awkReads,
650
+ unsafe: awkUnsafe
651
+ },
652
+ basename: {},
653
+ cat: { reads: positionals },
654
+ cd: {},
655
+ cut: { reads: positionals },
656
+ diff: { reads: positionals },
657
+ dirname: {},
658
+ echo: {},
659
+ eval: { unsafe: dynamicExec },
660
+ exec: { unsafe: dynamicExec },
661
+ file: { reads: positionals },
662
+ find: {
663
+ reads: findReads,
664
+ unsafe: findUnsafe
665
+ },
666
+ grep: { reads: positionalsAfterFirst },
667
+ head: { reads: positionals },
668
+ hexdump: { reads: positionals },
669
+ less: { reads: positionals },
670
+ ls: { reads: positionals },
671
+ more: { reads: positionals },
672
+ od: { reads: positionals },
673
+ printf: {},
674
+ pwd: {},
675
+ readlink: { reads: positionals },
676
+ realpath: { reads: positionals },
677
+ rg: { reads: positionalsAfterFirst },
678
+ sed: {
679
+ reads: sedReads,
680
+ unsafe: sedUnsafe,
681
+ writes: sedWrites
682
+ },
683
+ sort: { reads: positionals },
684
+ source: { unsafe: dynamicExec },
685
+ stat: { reads: positionals },
686
+ tail: { reads: positionals },
687
+ tree: { reads: positionals },
688
+ uniq: { reads: positionals },
689
+ wc: { reads: positionals },
690
+ xxd: { reads: positionals }
691
+ };
692
+ //#endregion
693
+ export { __toESM as a, __exportAll as i, parseBash as n, __commonJSMin as r, TOOLS as t };
694
+
695
+ //# sourceMappingURL=tools-DW1dbcCz.mjs.map