@zaly/agent 0.0.4 → 0.0.6

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 (53) hide show
  1. package/dist/{agent-GDLdDc2w.mjs → agent-DirSoZjM.mjs} +8 -9
  2. package/dist/agent-DirSoZjM.mjs.map +1 -0
  3. package/dist/{bash-QNMTQ1PD.mjs → bash-COgq4W7U.mjs} +2 -2
  4. package/dist/{bash-QNMTQ1PD.mjs.map → bash-COgq4W7U.mjs.map} +1 -1
  5. package/dist/compactions-3AjPqjeZ.mjs.map +1 -1
  6. package/dist/{fetch-D8cmmA3E.mjs → fetch-DXuxAg_t.mjs} +3 -3
  7. package/dist/{fetch-D8cmmA3E.mjs.map → fetch-DXuxAg_t.mjs.map} +1 -1
  8. package/dist/{grep-B2Ax7ewy.mjs → grep-B4GF0svc.mjs} +2 -2
  9. package/dist/{grep-B2Ax7ewy.mjs.map → grep-B4GF0svc.mjs.map} +1 -1
  10. package/dist/index-node-esm-DAnl9SaE.mjs +2114 -0
  11. package/dist/index-node-esm-DAnl9SaE.mjs.map +1 -0
  12. package/dist/index.d.mts +47 -42
  13. package/dist/index.d.mts.map +1 -1
  14. package/dist/index.mjs +28 -22
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/{jsonl-Dw_VBp46.mjs → jsonl-CvgEOakL.mjs} +2 -2
  17. package/dist/jsonl-CvgEOakL.mjs.map +1 -0
  18. package/dist/{manager-D-lWBTHG.mjs → manager-DHBfEtge.mjs} +12 -2
  19. package/dist/manager-DHBfEtge.mjs.map +1 -0
  20. package/dist/masker-Bv9KjkDF.mjs.map +1 -1
  21. package/dist/notify-DpG_m9iP.mjs.map +1 -1
  22. package/dist/{registry-CFmR5G3J.mjs → registry-Bao6L4Ue.mjs} +399 -73
  23. package/dist/registry-Bao6L4Ue.mjs.map +1 -0
  24. package/dist/session/claude.d.mts +2 -3
  25. package/dist/session/claude.d.mts.map +1 -1
  26. package/dist/session/claude.mjs +1 -1
  27. package/dist/{session-CUUdWFC5.mjs → session-B1lXSWhT.mjs} +4 -4
  28. package/dist/session-B1lXSWhT.mjs.map +1 -0
  29. package/dist/session.d.mts +8 -8
  30. package/dist/session.d.mts.map +1 -1
  31. package/dist/session.mjs +3 -3
  32. package/dist/{subagent-baqzjRMc.mjs → subagent-Zz-MQHk2.mjs} +3 -3
  33. package/dist/{subagent-baqzjRMc.mjs.map → subagent-Zz-MQHk2.mjs.map} +1 -1
  34. package/dist/swarm-BJ3gQA1Z.mjs.map +1 -1
  35. package/dist/{tasks-D8rARHZ1.mjs → tasks-BA-PCeGa.mjs} +4 -3
  36. package/dist/{tasks-D8rARHZ1.mjs.map → tasks-BA-PCeGa.mjs.map} +1 -1
  37. package/dist/{tasks-WmC270X2.mjs → tasks-WdRAHsOL.mjs} +5 -4
  38. package/dist/tasks-WdRAHsOL.mjs.map +1 -0
  39. package/dist/{tools-DW1dbcCz.mjs → tools-CZvBFp-v.mjs} +144 -38
  40. package/dist/tools-CZvBFp-v.mjs.map +1 -0
  41. package/dist/truncate-BSMXgiXj.mjs.map +1 -1
  42. package/dist/{uuid-ByXP5SO5.mjs → uuid-CAdJg4l8.mjs} +2 -2
  43. package/dist/{uuid-ByXP5SO5.mjs.map → uuid-CAdJg4l8.mjs.map} +1 -1
  44. package/package.json +12 -12
  45. package/dist/agent-GDLdDc2w.mjs.map +0 -1
  46. package/dist/index-node-esm-D6YQRKEz.mjs +0 -1537
  47. package/dist/index-node-esm-D6YQRKEz.mjs.map +0 -1
  48. package/dist/jsonl-Dw_VBp46.mjs.map +0 -1
  49. package/dist/manager-D-lWBTHG.mjs.map +0 -1
  50. package/dist/registry-CFmR5G3J.mjs.map +0 -1
  51. package/dist/session-CUUdWFC5.mjs.map +0 -1
  52. package/dist/tasks-WmC270X2.mjs.map +0 -1
  53. package/dist/tools-DW1dbcCz.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { a as __toESM, n as parseBash, r as __commonJSMin, t as TOOLS } from "./tools-DW1dbcCz.mjs";
