maka-agent 0.2.0-dev.30.20260912 → 0.2.0-dev.31.20260913

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 (194) hide show
  1. package/THIRD_PARTY_NOTICES.txt +392 -0
  2. package/dist/acp/maka-acp-agent.js +8 -2
  3. package/dist/acp/prompt-content.js +225 -0
  4. package/dist/acp/session-event-mapper.js +103 -0
  5. package/dist/acp/session-registry.js +654 -17
  6. package/dist/acp/stdio-server.js +10 -1
  7. package/dist/cli-core.js +1 -1
  8. package/dist/pi-transcript-tools.js +3 -2
  9. package/dist/pi-transcript.js +12 -2
  10. package/dist/runtime-host-session-channel.js +63 -9
  11. package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
  12. package/node_modules/@maka/core/dist/artifacts.js +6 -0
  13. package/node_modules/@maka/core/dist/attachments.js +7 -2
  14. package/node_modules/@maka/core/dist/durable-tool-result-projection.js +3 -1
  15. package/node_modules/@maka/core/dist/events.js +21 -0
  16. package/node_modules/@maka/core/dist/goal.js +44 -2
  17. package/node_modules/@maka/core/dist/permission.js +0 -1
  18. package/node_modules/@maka/core/dist/runtime-boundary.js +73 -29
  19. package/node_modules/@maka/core/dist/runtime-event.js +6 -3
  20. package/node_modules/@maka/core/dist/runtime-handoff.js +10 -2
  21. package/node_modules/@maka/core/dist/runtime-logical-execution.js +39 -14
  22. package/node_modules/@maka/core/dist/tool-result-archive-evidence.js +3 -1
  23. package/node_modules/@maka/core/dist/tool-result-record-schema.js +2 -1
  24. package/node_modules/@maka/core/dist/unified-diff.js +33 -26
  25. package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +49 -178
  26. package/node_modules/@maka/runtime/dist/ai-sdk-message-projection.js +7 -2
  27. package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +15 -53
  28. package/node_modules/@maka/runtime/dist/bash-model-output.js +7 -1
  29. package/node_modules/@maka/runtime/dist/bash-tail-buffer.js +13 -52
  30. package/node_modules/@maka/runtime/dist/builtin-tools.js +59 -111
  31. package/node_modules/@maka/runtime/dist/child-fd-input.js +3 -2
  32. package/node_modules/@maka/runtime/dist/context-budget-policy.js +1 -11
  33. package/node_modules/@maka/runtime/dist/context-budget.js +12 -1
  34. package/node_modules/@maka/runtime/dist/conversation-copy.js +104 -9
  35. package/node_modules/@maka/runtime/dist/filesystem-executor.js +10 -6
  36. package/node_modules/@maka/runtime/dist/filesystem-worker/client.js +77 -19
  37. package/node_modules/@maka/runtime/dist/filesystem-worker/launch-spec.js +66 -55
  38. package/node_modules/@maka/runtime/dist/filesystem-worker/operations.js +34 -97
  39. package/node_modules/@maka/runtime/dist/filesystem-worker/protocol.js +25 -10
  40. package/node_modules/@maka/runtime/dist/filesystem-worker/worker-entry.js +2 -0
  41. package/node_modules/@maka/runtime/dist/glob-search.js +74 -0
  42. package/node_modules/@maka/runtime/dist/goal-continuation.js +78 -8
  43. package/node_modules/@maka/runtime/dist/goal-state.js +7 -0
  44. package/node_modules/@maka/runtime/dist/grep-search.js +155 -0
  45. package/node_modules/@maka/runtime/dist/ledger-tool-result-archive-reader.js +84 -94
  46. package/node_modules/@maka/runtime/dist/model-history.js +25 -3
  47. package/node_modules/@maka/runtime/dist/pipe-tail-collector.js +6 -9
  48. package/node_modules/@maka/runtime/dist/read-page.js +231 -0
  49. package/node_modules/@maka/runtime/dist/request-projection.js +2 -15
  50. package/node_modules/@maka/runtime/dist/ripgrep-executable.js +62 -0
  51. package/node_modules/@maka/runtime/dist/ripgrep-guidance.js +81 -0
  52. package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +187 -20
  53. package/node_modules/@maka/runtime/dist/runtime-read-model.js +2 -1
  54. package/node_modules/@maka/runtime/dist/sandbox/linux-profile-path.js +7 -1
  55. package/node_modules/@maka/runtime/dist/sandbox/linux-sandbox.js +20 -5
  56. package/node_modules/@maka/runtime/dist/session-manager.js +6 -6
  57. package/node_modules/@maka/runtime/dist/session-recap.js +9 -5
  58. package/node_modules/@maka/runtime/dist/shell-exec.js +7 -25
  59. package/node_modules/@maka/runtime/dist/shell-run-manager.js +1 -1
  60. package/node_modules/@maka/runtime/dist/shell-run-tool-result.js +1 -1
  61. package/node_modules/@maka/runtime/dist/shell-tools.js +6 -12
  62. package/node_modules/@maka/runtime/dist/tool-availability.js +0 -1
  63. package/node_modules/@maka/runtime/dist/tool-output.js +1 -1
  64. package/node_modules/@maka/runtime/dist/tool-result-archive-capability.js +24 -36
  65. package/node_modules/@maka/runtime/dist/tool-result-archive-resource.js +32 -527
  66. package/node_modules/@maka/runtime/dist/tool-result-archive-transition.js +17 -119
  67. package/node_modules/@maka/runtime/dist/tool-result-archive.js +7 -25
  68. package/node_modules/@maka/runtime/dist/tool-runtime.js +7 -5
  69. package/node_modules/@maka/runtime/dist/workers/filesystem-worker.js +6933 -3681
  70. package/node_modules/@maka/runtime/dist/workspace-executor.js +20 -24
  71. package/node_modules/@maka/runtime/package.json +2 -0
  72. package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +185 -191
  73. package/node_modules/@maka/runtime-host/dist/client/reconnecting-connection.js +3 -0
  74. package/node_modules/@maka/runtime-host/dist/protocol/index.js +5 -1
  75. package/node_modules/@maka/runtime-host/dist/protocol/message.js +2 -2
  76. package/node_modules/@maka/runtime-host/dist/protocol/operations.js +1 -0
  77. package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +2 -2
  78. package/node_modules/@maka/runtime-host/dist/protocol/turn.js +10 -2
  79. package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +38 -0
  80. package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +2 -8
  81. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +2 -0
  82. package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +81 -7
  83. package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +13 -13
  84. package/node_modules/@maka/runtime-host/dist/server/interaction-coordinator.js +65 -0
  85. package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +1 -0
  86. package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +5 -2
  87. package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +88 -72
  88. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +21 -4
  89. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +145 -1
  90. package/node_modules/@maka/storage/dist/agent-run-store.js +5 -2
  91. package/node_modules/@maka/storage/dist/execution-stores.js +2 -1
  92. package/node_modules/@maka/storage/dist/runtime-transcript-query.js +27 -14
  93. package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +69 -3
  94. package/node_modules/balanced-match/LICENSE.md +23 -0
  95. package/node_modules/balanced-match/README.md +57 -0
  96. package/node_modules/balanced-match/dist/commonjs/index.js +59 -0
  97. package/node_modules/balanced-match/dist/commonjs/package.json +3 -0
  98. package/node_modules/balanced-match/dist/esm/index.js +54 -0
  99. package/node_modules/balanced-match/dist/esm/package.json +3 -0
  100. package/node_modules/balanced-match/package.json +68 -0
  101. package/node_modules/brace-expansion/LICENSE +23 -0
  102. package/node_modules/brace-expansion/README.md +105 -0
  103. package/node_modules/brace-expansion/dist/commonjs/index.js +289 -0
  104. package/node_modules/brace-expansion/dist/commonjs/package.json +3 -0
  105. package/node_modules/brace-expansion/dist/esm/index.js +285 -0
  106. package/node_modules/brace-expansion/dist/esm/package.json +3 -0
  107. package/node_modules/brace-expansion/package.json +64 -0
  108. package/node_modules/glob/LICENSE.md +63 -0
  109. package/node_modules/glob/README.md +1203 -0
  110. package/node_modules/glob/dist/commonjs/glob.js +248 -0
  111. package/node_modules/glob/dist/commonjs/has-magic.js +27 -0
  112. package/node_modules/glob/dist/commonjs/ignore.js +119 -0
  113. package/node_modules/glob/dist/commonjs/index.js +68 -0
  114. package/node_modules/glob/dist/commonjs/index.min.js +4 -0
  115. package/node_modules/glob/dist/commonjs/package.json +3 -0
  116. package/node_modules/glob/dist/commonjs/pattern.js +223 -0
  117. package/node_modules/glob/dist/commonjs/processor.js +301 -0
  118. package/node_modules/glob/dist/commonjs/walker.js +387 -0
  119. package/node_modules/glob/dist/esm/glob.js +244 -0
  120. package/node_modules/glob/dist/esm/has-magic.js +23 -0
  121. package/node_modules/glob/dist/esm/ignore.js +115 -0
  122. package/node_modules/glob/dist/esm/index.js +55 -0
  123. package/node_modules/glob/dist/esm/index.min.js +4 -0
  124. package/node_modules/glob/dist/esm/package.json +3 -0
  125. package/node_modules/glob/dist/esm/pattern.js +219 -0
  126. package/node_modules/glob/dist/esm/processor.js +294 -0
  127. package/node_modules/glob/dist/esm/walker.js +381 -0
  128. package/node_modules/glob/package.json +98 -0
  129. package/node_modules/minimatch/LICENSE.md +55 -0
  130. package/node_modules/minimatch/README.md +528 -0
  131. package/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js +14 -0
  132. package/node_modules/minimatch/dist/commonjs/ast.js +845 -0
  133. package/node_modules/minimatch/dist/commonjs/brace-expressions.js +150 -0
  134. package/node_modules/minimatch/dist/commonjs/escape.js +30 -0
  135. package/node_modules/minimatch/dist/commonjs/index.js +1127 -0
  136. package/node_modules/minimatch/dist/commonjs/package.json +3 -0
  137. package/node_modules/minimatch/dist/commonjs/unescape.js +38 -0
  138. package/node_modules/minimatch/dist/esm/assert-valid-pattern.js +10 -0
  139. package/node_modules/minimatch/dist/esm/ast.js +841 -0
  140. package/node_modules/minimatch/dist/esm/brace-expressions.js +146 -0
  141. package/node_modules/minimatch/dist/esm/escape.js +26 -0
  142. package/node_modules/minimatch/dist/esm/index.js +1114 -0
  143. package/node_modules/minimatch/dist/esm/package.json +3 -0
  144. package/node_modules/minimatch/dist/esm/unescape.js +34 -0
  145. package/node_modules/minimatch/package.json +73 -0
  146. package/node_modules/minipass/LICENSE.md +55 -0
  147. package/node_modules/minipass/README.md +825 -0
  148. package/node_modules/minipass/dist/commonjs/index.js +1038 -0
  149. package/node_modules/minipass/dist/commonjs/package.json +3 -0
  150. package/node_modules/minipass/dist/esm/index.js +1020 -0
  151. package/node_modules/minipass/dist/esm/package.json +3 -0
  152. package/node_modules/minipass/package.json +77 -0
  153. package/node_modules/path-scurry/LICENSE.md +55 -0
  154. package/node_modules/path-scurry/README.md +636 -0
  155. package/node_modules/path-scurry/dist/commonjs/index.js +2018 -0
  156. package/node_modules/path-scurry/dist/commonjs/package.json +3 -0
  157. package/node_modules/path-scurry/dist/esm/index.js +1983 -0
  158. package/node_modules/path-scurry/dist/esm/package.json +3 -0
  159. package/node_modules/path-scurry/node_modules/lru-cache/LICENSE.md +55 -0
  160. package/node_modules/path-scurry/node_modules/lru-cache/README.md +469 -0
  161. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel.js +7 -0
  162. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.js +1726 -0
  163. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.min.js +2 -0
  164. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.js +10 -0
  165. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel-cjs.d.cts.map +1 -0
  166. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel.js +7 -0
  167. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js +1726 -0
  168. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js +2 -0
  169. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel.js +9 -0
  170. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.js +1726 -0
  171. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.min.js +2 -0
  172. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.js +10 -0
  173. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/package.json +3 -0
  174. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.js +10 -0
  175. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.js +4 -0
  176. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.js +1722 -0
  177. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.min.js +2 -0
  178. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.js +7 -0
  179. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel-esm.d.mts.map +1 -0
  180. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel.js +19 -0
  181. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js +1722 -0
  182. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js +2 -0
  183. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel.js +6 -0
  184. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.js +1722 -0
  185. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.min.js +2 -0
  186. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.js +7 -0
  187. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/package.json +3 -0
  188. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.js +7 -0
  189. package/node_modules/path-scurry/node_modules/lru-cache/package.json +154 -0
  190. package/node_modules/path-scurry/package.json +72 -0
  191. package/package.json +1 -1
  192. package/node_modules/@maka/runtime/dist/active-tool-result-prune.js +0 -248
  193. package/node_modules/@maka/runtime/dist/active-tool-result-working-set.js +0 -218
  194. package/node_modules/@maka/runtime/dist/archive-read-tool.js +0 -115
