@opencode/codemode 0.0.0-beta-19296 → 0.0.0-beta-19378

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 (60) hide show
  1. package/README.md +6 -0
  2. package/dist/codemode.d.ts +8 -11
  3. package/dist/codemode.js +4 -8
  4. package/dist/data.d.ts +28 -0
  5. package/dist/data.js +130 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +1 -0
  8. package/dist/interpreter/errors.d.ts +4 -6
  9. package/dist/interpreter/errors.js +22 -6
  10. package/dist/interpreter/execute.d.ts +3 -3
  11. package/dist/interpreter/execute.js +11 -18
  12. package/dist/interpreter/globals.d.ts +13 -0
  13. package/dist/interpreter/globals.js +59 -0
  14. package/dist/interpreter/host.d.ts +41 -0
  15. package/dist/interpreter/host.js +44 -0
  16. package/dist/interpreter/methods.d.ts +3 -16
  17. package/dist/interpreter/methods.js +42 -239
  18. package/dist/interpreter/model.d.ts +12 -73
  19. package/dist/interpreter/model.js +0 -87
  20. package/dist/interpreter/promises.d.ts +12 -13
  21. package/dist/interpreter/promises.js +49 -26
  22. package/dist/interpreter/references.js +23 -70
  23. package/dist/interpreter/runner.d.ts +23 -0
  24. package/dist/interpreter/runner.js +42 -0
  25. package/dist/interpreter/runtime.d.ts +13 -95
  26. package/dist/interpreter/runtime.js +290 -723
  27. package/dist/openapi/spec.js +1 -1
  28. package/dist/stdlib/array.d.ts +3 -0
  29. package/dist/stdlib/array.js +73 -0
  30. package/dist/stdlib/collections.d.ts +6 -1
  31. package/dist/stdlib/collections.js +120 -1
  32. package/dist/stdlib/console.d.ts +3 -2
  33. package/dist/stdlib/console.js +25 -16
  34. package/dist/stdlib/date.d.ts +5 -4
  35. package/dist/stdlib/date.js +28 -12
  36. package/dist/stdlib/json.d.ts +4 -4
  37. package/dist/stdlib/json.js +23 -28
  38. package/dist/stdlib/math.d.ts +3 -7
  39. package/dist/stdlib/math.js +85 -153
  40. package/dist/stdlib/number.d.ts +2 -4
  41. package/dist/stdlib/number.js +30 -37
  42. package/dist/stdlib/object.d.ts +4 -6
  43. package/dist/stdlib/object.js +106 -75
  44. package/dist/stdlib/regexp.d.ts +4 -6
  45. package/dist/stdlib/regexp.js +35 -12
  46. package/dist/stdlib/string.d.ts +1 -3
  47. package/dist/stdlib/string.js +15 -17
  48. package/dist/stdlib/url.d.ts +10 -6
  49. package/dist/stdlib/url.js +102 -25
  50. package/dist/stdlib/value.d.ts +6 -5
  51. package/dist/stdlib/value.js +33 -32
  52. package/dist/tool-runtime.d.ts +16 -15
  53. package/dist/tool-runtime.js +13 -150
  54. package/dist/values.d.ts +22 -16
  55. package/dist/values.js +23 -17
  56. package/package.json +1 -1
  57. package/dist/interpreter/iterator.d.ts +0 -13
  58. package/dist/interpreter/iterator.js +0 -4
  59. package/dist/stdlib/promise.d.ts +0 -2
  60. package/dist/stdlib/promise.js +0 -1
@@ -1,29 +1,15 @@
1
1
  import { Effect } from "effect";