1
+ import { a as __toESM, n as parseBash, r as __commonJSMin, t as TOOLS } from "./tools-CZvBFp-v.mjs";
2
2
  import { normPath, prettyPath } from "@zaly/shared";
3
3
  import { createRegistry } from "@zaly/shared/registry";
4
4
  import { dirname, isAbsolute, relative } from "pathe";
@@ -24,11 +24,18 @@ import { dirname, isAbsolute, relative } from "pathe";
24
24
  */
25
25
  const bashHandler = { validate(input, ctx) {
26
26
  const parsed = parseBash(input);
27
- if (!parsed.ok) return {
28
- ask: `Allow this bash command? (${parsed.reason})`,
29
- reason: parsed.reason,
30
- verdict: "ask"
31
- };
27
+ if (!parsed.ok) {
28
+ if ([
29
+ "bash",
30
+ "read",
31
+ "write"
32
+ ].every((scope) => ctx.allowsAll?.(scope))) return { verdict: "allow" };
33
+ return {
34
+ ask: `Allow this bash command? (${parsed.reason})`,
35
+ reason: parsed.reason,
36
+ verdict: "ask"
37
+ };
38
+ }
32
39
  let verdict = "allow";
33
40
  let reason;
34
41
  const suggestions = [];
@@ -55,7 +62,7 @@ const bashHandler = { validate(input, ctx) {
55
62
  const reads = [...spec?.reads?.(seg.args) ?? [], ...seg.reads];
56
63
  const writes = [...spec?.writes?.(seg.args) ?? [], ...seg.writes.map((w) => w.path)];
57
64
  for (const path of reads) {
58
- if (seg.dyn?.has(path)) {
65
+ if (seg.dyn?.has(path) && !ctx.allowsAll?.("read")) {
59
66
  segVerdict = combine(segVerdict, "ask");
60
67
  segReason ??= `${seg.cmd}: read ${path}: dynamic path`;
61
68
  suggestions.push({
@@ -74,7 +81,7 @@ const bashHandler = { validate(input, ctx) {
74
81
  if (segVerdict === "deny") break;
75
82
  }
76
83
  if (segVerdict !== "deny") for (const path of writes) {
77
- if (seg.dyn?.has(path)) {
84
+ if (seg.dyn?.has(path) && !ctx.allowsAll?.("write")) {
78
85
  segVerdict = combine(segVerdict, "ask");
79
86
  segReason ??= `${seg.cmd}: write ${path}: dynamic path`;
80
87
  suggestions.push({
@@ -156,13 +163,15 @@ var import_ignore = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
156
163
  const EMPTY = "";
157
164
  const SPACE = " ";
158
165
  const ESCAPE = "\\";
159
- const REGEX_TEST_BLANK_LINE = /^\s+$/;
166
+ const REGEX_LITERAL_SPECIAL = /[.*+?()[\]{}^$|\\/]/;
167
+ const BOM = "";
160
168
  const REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/;
161
169
  const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/;
162
170
  const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/;
163
171
  const REGEX_SPLITALL_CRLF = /\r?\n/g;
164
- const REGEX_TEST_INVALID_PATH = /^\.{0,2}\/|^\.{1,2}$/;
165
- const REGEX_TEST_TRAILING_SLASH = /\/$/;
172
+ const DOUBLE_SLASH = "//";
173
+ const SLASH_CODE = 47;
174
+ const DOT_CODE = 46;
166
175
  const SLASH = "/";
167
176
  let TMP_KEY_IGNORE = "node-ignore";
168
177
  /* istanbul ignore else */
@@ -172,51 +181,316 @@ var import_ignore = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
172
181
  Object.defineProperty(object, key, { value });
173
182
  return value;
174
183
  };
175
- const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g;
176
184
  const RETURN_FALSE = () => false;
177
- const sanitizeRange = (range) => range.replace(REGEX_REGEXP_RANGE, (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) ? match : EMPTY);
178
185
  const cleanRangeBackSlash = (slashes) => {
179
186
  const { length } = slashes;
180
187
  return slashes.slice(0, length - length % 2);
181
188
  };
189
+ const POSIX_CLASSES = {
190
+ alnum: "0-9A-Za-z",
191
+ alpha: "A-Za-z",
192
+ blank: " \\t",
193
+ cntrl: "\\x00-\\x1f\\x7f",
194
+ digit: "0-9",
195
+ graph: "!-.0-~",
196
+ lower: "a-z",
197
+ print: " -.0-~",
198
+ punct: "!-.:-@\\[-`{-~",
199
+ space: " \\t\\n\\r",
200
+ upper: "A-Z",
201
+ xdigit: "0-9A-Fa-f"
202
+ };
203
+ const CLASS_MEMBERS_TO_ESCAPE = "\\]^-[";
204
+ const escapeMember = (char) => CLASS_MEMBERS_TO_ESCAPE.indexOf(char) < 0 ? char : ESCAPE + char;
205
+ const NON_SLASH = "(?!\\/)";
206
+ const classSource = (negated, body) => {
207
+ if (negated) return `[^\\/${body}]`;
208
+ const source = `[${body}]`;
209
+ return new RegExp(source).test("/") ? NON_SLASH + source : source;
210
+ };
211
+ const scanBracket = (pattern, start) => {
212
+ const { length } = pattern;
213
+ let index = start + 1;
214
+ let negated = EMPTY;
215
+ const lead = pattern[index];
216
+ if (lead === "!" || lead === "^") {
217
+ negated = "^";
218
+ index++;
219
+ }
220
+ let body = EMPTY;
221
+ let prev = EMPTY;
222
+ for (;;) {
223
+ const char = pattern[index];
224
+ if (char === UNDEFINED) return null;
225
+ if (char === ESCAPE) {
226
+ const escaped = pattern[index + 1];
227
+ if (escaped === UNDEFINED) return null;
228
+ body += escapeMember(escaped);
229
+ prev = escaped;
230
+ index++;
231
+ } else if (char === "-" && prev && index + 1 < length && pattern[index + 1] !== "]") {
232
+ index++;
233
+ let to = pattern[index];
234
+ if (to === ESCAPE) to = pattern[index += 1];
235
+ if (prev <= to) body += `-${escapeMember(to)}`;
236
+ prev = EMPTY;
237
+ } else if (char === "[" && pattern[index + 1] === ":") {
238
+ const nameStart = index + 2;
239
+ let end = nameStart;
240
+ while (end < length && pattern[end] !== "]") end++;
241
+ if (end === length) return null;
242
+ if (end > nameStart && pattern[end - 1] === ":") {
243
+ const expanded = POSIX_CLASSES[pattern.slice(nameStart, end - 1)];
244
+ if (expanded === UNDEFINED) return null;
245
+ body += expanded;
246
+ prev = EMPTY;
247
+ index = end;
248
+ } else {
249
+ body += escapeMember("[");
250
+ prev = "[";
251
+ index = nameStart - 2;
252
+ }
253
+ } else {
254
+ body += escapeMember(char);
255
+ prev = char;
256
+ }
257
+ index++;
258
+ if (pattern[index] === "]") return {
259
+ end: index,
260
+ source: classSource(negated, body)
261
+ };
262
+ }
263
+ };
264
+ const NEVER_MATCH = "[]";
265
+ const PLACEHOLDER = "\0";
266
+ const REGEX_RESTORE_PLACEHOLDER = new RegExp(`${PLACEHOLDER}(\\d+)${PLACEHOLDER}`, "g");
267
+ const TRAILING_WILDCARD = "";
268
+ const TRAILING_DOUBLESTAR = "";
269
+ const extractBrackets = (pattern) => {
270
+ const sources = [];
271
+ const hold = (source) => `${PLACEHOLDER}${sources.push(source) - 1}${PLACEHOLDER}`;
272
+ const { length } = pattern;
273
+ let out = EMPTY;
274
+ let index = 0;
275
+ while (index < length) {
276
+ const char = pattern[index];
277
+ if (char === ESCAPE) {
278
+ const escaped = pattern[index + 1];
279
+ if (escaped === UNDEFINED || escaped === SLASH && index + 2 === length) out += hold(NEVER_MATCH);
280
+ else if (escaped === "*" || escaped === "[" || escaped === SPACE || escaped === ESCAPE) out += pattern.slice(index, index + 2);
281
+ else out += hold(REGEX_LITERAL_SPECIAL.test(escaped) ? ESCAPE + escaped : escaped);
282
+ index += 2;
283
+ } else if (char === PLACEHOLDER) {
284
+ out += hold(`[${PLACEHOLDER}]`);
285
+ index++;
286
+ } else if (char === "[") {
287
+ const scanned = scanBracket(pattern, index);
288
+ if (scanned === null) {
289
+ out += hold(NEVER_MATCH);
290
+ index = length;
291
+ } else {
292
+ out += hold(scanned.source);
293
+ index = scanned.end + 1;
294
+ }
295
+ } else {
296
+ out += char;
297
+ index++;
298
+ }
299
+ }
300
+ return {
301
+ source: out,
302
+ sources
303
+ };
304
+ };
305
+ const DIRECT = null;
306
+ const REGEX_INNER_SLASH = /\/(?!$)/;
182
307
  const REPLACERS = [
183
- [/^\uFEFF/, () => EMPTY],
184
- [/((?:\\\\)*?)(\\?\s+)$/, (_, m1, m2) => m1 + (m2.indexOf("\\") === 0 ? SPACE : EMPTY)],
185
- [/(\\+?)\s/g, (_, m1) => {
186
- const { length } = m1;
187
- return m1.slice(0, length - length % 2) + SPACE;
188
- }],
308
+ [
309
+ /(\\+)( ?)/g,
310
+ (_, run, space) => space ? run.slice(0, run.length - run.length % 2) + SPACE : run,
311
+ "\\ "
312
+ ],
189
313
  [/[\\$.|*+(){^]/g, (match) => `\\${match}`],
190
- [/(?!\\)\?/g, () => "[^/]"],
191
- [/^\//, () => "^"],
192
- [/\//g, () => "\\/"],
193
- [/^\^*\\\*\\\*\\\//, () => "^(?:.*\\/)?"],
194
- [/^(?=[^^])/, function startingReplacer() {
195
- return !/\/(?!$)/.test(this) ? "(?:^|\\/)" : "^";
314
+ [
315
+ /(?!\\)\?/g,
316
+ () => "[^/]",
317
+ "?"
318
+ ],
319
+ [
320
+ /^\//,
321
+ () => "^",
322
+ SLASH
323
+ ],
324
+ [
325
+ /\//g,
326
+ () => "\\/",
327
+ SLASH
328
+ ],
329
+ [
330
+ /^\^*(?:\\\*\\\*\\\/)+/,
331
+ () => "^(?:.*\\/)?",
332
+ "*"
333
+ ],
334
+ [DIRECT, (source, pattern) => {
335
+ if (!source || source[0] === "^") return source;
336
+ return (!REGEX_INNER_SLASH.test(pattern) ? "(?:^|\\/)" : "^") + source;
196
337
  }],
197
- [/\\\/\\\*\\\*(?=\\\/|$)/g, (_, index, str) => index + 6 < str.length ? "(?:\\/[^\\/]+)*" : "\\/.+"],
198
- [/(^|[^\\]+)(\\\*)+(?=.+)/g, (_, p1, p2) => {
199
- return p1 + p2.replace(/\\\*/g, "[^\\/]*");
200
- }],
201
- [/\\\\\\(?=[$.|*+(){^])/g, () => ESCAPE],
202
- [/\\\\/g, () => ESCAPE],
203
- [/(\\)?\[([^\]/]*?)(\\*)($|\])/g, (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}` : close === "]" ? endEscape.length % 2 === 0 ? `[${sanitizeRange(range)}${endEscape}]` : "[]" : "[]"],
204
- [/(?:[^*])$/, (match) => /\/$/.test(match) ? `${match}$` : `${match}(?=$|\\/$)`]
338
+ [
339
+ /\\\/\\\*\\\*(?=\\\/|$)/g,
340
+ (_, index, str) => index + 6 < str.length ? str.slice(index + 6) === "\\/" ? "(?:\\/[^\\/]+)+" : "(?:\\/[^\\/]+)*" : `\\/${TRAILING_DOUBLESTAR}`,
341
+ "*"
342
+ ],
343
+ [
344
+ /(^|[^\\]+)(\\\*)+(?=.+)/g,
345
+ (_, p1, p2) => {
346
+ return p1 + p2.replace(/\\\*/g, "[^\\/]*");
347
+ },
348
+ "*"
349
+ ],
350
+ [
351
+ /(^|[^\\])((?:\\\\)*)\\\*$/,
352
+ (match, p1, p2) => p2.length / 2 % 2 === 0 ? p1 + p2 + TRAILING_WILDCARD : match,
353
+ "*"
354
+ ],
355
+ [
356
+ /\\\\\\(?=[$.|*+(){^])/g,
357
+ () => ESCAPE,
358
+ "\\\\"
359
+ ],
360
+ [
361
+ /\\\\/g,
362
+ () => ESCAPE,
363
+ "\\\\"
364
+ ],
365
+ [
366
+ /\\\[([^\]/]*?)(\\*)($|\])/g,
367
+ (match, range, endEscape, close) => `\\[${range}${cleanRangeBackSlash(endEscape)}${close}`,
368
+ "["
369
+ ],
370
+ [DIRECT, (source) => {
371
+ const last = source[source.length - 1];
372
+ if (!last || last === TRAILING_WILDCARD || last === TRAILING_DOUBLESTAR) return source;
373
+ return last === SLASH ? `${source}$` : `${source}(?=$|\\/$)`;
374
+ }]
205
375
  ];
206
- const REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\/)?\\\*$/;
376
+ const REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\/)?\uE000$/;
207
377
  const MODE_IGNORE = "regex";
208
378
  const MODE_CHECK_IGNORE = "checkRegex";
209
- const TRAILING_WILD_CARD_REPLACERS = {
210
- [MODE_IGNORE](_, p1) {
211
- return `${p1 ? `${p1}[^/]+` : "[^/]*"}(?=$|\\/$)`;
212
- },
213
- [MODE_CHECK_IGNORE](_, p1) {
214
- return `${p1 ? `${p1}[^/]*` : "[^/]*"}(?=$|\\/$)`;
379
+ const replaceTrailingWildcard = (_, p1) => {
380
+ return `${p1 ? `${p1}[^/]+` : "[^/]*"}(?=$|\\/$)`;
381
+ };
382
+ const REGEX_REPLACE_TRAILING_DOUBLESTAR = /\uE001$/;
383
+ const replaceTrailingDoublestar = () => ".+(?=$|\\/$)";
384
+ const WILDCARD = "[^\\/]*";
385
+ const separatorAfter = (run, at) => {
386
+ let separator = EMPTY;
387
+ for (let index = at + 1; index < run.length && !run[index].wildcard; index++) separator += run[index].single;
388
+ return separator;
389
+ };
390
+ const pinWildcards = (source) => {
391
+ if (source.indexOf(WILDCARD) < 0) return source;
392
+ const tokens = [];
393
+ const { length } = source;
394
+ let index = 0;
395
+ while (index < length) {
396
+ const char = source[index];
397
+ if (source.startsWith(WILDCARD, index)) {
398
+ tokens.push({ wildcard: true });
399
+ index += 6;
400
+ } else if (char === "[") {
401
+ let end = index + 1;
402
+ if (source[end] === "^") end++;
403
+ if (source[end] === "]") end++;
404
+ while (end < length && source[end] !== "]") end += source[end] === ESCAPE ? 2 : 1;
405
+ end++;
406
+ tokens.push({ single: source.slice(index, end) });
407
+ index = end;
408
+ } else if (char === ESCAPE) {
409
+ tokens.push({ single: source.slice(index, index + 2) });
410
+ index += 2;
411
+ } else if (char === "(") {
412
+ let depth = 0;
413
+ let end = index;
414
+ do {
415
+ if (source[end] === ESCAPE) end++;
416
+ else if (source[end] === "(") depth++;
417
+ else if (source[end] === ")") depth--;
418
+ end++;
419
+ } while (end < length && depth > 0);
420
+ if ("*+?".indexOf(source[end]) >= 0) end++;
421
+ tokens.push({ boundary: source.slice(index, end) });
422
+ index = end;
423
+ } else if (char === "^" || char === "$") {
424
+ tokens.push({ boundary: char });
425
+ index++;
426
+ } else {
427
+ tokens.push({ single: char });
428
+ index++;
429
+ }
215
430
  }
431
+ let out = EMPTY;
432
+ let run = [];
433
+ const flush = () => {
434
+ let lastWildcard;
435
+ run.forEach((token, at) => {
436
+ if (token.wildcard) lastWildcard = at;
437
+ });
438
+ run.forEach((token, at) => {
439
+ if (!token.wildcard) {
440
+ out += token.single;
441
+ return;
442
+ }
443
+ out += at === lastWildcard ? WILDCARD : `(?:(?!${separatorAfter(run, at)})[^\\/])*`;
444
+ });
445
+ run = [];
446
+ };
447
+ tokens.forEach((token) => {
448
+ if (token.boundary === void 0) {
449
+ run.push(token);
450
+ return;
451
+ }
452
+ flush();
453
+ out += token.boundary;
454
+ });
455
+ flush();
456
+ return out;
457
+ };
458
+ const makeRegexPrefix = (pattern) => {
459
+ const { source, sources } = extractBrackets(pattern);
460
+ const replaced = REPLACERS.reduce((prev, [matcher, replacer, required]) => {
461
+ if (matcher === DIRECT) return replacer(prev, pattern);
462
+ if (required !== UNDEFINED && prev.indexOf(required) < 0) return prev;
463
+ return matcher.test(prev) ? prev.replace(matcher, replacer.bind(pattern)) : prev;
464
+ }, source);
465
+ return sources.length ? replaced.replace(REGEX_RESTORE_PLACEHOLDER, (match, index) => sources[index]) : replaced;
466
+ };
467
+ const checkSourceOf = (body, prefix) => {
468
+ if (body[body.length - 1] === SLASH) prefix = makeRegexPrefix(body.slice(0, -1));
469
+ const head = prefix.slice(0, -1);
470
+ const last = prefix[prefix.length - 1];
471
+ return last === TRAILING_WILDCARD ? `${head}$` : last === TRAILING_DOUBLESTAR ? `${head}.*$` : NEVER_MATCH;
472
+ };
473
+ const matchesBasename = (body) => {
474
+ const index = body.indexOf(SLASH);
475
+ return index < 0 || index === body.length - 1;
476
+ };
477
+ const basenameOf = (path) => {
478
+ const end = path.length - 1;
479
+ const index = path.lastIndexOf(SLASH, path[end] === SLASH ? end - 1 : end);
480
+ return index < 0 ? path : path.slice(index + 1);
481
+ };
482
+ const parentOf = (path) => {
483
+ if (path.charCodeAt(0) === SLASH_CODE || path.indexOf(DOUBLE_SLASH) >= 0) {
484
+ const slices = path.split(SLASH).filter(Boolean);
485
+ slices.pop();
486
+ return slices.length ? slices.join(SLASH) + SLASH : EMPTY;
487
+ }
488
+ const end = path.length - 1;
489
+ const cut = path.lastIndexOf(SLASH, path.charCodeAt(end) === SLASH_CODE ? end - 1 : end);
490
+ return cut < 0 ? EMPTY : path.slice(0, cut + 1);
216
491
  };
217
- const makeRegexPrefix = (pattern) => REPLACERS.reduce((prev, [matcher, replacer]) => prev.replace(matcher, replacer.bind(pattern)), pattern);
218
492
  const isString = (subject) => typeof subject === "string";
219
- const checkPattern = (pattern) => pattern && isString(pattern) && !REGEX_TEST_BLANK_LINE.test(pattern) && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern) && pattern.indexOf("#") !== 0;
493
+ const checkPattern = (pattern) => pattern && isString(pattern) && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern);
220
494
  const splitPattern = (pattern) => pattern.split(REGEX_SPLITALL_CRLF).filter(Boolean);
221
495
  var IgnoreRule = class {
222
496
  constructor(pattern, mark, body, ignoreCase, negative, prefix) {
@@ -227,6 +501,9 @@ var import_ignore = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
227
501
  define(this, "ignoreCase", ignoreCase);
228
502
  define(this, "regexPrefix", prefix);
229
503
  }
504
+ get _basenameOnly() {
505
+ return define(this, "_basenameOnly", matchesBasename(this.body));
506
+ }
230
507
  get regex() {
231
508
  const key = "_regex";
232
509
  if (this[key]) return this[key];
@@ -238,18 +515,33 @@ var import_ignore = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
238
515
  return this._make(MODE_CHECK_IGNORE, key);
239
516
  }
240
517
  _make(mode, key) {
241
- const str = this.regexPrefix.replace(REGEX_REPLACE_TRAILING_WILDCARD, TRAILING_WILD_CARD_REPLACERS[mode]);
518
+ const str = pinWildcards(mode === MODE_IGNORE ? this.regexPrefix.replace(REGEX_REPLACE_TRAILING_WILDCARD, replaceTrailingWildcard).replace(REGEX_REPLACE_TRAILING_DOUBLESTAR, replaceTrailingDoublestar) : checkSourceOf(this.body, this.regexPrefix));
242
519
  const regex = this.ignoreCase ? new RegExp(str, "i") : new RegExp(str);
243
520
  return define(this, key, regex);
244
521
  }
245
522
  };
523
+ const isLineEnd = (char) => char === "\r" || char === "\n";
524
+ const trimEnd = (body) => {
525
+ let end = body.length;
526
+ while (end && isLineEnd(body[end - 1])) end--;
527
+ const lineEnd = end;
528
+ while (end && body[end - 1] === SPACE) end--;
529
+ if (end === lineEnd) return body.slice(0, end);
530
+ let backslashes = 0;
531
+ while (backslashes < end && body[end - backslashes - 1] === ESCAPE) backslashes++;
532
+ return backslashes % 2 ? body.slice(0, end - 1) + SPACE : body.slice(0, end);
533
+ };
246
534
  const createRule = ({ pattern, mark }, ignoreCase) => {
535
+ let body = pattern[0] === BOM ? pattern.slice(1) : pattern;
536
+ if (body[0] === "#") return;
247
537
  let negative = false;
248
- let body = pattern;
249
- if (body.indexOf("!") === 0) {
538
+ if (body[0] === "!") {
250
539
  negative = true;
251
- body = body.substr(1);
540
+ body = body.slice(1);
252
541
  }
542
+ const last = body[body.length - 1];
543
+ if (last === SPACE || last === "\r" || last === "\n") body = trimEnd(body);
544
+ if (!body) return;
253
545
  body = body.replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, "!").replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, "#");
254
546
  const regexPrefix = makeRegexPrefix(body);
255
547
  return new IgnoreRule(pattern, mark, body, ignoreCase, negative, regexPrefix);
@@ -258,37 +550,67 @@ var import_ignore = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
258
550
  constructor(ignoreCase) {
259
551
  this._ignoreCase = ignoreCase;
260
552
  this._rules = [];
553
+ this._basenameCount = 0;
261
554
  }
262
555
  _add(pattern) {
263
556
  if (pattern && pattern[KEY_IGNORE]) {
264
557
  this._rules = this._rules.concat(pattern._rules._rules);
558
+ this._basenameCount += pattern._rules._basenameCount;
265
559
  this._added = true;
266
560
  return;
267
561
  }
268
562
  if (isString(pattern)) pattern = { pattern };
269
- if (checkPattern(pattern.pattern)) {
270
- const rule = createRule(pattern, this._ignoreCase);
563
+ const rule = checkPattern(pattern.pattern) && createRule(pattern, this._ignoreCase);
564
+ if (rule) {
271
565
  this._added = true;
272
566
  this._rules.push(rule);
567
+ if (matchesBasename(rule.body)) this._basenameCount++;
273
568
  }
274
569
  }
275
570
  add(pattern) {
276
571
  this._added = false;
277
572
  makeArray(isString(pattern) ? splitPattern(pattern) : pattern).forEach(this._add, this);
573
+ if (this._added) this._literalRules = UNDEFINED;
278
574
  return this._added;
279
575
  }
576
+ testLiteral(path) {
577
+ const rules = this._literalRules || (this._literalRules = this._rules.filter(({ body }) => body[body.length - (body[body.length - 1] === SLASH ? 2 : 1)] === "*"));
578
+ let ignored = false;
579
+ let unignored = false;
580
+ let matchedRule;
581
+ for (let index = rules.length - 1; index >= 0; index--) {
582
+ const rule = rules[index];
583
+ if (rule.checkRegex.test(path)) {
584
+ ignored = !rule.negative;
585
+ unignored = rule.negative;
586
+ matchedRule = rule.negative ? UNDEFINED : rule;
587
+ break;
588
+ }
589
+ }
590
+ const ret = {
591
+ ignored,
592
+ unignored
593
+ };
594
+ if (matchedRule) ret.rule = matchedRule;
595
+ return ret;
596
+ }
280
597
  test(path, checkUnignored, mode) {
281
598
  let ignored = false;
282
599
  let unignored = false;
283
600
  let matchedRule;
284
- this._rules.forEach((rule) => {
601
+ const rules = this._rules;
602
+ const { length } = rules;
603
+ const shortcut = this._basenameCount * 2 >= length;
604
+ const basename = shortcut ? basenameOf(path) : path;
605
+ for (let index = 0; index < length; index++) {
606
+ const rule = rules[index];
285
607
  const { negative } = rule;
286
- if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) return;
287
- if (!rule[mode].test(path)) return;
288
- ignored = !negative;
289
- unignored = negative;
290
- matchedRule = negative ? UNDEFINED : rule;
291
- });
608
+ if (!(unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) && rule[mode].test(shortcut && rule._basenameOnly ? basename : path)) {
609
+ ignored = !negative;
610
+ unignored = negative;
611
+ matchedRule = negative ? UNDEFINED : rule;
612
+ }
613
+ }
292
614
  const ret = {
293
615
  ignored,
294
616
  unignored
@@ -306,7 +628,16 @@ var import_ignore = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
306
628
  if (checkPath.isNotRelative(path)) return doThrow(`path should be a \`path.relative()\`d string, but got "${originalPath}"`, RangeError);
307
629
  return true;
308
630
  };
309
- const isNotRelative = (path) => REGEX_TEST_INVALID_PATH.test(path);
631
+ const isNotRelative = (path) => {
632
+ const first = path.charCodeAt(0);
633
+ if (first === SLASH_CODE) return true;
634
+ if (first !== DOT_CODE) return false;
635
+ if (path.length === 1) return true;
636
+ const second = path.charCodeAt(1);
637
+ if (second === SLASH_CODE) return true;
638
+ if (second !== DOT_CODE) return false;
639
+ return path.length === 2 || path.charCodeAt(2) === SLASH_CODE;
640
+ };
310
641
  checkPath.isNotRelative = isNotRelative;
311
642
  /* istanbul ignore next */
312
643
  checkPath.convert = (p) => p;
@@ -328,28 +659,23 @@ var import_ignore = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
328
659
  addPattern(pattern) {
329
660
  return this.add(pattern);
330
661
  }
331
- _test(originalPath, cache, checkUnignored, slices) {
662
+ _test(originalPath, cache, checkUnignored) {
332
663
  const path = originalPath && checkPath.convert(originalPath);
333
664
  checkPath(path, originalPath, this._strictPathCheck ? throwError : RETURN_FALSE);
334
- return this._t(path, cache, checkUnignored, slices);
665
+ return this._t(path, cache, checkUnignored);
335
666
  }
336
667
  checkIgnore(path) {
337
- if (!REGEX_TEST_TRAILING_SLASH.test(path)) return this.test(path);
338
- const slices = path.split(SLASH).filter(Boolean);
339
- slices.pop();
340
- if (slices.length) {
341
- const parent = this._t(slices.join(SLASH) + SLASH, this._testCache, true, slices);
342
- if (parent.ignored) return parent;
343
- }
344
- return this._rules.test(path, false, MODE_CHECK_IGNORE);
668
+ if (path.charCodeAt(path.length - 1) !== SLASH_CODE) return this.test(path);
669
+ const dir = this._t(path, this._testCache, true);
670
+ if (dir.ignored) return dir;
671
+ const literal = this._rules.testLiteral(path);
672
+ return literal.ignored || literal.unignored ? literal : dir;
345
673
  }
346
- _t(path, cache, checkUnignored, slices) {
674
+ _t(path, cache, checkUnignored) {
347
675
  if (path in cache) return cache[path];
348
- if (!slices) slices = path.split(SLASH).filter(Boolean);
349
- slices.pop();
350
- if (!slices.length) return cache[path] = this._rules.test(path, checkUnignored, MODE_IGNORE);
351
- const parent = this._t(slices.join(SLASH) + SLASH, cache, checkUnignored, slices);
352
- return cache[path] = parent.ignored ? parent : this._rules.test(path, checkUnignored, MODE_IGNORE);
676
+ const parentPath = parentOf(path);
677
+ const parent = parentPath ? this._t(parentPath, cache, checkUnignored) : UNDEFINED;
678
+ return cache[path] = parent && parent.ignored ? parent : this._rules.test(path, checkUnignored, MODE_IGNORE);
353
679
  }
354
680
  ignores(path) {
355
681
  return this._test(path, this._ignoreCache, false).ignored;
@@ -561,4 +887,4 @@ const handlerRegistry = createRegistry("scope").from({
561
887
  //#endregion
562
888
  export { handlerRegistry as t };
563
889
 
564
- //# sourceMappingURL=registry-CFmR5G3J.mjs.map
890
+ //# sourceMappingURL=registry-Bao6L4Ue.mjs.map