@@ -0,0 +1,289 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EXPANSION_MAX_LENGTH = exports.EXPANSION_MAX = void 0;
4
+ exports.expand = expand;
5
+ const balanced_match_1 = require("balanced-match");
6
+ const escSlash = '\0SLASH' + Math.random() + '\0';
7
+ const escOpen = '\0OPEN' + Math.random() + '\0';
8
+ const escClose = '\0CLOSE' + Math.random() + '\0';
9
+ const escComma = '\0COMMA' + Math.random() + '\0';
10
+ const escPeriod = '\0PERIOD' + Math.random() + '\0';
11
+ const escSlashPattern = new RegExp(escSlash, 'g');
12
+ const escOpenPattern = new RegExp(escOpen, 'g');
13
+ const escClosePattern = new RegExp(escClose, 'g');
14
+ const escCommaPattern = new RegExp(escComma, 'g');
15
+ const escPeriodPattern = new RegExp(escPeriod, 'g');
16
+ const slashPattern = /\\\\/g;
17
+ const openPattern = /\\{/g;
18
+ const closePattern = /\\}/g;
19
+ const commaPattern = /\\,/g;
20
+ const periodPattern = /\\\./g;
21
+ exports.EXPANSION_MAX = 100_000;
22
+ // `EXPANSION_MAX` caps the *number* of expansions, but not their length. An
23
+ // input like `'{a,b}'.repeat(1500)` stays under that count - its output is
24
+ // truncated to 100k results - while making every result ~1500 characters
25
+ // long. The result set, and the intermediate arrays built while combining
26
+ // brace sets, then grow large enough to exhaust memory and crash the process
27
+ // (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of
28
+ // characters the accumulator may hold at any point, so memory stays flat no
29
+ // matter how many brace groups are chained. The limit sits well above any
30
+ // realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
31
+ // characters) so legitimate input is unaffected.
32
+ exports.EXPANSION_MAX_LENGTH = 4_000_000;
33
+ function numeric(str) {
34
+ return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
35
+ }
36
+ function escapeBraces(str) {
37
+ return str
38
+ .replace(slashPattern, escSlash)
39
+ .replace(openPattern, escOpen)
40
+ .replace(closePattern, escClose)
41
+ .replace(commaPattern, escComma)
42
+ .replace(periodPattern, escPeriod);
43
+ }
44
+ function unescapeBraces(str) {
45
+ return str
46
+ .replace(escSlashPattern, '\\')
47
+ .replace(escOpenPattern, '{')
48
+ .replace(escClosePattern, '}')
49
+ .replace(escCommaPattern, ',')
50
+ .replace(escPeriodPattern, '.');
51
+ }
52
+ /**
53
+ * Basically just str.split(","), but handling cases
54
+ * where we have nested braced sections, which should be
55
+ * treated as individual members, like {a,{b,c},d}
56
+ */
57
+ function parseCommaParts(str) {
58
+ if (!str) {
59
+ return [''];
60
+ }
61
+ const parts = [];
62
+ const m = (0, balanced_match_1.balanced)('{', '}', str);
63
+ if (!m) {
64
+ return str.split(',');
65
+ }
66
+ const { pre, body, post } = m;
67
+ const p = pre.split(',');
68
+ p[p.length - 1] += '{' + body + '}';
69
+ const postParts = parseCommaParts(post);
70
+ if (post.length) {
71
+ ;
72
+ p[p.length - 1] += postParts.shift();
73
+ p.push.apply(p, postParts);
74
+ }
75
+ parts.push.apply(parts, p);
76
+ return parts;
77
+ }
78
+ function expand(str, options = {}) {
79
+ if (!str) {
80
+ return [];
81
+ }
82
+ const { max = exports.EXPANSION_MAX, maxLength = exports.EXPANSION_MAX_LENGTH } = options;
83
+ // I don't know why Bash 4.3 does this, but it does.
84
+ // Anything starting with {} will have the first two bytes preserved
85
+ // but *only* at the top level, so {},a}b will not expand to anything,
86
+ // but a{},b}c will be expanded to [a}c,abc].
87
+ // One could argue that this is a bug in Bash, but since the goal of
88
+ // this module is to match Bash's rules, we escape a leading {}
89
+ if (str.slice(0, 2) === '{}') {
90
+ str = '\\{\\}' + str.slice(2);
91
+ }
92
+ return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
93
+ }
94
+ function embrace(str) {
95
+ return '{' + str + '}';
96
+ }
97
+ function isPadded(el) {
98
+ return /^-?0\d/.test(el);
99
+ }
100
+ function lte(i, y) {
101
+ return i <= y;
102
+ }
103
+ function gte(i, y) {
104
+ return i >= y;
105
+ }
106
+ // Build `{ acc[a] + pre + values[v] }` for every combination, capping the
107
+ // number of results at `max` and the total number of characters at `maxLength`.
108
+ // This is the one place output grows, so bounding it here keeps the single
109
+ // accumulator - and therefore memory - flat regardless of how many brace groups
110
+ // are combined (CVE-2026-14257).
111
+ function combine(acc, pre, values, max, maxLength, dropEmpties) {
112
+ const out = [];
113
+ let length = 0;
114
+ for (let a = 0; a < acc.length; a++) {
115
+ for (let v = 0; v < values.length; v++) {
116
+ if (out.length >= max)
117
+ return out;
118
+ const expansion = acc[a] + pre + values[v];
119
+ // Bash drops empty results at the top level. Skip them before they count
120
+ // against `max`, so `max` bounds the number of *kept* results.
121
+ if (dropEmpties && !expansion)
122
+ continue;
123
+ if (length + expansion.length > maxLength)
124
+ return out;
125
+ out.push(expansion);
126
+ length += expansion.length;
127
+ }
128
+ }
129
+ return out;
130
+ }
131
+ // The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
132
+ // sequence body.
133
+ function expandSequence(body, isAlphaSequence, max, maxLength) {
134
+ const n = body.split(/\.\./);
135
+ const N = [];
136
+ // A sequence body always splits into two or three parts, but the compiler
137
+ // can't know that.
138
+ /* c8 ignore start */
139
+ if (n[0] === undefined || n[1] === undefined) {
140
+ return N;
141
+ }
142
+ /* c8 ignore stop */
143
+ const x = numeric(n[0]);
144
+ const y = numeric(n[1]);
145
+ const width = Math.max(n[0].length, n[1].length);
146
+ let incr = n.length === 3 && n[2] !== undefined ?
147
+ Math.max(Math.abs(numeric(n[2])), 1)
148
+ : 1;
149
+ let test = lte;
150
+ const reverse = y < x;
151
+ if (reverse) {
152
+ incr *= -1;
153
+ test = gte;
154
+ }
155
+ const pad = n.some(isPadded);
156
+ let length = 0;
157
+ for (let i = x; test(i, y) && N.length < max; i += incr) {
158
+ let c;
159
+ if (isAlphaSequence) {
160
+ c = String.fromCharCode(i);
161
+ if (c === '\\') {
162
+ c = '';
163
+ }
164
+ }
165
+ else {
166
+ c = String(i);
167
+ if (pad) {
168
+ const need = width - c.length;
169
+ if (need > 0) {
170
+ const z = new Array(need + 1).join('0');
171
+ if (i < 0) {
172
+ c = '-' + z + c.slice(1);
173
+ }
174
+ else {
175
+ c = z + c;
176
+ }
177
+ }
178
+ }
179
+ }
180
+ if (length + c.length > maxLength)
181
+ break;
182
+ N.push(c);
183
+ length += c.length;
184
+ }
185
+ return N;
186
+ }
187
+ function expand_(str, max, maxLength, isTop) {
188
+ // Consume the string's top-level brace groups left to right, threading a
189
+ // running set of combined prefixes (`acc`). Expanding the tail iteratively -
190
+ // rather than recursing on `m.post` once per group - keeps the native stack
191
+ // depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no
192
+ // longer overflow the stack, and leaves a single accumulator whose size
193
+ // `maxLength` bounds directly (CVE-2026-14257).
194
+ let acc = [''];
195
+ // Bash drops empty results, but only when the *first* top-level group is a
196
+ // comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
197
+ // is on the final strings, so it is applied to whichever `combine` produces
198
+ // them (the one with no brace set left in the tail).
199
+ let dropEmpties = false;
200
+ let firstGroup = true;
201
+ for (;;) {
202
+ const m = (0, balanced_match_1.balanced)('{', '}', str);
203
+ // No brace set left: the rest of the string is literal.
204
+ if (!m) {
205
+ return combine(acc, str, [''], max, maxLength, dropEmpties);
206
+ }
207
+ // no need to expand pre, since it is guaranteed to be free of brace-sets
208
+ const pre = m.pre;
209
+ if (/\$$/.test(pre)) {
210
+ acc = combine(acc, pre + '{' + m.body + '}', [''], max, maxLength, dropEmpties && !m.post.length);
211
+ firstGroup = false;
212
+ if (!m.post.length)
213
+ break;
214
+ str = m.post;
215
+ continue;
216
+ }
217
+ const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
218
+ const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
219
+ const isSequence = isNumericSequence || isAlphaSequence;
220
+ const isOptions = m.body.indexOf(',') >= 0;
221
+ if (!isSequence && !isOptions) {
222
+ // {a},b}
223
+ if (m.post.match(/,(?!,).*\}/)) {
224
+ str = m.pre + '{' + m.body + escClose + m.post;
225
+ isTop = true;
226
+ continue;
227
+ }
228
+ // Nothing here expands, so the whole remaining string is literal.
229
+ return combine(acc, pre + '{' + m.body + '}' + m.post, [''], max, maxLength, dropEmpties);
230
+ }
231
+ if (firstGroup) {
232
+ dropEmpties = isTop && !isSequence;
233
+ firstGroup = false;
234
+ }
235
+ let values;
236
+ if (isSequence) {
237
+ values = expandSequence(m.body, isAlphaSequence, max, maxLength);
238
+ }
239
+ else {
240
+ let n = parseCommaParts(m.body);
241
+ if (n.length === 1 && n[0] !== undefined) {
242
+ // x{{a,b}}y ==> x{a}y x{b}y
243
+ n = expand_(n[0], max, maxLength, false).map(embrace);
244
+ //XXX is this necessary? Can't seem to hit it in tests.
245
+ /* c8 ignore start */
246
+ if (n.length === 1) {
247
+ acc = combine(acc, pre + n[0], [''], max, maxLength, dropEmpties && !m.post.length);
248
+ if (!m.post.length)
249
+ break;
250
+ str = m.post;
251
+ continue;
252
+ }
253
+ /* c8 ignore stop */
254
+ }
255
+ // Values that `combine` is going to drop as empty produce no result, so
256
+ // they must not count against `max` - otherwise `{a,,b}` with `max: 2`
257
+ // would stop at `['a', '']` and yield one result instead of two. Skipping
258
+ // them outright keeps `values` bounded while leaving `max` a bound on
259
+ // *kept* results.
260
+ let dropsEmpties = dropEmpties && !m.post.length && !pre;
261
+ for (let d = 0; dropsEmpties && d < acc.length; d++) {
262
+ if (acc[d]) {
263
+ dropsEmpties = false;
264
+ }
265
+ }
266
+ values = [];
267
+ let valuesLength = 0;
268
+ outer: for (let j = 0; j < n.length; j++) {
269
+ const expanded = expand_(n[j], max, maxLength, false);
270
+ for (let k = 0; k < expanded.length; k++) {
271
+ const v = expanded[k];
272
+ if (dropsEmpties && !v)
273
+ continue;
274
+ if (values.length >= max || valuesLength + v.length > maxLength) {
275
+ break outer;
276
+ }
277
+ values.push(v);
278
+ valuesLength += v.length;
279
+ }
280
+ }
281
+ }
282
+ acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length);
283
+ if (!m.post.length)
284
+ break;
285
+ str = m.post;
286
+ }
287
+ return acc;
288
+ }
289
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,285 @@
1
+ import { balanced } from 'balanced-match';
2
+ const escSlash = '\0SLASH' + Math.random() + '\0';
3
+ const escOpen = '\0OPEN' + Math.random() + '\0';
4
+ const escClose = '\0CLOSE' + Math.random() + '\0';
5
+ const escComma = '\0COMMA' + Math.random() + '\0';
6
+ const escPeriod = '\0PERIOD' + Math.random() + '\0';
7
+ const escSlashPattern = new RegExp(escSlash, 'g');
8
+ const escOpenPattern = new RegExp(escOpen, 'g');
9
+ const escClosePattern = new RegExp(escClose, 'g');
10
+ const escCommaPattern = new RegExp(escComma, 'g');
11
+ const escPeriodPattern = new RegExp(escPeriod, 'g');
12
+ const slashPattern = /\\\\/g;
13
+ const openPattern = /\\{/g;
14
+ const closePattern = /\\}/g;
15
+ const commaPattern = /\\,/g;
16
+ const periodPattern = /\\\./g;
17
+ export const EXPANSION_MAX = 100_000;
18
+ // `EXPANSION_MAX` caps the *number* of expansions, but not their length. An
19
+ // input like `'{a,b}'.repeat(1500)` stays under that count - its output is
20
+ // truncated to 100k results - while making every result ~1500 characters
21
+ // long. The result set, and the intermediate arrays built while combining
22
+ // brace sets, then grow large enough to exhaust memory and crash the process
23
+ // (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of
24
+ // characters the accumulator may hold at any point, so memory stays flat no
25
+ // matter how many brace groups are chained. The limit sits well above any
26
+ // realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
27
+ // characters) so legitimate input is unaffected.
28
+ export const EXPANSION_MAX_LENGTH = 4_000_000;
29
+ function numeric(str) {
30
+ return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
31
+ }
32
+ function escapeBraces(str) {
33
+ return str
34
+ .replace(slashPattern, escSlash)
35
+ .replace(openPattern, escOpen)
36
+ .replace(closePattern, escClose)
37
+ .replace(commaPattern, escComma)
38
+ .replace(periodPattern, escPeriod);
39
+ }
40
+ function unescapeBraces(str) {
41
+ return str
42
+ .replace(escSlashPattern, '\\')
43
+ .replace(escOpenPattern, '{')
44
+ .replace(escClosePattern, '}')
45
+ .replace(escCommaPattern, ',')
46
+ .replace(escPeriodPattern, '.');
47
+ }
48
+ /**
49
+ * Basically just str.split(","), but handling cases
50
+ * where we have nested braced sections, which should be
51
+ * treated as individual members, like {a,{b,c},d}
52
+ */
53
+ function parseCommaParts(str) {
54
+ if (!str) {
55
+ return [''];
56
+ }
57
+ const parts = [];
58
+ const m = balanced('{', '}', str);
59
+ if (!m) {
60
+ return str.split(',');
61
+ }
62
+ const { pre, body, post } = m;
63
+ const p = pre.split(',');
64
+ p[p.length - 1] += '{' + body + '}';
65
+ const postParts = parseCommaParts(post);
66
+ if (post.length) {
67
+ ;
68
+ p[p.length - 1] += postParts.shift();
69
+ p.push.apply(p, postParts);
70
+ }
71
+ parts.push.apply(parts, p);
72
+ return parts;
73
+ }
74
+ export function expand(str, options = {}) {
75
+ if (!str) {
76
+ return [];
77
+ }
78
+ const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH } = options;
79
+ // I don't know why Bash 4.3 does this, but it does.
80
+ // Anything starting with {} will have the first two bytes preserved
81
+ // but *only* at the top level, so {},a}b will not expand to anything,
82
+ // but a{},b}c will be expanded to [a}c,abc].
83
+ // One could argue that this is a bug in Bash, but since the goal of
84
+ // this module is to match Bash's rules, we escape a leading {}
85
+ if (str.slice(0, 2) === '{}') {
86
+ str = '\\{\\}' + str.slice(2);
87
+ }
88
+ return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
89
+ }
90
+ function embrace(str) {
91
+ return '{' + str + '}';
92
+ }
93
+ function isPadded(el) {
94
+ return /^-?0\d/.test(el);
95
+ }
96
+ function lte(i, y) {
97
+ return i <= y;
98
+ }
99
+ function gte(i, y) {
100
+ return i >= y;
101
+ }
102
+ // Build `{ acc[a] + pre + values[v] }` for every combination, capping the
103
+ // number of results at `max` and the total number of characters at `maxLength`.
104
+ // This is the one place output grows, so bounding it here keeps the single
105
+ // accumulator - and therefore memory - flat regardless of how many brace groups
106
+ // are combined (CVE-2026-14257).
107
+ function combine(acc, pre, values, max, maxLength, dropEmpties) {
108
+ const out = [];
109
+ let length = 0;
110
+ for (let a = 0; a < acc.length; a++) {
111
+ for (let v = 0; v < values.length; v++) {
112
+ if (out.length >= max)
113
+ return out;
114
+ const expansion = acc[a] + pre + values[v];
115
+ // Bash drops empty results at the top level. Skip them before they count
116
+ // against `max`, so `max` bounds the number of *kept* results.
117
+ if (dropEmpties && !expansion)
118
+ continue;
119
+ if (length + expansion.length > maxLength)
120
+ return out;
121
+ out.push(expansion);
122
+ length += expansion.length;
123
+ }
124
+ }
125
+ return out;
126
+ }
127
+ // The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
128
+ // sequence body.
129
+ function expandSequence(body, isAlphaSequence, max, maxLength) {
130
+ const n = body.split(/\.\./);
131
+ const N = [];
132
+ // A sequence body always splits into two or three parts, but the compiler
133
+ // can't know that.
134
+ /* c8 ignore start */
135
+ if (n[0] === undefined || n[1] === undefined) {
136
+ return N;
137
+ }
138
+ /* c8 ignore stop */
139
+ const x = numeric(n[0]);
140
+ const y = numeric(n[1]);
141
+ const width = Math.max(n[0].length, n[1].length);
142
+ let incr = n.length === 3 && n[2] !== undefined ?
143
+ Math.max(Math.abs(numeric(n[2])), 1)
144
+ : 1;
145
+ let test = lte;
146
+ const reverse = y < x;
147
+ if (reverse) {
148
+ incr *= -1;
149
+ test = gte;
150
+ }
151
+ const pad = n.some(isPadded);
152
+ let length = 0;
153
+ for (let i = x; test(i, y) && N.length < max; i += incr) {
154
+ let c;
155
+ if (isAlphaSequence) {
156
+ c = String.fromCharCode(i);
157
+ if (c === '\\') {
158
+ c = '';
159
+ }
160
+ }
161
+ else {
162
+ c = String(i);
163
+ if (pad) {
164
+ const need = width - c.length;
165
+ if (need > 0) {
166
+ const z = new Array(need + 1).join('0');
167
+ if (i < 0) {
168
+ c = '-' + z + c.slice(1);
169
+ }
170
+ else {
171
+ c = z + c;
172
+ }
173
+ }
174
+ }
175
+ }
176
+ if (length + c.length > maxLength)
177
+ break;
178
+ N.push(c);
179
+ length += c.length;
180
+ }
181
+ return N;
182
+ }
183
+ function expand_(str, max, maxLength, isTop) {
184
+ // Consume the string's top-level brace groups left to right, threading a
185
+ // running set of combined prefixes (`acc`). Expanding the tail iteratively -
186
+ // rather than recursing on `m.post` once per group - keeps the native stack
187
+ // depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no
188
+ // longer overflow the stack, and leaves a single accumulator whose size
189
+ // `maxLength` bounds directly (CVE-2026-14257).
190
+ let acc = [''];
191
+ // Bash drops empty results, but only when the *first* top-level group is a
192
+ // comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
193
+ // is on the final strings, so it is applied to whichever `combine` produces
194
+ // them (the one with no brace set left in the tail).
195
+ let dropEmpties = false;
196
+ let firstGroup = true;
197
+ for (;;) {
198
+ const m = balanced('{', '}', str);
199
+ // No brace set left: the rest of the string is literal.
200
+ if (!m) {
201
+ return combine(acc, str, [''], max, maxLength, dropEmpties);
202
+ }
203
+ // no need to expand pre, since it is guaranteed to be free of brace-sets
204
+ const pre = m.pre;
205
+ if (/\$$/.test(pre)) {
206
+ acc = combine(acc, pre + '{' + m.body + '}', [''], max, maxLength, dropEmpties && !m.post.length);
207
+ firstGroup = false;
208
+ if (!m.post.length)
209
+ break;
210
+ str = m.post;
211
+ continue;
212
+ }
213
+ const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
214
+ const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
215
+ const isSequence = isNumericSequence || isAlphaSequence;
216
+ const isOptions = m.body.indexOf(',') >= 0;
217
+ if (!isSequence && !isOptions) {
218
+ // {a},b}
219
+ if (m.post.match(/,(?!,).*\}/)) {
220
+ str = m.pre + '{' + m.body + escClose + m.post;
221
+ isTop = true;
222
+ continue;
223
+ }
224
+ // Nothing here expands, so the whole remaining string is literal.
225
+ return combine(acc, pre + '{' + m.body + '}' + m.post, [''], max, maxLength, dropEmpties);
226
+ }
227
+ if (firstGroup) {
228
+ dropEmpties = isTop && !isSequence;
229
+ firstGroup = false;
230
+ }
231
+ let values;
232
+ if (isSequence) {
233
+ values = expandSequence(m.body, isAlphaSequence, max, maxLength);
234
+ }
235
+ else {
236
+ let n = parseCommaParts(m.body);
237
+ if (n.length === 1 && n[0] !== undefined) {
238
+ // x{{a,b}}y ==> x{a}y x{b}y
239
+ n = expand_(n[0], max, maxLength, false).map(embrace);
240
+ //XXX is this necessary? Can't seem to hit it in tests.
241
+ /* c8 ignore start */
242
+ if (n.length === 1) {
243
+ acc = combine(acc, pre + n[0], [''], max, maxLength, dropEmpties && !m.post.length);
244
+ if (!m.post.length)
245
+ break;
246
+ str = m.post;
247
+ continue;
248
+ }
249
+ /* c8 ignore stop */
250
+ }
251
+ // Values that `combine` is going to drop as empty produce no result, so
252
+ // they must not count against `max` - otherwise `{a,,b}` with `max: 2`
253
+ // would stop at `['a', '']` and yield one result instead of two. Skipping
254
+ // them outright keeps `values` bounded while leaving `max` a bound on
255
+ // *kept* results.
256
+ let dropsEmpties = dropEmpties && !m.post.length && !pre;
257
+ for (let d = 0; dropsEmpties && d < acc.length; d++) {
258
+ if (acc[d]) {
259
+ dropsEmpties = false;
260
+ }
261
+ }
262
+ values = [];
263
+ let valuesLength = 0;
264
+ outer: for (let j = 0; j < n.length; j++) {
265
+ const expanded = expand_(n[j], max, maxLength, false);
266
+ for (let k = 0; k < expanded.length; k++) {
267
+ const v = expanded[k];
268
+ if (dropsEmpties && !v)
269
+ continue;
270
+ if (values.length >= max || valuesLength + v.length > maxLength) {
271
+ break outer;
272
+ }
273
+ values.push(v);
274
+ valuesLength += v.length;
275
+ }
276
+ }
277
+ }
278
+ acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length);
279
+ if (!m.post.length)
280
+ break;
281
+ str = m.post;
282
+ }
283
+ return acc;
284
+ }
285
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "brace-expansion",
3
+ "description": "Brace expansion as known from sh/bash",
4
+ "version": "5.0.9",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "exports": {
9
+ "./package.json": "./package.json",
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/esm/index.d.ts",
13
+ "default": "./dist/esm/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/commonjs/index.d.ts",
17
+ "default": "./dist/commonjs/index.js"
18
+ }
19
+ }
20
+ },
21
+ "type": "module",
22
+ "scripts": {
23
+ "preversion": "npm test",
24
+ "postversion": "npm publish",
25
+ "prepublishOnly": "git push origin --follow-tags",
26
+ "prepare": "tshy",
27
+ "pretest": "npm run prepare",
28
+ "presnap": "npm run prepare",
29
+ "test": "tap",
30
+ "snap": "tap",
31
+ "format": "prettier --write .",
32
+ "benchmark": "node benchmark/index.js",
33
+ "typedoc": "typedoc --tsconfig .tshy/esm.json ./src/*.ts"
34
+ },
35
+ "devDependencies": {
36
+ "@types/brace-expansion": "^1.1.2",
37
+ "@types/node": "^25.2.1",
38
+ "mkdirp": "^3.0.1",
39
+ "prettier": "^3.3.2",
40
+ "tap": "^21.6.2",
41
+ "tshy": "^3.0.2",
42
+ "typedoc": "^0.28.5"
43
+ },
44
+ "dependencies": {
45
+ "balanced-match": "^4.0.2"
46
+ },
47
+ "license": "MIT",
48
+ "engines": {
49
+ "node": "20 || >=22"
50
+ },
51
+ "tshy": {
52
+ "exports": {
53
+ "./package.json": "./package.json",
54
+ ".": "./src/index.ts"
55
+ }
56
+ },
57
+ "main": "./dist/commonjs/index.js",
58
+ "types": "./dist/commonjs/index.d.ts",
59
+ "module": "./dist/esm/index.js",
60
+ "repository": {
61
+ "type": "git",
62
+ "url": "git+https://github.com/juliangruber/brace-expansion.git"
63
+ }
64
+ }