@molecule/api-ai-tools 1.13.1 → 1.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,10 +32,246 @@
32
32
  *
33
33
  * @module
34
34
  */
35
- /** A command's words, quotes kept whole — the same reading a printed-source check uses. */
36
- const WORD = /"(?:\\.|[^"\\])*"|'[^']*'|\S+/g;
37
35
  /** Shell words that stand alone: grouping, never an argument. */
38
36
  const GROUPING = new Set(['(', ')', '{', '}']);
37
+ /** The index just past a single-quoted string that starts at `at` (its opening quote). */
38
+ function singleQuotedEnd(text, at) {
39
+ const close = text.indexOf("'", at + 1);
40
+ return close === -1 ? text.length : close + 1;
41
+ }
42
+ /**
43
+ * The index just past a double-quoted string that starts at `at`. A command substitution or a
44
+ * backtick inside it is skipped as a unit, because a `"` inside one belongs to the nested command,
45
+ * not to this string (`DIR="$(cd "$(dirname "$0")" && pwd)"`).
46
+ */
47
+ function doubleQuotedEnd(text, at) {
48
+ let i = at + 1;
49
+ while (i < text.length) {
50
+ const char = text[i] ?? '';
51
+ if (char === '\\') {
52
+ i += 2;
53
+ continue;
54
+ }
55
+ if (char === '"')
56
+ return i + 1;
57
+ if (char === '`') {
58
+ i = backtickEnd(text, i);
59
+ continue;
60
+ }
61
+ if (char === '$' && text[i + 1] === '(') {
62
+ i = substitutionEnd(text, i + 2);
63
+ continue;
64
+ }
65
+ if (char === '$' && text[i + 1] === '{') {
66
+ i = parameterEnd(text, i + 2);
67
+ continue;
68
+ }
69
+ i += 1;
70
+ }
71
+ return text.length;
72
+ }
73
+ /** The index just past a backtick substitution that starts at `at` (`\`` is literal, not a close). */
74
+ function backtickEnd(text, at) {
75
+ let i = at + 1;
76
+ while (i < text.length) {
77
+ if (text[i] === '\\') {
78
+ i += 2;
79
+ continue;
80
+ }
81
+ if (text[i] === '`')
82
+ return i + 1;
83
+ i += 1;
84
+ }
85
+ return text.length;
86
+ }
87
+ /**
88
+ * The index just past a `$( … )` command substitution whose body starts at `at`. The body is NOT
89
+ * evaluated and its whitespace splits nothing: only its closing `)` is looked for, through quotes,
90
+ * escapes and nested substitutions. An unclosed substitution runs to the end of the text.
91
+ */
92
+ function substitutionEnd(text, at) {
93
+ let depth = 1;
94
+ let i = at;
95
+ while (i < text.length) {
96
+ const char = text[i] ?? '';
97
+ // A `#` in the nested command starts a comment, so a `$(` or `)` inside it is data — the same
98
+ // reading `splitCommand` makes (`$(printf x # $(` opens nothing).
99
+ if (char === '#' && commentStartsAt(text, i)) {
100
+ const newline = text.indexOf('\n', i);
101
+ i = newline === -1 ? text.length : newline;
102
+ continue;
103
+ }
104
+ if (char === '\\') {
105
+ i += 2;
106
+ continue;
107
+ }
108
+ if (char === "'") {
109
+ i = singleQuotedEnd(text, i);
110
+ continue;
111
+ }
112
+ if (char === '"') {
113
+ i = doubleQuotedEnd(text, i);
114
+ continue;
115
+ }
116
+ if (char === '`') {
117
+ i = backtickEnd(text, i);
118
+ continue;
119
+ }
120
+ if (char === '$' && text[i + 1] === '(') {
121
+ i = substitutionEnd(text, i + 2);
122
+ continue;
123
+ }
124
+ if (char === '$' && text[i + 1] === '{') {
125
+ i = parameterEnd(text, i + 2);
126
+ continue;
127
+ }
128
+ if (char === '(')
129
+ depth += 1;
130
+ else if (char === ')') {
131
+ depth -= 1;
132
+ if (depth === 0)
133
+ return i + 1;
134
+ }
135
+ i += 1;
136
+ }
137
+ return text.length;
138
+ }
139
+ /** The index just past a `${ … }` parameter expansion whose body starts at `at`. */
140
+ function parameterEnd(text, at) {
141
+ let depth = 1;
142
+ let i = at;
143
+ while (i < text.length) {
144
+ const char = text[i] ?? '';
145
+ if (char === '\\') {
146
+ i += 2;
147
+ continue;
148
+ }
149
+ if (char === "'") {
150
+ i = singleQuotedEnd(text, i);
151
+ continue;
152
+ }
153
+ if (char === '"') {
154
+ i = doubleQuotedEnd(text, i);
155
+ continue;
156
+ }
157
+ if (char === '`') {
158
+ i = backtickEnd(text, i);
159
+ continue;
160
+ }
161
+ if (char === '$' && text[i + 1] === '(') {
162
+ i = substitutionEnd(text, i + 2);
163
+ continue;
164
+ }
165
+ if (char === '$' && text[i + 1] === '{') {
166
+ depth += 1;
167
+ i += 2;
168
+ continue;
169
+ }
170
+ if (char === '}') {
171
+ depth -= 1;
172
+ if (depth === 0)
173
+ return i + 1;
174
+ }
175
+ i += 1;
176
+ }
177
+ return text.length;
178
+ }
179
+ /**
180
+ * The index just past the shell word that starts at `at` (a non-whitespace character): a word ends
181
+ * at unquoted whitespace, and every quoted part, command substitution (`$( … )`, backticks),
182
+ * parameter expansion (`${ … }`) and process substitution (`<( … )`) inside it is skipped as a
183
+ * unit — so the spaces in `UID_VAL=h$(date +%s)` belong to that one word.
184
+ *
185
+ * Nothing is evaluated or expanded: this finds word BOUNDARIES only, and returns the text as
186
+ * written. A backslash-newline is a line continuation, so it ends the word and is skipped.
187
+ */
188
+ function shellWordEnd(text, at) {
189
+ let i = at;
190
+ while (i < text.length) {
191
+ const char = text[i] ?? '';
192
+ if (/\s/.test(char))
193
+ break;
194
+ // Grouping punctuation is a shell operator, never part of the word beside it (`tail -25)`,
195
+ // `(npx …`), so a caller can step over the closer the way it always has.
196
+ if (GROUPING.has(char))
197
+ break;
198
+ if (char === '\\') {
199
+ if (text[i + 1] === '\n')
200
+ break;
201
+ i += 2;
202
+ continue;
203
+ }
204
+ if (char === "'") {
205
+ i = singleQuotedEnd(text, i);
206
+ continue;
207
+ }
208
+ if (char === '"') {
209
+ i = doubleQuotedEnd(text, i);
210
+ continue;
211
+ }
212
+ if (char === '`') {
213
+ i = backtickEnd(text, i);
214
+ continue;
215
+ }
216
+ if (char === '$' && text[i + 1] === '(') {
217
+ i = substitutionEnd(text, i + 2);
218
+ continue;
219
+ }
220
+ if (char === '$' && text[i + 1] === '{') {
221
+ i = parameterEnd(text, i + 2);
222
+ continue;
223
+ }
224
+ if ((char === '<' || char === '>') && text[i + 1] === '(') {
225
+ i = substitutionEnd(text, i + 2);
226
+ continue;
227
+ }
228
+ i += 1;
229
+ }
230
+ return i;
231
+ }
232
+ /** One text's shell words, quotes kept, grouping punctuation still its own word. */
233
+ function shellWordSpans(text) {
234
+ const words = [];
235
+ let i = 0;
236
+ while (i < text.length) {
237
+ const char = text[i] ?? '';
238
+ if (char === '\\' && text[i + 1] === '\n') {
239
+ i += 2;
240
+ continue;
241
+ }
242
+ if (/\s/.test(char)) {
243
+ i += 1;
244
+ continue;
245
+ }
246
+ if (GROUPING.has(char)) {
247
+ words.push({ text: char, start: i });
248
+ i += 1;
249
+ continue;
250
+ }
251
+ const end = shellWordEnd(text, i);
252
+ words.push({ text: text.slice(i, end), start: i });
253
+ i = end;
254
+ }
255
+ return words;
256
+ }
257
+ /**
258
+ * The words {@link segmentWords} keeps, with the offset each was written at: quotes kept whole,
259
+ * grouping words dropped, and a leading `(`/`{` taken off the first word. One walk answers both
260
+ * readings, so a caller splicing text at a word's offset and a caller matching that word can
261
+ * never disagree.
262
+ */
263
+ function segmentWordSpans(text) {
264
+ const words = shellWordSpans(text).filter((word) => !GROUPING.has(word.text));
265
+ const first = words[0];
266
+ if (first !== undefined) {
267
+ const bare = first.text.replace(/^[({]+/, '');
268
+ if (bare === '')
269
+ words.shift();
270
+ else if (bare !== first.text)
271
+ words[0] = { text: bare, start: first.start + (first.text.length - bare.length) };
272
+ }
273
+ return words;
274
+ }
39
275
  /**
40
276
  * A redirection written as ONE word, its target attached: `2>&1`, `>out.log`, `&>/dev/null`,
41
277
  * `<<'EOF'`. Matched against a word of the statement, so a redirect's target written as its own
@@ -707,6 +943,8 @@ function splitCommand(command) {
707
943
  const source = blankHeredocBodies(command);
708
944
  const parts = [];
709
945
  const substitutions = [];
946
+ const subshells = [];
947
+ const subshellOpens = [];
710
948
  /** Where each open `$(` body starts; -1 for a bare `(` opened inside one. */
711
949
  const subOpens = [];
712
950
  /** Where each open backtick body starts. */
@@ -855,11 +1093,18 @@ function splitCommand(command) {
855
1093
  // `{ … }` writes through that group, so the depth travels with every character a caller
856
1094
  // reading a redirect may ask about.
857
1095
  if (char === '(' || char === '{') {
1096
+ if (char === '(')
1097
+ subshellOpens.push(i + 1);
858
1098
  put(char);
859
1099
  groupDepth += 1;
860
1100
  continue;
861
1101
  }
862
1102
  if (char === ')' || char === '}') {
1103
+ if (char === ')') {
1104
+ const start = subshellOpens.pop();
1105
+ if (start !== undefined)
1106
+ subshells.push({ start, end: i });
1107
+ }
863
1108
  groupDepth = Math.max(0, groupDepth - 1);
864
1109
  put(char);
865
1110
  continue;
@@ -903,7 +1148,9 @@ function splitCommand(command) {
903
1148
  });
904
1149
  lastAfter = part.after;
905
1150
  }
906
- return { parts: out, substitutions };
1151
+ for (const start of subshellOpens)
1152
+ subshells.push({ start, end: source.length });
1153
+ return { parts: out, substitutions, subshells };
907
1154
  }
908
1155
  /**
909
1156
  * A command's statements and pipeline stages — {@link splitCommand}'s parts on their own.
@@ -980,20 +1227,8 @@ function redirectTargetOf(text, depths, program, args) {
980
1227
  * @returns The words.
981
1228
  */
982
1229
  function segmentWords(text) {
983
- const words = text.match(WORD) ?? [];
984
- const cleaned = words.filter((word) => !GROUPING.has(word));
985
- const first = cleaned[0];
986
- if (first !== undefined) {
987
- const bare = first.replace(/^[({]+/, '');
988
- if (bare === '')
989
- cleaned.shift();
990
- else
991
- cleaned[0] = bare;
992
- }
993
- return cleaned;
1230
+ return segmentWordSpans(text).map((word) => word.text);
994
1231
  }
995
- /** {@link WORD} anchored at an offset, for walking a statement's raw words. */
996
- const WORD_AT = new RegExp(WORD.source, 'y');
997
1232
  /**
998
1233
  * A statement's own leading `NAME=value` words, and where they end.
999
1234
  *
@@ -1008,19 +1243,25 @@ function leadingAssignments(text) {
1008
1243
  const words = [];
1009
1244
  let at = 0;
1010
1245
  for (let guard = 0; guard < MAX_WRAPPERS; guard++) {
1011
- while (at < text.length && /\s/.test(text[at] ?? ''))
1246
+ while (at < text.length) {
1247
+ if (text[at] === '\\' && text[at + 1] === '\n') {
1248
+ at += 2;
1249
+ continue;
1250
+ }
1251
+ if (!/\s/.test(text[at] ?? ''))
1252
+ break;
1012
1253
  at += 1;
1254
+ }
1013
1255
  // Grouping in front of the statement (`(npx …)`, `{ …`): not a word the shell assigns with.
1014
1256
  if (text[at] === '(' || text[at] === '{') {
1015
1257
  at += 1;
1016
1258
  continue;
1017
1259
  }
1018
- WORD_AT.lastIndex = at;
1019
- const match = WORD_AT.exec(text);
1020
- if (!match || !ENV_ASSIGNMENT.test(match[0]))
1260
+ const word = text.slice(at, shellWordEnd(text, at));
1261
+ if (!ENV_ASSIGNMENT.test(word))
1021
1262
  return { words, end: at };
1022
- words.push(match[0]);
1023
- at += match[0].length;
1263
+ words.push(word);
1264
+ at += word.length;
1024
1265
  }
1025
1266
  return { words, end: at };
1026
1267
  }
@@ -1117,6 +1358,31 @@ function executedCommandsOf(command, depth) {
1117
1358
  }
1118
1359
  return out;
1119
1360
  }
1361
+ /**
1362
+ * The direct executable command-substitution bodies in shell text, in source order.
1363
+ *
1364
+ * Uses the same quote, comment and heredoc boundaries as {@link executedCommands}.
1365
+ * Single-quoted and escaped text is inert. Nested substitutions stay inside their
1366
+ * parent's body so a caller can recurse with a separate working-directory scope
1367
+ * for each body; a `cd` inside one must not affect its sibling or the outer shell.
1368
+ *
1369
+ * @param command - The shell text to read, including any leading assignments.
1370
+ * @returns Each direct `$(…)` or backtick body, without its delimiters.
1371
+ */
1372
+ export function commandSubstitutions(command) {
1373
+ if (typeof command !== 'string' || !command.trim())
1374
+ return [];
1375
+ const { substitutions } = splitCommand(command);
1376
+ const bodies = [];
1377
+ let parentEnd = -1;
1378
+ for (const { start, end } of substitutions.sort((a, b) => a.start - b.start || b.end - a.end)) {
1379
+ if (start < parentEnd)
1380
+ continue;
1381
+ bodies.push(command.slice(start, end));
1382
+ parentEnd = end;
1383
+ }
1384
+ return bodies;
1385
+ }
1120
1386
  /**
1121
1387
  * Every command a shell command actually executes, at any depth — the statements themselves, the
1122
1388
  * body of a `sh -c '<command>'`, and the body of every command substitution (`$(…)`, backticks).
@@ -1154,29 +1420,7 @@ export function executedCommands(command) {
1154
1420
  * @returns The word's offset in `text`, or null when there is no such word.
1155
1421
  */
1156
1422
  function wordOffset(text, index) {
1157
- const placement = new RegExp(WORD.source, 'g');
1158
- let kept = 0;
1159
- let first = true;
1160
- for (let match = placement.exec(text); match !== null; match = placement.exec(text)) {
1161
- if (GROUPING.has(match[0]))
1162
- continue;
1163
- if (first) {
1164
- first = false;
1165
- const bare = match[0].replace(/^[({]+/, '');
1166
- // `segmentWords` shifts a first word that was nothing but grouping away, so the NEXT word
1167
- // is not stripped and is counted from zero.
1168
- if (bare === '')
1169
- continue;
1170
- if (kept === index)
1171
- return match.index + (match[0].length - bare.length);
1172
- kept += 1;
1173
- continue;
1174
- }
1175
- if (kept === index)
1176
- return match.index;
1177
- kept += 1;
1178
- }
1179
- return null;
1423
+ return segmentWordSpans(text)[index]?.start ?? null;
1180
1424
  }
1181
1425
  /**
1182
1426
  * Every statement of a command, with its own assignments and where it sits — assignment-only
@@ -1289,9 +1533,9 @@ export function statementArgumentEnd(command, start, end) {
1289
1533
  }
1290
1534
  at = cursor - 1;
1291
1535
  }
1292
- const words = [...command.slice(start, at).matchAll(new RegExp(WORD.source, 'g'))].map((m) => ({
1293
- text: m[0],
1294
- index: start + (m.index ?? 0),
1536
+ const words = shellWordSpans(command.slice(start, at)).map((word) => ({
1537
+ text: word.text,
1538
+ index: start + word.start,
1295
1539
  }));
1296
1540
  // A trailing redirection belongs to the statement but is not an argument of its program. An
1297
1541
  // option written after it would still parse, but the option belongs with the program's own
@@ -1404,7 +1648,8 @@ function locatedSegmentsOf(command, depth) {
1404
1648
  if (typeof command !== 'string' || depth > MAX_NESTING)
1405
1649
  return [];
1406
1650
  const out = [];
1407
- for (const part of splitSegments(command)) {
1651
+ const { parts, subshells } = splitCommand(command);
1652
+ for (const part of parts) {
1408
1653
  const words = segmentWords(part.text);
1409
1654
  const start = commandStart(words);
1410
1655
  const leading = leadingAssignments(part.text);
@@ -1428,6 +1673,12 @@ function locatedSegmentsOf(command, depth) {
1428
1673
  : part.start + (wordOffset(part.text, start.envInsert) ?? leading.end),
1429
1674
  programOffset: words[start.at] === undefined ? null : part.start + (wordOffset(part.text, start.at) ?? 0),
1430
1675
  };
1676
+ const scopeAt = placed.programOffset ?? part.start + (wordOffset(part.text, 0) ?? 0);
1677
+ const shellScope = subshells
1678
+ .filter(({ start, end }) => start <= scopeAt && scopeAt < end)
1679
+ .sort((a, b) => a.start - b.start)
1680
+ .map(({ start }) => `group:${start}`);
1681
+ const scoped = shellScope.length === 0 ? {} : { shellScope };
1431
1682
  // The runner the word RUNS names, when that is not the word's own name (`node <path>/playwright`
1432
1683
  // is a `playwright` invocation, xr-molecule-flash-m179).
1433
1684
  const program = words[start.at] === undefined ? '' : (start.program ?? programName(words[start.at] ?? ''));
@@ -1441,9 +1692,14 @@ function locatedSegmentsOf(command, depth) {
1441
1692
  continue;
1442
1693
  out.push({
1443
1694
  ...entry,
1695
+ shellScope: [...shellScope, `shell:${part.start}`, ...(entry.shellScope ?? [])],
1444
1696
  // The variables this statement bound before the shell reached it are the nested
1445
1697
  // command's too: `env BASE_URL=… sh -c '… npx playwright test …'` passes them down.
1446
1698
  assignments: [...new Set([...assignments, ...entry.assignments])],
1699
+ sourceAssignments: [
1700
+ ...(i === 0 ? assignments : []),
1701
+ ...(entry.sourceAssignments ?? entry.assignments),
1702
+ ],
1447
1703
  // A nested statement's positions are positions in the nested string, not in this
1448
1704
  // command. The FIRST one keeps this statement's own separator: the shell reads the
1449
1705
  // nested string where this statement stands.
@@ -1469,6 +1725,7 @@ function locatedSegmentsOf(command, depth) {
1469
1725
  if (assignments.length > 0)
1470
1726
  out.push({
1471
1727
  segment: null,
1728
+ ...scoped,
1472
1729
  assignments,
1473
1730
  ...placed,
1474
1731
  programOffset: null,
@@ -1479,6 +1736,7 @@ function locatedSegmentsOf(command, depth) {
1479
1736
  continue;
1480
1737
  }
1481
1738
  out.push({
1739
+ ...scoped,
1482
1740
  segment: {
1483
1741
  program,
1484
1742
  args,
@@ -1554,16 +1812,13 @@ export function withoutTimeoutWrapper(command, which) {
1554
1812
  continue;
1555
1813
  // Every word in front of the program: the assignments and the wrappers. The duration belongs
1556
1814
  // to the wrapper, so the walk has to see the words, not just the parse's total bound.
1557
- const prefix = command.slice(located.start, located.programOffset);
1558
- const words = [];
1559
- const at = new RegExp(WORD.source, 'g');
1560
- for (let match = at.exec(prefix); match !== null; match = at.exec(prefix)) {
1561
- words.push({
1562
- text: match[0],
1563
- start: located.start + match.index,
1564
- end: located.start + match.index + match[0].length,
1565
- });
1566
- }
1815
+ const start = located.start;
1816
+ const prefix = command.slice(start, located.programOffset);
1817
+ const words = shellWordSpans(prefix).map((word) => ({
1818
+ text: word.text,
1819
+ start: start + word.start,
1820
+ end: start + word.start + word.text.length,
1821
+ }));
1567
1822
  for (let i = 0; i < words.length; i += 1) {
1568
1823
  const word = words[i];
1569
1824
  if (word === undefined || programName(word.text) !== 'timeout')
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@
12
12
  * (identity, tool listing, project docs, discovered skills).
13
13
  *
14
14
  * @remarks
15
+ * - **`yieldOnFirstFailureFor`** can yield one still-running deployed task's concrete diagnostic; callers opt out after a prior wait result or unknown history.
15
16
  * - **This package only defines the tools — it runs no model loop.** Hand them to
16
17
  * the bonded AI provider (`chat({ tools, … })`) or to an
17
18
  * `@molecule/api-ai-agents` run.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuIG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,wBAAwB,CAAA;AACtC,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAA;AACnC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,YAAY,CAAA;AAC1B,cAAc,sBAAsB,CAAA;AACpC,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwIG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,wBAAwB,CAAA;AACtC,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAA;AACnC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,YAAY,CAAA;AAC1B,cAAc,sBAAsB,CAAA;AACpC,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@
12
12
  * (identity, tool listing, project docs, discovered skills).
13
13
  *
14
14
  * @remarks
15
+ * - **`yieldOnFirstFailureFor`** can yield one still-running deployed task's concrete diagnostic; callers opt out after a prior wait result or unknown history.
15
16
  * - **This package only defines the tools — it runs no model loop.** Hand them to
16
17
  * the bonded AI provider (`chat({ tools, … })`) or to an
17
18
  * `@molecule/api-ai-agents` run.
@@ -87,7 +87,9 @@ export declare function withSuiteConfig(command: string, config: string | null |
87
87
  * The re-run keeps the run's `> <file>` redirect only in the sense of keeping its OUTPUT there:
88
88
  * the target is rewritten to a fresh sibling ({@link redirectRunnerOutputsToFreshFiles}), so a
89
89
  * re-run never overwrites the log the run itself is the evidence for (xr-molecule-flash-m173) —
90
- * and the setup around the run keeps its own file writes untouched (xr-molecule-flash-m429).
90
+ * and the setup around the run keeps its own file writes untouched (xr-molecule-flash-m429). A
91
+ * `tail`/`head`/`cat`/`grep` chained after the run that reads that exact log is shown the fresh
92
+ * sibling instead, so the re-run displays the run it performed (xr-molecule-flash-o03).
91
93
  *
92
94
  * `config` is the config the run was measured under ({@link withSuiteConfig}): the narrowed re-run
93
95
  * carries it whenever the command itself does not, so a run that dropped `--config` cannot be
@@ -1 +1 @@
1
- {"version":3,"file":"suite-overlap.d.ts","sourceRoot":"","sources":["../src/suite-overlap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAaH;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAoB1D;AAKD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAS1F;AAoOD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,QAAQ,GAAE,SAAS,MAAM,EAAO,EAChC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EACtB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EACnB,GAAG,GAAE,SAAS,aAAa,EAAO,GACjC,MAAM,CAgDR;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAmCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,SAAS,aAAa,EAAO,GAAG,MAAM,CAe3F;AAwOD;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,SAAS,EAAE,OAAO,CAAA;IAClB,oFAAoF;IACpF,MAAM,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,gBAAgB,EACzD,SAAS,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAC7B,QAAQ,EAAE,SAAS,CAAC,EAAE,GACrB,CAAC,GAAG,IAAI,CAMV;AA2FD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACvC;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAYtF"}
1
+ {"version":3,"file":"suite-overlap.d.ts","sourceRoot":"","sources":["../src/suite-overlap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAaH;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAoB1D;AAKD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAS1F;AA4VD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,QAAQ,GAAE,SAAS,MAAM,EAAO,EAChC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EACtB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EACnB,GAAG,GAAE,SAAS,aAAa,EAAO,GACjC,MAAM,CAgDR;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAmCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,SAAS,aAAa,EAAO,GAAG,MAAM,CAe3F;AAwOD;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,SAAS,EAAE,OAAO,CAAA;IAClB,oFAAoF;IACpF,MAAM,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,gBAAgB,EACzD,SAAS,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAC7B,QAAQ,EAAE,SAAS,CAAC,EAAE,GACrB,CAAC,GAAG,IAAI,CAMV;AA2FD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACvC;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAYtF"}