clanka 0.2.28 → 0.2.29

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.
@@ -1,3 +1,8 @@
1
+ const callTemplateTargets = ["applyPatch", "taskComplete"];
2
+ const objectPropertyTargets = [
3
+ { functionName: "writeFile", propertyName: "content" },
4
+ { functionName: "updateTask", propertyName: "description" },
5
+ ];
1
6
  const isIdentifierChar = (char) => char !== undefined && /[A-Za-z0-9_$]/.test(char);
2
7
  const isIdentifierStartChar = (char) => char !== undefined && /[A-Za-z_$]/.test(char);
3
8
  const hasIdentifierBoundary = (text, index, length) => !isIdentifierChar(text[index - 1]) && !isIdentifierChar(text[index + length]);
@@ -12,11 +17,11 @@ const findNextIdentifier = (text, identifier, from) => {
12
17
  return -1;
13
18
  };
14
19
  const skipWhitespace = (text, start) => {
15
- let i = start;
16
- while (i < text.length && /\s/.test(text[i])) {
17
- i++;
20
+ let index = start;
21
+ while (index < text.length && /\s/.test(text[index])) {
22
+ index++;
18
23
  }
19
- return i;
24
+ return index;
20
25
  };
21
26
  const parseIdentifier = (text, start) => {
22
27
  if (!isIdentifierStartChar(text[start])) {
@@ -32,28 +37,125 @@ const parseIdentifier = (text, start) => {
32
37
  };
33
38
  };
34
39
  const findPreviousNonWhitespace = (text, from) => {
35
- let i = from;
36
- while (i >= 0 && /\s/.test(text[i])) {
37
- i--;
40
+ let index = from;
41
+ while (index >= 0 && /\s/.test(text[index])) {
42
+ index--;
38
43
  }
39
- return i;
44
+ return index;
40
45
  };
41
46
  const findNextNonWhitespace = (text, from) => {
42
- let i = from;
43
- while (i < text.length && /\s/.test(text[i])) {
44
- i++;
47
+ let index = from;
48
+ while (index < text.length && /\s/.test(text[index])) {
49
+ index++;
50
+ }
51
+ return index;
52
+ };
53
+ const isEscaped = (text, index) => {
54
+ let slashCount = 0;
55
+ let cursor = index - 1;
56
+ while (cursor >= 0 && text[cursor] === "\\") {
57
+ slashCount++;
58
+ cursor--;
59
+ }
60
+ return slashCount % 2 === 1;
61
+ };
62
+ const needsTemplateEscaping = (text) => {
63
+ for (let index = 0; index < text.length; index++) {
64
+ const char = text[index];
65
+ if (char === "`" && !isEscaped(text, index)) {
66
+ return true;
67
+ }
68
+ if (char === "$" && text[index + 1] === "{" && !isEscaped(text, index)) {
69
+ return true;
70
+ }
71
+ }
72
+ return false;
73
+ };
74
+ const findTemplateEnd = (text, start, isTerminator) => {
75
+ let end = -1;
76
+ for (let index = start + 1; index < text.length; index++) {
77
+ if (text[index] !== "`" || isEscaped(text, index)) {
78
+ continue;
79
+ }
80
+ if (isTerminator(text[index + 1])) {
81
+ end = index;
82
+ continue;
83
+ }
84
+ const next = skipWhitespace(text, index + 1);
85
+ if (isTerminator(text[next])) {
86
+ end = index;
87
+ }
88
+ }
89
+ return end;
90
+ };
91
+ const findTypeAnnotationAssignment = (text, start) => {
92
+ let index = start;
93
+ while (index < text.length) {
94
+ const char = text[index];
95
+ if (char === "=") {
96
+ return index;
97
+ }
98
+ if (char === "\n" || char === ";") {
99
+ return -1;
100
+ }
101
+ index++;
45
102
  }
46
- return i;
103
+ return -1;
104
+ };
105
+ const findClosingParen = (text, openParen) => {
106
+ let depth = 1;
107
+ for (let index = openParen + 1; index < text.length; index++) {
108
+ const char = text[index];
109
+ if (char === "(") {
110
+ depth++;
111
+ continue;
112
+ }
113
+ if (char === ")") {
114
+ depth--;
115
+ if (depth === 0) {
116
+ return index;
117
+ }
118
+ }
119
+ }
120
+ return -1;
121
+ };
122
+ const findClosingBrace = (text, openBrace) => {
123
+ let depth = 1;
124
+ let stringDelimiter;
125
+ for (let index = openBrace + 1; index < text.length; index++) {
126
+ const char = text[index];
127
+ if (stringDelimiter !== undefined) {
128
+ if (char === stringDelimiter && !isEscaped(text, index)) {
129
+ stringDelimiter = undefined;
130
+ }
131
+ continue;
132
+ }
133
+ if (char === '"' || char === "'" || char === "`") {
134
+ stringDelimiter = char;
135
+ continue;
136
+ }
137
+ if (char === "{") {
138
+ depth++;
139
+ continue;
140
+ }
141
+ if (char === "}") {
142
+ depth--;
143
+ if (depth === 0) {
144
+ return index;
145
+ }
146
+ }
147
+ }
148
+ return -1;
47
149
  };
48
150
  const findObjectValueTerminator = (text, start) => {
49
151
  let parenDepth = 0;
50
152
  let bracketDepth = 0;
51
153
  let braceDepth = 0;
52
154
  let stringDelimiter;
53
- for (let i = start; i < text.length; i++) {
54
- const char = text[i];
155
+ for (let index = start; index < text.length; index++) {
156
+ const char = text[index];
55
157
  if (stringDelimiter !== undefined) {
56
- if (char === stringDelimiter && !isEscaped(text, i)) {
158
+ if (char === stringDelimiter && !isEscaped(text, index)) {
57
159
  stringDelimiter = undefined;
58
160
  }
59
161
  continue;
@@ -88,7 +190,7 @@ const findObjectValueTerminator = (text, start) => {
88
190
  }
89
191
  if (char === "}") {
90
192
  if (parenDepth === 0 && bracketDepth === 0 && braceDepth === 0) {
91
- return i;
193
+ return index;
92
194
  }
93
195
  if (braceDepth > 0) {
94
196
  braceDepth--;
@@ -99,13 +201,13 @@ const findObjectValueTerminator = (text, start) => {
99
201
  parenDepth === 0 &&
100
202
  bracketDepth === 0 &&
101
203
  braceDepth === 0) {
102
- return i;
204
+ return index;
103
205
  }
104
206
  }
105
207
  return -1;
106
208
  };
107
209
  const collectExpressionIdentifiers = (text, start, end) => {
108
- const out = new Set();
210
+ const identifiers = new Set();
109
211
  let cursor = start;
110
212
  while (cursor < end) {
111
213
  const identifier = parseIdentifier(text, cursor);
@@ -113,37 +215,14 @@ const collectExpressionIdentifiers = (text, start, end) => {
113
215
  cursor++;
114
216
  continue;
115
217
  }
116
- const previousNonWhitespace = findPreviousNonWhitespace(text, cursor - 1);
117
- const nextNonWhitespace = findNextNonWhitespace(text, identifier.end);
118
- if (text[previousNonWhitespace] !== "." &&
119
- text[nextNonWhitespace] !== "." &&
120
- text[nextNonWhitespace] !== "(") {
121
- out.add(identifier.name);
218
+ const previous = findPreviousNonWhitespace(text, cursor - 1);
219
+ const next = findNextNonWhitespace(text, identifier.end);
220
+ if (text[previous] !== "." && text[next] !== "." && text[next] !== "(") {
221
+ identifiers.add(identifier.name);
122
222
  }
123
223
  cursor = identifier.end;
124
224
  }
125
- return out;
126
- };
127
- const isEscaped = (text, index) => {
128
- let slashCount = 0;
129
- let i = index - 1;
130
- while (i >= 0 && text[i] === "\\") {
131
- slashCount++;
132
- i--;
133
- }
134
- return slashCount % 2 === 1;
135
- };
136
- const needsTemplateEscaping = (text) => {
137
- for (let i = 0; i < text.length; i++) {
138
- const char = text[i];
139
- if (char === "`" && !isEscaped(text, i)) {
140
- return true;
141
- }
142
- if (char === "$" && text[i + 1] === "{" && !isEscaped(text, i)) {
143
- return true;
144
- }
145
- }
146
- return false;
225
+ return identifiers;
147
226
  };
148
227
  const normalizePatchEscapedQuotes = (text) => text.includes("*** Begin Patch")
149
228
  ? text.replace(/\\"([A-Za-z0-9_$.-]+)\\"/g, (match, content, index) => {
@@ -166,35 +245,36 @@ const normalizeNonPatchEscapedTemplateMarkers = (text) => text
166
245
  .replace(/\\{2,}(?=`|\$\{)/g, "\\")
167
246
  .replace(/(^|\s)\\+(?=\.[A-Za-z0-9_-]+\/)/g, "$1");
168
247
  const escapeTemplateLiteralContent = (text) => {
169
- const normalizedPatchQuotes = normalizePatchEscapedQuotes(text);
170
- const isPatchContent = normalizedPatchQuotes.includes("*** Begin Patch");
248
+ const patchNormalized = normalizePatchEscapedQuotes(text);
249
+ const isPatchContent = patchNormalized.includes("*** Begin Patch");
171
250
  const normalized = isPatchContent
172
- ? normalizedPatchQuotes
173
- : normalizeNonPatchEscapedTemplateMarkers(normalizedPatchQuotes);
251
+ ? patchNormalized
252
+ : normalizeNonPatchEscapedTemplateMarkers(patchNormalized);
174
253
  if (!needsTemplateEscaping(normalized) &&
175
- !(isPatchContent && normalized.includes("\\"))) {
254
+ !(isPatchContent && normalized.includes('\\"'))) {
176
255
  return normalized;
177
256
  }
178
257
  let out = "";
179
- for (let i = 0; i < normalized.length; i++) {
180
- const char = normalized[i];
258
+ for (let index = 0; index < normalized.length; index++) {
259
+ const char = normalized[index];
181
260
  if (char === "\\") {
182
- if (!isPatchContent &&
183
- (normalized[i + 1] === "`" ||
184
- (normalized[i + 1] === "$" && normalized[i + 2] === "{"))) {
261
+ if ((normalized[index + 1] === "`" && isEscaped(normalized, index + 1)) ||
262
+ (normalized[index + 1] === "$" &&
263
+ normalized[index + 2] === "{" &&
264
+ isEscaped(normalized, index + 1))) {
185
265
  out += "\\";
186
266
  continue;
187
267
  }
188
268
  out += "\\\\";
189
269
  continue;
190
270
  }
191
- if (char === "`" && !isEscaped(normalized, i)) {
271
+ if (char === "`" && !isEscaped(normalized, index)) {
192
272
  out += "\\`";
193
273
  continue;
194
274
  }
195
275
  if (char === "$" &&
196
- normalized[i + 1] === "{" &&
197
- !isEscaped(normalized, i)) {
276
+ normalized[index + 1] === "{" &&
277
+ !isEscaped(normalized, index)) {
198
278
  out += "\\$";
199
279
  continue;
200
280
  }
@@ -202,230 +282,122 @@ const escapeTemplateLiteralContent = (text) => {
202
282
  }
203
283
  return out;
204
284
  };
205
- const findTemplateEnd = (text, start, isTerminator) => {
206
- let end = -1;
207
- for (let i = start + 1; i < text.length; i++) {
208
- if (text[i] !== "`" || isEscaped(text, i)) {
209
- continue;
210
- }
211
- if (isTerminator(text[i + 1])) {
212
- end = i;
213
- continue;
214
- }
215
- const next = skipWhitespace(text, i + 1);
216
- if (isTerminator(text[next])) {
217
- end = i;
218
- }
219
- }
220
- return end;
221
- };
222
- const findTypeAnnotationAssignment = (text, start) => {
223
- let i = start;
224
- while (i < text.length) {
225
- const char = text[i];
226
- if (char === "=") {
227
- return i;
228
- }
229
- if (char === "\n" || char === ";") {
230
- return -1;
231
- }
232
- i++;
233
- }
234
- return -1;
235
- };
236
- const findClosingParen = (text, openParen) => {
237
- let depth = 1;
238
- for (let i = openParen + 1; i < text.length; i++) {
239
- const char = text[i];
240
- if (char === "(") {
241
- depth++;
242
- continue;
243
- }
244
- if (char === ")") {
245
- depth--;
246
- if (depth === 0) {
247
- return i;
248
- }
249
- }
250
- }
251
- return -1;
252
- };
253
- const findClosingBrace = (text, openBrace) => {
254
- let depth = 1;
255
- let stringDelimiter;
256
- for (let i = openBrace + 1; i < text.length; i++) {
257
- const char = text[i];
258
- if (stringDelimiter !== undefined) {
259
- if (char === stringDelimiter && !isEscaped(text, i)) {
260
- stringDelimiter = undefined;
261
- }
262
- continue;
263
- }
264
- if (char === '"' || char === "'" || char === "`") {
265
- stringDelimiter = char;
266
- continue;
267
- }
268
- if (char === "{") {
269
- depth++;
270
- continue;
271
- }
272
- if (char === "}") {
273
- depth--;
274
- if (depth === 0) {
275
- return i;
276
- }
277
- }
278
- }
279
- return -1;
280
- };
281
- const fixObjectLiteralTemplateValues = (text) => text.replace(/\\{2,}(?=`|\$\{)/g, "\\");
282
- const fixAssignedObjectTemplateValues = (script, variableName) => {
285
+ const normalizeObjectLiteralTemplateMarkers = (text) => text.replace(/\\{2,}(?=`|\$\{)/g, "\\");
286
+ const replaceSlice = (text, start, end, replacement) => `${text.slice(0, start)}${replacement}${text.slice(end)}`;
287
+ const rewriteTemplateContents = (script, findNext, rewrite) => {
283
288
  let out = script;
284
289
  let cursor = 0;
285
290
  while (cursor < out.length) {
286
- const variableStart = findNextIdentifier(out, variableName, cursor);
287
- if (variableStart === -1) {
291
+ const range = findNext(out, cursor);
292
+ if (range === undefined) {
288
293
  break;
289
294
  }
290
- let assignmentStart = skipWhitespace(out, variableStart + variableName.length);
291
- if (out[assignmentStart] === ":") {
292
- assignmentStart = findTypeAnnotationAssignment(out, assignmentStart + 1);
293
- if (assignmentStart === -1) {
294
- cursor = variableStart + variableName.length;
295
- continue;
296
- }
297
- }
298
- if (out[assignmentStart] !== "=" ||
299
- out[assignmentStart + 1] === "=" ||
300
- out[assignmentStart + 1] === ">") {
301
- cursor = variableStart + variableName.length;
302
- continue;
303
- }
304
- const objectStart = skipWhitespace(out, assignmentStart + 1);
305
- if (out[objectStart] !== "{") {
306
- cursor = objectStart + 1;
307
- continue;
308
- }
309
- const objectEnd = findClosingBrace(out, objectStart);
310
- if (objectEnd === -1) {
311
- cursor = objectStart + 1;
312
- continue;
313
- }
314
- const original = out.slice(objectStart, objectEnd + 1);
315
- const escaped = fixObjectLiteralTemplateValues(original);
316
- if (escaped !== original) {
317
- out = `${out.slice(0, objectStart)}${escaped}${out.slice(objectEnd + 1)}`;
318
- cursor = objectEnd + (escaped.length - original.length) + 1;
295
+ const original = out.slice(range.contentStart, range.contentEnd);
296
+ const updated = rewrite(original);
297
+ if (updated !== original) {
298
+ out = replaceSlice(out, range.contentStart, range.contentEnd, updated);
299
+ cursor = range.nextCursor + (updated.length - original.length);
319
300
  continue;
320
301
  }
321
- cursor = objectEnd + 1;
322
- }
323
- return out;
324
- };
325
- const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\\]\\]/g, "\\$&");
326
- const collectObjectEntryMapSources = (script, valueIdentifier) => {
327
- const out = new Set();
328
- const pattern = new RegExp(`Object\\.entries\\(\\s*([A-Za-z_$][A-Za-z0-9_$]*)\\s*\\)\\s*\\.map\\(\\s*(?:async\\s*)?\\(\\s*\\[\\s*[A-Za-z_$][A-Za-z0-9_$]*\\s*,\\s*${escapeRegExp(valueIdentifier)}\\s*\\]\\s*\\)\\s*=>`, "g");
329
- for (const match of script.matchAll(pattern)) {
330
- const sourceIdentifier = match[1];
331
- if (sourceIdentifier !== undefined) {
332
- out.add(sourceIdentifier);
333
- }
302
+ cursor = range.nextCursor;
334
303
  }
335
304
  return out;
336
305
  };
337
- const findCallTemplateEnd = (text, templateStart, openParen) => {
338
- const closeParen = findClosingParen(text, openParen);
339
- if (closeParen === -1) {
340
- return -1;
341
- }
342
- for (let i = closeParen - 1; i > templateStart; i--) {
343
- if (text[i] === "`" && !isEscaped(text, i)) {
344
- return i;
345
- }
346
- }
347
- return -1;
348
- };
349
- const fixCallTemplateArgument = (script, functionName) => {
350
- let out = script;
351
- let cursor = 0;
352
- while (cursor < out.length) {
353
- const callStart = findNextIdentifier(out, functionName, cursor);
306
+ const findDirectCallTemplate = (text, functionName, from) => {
307
+ let cursor = from;
308
+ while (cursor < text.length) {
309
+ const callStart = findNextIdentifier(text, functionName, cursor);
354
310
  if (callStart === -1) {
355
- break;
311
+ return undefined;
356
312
  }
357
- const openParen = skipWhitespace(out, callStart + functionName.length);
358
- if (out[openParen] !== "(") {
313
+ const openParen = skipWhitespace(text, callStart + functionName.length);
314
+ if (text[openParen] !== "(") {
359
315
  cursor = callStart + functionName.length;
360
316
  continue;
361
317
  }
362
- const templateStart = skipWhitespace(out, openParen + 1);
363
- if (out[templateStart] !== "`") {
318
+ const templateStart = skipWhitespace(text, openParen + 1);
319
+ if (text[templateStart] !== "`") {
364
320
  cursor = openParen + 1;
365
321
  continue;
366
322
  }
367
- const templateEnd = findCallTemplateEnd(out, templateStart, openParen);
323
+ const closeParen = findClosingParen(text, openParen);
324
+ let templateEnd = -1;
325
+ if (closeParen !== -1) {
326
+ for (let index = closeParen - 1; index > templateStart; index--) {
327
+ if (text[index] === "`" && !isEscaped(text, index)) {
328
+ templateEnd = index;
329
+ break;
330
+ }
331
+ }
332
+ }
333
+ else {
334
+ const patchEnd = text.indexOf("*** End Patch", templateStart);
335
+ const searchStart = patchEnd === -1 ? templateStart + 1 : patchEnd + 1;
336
+ for (let index = searchStart; index < text.length; index++) {
337
+ if (text[index] !== "`" || isEscaped(text, index)) {
338
+ continue;
339
+ }
340
+ const candidate = skipWhitespace(text, index + 1);
341
+ if (text[candidate] === ")") {
342
+ templateEnd = index;
343
+ break;
344
+ }
345
+ }
346
+ }
368
347
  if (templateEnd === -1) {
369
348
  cursor = templateStart + 1;
370
349
  continue;
371
350
  }
372
- const original = out.slice(templateStart + 1, templateEnd);
373
- const escaped = escapeTemplateLiteralContent(original);
374
- if (escaped !== original) {
375
- out = `${out.slice(0, templateStart + 1)}${escaped}${out.slice(templateEnd)}`;
376
- cursor = templateEnd + (escaped.length - original.length) + 1;
377
- continue;
378
- }
379
- cursor = templateEnd + 1;
351
+ return {
352
+ contentStart: templateStart + 1,
353
+ contentEnd: templateEnd,
354
+ nextCursor: templateEnd + 1,
355
+ };
380
356
  }
381
- return out;
357
+ return undefined;
382
358
  };
383
- const fixCallObjectPropertyTemplate = (script, functionName, propertyName) => {
384
- let out = script;
385
- let cursor = 0;
386
- while (cursor < out.length) {
387
- const callStart = findNextIdentifier(out, functionName, cursor);
359
+ const findObjectPropertyTemplate = (text, target, from) => {
360
+ let cursor = from;
361
+ while (cursor < text.length) {
362
+ const callStart = findNextIdentifier(text, target.functionName, cursor);
388
363
  if (callStart === -1) {
389
- break;
364
+ return undefined;
390
365
  }
391
- const openParen = skipWhitespace(out, callStart + functionName.length);
392
- if (out[openParen] !== "(") {
393
- cursor = callStart + functionName.length;
366
+ const openParen = skipWhitespace(text, callStart + target.functionName.length);
367
+ if (text[openParen] !== "(") {
368
+ cursor = callStart + target.functionName.length;
394
369
  continue;
395
370
  }
396
- const propertyKey = findNextIdentifier(out, propertyName, openParen + 1);
371
+ const propertyKey = findNextIdentifier(text, target.propertyName, openParen + 1);
397
372
  if (propertyKey === -1) {
398
373
  cursor = openParen + 1;
399
374
  continue;
400
375
  }
401
- const colon = skipWhitespace(out, propertyKey + propertyName.length);
402
- if (out[colon] !== ":") {
403
- cursor = propertyKey + propertyName.length;
376
+ const colon = skipWhitespace(text, propertyKey + target.propertyName.length);
377
+ if (text[colon] !== ":") {
378
+ cursor = propertyKey + target.propertyName.length;
404
379
  continue;
405
380
  }
406
- const templateStart = skipWhitespace(out, colon + 1);
407
- if (out[templateStart] !== "`") {
381
+ const templateStart = skipWhitespace(text, colon + 1);
382
+ if (text[templateStart] !== "`") {
408
383
  cursor = templateStart + 1;
409
384
  continue;
410
385
  }
411
- const templateEnd = findTemplateEnd(out, templateStart, (char) => char === "}" || char === ",");
386
+ const templateEnd = findTemplateEnd(text, templateStart, (char) => char === "}" || char === ",");
412
387
  if (templateEnd === -1) {
413
388
  cursor = templateStart + 1;
414
389
  continue;
415
390
  }
416
- const original = out.slice(templateStart + 1, templateEnd);
417
- const escaped = escapeTemplateLiteralContent(original);
418
- if (escaped !== original) {
419
- out = `${out.slice(0, templateStart + 1)}${escaped}${out.slice(templateEnd)}`;
420
- cursor = templateEnd + (escaped.length - original.length) + 1;
421
- continue;
422
- }
423
- cursor = templateEnd + 1;
391
+ return {
392
+ contentStart: templateStart + 1,
393
+ contentEnd: templateEnd,
394
+ nextCursor: templateEnd + 1,
395
+ };
424
396
  }
425
- return out;
397
+ return undefined;
426
398
  };
427
399
  const collectCallArgumentIdentifiers = (script, functionName) => {
428
- const out = new Set();
400
+ const identifiers = new Set();
429
401
  let cursor = 0;
430
402
  while (cursor < script.length) {
431
403
  const callStart = findNextIdentifier(script, functionName, cursor);
@@ -445,57 +417,98 @@ const collectCallArgumentIdentifiers = (script, functionName) => {
445
417
  }
446
418
  const argumentEnd = skipWhitespace(script, identifier.end);
447
419
  if (script[argumentEnd] === ")" || script[argumentEnd] === ",") {
448
- out.add(identifier.name);
420
+ identifiers.add(identifier.name);
449
421
  }
450
422
  cursor = identifier.end;
451
423
  }
452
- return out;
424
+ return identifiers;
453
425
  };
454
- const collectCallObjectPropertyIdentifiers = (script, functionName, propertyName) => {
455
- const out = new Set();
426
+ const collectObjectPropertyIdentifiers = (script, target) => {
427
+ const identifiers = new Set();
456
428
  let cursor = 0;
457
429
  while (cursor < script.length) {
458
- const callStart = findNextIdentifier(script, functionName, cursor);
430
+ const callStart = findNextIdentifier(script, target.functionName, cursor);
459
431
  if (callStart === -1) {
460
432
  break;
461
433
  }
462
- const openParen = skipWhitespace(script, callStart + functionName.length);
434
+ const openParen = skipWhitespace(script, callStart + target.functionName.length);
463
435
  if (script[openParen] !== "(") {
464
- cursor = callStart + functionName.length;
436
+ cursor = callStart + target.functionName.length;
465
437
  continue;
466
438
  }
467
- const propertyKey = findNextIdentifier(script, propertyName, openParen + 1);
439
+ const propertyKey = findNextIdentifier(script, target.propertyName, openParen + 1);
468
440
  if (propertyKey === -1) {
469
441
  cursor = openParen + 1;
470
442
  continue;
471
443
  }
472
- const afterProperty = skipWhitespace(script, propertyKey + propertyName.length);
444
+ const afterProperty = skipWhitespace(script, propertyKey + target.propertyName.length);
473
445
  if (script[afterProperty] === ":") {
474
446
  const valueStart = skipWhitespace(script, afterProperty + 1);
475
447
  const valueEnd = findObjectValueTerminator(script, valueStart);
476
448
  if (valueEnd !== -1) {
477
449
  for (const identifier of collectExpressionIdentifiers(script, valueStart, valueEnd)) {
478
- out.add(identifier);
450
+ identifiers.add(identifier);
479
451
  }
480
452
  }
481
453
  cursor = valueStart + 1;
482
454
  continue;
483
455
  }
484
456
  if (script[afterProperty] === "}" || script[afterProperty] === ",") {
485
- out.add(propertyName);
457
+ identifiers.add(target.propertyName);
486
458
  cursor = afterProperty + 1;
487
459
  continue;
488
460
  }
489
461
  cursor = afterProperty + 1;
490
462
  }
491
- return out;
463
+ return identifiers;
492
464
  };
493
- const callObjectPropertyTargets = [
494
- ["writeFile", "content"],
495
- ["updateTask", "description"],
496
- ];
497
- const fixTargetCallObjectPropertyTemplates = (script) => callObjectPropertyTargets.reduce((current, [functionName, propertyName]) => fixCallObjectPropertyTemplate(current, functionName, propertyName), script);
498
- const fixAssignedTemplate = (script, variableName) => {
465
+ const rewriteAssignedTemplate = (script, variableName) => rewriteTemplateContents(script, (text, from) => {
466
+ let cursor = from;
467
+ while (cursor < text.length) {
468
+ const variableStart = findNextIdentifier(text, variableName, cursor);
469
+ if (variableStart === -1) {
470
+ return undefined;
471
+ }
472
+ let assignmentStart = skipWhitespace(text, variableStart + variableName.length);
473
+ if (text[assignmentStart] === ":") {
474
+ assignmentStart = findTypeAnnotationAssignment(text, assignmentStart + 1);
475
+ if (assignmentStart === -1) {
476
+ cursor = variableStart + variableName.length;
477
+ continue;
478
+ }
479
+ }
480
+ if (text[assignmentStart] !== "=" ||
481
+ text[assignmentStart + 1] === "=" ||
482
+ text[assignmentStart + 1] === ">") {
483
+ cursor = variableStart + variableName.length;
484
+ continue;
485
+ }
486
+ const templateStart = skipWhitespace(text, assignmentStart + 1);
487
+ if (text[templateStart] !== "`") {
488
+ cursor = templateStart + 1;
489
+ continue;
490
+ }
491
+ const templateEnd = findTemplateEnd(text, templateStart, (char) => char === undefined ||
492
+ char === "\n" ||
493
+ char === "\r" ||
494
+ char === ";" ||
495
+ char === "," ||
496
+ char === ")" ||
497
+ char === "}" ||
498
+ char === "]");
499
+ if (templateEnd === -1) {
500
+ cursor = templateStart + 1;
501
+ continue;
502
+ }
503
+ return {
504
+ contentStart: templateStart + 1,
505
+ contentEnd: templateEnd,
506
+ nextCursor: templateEnd + 1,
507
+ };
508
+ }
509
+ return undefined;
510
+ }, escapeTemplateLiteralContent);
511
+ const rewriteAssignedObjectLiteral = (script, variableName) => {
499
512
  let out = script;
500
513
  let cursor = 0;
501
514
  while (cursor < out.length) {
@@ -517,63 +530,84 @@ const fixAssignedTemplate = (script, variableName) => {
517
530
  cursor = variableStart + variableName.length;
518
531
  continue;
519
532
  }
520
- const templateStart = skipWhitespace(out, assignmentStart + 1);
521
- if (out[templateStart] !== "`") {
522
- cursor = templateStart + 1;
533
+ const objectStart = skipWhitespace(out, assignmentStart + 1);
534
+ if (out[objectStart] !== "{") {
535
+ cursor = objectStart + 1;
523
536
  continue;
524
537
  }
525
- const templateEnd = findTemplateEnd(out, templateStart, (char) => char === undefined ||
526
- char === "\n" ||
527
- char === "\r" ||
528
- char === ";" ||
529
- char === "," ||
530
- char === ")" ||
531
- char === "}" ||
532
- char === "]");
533
- if (templateEnd === -1) {
534
- cursor = templateStart + 1;
538
+ const objectEnd = findClosingBrace(out, objectStart);
539
+ if (objectEnd === -1) {
540
+ cursor = objectStart + 1;
535
541
  continue;
536
542
  }
537
- const original = out.slice(templateStart + 1, templateEnd);
538
- const escaped = escapeTemplateLiteralContent(original);
539
- if (escaped !== original) {
540
- out = `${out.slice(0, templateStart + 1)}${escaped}${out.slice(templateEnd)}`;
541
- cursor = templateEnd + (escaped.length - original.length) + 1;
543
+ const original = out.slice(objectStart, objectEnd + 1);
544
+ const updated = normalizeObjectLiteralTemplateMarkers(original);
545
+ if (updated !== original) {
546
+ out = replaceSlice(out, objectStart, objectEnd + 1, updated);
547
+ cursor = objectEnd + 1 + (updated.length - original.length);
542
548
  continue;
543
549
  }
544
- cursor = templateEnd + 1;
550
+ cursor = objectEnd + 1;
545
551
  }
546
552
  return out;
547
553
  };
548
- const fixAssignedTemplatesForToolCalls = (script) => {
554
+ const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\\]\\]/g, "\\$&");
555
+ const collectObjectEntryMapSources = (script, valueIdentifier) => {
549
556
  const identifiers = new Set();
550
- for (const functionName of ["applyPatch", "taskComplete"]) {
557
+ const pattern = new RegExp(`Object\\.entries\\(\\s*([A-Za-z_$][A-Za-z0-9_$]*)\\s*\\)\\s*\\.map\\(\\s*(?:async\\s*)?\\(\\s*\\[\\s*[A-Za-z_$][A-Za-z0-9_$]*\\s*,\\s*${escapeRegExp(valueIdentifier)}\\s*\\]\\s*\\)\\s*=>`, "g");
558
+ for (const match of script.matchAll(pattern)) {
559
+ if (match[1] !== undefined) {
560
+ identifiers.add(match[1]);
561
+ }
562
+ }
563
+ return identifiers;
564
+ };
565
+ const rewriteDirectTemplates = (script) => {
566
+ let out = script;
567
+ for (const target of objectPropertyTargets) {
568
+ out = rewriteTemplateContents(out, (text, from) => findObjectPropertyTemplate(text, target, from), escapeTemplateLiteralContent);
569
+ }
570
+ for (const functionName of callTemplateTargets) {
571
+ out = rewriteTemplateContents(out, (text, from) => findDirectCallTemplate(text, functionName, from), escapeTemplateLiteralContent);
572
+ }
573
+ return out;
574
+ };
575
+ const collectReferencedTemplateIdentifiers = (script) => {
576
+ const templateIdentifiers = new Set();
577
+ for (const functionName of callTemplateTargets) {
551
578
  for (const identifier of collectCallArgumentIdentifiers(script, functionName)) {
552
- identifiers.add(identifier);
579
+ templateIdentifiers.add(identifier);
553
580
  }
554
581
  }
555
- for (const [functionName, propertyName] of callObjectPropertyTargets) {
556
- for (const identifier of collectCallObjectPropertyIdentifiers(script, functionName, propertyName)) {
557
- identifiers.add(identifier);
582
+ for (const target of objectPropertyTargets) {
583
+ for (const identifier of collectObjectPropertyIdentifiers(script, target)) {
584
+ templateIdentifiers.add(identifier);
558
585
  }
559
586
  }
560
587
  if (script.includes("*** Begin Patch")) {
561
- identifiers.add("patch");
588
+ templateIdentifiers.add("patch");
562
589
  }
563
- const objectTemplateIdentifiers = new Set();
564
- for (const identifier of identifiers) {
565
- for (const sourceIdentifier of collectObjectEntryMapSources(script, identifier)) {
566
- objectTemplateIdentifiers.add(sourceIdentifier);
590
+ const objectIdentifiers = new Set();
591
+ for (const identifier of templateIdentifiers) {
592
+ for (const source of collectObjectEntryMapSources(script, identifier)) {
593
+ objectIdentifiers.add(source);
567
594
  }
568
595
  }
596
+ return {
597
+ templateIdentifiers,
598
+ objectIdentifiers,
599
+ };
600
+ };
601
+ const rewriteAssignedTargets = (script) => {
602
+ const { templateIdentifiers, objectIdentifiers } = collectReferencedTemplateIdentifiers(script);
569
603
  let out = script;
570
- for (const identifier of identifiers) {
571
- out = fixAssignedTemplate(out, identifier);
604
+ for (const identifier of templateIdentifiers) {
605
+ out = rewriteAssignedTemplate(out, identifier);
572
606
  }
573
- for (const identifier of objectTemplateIdentifiers) {
574
- out = fixAssignedObjectTemplateValues(out, identifier);
607
+ for (const identifier of objectIdentifiers) {
608
+ out = rewriteAssignedObjectLiteral(out, identifier);
575
609
  }
576
610
  return out;
577
611
  };
578
- export const preprocessScript = (script) => fixAssignedTemplatesForToolCalls(["applyPatch", "taskComplete"].reduce((current, functionName) => fixCallTemplateArgument(current, functionName), fixTargetCallObjectPropertyTemplates(script)));
612
+ export const preprocessScript = (script) => rewriteAssignedTargets(rewriteDirectTemplates(script));
579
613
  //# sourceMappingURL=ScriptPreprocessing.js.map