2
- import { CodeModeFunction, CodeModeGenerator, CoercionFunction, ErrorConstructorReference, GlobalMethodReference, GlobalNamespace, IntrinsicReference, InterpreterRuntimeError, JsonMethodReference, PromiseCapabilityFunction, PromiseNamespace, UriFunction, } from "./model.js";
3
- import { containsOpaqueReference, isRuntimeReference, rejectCircularInsertion, typeofValue } from "./references.js";
4
- import { isBlockedMember } from "../tool-runtime.js";
5
- import { CodeModeDate, CodeModeMap, CodeModePromise, CodeModeRegExp, CodeModeSet, CodeModeURL, CodeModeURLSearchParams, isCodeModeValue, } from "../values.js";
6
- import { dateSetterArgumentCount, invokeDateMethod, invokeDateStatic } from "../stdlib/date.js";
7
- import { invokeMathMethod } from "../stdlib/math.js";
8
- import { invokeNumberMethod, invokeNumberStatic } from "../stdlib/number.js";
9
- import { invokeObjectMethod } from "../stdlib/object.js";
10
- import { invokeRegExpMethod, invokeRegExpStatic, matchToValue, toHostRegex } from "../stdlib/regexp.js";
11
- import { invokeStringStatic } from "../stdlib/string.js";
12
- import { invokeURLMethod, invokeURLStatic, uriArgument } from "../stdlib/url.js";
13
- import { boundedData, coerceToNumber, coerceToString, errorBrandName } from "../stdlib/value.js";
14
- import { preserveConsumerError } from "./iterator.js";
15
- export const isSupportedCallback = (value) => value instanceof CodeModeFunction ||
16
- value instanceof CoercionFunction ||
17
- value instanceof UriFunction ||
18
- value instanceof PromiseCapabilityFunction ||
19
- value instanceof GlobalMethodReference ||
20
- value instanceof JsonMethodReference ||
21
- value instanceof IntrinsicReference ||
22
- value instanceof ErrorConstructorReference ||
23
- // Callable namespaces dispatch like JS: Array/Object/Date/RegExp construct,
24
- // new-requiring constructors throw a TypeError. Math/JSON/console stay non-callable.
25
- (value instanceof GlobalNamespace && typeofValue(value) === "function") ||
26
- value instanceof PromiseNamespace;
2
+ import { isBlockedMember, toProgram } from "../data.js";
3
+ import { dateSetterArgumentCount, invokeDateMethod } from "../stdlib/date.js";
4
+ import { invokeNumberMethod } from "../stdlib/number.js";
5
+ import { invokeRegExpMethod, matchToValue, toHostRegex } from "../stdlib/regexp.js";
6
+ import { invokeURLMethod, uriArgument } from "../stdlib/url.js";
7
+ import { coerceToNumber, coerceToString, errorBrandName } from "../stdlib/value.js";
8
+ import { compareText } from "../tool-runtime.js";
9
+ import { Values } from "../values.js";
10
+ import { IntrinsicReference, InterpreterRuntimeError } from "./model.js";
11
+ import { containsOpaqueReference, rejectCircularInsertion, typeofValue } from "./references.js";
12
+ import { applyCollectionCallback, isSupportedCallback, toPrimitive } from "./runner.js";
27
13
  export const invokeIntrinsic = (runner, ref, args, node) => {
28
14
  if (typeof ref.receiver === "string") {
29
15
  if (ref.name === "replace" || ref.name === "replaceAll") {
@@ -41,7 +27,7 @@ export const invokeIntrinsic = (runner, ref, args, node) => {
41
27
  if (Array.isArray(ref.receiver)) {
42
28
  return invokeArrayMethod(runner, ref.receiver, ref.name, args, node);
43
29
  }
44
- if (ref.receiver instanceof CodeModeDate) {
30
+ if (ref.receiver instanceof Values.Date) {
45
31
  const target = ref.receiver;
46
32
  const argumentCount = dateSetterArgumentCount(ref.name);
47
33
  if (argumentCount === undefined)
@@ -52,70 +38,31 @@ export const invokeIntrinsic = (runner, ref, args, node) => {
52
38
  concurrency: 1,
53
39
  }), (values) => invokeDateMethod(target, ref.name, values, node, initialTime));
54
40
  }
55
- if (ref.receiver instanceof CodeModeRegExp) {
41
+ if (ref.receiver instanceof Values.RegExp) {
56
42
  return Effect.succeed(invokeRegExpMethod(ref.receiver, ref.name, args, node));
57
43
  }
58
- if (ref.receiver instanceof CodeModeMap) {
44
+ if (ref.receiver instanceof Values.Map) {
59
45
  return invokeMapMethod(runner, ref.receiver, ref.name, args, node);
60
46
  }
61
- if (ref.receiver instanceof CodeModeSet) {
47
+ if (ref.receiver instanceof Values.Set) {
62
48
  return invokeSetMethod(runner, ref.receiver, ref.name, args, node);
63
49
  }
64
- if (ref.receiver instanceof CodeModeURL) {
50
+ if (ref.receiver instanceof Values.URL) {
65
51
  return Effect.succeed(invokeURLMethod(ref.receiver, ref.name, node));
66
52
  }
67
- if (ref.receiver instanceof CodeModeURLSearchParams) {
53
+ if (ref.receiver instanceof Values.URLSearchParams) {
68
54
  return invokeURLSearchParamsMethod(runner, ref.receiver, ref.name, args, node);
69
55
  }
70
56
  throw new InterpreterRuntimeError(`Method '${ref.name}' is not available.`, node);
71
57
  };
72
- const coerceNumericArgument = (runner, value, node) => {
73
- if (value === null || typeof value !== "object" || Array.isArray(value) || isCodeModeValue(value)) {
74
- return Effect.succeed(coerceToNumber(value));
75
- }
76
- const object = value;
77
- return Effect.gen(function* () {
78
- if (Object.hasOwn(object, "valueOf") && typeofValue(object.valueOf) === "function") {
79
- const result = yield* runner.invokeCallable(object.valueOf, [], node);
80
- if (result === null || (typeof result !== "object" && typeof result !== "function")) {
81
- return coerceToNumber(result);
82
- }
83
- }
84
- if (!Object.hasOwn(object, "toString"))
85
- return coerceToNumber(value);
86
- if (typeofValue(object.toString) === "function") {
87
- const result = yield* runner.invokeCallable(object.toString, [], node);
88
- if (result === null || (typeof result !== "object" && typeof result !== "function")) {
89
- return coerceToNumber(result);
90
- }
91
- }
92
- throw new InterpreterRuntimeError("Cannot convert object to primitive value.", node).as("TypeError");
93
- });
94
- };
95
- export const invokeGlobalMethod = (ref, args, node) => {
96
- if (ref.namespace === "console")
97
- throw new InterpreterRuntimeError(`console.${ref.name} is not available.`, node);
98
- if (ref.namespace === "Object")
99
- return invokeObjectMethod(ref.name, args, node);
100
- if (ref.namespace === "Math")
101
- return invokeMathMethod(ref.name, args, node);
102
- if (ref.namespace === "Array")
103
- return invokeArrayStatic(ref.name, args, node);
104
- if (ref.namespace === "Number")
105
- return invokeNumberStatic(ref.name, args, node);
106
- if (ref.namespace === "String")
107
- return invokeStringStatic(ref.name, args, node);
108
- if (ref.namespace === "URL")
109
- return invokeURLStatic(ref.name, args, node);
110
- if (ref.namespace === "Date")
111
- return invokeDateStatic(ref.name, args, node);
112
- if (ref.namespace === "RegExp")
113
- return invokeRegExpStatic(ref.name, args, node);
114
- if (ref.namespace === "Map" || ref.namespace === "Set" || ref.namespace === "URLSearchParams") {
115
- throw new InterpreterRuntimeError(`${ref.namespace}.${ref.name} is not available.`, node);
116
- }
117
- throw new InterpreterRuntimeError(`${ref.namespace}.${ref.name} is not available.`, node);
118
- };
58
+ /**
59
+ * ToPrimitive: tries an object's own `valueOf`/`toString` in hint order and returns the first
60
+ * primitive result. Runtime values behave like their JS counterparts (Date yields its time under a
61
+ * number hint; the rest yield their string form). An inherited `toString` yields the default
62
+ * string form, so plain objects become "[object Object]" and arrays join.
63
+ */
64
+ const coerceNumericArgument = (runner, value, node) => Effect.map(toPrimitive(runner, value, "number", node), coerceToNumber);
65
+ // console is intercepted by the interpreter before reaching here.
119
66
  const requireDataArgument = (name, index, arg, node) => {
120
67
  if (containsOpaqueReference(arg)) {
121
68
  throw new InterpreterRuntimeError(`String.${name} expects argument ${index + 1} to be a data value.`, node, "InvalidDataValue");
@@ -129,7 +76,7 @@ const invokeStringMethod = (value, name, args, node) => {
129
76
  const optNum = (index) => (args[index] === undefined ? undefined : num(index));
130
77
  const optStr = (index) => (args[index] === undefined ? undefined : str(index));
131
78
  const rejectRegex = () => {
132
- if (args[0] instanceof CodeModeRegExp) {
79
+ if (args[0] instanceof Values.RegExp) {
133
80
  throw new InterpreterRuntimeError(`String.${name} cannot take a regular expression; use regex.test(string) or String.search instead.`, node).as("TypeError");
134
81
  }
135
82
  };
@@ -172,7 +119,7 @@ const invokeStringMethod = (value, name, args, node) => {
172
119
  result = requestedLimit !== undefined && requestedLimit >>> 0 === 0 ? [] : [value];
173
120
  break;
174
121
  }
175
- if (args[0] instanceof CodeModeRegExp) {
122
+ if (args[0] instanceof Values.RegExp) {
176
123
  result = value.split(args[0].regex, optNum(1));
177
124
  break;
178
125
  }
@@ -203,7 +150,7 @@ const invokeStringMethod = (value, name, args, node) => {
203
150
  break;
204
151
  case "replace":
205
152
  case "replaceAll": {
206
- if (args[0] instanceof CodeModeRegExp) {
153
+ if (args[0] instanceof Values.RegExp) {
207
154
  const pattern = args[0].regex;
208
155
  const replacement = str(1);
209
156
  if (name === "replaceAll" && !pattern.global) {
@@ -226,7 +173,7 @@ const invokeStringMethod = (value, name, args, node) => {
226
173
  return null;
227
174
  // Preserve the own `index` and `groups` properties on non-global matches.
228
175
  if (pattern.global)
229
- return boundedData(matched, "String.match result");
176
+ return toProgram(matched, "String.match result");
230
177
  return matchToValue(matched);
231
178
  }
232
179
  case "matchAll": {
@@ -278,138 +225,7 @@ const invokeStringMethod = (value, name, args, node) => {
278
225
  default:
279
226
  throw new InterpreterRuntimeError(`String method '${name}' is not available.`, node);
280
227
  }
281
- return boundedData(result, `String.${name} result`);
282
- };
283
- export const arrayStatics = new Set(["isArray", "of", "from"]);
284
- const invokeArrayStatic = (name, args, node) => {
285
- switch (name) {
286
- case "isArray":
287
- return Array.isArray(args[0]);
288
- case "of":
289
- return [...args];
290
- default:
291
- throw new InterpreterRuntimeError(`Array.${name} is not available.`, node);
292
- }
293
- };
294
- const arrayLikeSource = (source, node) => {
295
- if (source instanceof CodeModePromise) {
296
- throw new InterpreterRuntimeError("Array.from received an un-awaited Promise; await it before creating the array.", node, "InvalidDataValue");
297
- }
298
- if (source !== null &&
299
- typeof source === "object" &&
300
- (Object.getPrototypeOf(source) === Object.prototype || Object.getPrototypeOf(source) === null) &&
301
- typeof source.length === "number") {
302
- const length = source.length;
303
- const normalized = Number.isNaN(length) || length <= 0 ? 0 : Math.trunc(length);
304
- if (normalized > 4_294_967_295)
305
- throw new RangeError("Invalid array length");
306
- return { length: normalized, source };
307
- }
308
- throw new InterpreterRuntimeError("Array.from expects an array, string, Map, Set, or array-like value.", node, "InvalidDataValue");
309
- };
310
- export const invokeArrayFrom = (runner, args, node) => {
311
- const source = args[0];
312
- const apply = args.length < 2 || args[1] === undefined ? undefined : applyCollectionCallback(runner, args[1], "Array.from", node);
313
- return Effect.gen(function* () {
314
- const cursor = yield* runner.syncIterator(source, node);
315
- if (cursor === undefined) {
316
- if (source instanceof CodeModeGenerator) {
317
- throw new InterpreterRuntimeError("Array.from expects a synchronous iterable or array-like value.", node).as("TypeError");
318
- }
319
- const arrayLike = arrayLikeSource(source, node);
320
- const values = [];
321
- for (let index = 0; index < arrayLike.length; index += 1) {
322
- const item = Reflect.get(arrayLike.source, index);
323
- values.push(apply === undefined ? item : yield* apply([item, index]));
324
- }
325
- return values;
326
- }
327
- const values = [];
328
- let index = 0;
329
- while (true) {
330
- const step = yield* cursor.next;
331
- if (step.done)
332
- return values;
333
- values.push(apply === undefined ? step.value : yield* preserveConsumerError(cursor, apply([step.value, index])));
334
- index += 1;
335
- }
336
- });
337
- };
338
- export const invokeGroupBy = (runner, namespace, args, node) => {
339
- const source = args[0];
340
- if (source === null || source === undefined) {
341
- throw new InterpreterRuntimeError(`${namespace}.groupBy expects an iterable collection.`, node).as("TypeError");
342
- }
343
- const apply = applyCollectionCallback(runner, args[1], `${namespace}.groupBy`, node);
344
- return Effect.gen(function* () {
345
- const cursor = yield* runner.syncIterator(source, node);
346
- if (cursor === undefined) {
347
- throw new InterpreterRuntimeError(`${namespace}.groupBy expects an iterable collection.`, node).as("TypeError");
348
- }
349
- if (namespace === "Map") {
350
- const result = new CodeModeMap();
351
- let index = 0;
352
- while (true) {
353
- const step = yield* cursor.next;
354
- if (step.done)
355
- return result;
356
- const item = step.value;
357
- const key = yield* preserveConsumerError(cursor, apply([item, index]));
358
- const group = result.map.get(key);
359
- if (group === undefined)
360
- result.map.set(key, [item]);
361
- else
362
- group.push(item);
363
- index += 1;
364
- }
365
- }
366
- const result = Object.create(null);
367
- let index = 0;
368
- while (true) {
369
- const step = yield* cursor.next;
370
- if (step.done)
371
- return result;
372
- const item = step.value;
373
- const key = yield* preserveConsumerError(cursor, Effect.flatMap(apply([item, index]), (value) => coerceGroupByPropertyKey(runner, value, node)));
374
- if (isBlockedMember(key)) {
375
- return yield* preserveConsumerError(cursor, Effect.fail(new InterpreterRuntimeError(`Property '${key}' is not available.`, node)));
376
- }
377
- const group = result[key];
378
- if (group === undefined)
379
- result[key] = [item];
380
- else
381
- group.push(item);
382
- index += 1;
383
- }
384
- });
385
- };
386
- const coerceGroupByPropertyKey = (runner, value, node) => {
387
- if (value === null || typeof value !== "object" || Array.isArray(value) || isCodeModeValue(value)) {
388
- return Effect.succeed(coerceToString(value));
389
- }
390
- if (value instanceof CodeModePromise)
391
- return Effect.succeed("[object Promise]");
392
- if (isRuntimeReference(value)) {
393
- throw new InterpreterRuntimeError("Object.groupBy callback must return a data value.", node, "InvalidDataValue");
394
- }
395
- const object = value;
396
- if (!Object.hasOwn(object, "toString"))
397
- return Effect.succeed(coerceToString(value));
398
- return Effect.gen(function* () {
399
- if (typeofValue(object.toString) === "function") {
400
- const result = yield* runner.invokeCallable(object.toString, [], node);
401
- if (result === null || (typeof result !== "object" && typeof result !== "function")) {
402
- return coerceToString(result);
403
- }
404
- }
405
- if (Object.hasOwn(object, "valueOf") && typeofValue(object.valueOf) === "function") {
406
- const result = yield* runner.invokeCallable(object.valueOf, [], node);
407
- if (result === null || (typeof result !== "object" && typeof result !== "function")) {
408
- return coerceToString(result);
409
- }
410
- }
411
- throw new InterpreterRuntimeError("Cannot convert object to primitive value.", node).as("TypeError");
412
- });
228
+ return toProgram(result, `String.${name} result`);
413
229
  };
414
230
  const invokeStringReplacer = (runner, value, name, args, node) => {
415
231
  const apply = applyCollectionCallback(runner, args[1], `String.${name}`, node);
@@ -434,7 +250,7 @@ const invokeStringReplacer = (runner, value, name, args, node) => {
434
250
  return match;
435
251
  };
436
252
  const pattern = args[0];
437
- if (pattern instanceof CodeModeRegExp) {
253
+ if (pattern instanceof Values.RegExp) {
438
254
  if (name === "replaceAll" && !pattern.regex.global) {
439
255
  throw new InterpreterRuntimeError(`String.replaceAll requires a regular expression with the global (g) flag: write /${pattern.regex.source}/${pattern.regex.flags}g, or use String.replace to replace only the first match.`, node);
440
256
  }
@@ -455,27 +271,18 @@ const invokeStringReplacer = (runner, value, name, args, node) => {
455
271
  let end = 0;
456
272
  for (const match of matches) {
457
273
  const replacement = yield* apply(match.args);
458
- // Error values are branded plain objects; boundedData would strip the brand before coercion.
459
- output.push(value.slice(end, match.offset), replacement instanceof CodeModePromise
274
+ // Error values are branded plain objects; toProgram would strip the brand before coercion.
275
+ output.push(value.slice(end, match.offset), replacement instanceof Values.Promise
460
276
  ? "[object Promise]"
461
277
  : errorBrandName(replacement)
462
278
  ? coerceToString(replacement)
463
- : coerceToString(boundedData(replacement, `String.${name} replacer result`)));
279
+ : coerceToString(toProgram(replacement, `String.${name} replacer result`)));
464
280
  end = match.offset + match.match.length;
465
281
  }
466
282
  output.push(value.slice(end));
467
- return boundedData(output.join(""), `String.${name} result`);
283
+ return toProgram(output.join(""), `String.${name} result`);
468
284
  });
469
285
  };
470
- export const applyCollectionCallback = (runner, callback, name, node) => {
471
- if (!isSupportedCallback(callback)) {
472
- if (typeofValue(callback) === "function") {
473
- throw new InterpreterRuntimeError(`${name} cannot use this callable as a callback; wrap it in an arrow function, e.g. (value) => tools.ns.tool(value).`, node);
474
- }
475
- throw new InterpreterRuntimeError(`${name} expects a function callback.`, node).as("TypeError");
476
- }
477
- return (callbackArgs) => runner.invokeCallable(callback, callbackArgs, node);
478
- };
479
286
  const invokeMapMethod = (runner, target, name, args, node) => {
480
287
  switch (name) {
481
288
  case "get":
@@ -562,7 +369,7 @@ const invokeSetOperation = (runner, target, name, source, node) => Effect.gen(fu
562
369
  return result;
563
370
  }
564
371
  if (name === "intersection") {
565
- const result = new CodeModeSet();
372
+ const result = new Values.Set();
566
373
  if (target.set.size <= other.size) {
567
374
  for (const item of target.set.values()) {
568
375
  if (yield* other.has(item))
@@ -631,27 +438,27 @@ const invokeSetOperation = (runner, target, name, source, node) => Effect.gen(fu
631
438
  return true;
632
439
  });
633
440
  const copySet = (source) => {
634
- const result = new CodeModeSet();
441
+ const result = new Values.Set();
635
442
  for (const item of source.set.values())
636
443
  result.set.add(item);
637
444
  return result;
638
445
  };
639
446
  const loadSetRecord = (runner, source, name, node) => {
640
- if (source instanceof CodeModeSet) {
447
+ if (source instanceof Values.Set) {
641
448
  return Effect.succeed({
642
449
  size: source.set.size,
643
450
  has: (item) => Effect.succeed(source.set.has(item)),
644
451
  keys: () => Effect.succeed(source.set.values()),
645
452
  });
646
453
  }
647
- if (source instanceof CodeModeMap) {
454
+ if (source instanceof Values.Map) {
648
455
  return Effect.succeed({
649
456
  size: source.map.size,
650
457
  has: (item) => Effect.succeed(source.map.has(item)),
651
458
  keys: () => Effect.succeed(source.map.keys()),
652
459
  });
653
460
  }
654
- if (source === null || typeof source !== "object" || isCodeModeValue(source)) {
461
+ if (source === null || typeof source !== "object" || Values.isValue(source)) {
655
462
  throw new InterpreterRuntimeError(`Set.${name} expects a Set-like object.`, node).as("TypeError");
656
463
  }
657
464
  const object = source;
@@ -756,7 +563,7 @@ const invokeArrayMethod = (runner, target, name, args, node) => {
756
563
  if (args.length > 1 || (args.length === 1 && typeof args[0] !== "string")) {
757
564
  throw new InterpreterRuntimeError("Array.join expects zero arguments or one string separator.", node);
758
565
  }
759
- const input = boundedData(target, "Array.join input");
566
+ const input = toProgram(target, "Array.join input");
760
567
  return Effect.succeed(input.map((item) => coerceToString(item ?? "")).join(args.length === 0 ? "," : args[0]));
761
568
  }
762
569
  case "includes":
@@ -992,11 +799,7 @@ const invokeArrayMethod = (runner, target, name, args, node) => {
992
799
  };
993
800
  const sortArray = (runner, target, comparator, name, node) => {
994
801
  if (comparator === undefined) {
995
- return Effect.sync(() => [...target].sort((a, b) => {
996
- const left = coerceToString(a);
997
- const right = coerceToString(b);
998
- return left < right ? -1 : left > right ? 1 : 0;
999
- }));
802
+ return Effect.sync(() => [...target].sort((a, b) => compareText(coerceToString(a), coerceToString(b))));
1000
803
  }
1001
804
  const apply = applyCollectionCallback(runner, comparator, name, node);
1002
805
  const mergeSort = (items) => {
@@ -1,23 +1,10 @@
1
+ import type { BlockStatement, Expression, Node, Pattern } from "acorn";
1
2
  import type { Effect } from "effect";
2
- import type { SafeObject } from "../tool-runtime.js";
3
- import type { CodeModePromise, CodeModeRegExp, CodeModeURL } from "../values.js";
4
- export type SourcePosition = {
5
- line: number;
6
- column: number;
7
- };
8
- export type SourceLocation = {
9
- start: SourcePosition;
10
- end: SourcePosition;
11
- };
12
- export type AstNode = {
13
- type: string;
14
- loc?: SourceLocation;
15
- [key: string]: unknown;
16
- };
17
- export type ProgramNode = AstNode & {
18
- type: "Program";
19
- body: Array<AstNode>;
20
- };
3
+ import type { DiagnosticKind } from "../codemode.js";
4
+ import type { SafeObject } from "../data.js";
5
+ import type { Values } from "../values.js";
6
+ /** Any parsed node; the interpreter narrows on `type` and reads `loc` for diagnostics. */
7
+ export type AstNode = Node;
21
8
  export type Binding = {
22
9
  mutable: boolean;
23
10
  value: unknown;
@@ -36,16 +23,16 @@ export type StatementResult = {
36
23
  label?: string;
37
24
  };
38
25
  export type MemberReference = {
39
- target: SafeObject | Array<unknown> | CodeModeRegExp | CodeModeURL;
26
+ target: SafeObject | Array<unknown> | Values.RegExp | Values.URL;
40
27
  key: PropertyKey;
41
28
  };
42
29
  export declare class CodeModeFunction {
43
- readonly parameters: ReadonlyArray<AstNode>;
44
- readonly body: AstNode;
30
+ readonly parameters: ReadonlyArray<Pattern>;
31
+ readonly body: BlockStatement | Expression;
45
32
  readonly capturedScopes: ReadonlyArray<Map<string, Binding>>;
46
33
  readonly async: boolean;
47
34
  readonly generator: boolean;
48
- constructor(parameters: ReadonlyArray<AstNode>, body: AstNode, capturedScopes: ReadonlyArray<Map<string, Binding>>, async: boolean, generator: boolean);
35
+ constructor(parameters: ReadonlyArray<Pattern>, body: BlockStatement | Expression, capturedScopes: ReadonlyArray<Map<string, Binding>>, async: boolean, generator: boolean);
49
36
  }
50
37
  export type GeneratorRequestKind = "next" | "return" | "throw";
51
38
  export declare class CodeModeGenerator {
@@ -67,51 +54,14 @@ export declare class ComputedValue {
67
54
  readonly value: unknown;
68
55
  constructor(value: unknown);
69
56
  }
70
- export declare class PromiseNamespace {
71
- }
72
- export declare class SymbolNamespace {
73
- }
74
57
  export declare const AsyncIteratorSymbol: unique symbol;
75
58
  export declare const IteratorSymbol: unique symbol;
76
59
  export declare const IteratorSymbols: readonly [typeof AsyncIteratorSymbol, typeof IteratorSymbol];
77
- export type PromiseMethodName = "all" | "allSettled" | "race" | "any" | "resolve" | "reject";
78
- export declare class PromiseMethodReference {
79
- readonly name: PromiseMethodName;
80
- constructor(name: PromiseMethodName);
81
- }
82
60
  export type PromiseInstanceMethodName = "then" | "catch" | "finally";
83
61
  export declare class PromiseInstanceMethodReference {
84
- readonly promise: CodeModePromise;
62
+ readonly promise: Values.Promise;
85
63
  readonly name: PromiseInstanceMethodName;
86
- constructor(promise: CodeModePromise, name: PromiseInstanceMethodName);
87
- }
88
- export declare class PromiseCapabilityFunction {
89
- readonly settle: (value: unknown) => void;
90
- constructor(settle: (value: unknown) => void);
91
- }
92
- export type GlobalNamespaceName = "Object" | "Math" | "JSON" | "Array" | "console" | "Date" | "RegExp" | "Map" | "Set" | "URL" | "URLSearchParams";
93
- export declare class GlobalNamespace {
94
- readonly name: GlobalNamespaceName;
95
- constructor(name: GlobalNamespaceName);
96
- }
97
- export declare class GlobalMethodReference {
98
- readonly namespace: Exclude<GlobalNamespaceName, "JSON"> | "Number" | "String";
99
- readonly name: string;
100
- constructor(namespace: Exclude<GlobalNamespaceName, "JSON"> | "Number" | "String", name: string);
101
- }
102
- export declare class JsonMethodReference {
103
- readonly name: "parse" | "stringify";
104
- constructor(name: "parse" | "stringify");
105
- }
106
- export declare class CoercionFunction {
107
- readonly name: "Number" | "String" | "Boolean" | "parseInt" | "parseFloat" | "isFinite" | "isNaN";
108
- constructor(name: "Number" | "String" | "Boolean" | "parseInt" | "parseFloat" | "isFinite" | "isNaN");
109
- }
110
- export declare class UriFunction {
111
- readonly name: "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent";
112
- constructor(name: "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent");
113
- }
114
- export declare class SearchFunction {
64
+ constructor(promise: Values.Promise, name: PromiseInstanceMethodName);
115
65
  }
116
66
  export declare class ProgramThrow {
117
67
  readonly value: unknown;
@@ -121,11 +71,6 @@ export declare class GeneratorReturn {
121
71
  readonly value: unknown;
122
72
  constructor(value: unknown);
123
73
  }
124
- export declare class ErrorConstructorReference {
125
- readonly name: string;
126
- constructor(name: string);
127
- }
128
- export type DiagnosticKind = "ParseError" | "UnsupportedSyntax" | "UnknownTool" | "InvalidToolInput" | "InvalidToolOutput" | "InvalidDataValue" | "ToolCallLimitExceeded" | "TimeoutExceeded" | "ToolFailure" | "ExecutionFailure";
129
74
  export declare const OptionalShortCircuit: unique symbol;
130
75
  export declare const supportedSyntaxMessage = "Supported orchestration syntax: tools.* calls (they return promises - resolve them with await), data literals, destructuring, optional chaining, template literals, conditionals, switch, loops (incl. for...of and for...in over object/array/tools keys), arrow functions, spread, try/catch, array methods (map/filter/find/findIndex/some/every/reduce/flatMap/forEach/sort/slice/concat/indexOf/lastIndexOf/at/flat/reverse/includes/join), string methods (incl. match/matchAll/replace/split with regular expressions), Date/RegExp/Map/Set/URL/URLSearchParams, URI encoding helpers, Object/Math/JSON helpers, captured console.log/warn/error/dir/table, Promise.all/allSettled/race/any/resolve/reject over arrays mixing promises and plain values for parallel tool calls, promise chaining with .then/.catch/.finally, and new Promise((resolve, reject) => ...) construction.";
131
76
  export declare class InterpreterRuntimeError extends Error {
@@ -138,12 +83,6 @@ export declare class InterpreterRuntimeError extends Error {
138
83
  }
139
84
  export declare const unsupportedSyntax: (kind: string, node: AstNode) => InterpreterRuntimeError;
140
85
  export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
141
- export declare const asNode: (value: unknown, context: string) => AstNode;
142
- export declare const getArray: (node: AstNode, key: string) => Array<unknown>;
143
- export declare const getString: (node: AstNode, key: string) => string;
144
- export declare const getBoolean: (node: AstNode, key: string) => boolean;
145
- export declare const getOptionalNode: (node: AstNode, key: string) => AstNode | undefined;
146
- export declare const getNode: (node: AstNode, key: string) => AstNode;
147
86
  export declare const sourceLocation: (node: AstNode) => {
148
87
  readonly line: number;
149
88
  readonly column: number;
@@ -42,19 +42,9 @@ export class ComputedValue {
42
42
  this.value = value;
43
43
  }
44
44
  }
45
- export class PromiseNamespace {
46
- }
47
- export class SymbolNamespace {
48
- }
49
45
  export const AsyncIteratorSymbol = Symbol("codemode.async-iterator");
50
46
  export const IteratorSymbol = Symbol("codemode.iterator");
51
47
  export const IteratorSymbols = [AsyncIteratorSymbol, IteratorSymbol];
52
- export class PromiseMethodReference {
53
- name;
54
- constructor(name) {
55
- this.name = name;
56
- }
57
- }
58
48
  export class PromiseInstanceMethodReference {
59
49
  promise;
60
50
  name;
@@ -63,46 +53,6 @@ export class PromiseInstanceMethodReference {
63
53
  this.name = name;
64
54
  }
65
55
  }
66
- export class PromiseCapabilityFunction {
67
- settle;
68
- constructor(settle) {
69
- this.settle = settle;
70
- }
71
- }
72
- export class GlobalNamespace {
73
- name;
74
- constructor(name) {
75
- this.name = name;
76
- }
77
- }
78
- export class GlobalMethodReference {
79
- namespace;
80
- name;
81
- constructor(namespace, name) {
82
- this.namespace = namespace;
83
- this.name = name;
84
- }
85
- }
86
- export class JsonMethodReference {
87
- name;
88
- constructor(name) {
89
- this.name = name;
90
- }
91
- }
92
- export class CoercionFunction {
93
- name;
94
- constructor(name) {
95
- this.name = name;
96
- }
97
- }
98
- export class UriFunction {
99
- name;
100
- constructor(name) {
101
- this.name = name;
102
- }
103
- }
104
- export class SearchFunction {
105
- }
106
56
  export class ProgramThrow {
107
57
  value;
108
58
  constructor(value) {
@@ -115,12 +65,6 @@ export class GeneratorReturn {
115
65
  this.value = value;
116
66
  }
117
67
  }
118
- export class ErrorConstructorReference {
119
- name;
120
- constructor(name) {
121
- this.name = name;
122
- }
123
- }
124
68
  export const OptionalShortCircuit = Symbol("codemode.optional-short-circuit");
125
69
  export const supportedSyntaxMessage = "Supported orchestration syntax: tools.* calls (they return promises - resolve them with await), data literals, destructuring, optional chaining, template literals, conditionals, switch, loops (incl. for...of and for...in over object/array/tools keys), arrow functions, spread, try/catch, array methods (map/filter/find/findIndex/some/every/reduce/flatMap/forEach/sort/slice/concat/indexOf/lastIndexOf/at/flat/reverse/includes/join), string methods (incl. match/matchAll/replace/split with regular expressions), Date/RegExp/Map/Set/URL/URLSearchParams, URI encoding helpers, Object/Math/JSON helpers, captured console.log/warn/error/dir/table, Promise.all/allSettled/race/any/resolve/reject over arrays mixing promises and plain values for parallel tool calls, promise chaining with .then/.catch/.finally, and new Promise((resolve, reject) => ...) construction.";
126
70
  export class InterpreterRuntimeError extends Error {
@@ -143,37 +87,6 @@ export class InterpreterRuntimeError extends Error {
143
87
  }
144
88
  export const unsupportedSyntax = (kind, node) => new InterpreterRuntimeError(`Syntax '${kind}' is not supported. ${supportedSyntaxMessage}`, node, "UnsupportedSyntax", [supportedSyntaxMessage]);
145
89
  export const isRecord = (value) => typeof value === "object" && value !== null;
146
- export const asNode = (value, context) => {
147
- if (!isRecord(value) || typeof value.type !== "string") {
148
- throw new InterpreterRuntimeError(`Invalid AST node while reading ${context}.`);
149
- }
150
- return value;
151
- };
152
- export const getArray = (node, key) => {
153
- const value = node[key];
154
- if (!Array.isArray(value))
155
- throw new InterpreterRuntimeError(`Expected '${key}' to be an array.`, node);
156
- return value;
157
- };
158
- export const getString = (node, key) => {
159
- const value = node[key];
160
- if (typeof value !== "string")
161
- throw new InterpreterRuntimeError(`Expected '${key}' to be a string.`, node);
162
- return value;
163
- };
164
- export const getBoolean = (node, key) => {
165
- const value = node[key];
166
- if (typeof value !== "boolean")
167
- throw new InterpreterRuntimeError(`Expected '${key}' to be a boolean.`, node);
168
- return value;
169
- };
170
- export const getOptionalNode = (node, key) => {
171
- const value = node[key];
172
- if (value === undefined || value === null)
173
- return undefined;
174
- return asNode(value, key);
175
- };
176
- export const getNode = (node, key) => asNode(node[key], key);
177
90
  export const sourceLocation = (node) => ({
178
91
  line: Math.max(1, (node.loc?.start.line ?? 2) - 1),
179
92
  column: Math.max(1, (node.loc?.start.column ?? 4) - 3),