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

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 (41) 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 +1 -1
  9. package/dist/interpreter/errors.js +2 -2
  10. package/dist/interpreter/execute.d.ts +3 -3
  11. package/dist/interpreter/execute.js +9 -15
  12. package/dist/interpreter/methods.d.ts +9 -2
  13. package/dist/interpreter/methods.js +54 -76
  14. package/dist/interpreter/model.d.ts +12 -32
  15. package/dist/interpreter/model.js +0 -31
  16. package/dist/interpreter/promises.d.ts +8 -8
  17. package/dist/interpreter/promises.js +4 -4
  18. package/dist/interpreter/references.js +12 -42
  19. package/dist/interpreter/runtime.d.ts +2 -3
  20. package/dist/interpreter/runtime.js +255 -311
  21. package/dist/openapi/spec.js +1 -1
  22. package/dist/stdlib/console.js +14 -14
  23. package/dist/stdlib/date.d.ts +2 -2
  24. package/dist/stdlib/date.js +1 -1
  25. package/dist/stdlib/json.js +17 -26
  26. package/dist/stdlib/number.d.ts +1 -1
  27. package/dist/stdlib/number.js +4 -3
  28. package/dist/stdlib/object.js +11 -10
  29. package/dist/stdlib/regexp.d.ts +2 -2
  30. package/dist/stdlib/regexp.js +3 -3
  31. package/dist/stdlib/string.d.ts +1 -1
  32. package/dist/stdlib/string.js +1 -1
  33. package/dist/stdlib/url.d.ts +3 -3
  34. package/dist/stdlib/url.js +7 -6
  35. package/dist/stdlib/value.d.ts +2 -3
  36. package/dist/stdlib/value.js +14 -15
  37. package/dist/tool-runtime.d.ts +16 -15
  38. package/dist/tool-runtime.js +13 -150
  39. package/dist/values.d.ts +22 -16
  40. package/dist/values.js +23 -17
  41. package/package.json +1 -1
@@ -1,8 +1,9 @@
1
1
  import { Effect } from "effect";
2
2
  import { CodeModeFunction, CodeModeGenerator, CoercionFunction, ErrorConstructorReference, GlobalMethodReference, GlobalNamespace, IntrinsicReference, InterpreterRuntimeError, JsonMethodReference, PromiseCapabilityFunction, PromiseNamespace, UriFunction, } from "./model.js";
3
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";
4
+ import { isBlockedMember, toProgram } from "../data.js";
5
+ import { compareText } from "../tool-runtime.js";
6
+ import { Values } from "../values.js";
6
7
  import { dateSetterArgumentCount, invokeDateMethod, invokeDateStatic } from "../stdlib/date.js";
7
8
  import { invokeMathMethod } from "../stdlib/math.js";
8
9
  import { invokeNumberMethod, invokeNumberStatic } from "../stdlib/number.js";
@@ -10,7 +11,7 @@ import { invokeObjectMethod } from "../stdlib/object.js";
10
11
  import { invokeRegExpMethod, invokeRegExpStatic, matchToValue, toHostRegex } from "../stdlib/regexp.js";
11
12
  import { invokeStringStatic } from "../stdlib/string.js";
12
13
  import { invokeURLMethod, invokeURLStatic, uriArgument } from "../stdlib/url.js";
13
- import { boundedData, coerceToNumber, coerceToString, errorBrandName } from "../stdlib/value.js";
14
+ import { coerceToNumber, coerceToString, errorBrandName } from "../stdlib/value.js";
14
15
  import { preserveConsumerError } from "./iterator.js";
15
16
  export const isSupportedCallback = (value) => value instanceof CodeModeFunction ||
16
17
  value instanceof CoercionFunction ||
@@ -41,7 +42,7 @@ export const invokeIntrinsic = (runner, ref, args, node) => {
41
42
  if (Array.isArray(ref.receiver)) {
42
43
  return invokeArrayMethod(runner, ref.receiver, ref.name, args, node);
43
44
  }
44
- if (ref.receiver instanceof CodeModeDate) {
45
+ if (ref.receiver instanceof Values.Date) {
45
46
  const target = ref.receiver;
46
47
  const argumentCount = dateSetterArgumentCount(ref.name);
47
48
  if (argumentCount === undefined)
@@ -52,49 +53,53 @@ export const invokeIntrinsic = (runner, ref, args, node) => {
52
53
  concurrency: 1,
53
54
  }), (values) => invokeDateMethod(target, ref.name, values, node, initialTime));
54
55
  }
55
- if (ref.receiver instanceof CodeModeRegExp) {
56
+ if (ref.receiver instanceof Values.RegExp) {
56
57
  return Effect.succeed(invokeRegExpMethod(ref.receiver, ref.name, args, node));
57
58
  }
58
- if (ref.receiver instanceof CodeModeMap) {
59
+ if (ref.receiver instanceof Values.Map) {
59
60
  return invokeMapMethod(runner, ref.receiver, ref.name, args, node);
60
61
  }
61
- if (ref.receiver instanceof CodeModeSet) {
62
+ if (ref.receiver instanceof Values.Set) {
62
63
  return invokeSetMethod(runner, ref.receiver, ref.name, args, node);
63
64
  }
64
- if (ref.receiver instanceof CodeModeURL) {
65
+ if (ref.receiver instanceof Values.URL) {
65
66
  return Effect.succeed(invokeURLMethod(ref.receiver, ref.name, node));
66
67
  }
67
- if (ref.receiver instanceof CodeModeURLSearchParams) {
68
+ if (ref.receiver instanceof Values.URLSearchParams) {
68
69
  return invokeURLSearchParamsMethod(runner, ref.receiver, ref.name, args, node);
69
70
  }
70
71
  throw new InterpreterRuntimeError(`Method '${ref.name}' is not available.`, node);
71
72
  };
72
- const coerceNumericArgument = (runner, value, node) => {
73
- if (value === null || typeof value !== "object" || Array.isArray(value) || isCodeModeValue(value)) {
74
- return Effect.succeed(coerceToNumber(value));
73
+ /**
74
+ * ToPrimitive: tries an object's own `valueOf`/`toString` in hint order and returns the first
75
+ * primitive result. Runtime values behave like their JS counterparts (Date yields its time under a
76
+ * number hint; the rest yield their string form). An inherited `toString` yields the default
77
+ * string form, so plain objects become "[object Object]" and arrays join.
78
+ */
79
+ export const toPrimitive = (runner, value, hint, node) => {
80
+ if (value === null || typeof value !== "object")
81
+ return Effect.succeed(value);
82
+ if (Values.isValue(value)) {
83
+ return Effect.succeed(value instanceof Values.Date && hint === "number" ? value.time : coerceToString(value));
75
84
  }
76
85
  const object = value;
86
+ const order = hint === "number" ? ["valueOf", "toString"] : ["toString", "valueOf"];
77
87
  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
- }
88
+ for (const method of order) {
89
+ if (method === "toString" && !Object.hasOwn(object, "toString"))
90
+ return coerceToString(value);
91
+ if (!Object.hasOwn(object, method) || typeofValue(object[method]) !== "function")
92
+ continue;
93
+ const result = yield* runner.invokeCallable(object[method], [], node);
94
+ if (result === null || (typeof result !== "object" && typeof result !== "function"))
95
+ return result;
91
96
  }
92
97
  throw new InterpreterRuntimeError("Cannot convert object to primitive value.", node).as("TypeError");
93
98
  });
94
99
  };
100
+ const coerceNumericArgument = (runner, value, node) => Effect.map(toPrimitive(runner, value, "number", node), coerceToNumber);
101
+ // console is intercepted by the interpreter before reaching here.
95
102
  export const invokeGlobalMethod = (ref, args, node) => {
96
- if (ref.namespace === "console")
97
- throw new InterpreterRuntimeError(`console.${ref.name} is not available.`, node);
98
103
  if (ref.namespace === "Object")
99
104
  return invokeObjectMethod(ref.name, args, node);
100
105
  if (ref.namespace === "Math")
@@ -111,9 +116,6 @@ export const invokeGlobalMethod = (ref, args, node) => {
111
116
  return invokeDateStatic(ref.name, args, node);
112
117
  if (ref.namespace === "RegExp")
113
118
  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
119
  throw new InterpreterRuntimeError(`${ref.namespace}.${ref.name} is not available.`, node);
118
120
  };
119
121
  const requireDataArgument = (name, index, arg, node) => {
@@ -129,7 +131,7 @@ const invokeStringMethod = (value, name, args, node) => {
129
131
  const optNum = (index) => (args[index] === undefined ? undefined : num(index));
130
132
  const optStr = (index) => (args[index] === undefined ? undefined : str(index));
131
133
  const rejectRegex = () => {
132
- if (args[0] instanceof CodeModeRegExp) {
134
+ if (args[0] instanceof Values.RegExp) {
133
135
  throw new InterpreterRuntimeError(`String.${name} cannot take a regular expression; use regex.test(string) or String.search instead.`, node).as("TypeError");
134
136
  }
135
137
  };
@@ -172,7 +174,7 @@ const invokeStringMethod = (value, name, args, node) => {
172
174
  result = requestedLimit !== undefined && requestedLimit >>> 0 === 0 ? [] : [value];
173
175
  break;
174
176
  }
175
- if (args[0] instanceof CodeModeRegExp) {
177
+ if (args[0] instanceof Values.RegExp) {
176
178
  result = value.split(args[0].regex, optNum(1));
177
179
  break;
178
180
  }
@@ -203,7 +205,7 @@ const invokeStringMethod = (value, name, args, node) => {
203
205
  break;
204
206
  case "replace":
205
207
  case "replaceAll": {
206
- if (args[0] instanceof CodeModeRegExp) {
208
+ if (args[0] instanceof Values.RegExp) {
207
209
  const pattern = args[0].regex;
208
210
  const replacement = str(1);
209
211
  if (name === "replaceAll" && !pattern.global) {
@@ -226,7 +228,7 @@ const invokeStringMethod = (value, name, args, node) => {
226
228
  return null;
227
229
  // Preserve the own `index` and `groups` properties on non-global matches.
228
230
  if (pattern.global)
229
- return boundedData(matched, "String.match result");
231
+ return toProgram(matched, "String.match result");
230
232
  return matchToValue(matched);
231
233
  }
232
234
  case "matchAll": {
@@ -278,7 +280,7 @@ const invokeStringMethod = (value, name, args, node) => {
278
280
  default:
279
281
  throw new InterpreterRuntimeError(`String method '${name}' is not available.`, node);
280
282
  }
281
- return boundedData(result, `String.${name} result`);
283
+ return toProgram(result, `String.${name} result`);
282
284
  };
283
285
  export const arrayStatics = new Set(["isArray", "of", "from"]);
284
286
  const invokeArrayStatic = (name, args, node) => {
@@ -292,7 +294,7 @@ const invokeArrayStatic = (name, args, node) => {
292
294
  }
293
295
  };
294
296
  const arrayLikeSource = (source, node) => {
295
- if (source instanceof CodeModePromise) {
297
+ if (source instanceof Values.Promise) {
296
298
  throw new InterpreterRuntimeError("Array.from received an un-awaited Promise; await it before creating the array.", node, "InvalidDataValue");
297
299
  }
298
300
  if (source !== null &&
@@ -347,7 +349,7 @@ export const invokeGroupBy = (runner, namespace, args, node) => {
347
349
  throw new InterpreterRuntimeError(`${namespace}.groupBy expects an iterable collection.`, node).as("TypeError");
348
350
  }
349
351
  if (namespace === "Map") {
350
- const result = new CodeModeMap();
352
+ const result = new Values.Map();
351
353
  let index = 0;
352
354
  while (true) {
353
355
  const step = yield* cursor.next;
@@ -384,32 +386,12 @@ export const invokeGroupBy = (runner, namespace, args, node) => {
384
386
  });
385
387
  };
386
388
  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)
389
+ if (value instanceof Values.Promise)
391
390
  return Effect.succeed("[object Promise]");
392
- if (isRuntimeReference(value)) {
391
+ if (!Values.isValue(value) && isRuntimeReference(value)) {
393
392
  throw new InterpreterRuntimeError("Object.groupBy callback must return a data value.", node, "InvalidDataValue");
394
393
  }
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
- });
394
+ return Effect.map(toPrimitive(runner, value, "string", node), coerceToString);
413
395
  };
414
396
  const invokeStringReplacer = (runner, value, name, args, node) => {
415
397
  const apply = applyCollectionCallback(runner, args[1], `String.${name}`, node);
@@ -434,7 +416,7 @@ const invokeStringReplacer = (runner, value, name, args, node) => {
434
416
  return match;
435
417
  };
436
418
  const pattern = args[0];
437
- if (pattern instanceof CodeModeRegExp) {
419
+ if (pattern instanceof Values.RegExp) {
438
420
  if (name === "replaceAll" && !pattern.regex.global) {
439
421
  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
422
  }
@@ -455,16 +437,16 @@ const invokeStringReplacer = (runner, value, name, args, node) => {
455
437
  let end = 0;
456
438
  for (const match of matches) {
457
439
  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
440
+ // Error values are branded plain objects; toProgram would strip the brand before coercion.
441
+ output.push(value.slice(end, match.offset), replacement instanceof Values.Promise
460
442
  ? "[object Promise]"
461
443
  : errorBrandName(replacement)
462
444
  ? coerceToString(replacement)
463
- : coerceToString(boundedData(replacement, `String.${name} replacer result`)));
445
+ : coerceToString(toProgram(replacement, `String.${name} replacer result`)));
464
446
  end = match.offset + match.match.length;
465
447
  }
466
448
  output.push(value.slice(end));
467
- return boundedData(output.join(""), `String.${name} result`);
449
+ return toProgram(output.join(""), `String.${name} result`);
468
450
  });
469
451
  };
470
452
  export const applyCollectionCallback = (runner, callback, name, node) => {
@@ -562,7 +544,7 @@ const invokeSetOperation = (runner, target, name, source, node) => Effect.gen(fu
562
544
  return result;
563
545
  }
564
546
  if (name === "intersection") {
565
- const result = new CodeModeSet();
547
+ const result = new Values.Set();
566
548
  if (target.set.size <= other.size) {
567
549
  for (const item of target.set.values()) {
568
550
  if (yield* other.has(item))
@@ -631,27 +613,27 @@ const invokeSetOperation = (runner, target, name, source, node) => Effect.gen(fu
631
613
  return true;
632
614
  });
633
615
  const copySet = (source) => {
634
- const result = new CodeModeSet();
616
+ const result = new Values.Set();
635
617
  for (const item of source.set.values())
636
618
  result.set.add(item);
637
619
  return result;
638
620
  };
639
621
  const loadSetRecord = (runner, source, name, node) => {
640
- if (source instanceof CodeModeSet) {
622
+ if (source instanceof Values.Set) {
641
623
  return Effect.succeed({
642
624
  size: source.set.size,
643
625
  has: (item) => Effect.succeed(source.set.has(item)),
644
626
  keys: () => Effect.succeed(source.set.values()),
645
627
  });
646
628
  }
647
- if (source instanceof CodeModeMap) {
629
+ if (source instanceof Values.Map) {
648
630
  return Effect.succeed({
649
631
  size: source.map.size,
650
632
  has: (item) => Effect.succeed(source.map.has(item)),
651
633
  keys: () => Effect.succeed(source.map.keys()),
652
634
  });
653
635
  }
654
- if (source === null || typeof source !== "object" || isCodeModeValue(source)) {
636
+ if (source === null || typeof source !== "object" || Values.isValue(source)) {
655
637
  throw new InterpreterRuntimeError(`Set.${name} expects a Set-like object.`, node).as("TypeError");
656
638
  }
657
639
  const object = source;
@@ -756,7 +738,7 @@ const invokeArrayMethod = (runner, target, name, args, node) => {
756
738
  if (args.length > 1 || (args.length === 1 && typeof args[0] !== "string")) {
757
739
  throw new InterpreterRuntimeError("Array.join expects zero arguments or one string separator.", node);
758
740
  }
759
- const input = boundedData(target, "Array.join input");
741
+ const input = toProgram(target, "Array.join input");
760
742
  return Effect.succeed(input.map((item) => coerceToString(item ?? "")).join(args.length === 0 ? "," : args[0]));
761
743
  }
762
744
  case "includes":
@@ -992,11 +974,7 @@ const invokeArrayMethod = (runner, target, name, args, node) => {
992
974
  };
993
975
  const sortArray = (runner, target, comparator, name, node) => {
994
976
  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
- }));
977
+ return Effect.sync(() => [...target].sort((a, b) => compareText(coerceToString(a), coerceToString(b))));
1000
978
  }
1001
979
  const apply = applyCollectionCallback(runner, comparator, name, node);
1002
980
  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 {
@@ -81,9 +68,9 @@ export declare class PromiseMethodReference {
81
68
  }
82
69
  export type PromiseInstanceMethodName = "then" | "catch" | "finally";
83
70
  export declare class PromiseInstanceMethodReference {
84
- readonly promise: CodeModePromise;
71
+ readonly promise: Values.Promise;
85
72
  readonly name: PromiseInstanceMethodName;
86
- constructor(promise: CodeModePromise, name: PromiseInstanceMethodName);
73
+ constructor(promise: Values.Promise, name: PromiseInstanceMethodName);
87
74
  }
88
75
  export declare class PromiseCapabilityFunction {
89
76
  readonly settle: (value: unknown) => void;
@@ -125,7 +112,6 @@ export declare class ErrorConstructorReference {
125
112
  readonly name: string;
126
113
  constructor(name: string);
127
114
  }
128
- export type DiagnosticKind = "ParseError" | "UnsupportedSyntax" | "UnknownTool" | "InvalidToolInput" | "InvalidToolOutput" | "InvalidDataValue" | "ToolCallLimitExceeded" | "TimeoutExceeded" | "ToolFailure" | "ExecutionFailure";
129
115
  export declare const OptionalShortCircuit: unique symbol;
130
116
  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
117
  export declare class InterpreterRuntimeError extends Error {
@@ -138,12 +124,6 @@ export declare class InterpreterRuntimeError extends Error {
138
124
  }
139
125
  export declare const unsupportedSyntax: (kind: string, node: AstNode) => InterpreterRuntimeError;
140
126
  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
127
  export declare const sourceLocation: (node: AstNode) => {
148
128
  readonly line: number;
149
129
  readonly column: number;
@@ -143,37 +143,6 @@ export class InterpreterRuntimeError extends Error {
143
143
  }
144
144
  export const unsupportedSyntax = (kind, node) => new InterpreterRuntimeError(`Syntax '${kind}' is not supported. ${supportedSyntaxMessage}`, node, "UnsupportedSyntax", [supportedSyntaxMessage]);
145
145
  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
146
  export const sourceLocation = (node) => ({
178
147
  line: Math.max(1, (node.loc?.start.line ?? 2) - 1),
179
148
  column: Math.max(1, (node.loc?.start.column ?? 4) - 3),
@@ -2,7 +2,7 @@ import { Effect, Exit, Scope } from "effect";
2
2
  import type { Diagnostic } from "../codemode.js";
3
3
  import { type AstNode, InterpreterRuntimeError, PromiseInstanceMethodReference, PromiseMethodReference } from "./model.js";
4
4
  import { type CallbackRunner } from "./methods.js";
5
- import { CodeModePromise } from "../values.js";
5
+ import { Values } from "../values.js";
6
6
  import type { SyncIteratorRunner } from "./iterator.js";
7
7
  export declare class PromiseRuntime<R> {
8
8
  private readonly scope;
@@ -12,18 +12,18 @@ export declare class PromiseRuntime<R> {
12
12
  private readonly failures;
13
13
  private nextID;
14
14
  constructor(scope: Scope.Scope);
15
- create(effect: Effect.Effect<unknown, unknown, R>): Effect.Effect<CodeModePromise, never, R>;
16
- markObserved(promise: CodeModePromise): void;
17
- await(promise: CodeModePromise): Effect.Effect<Exit.Exit<unknown, unknown>>;
15
+ create(effect: Effect.Effect<unknown, unknown, R>): Effect.Effect<Values.Promise, never, R>;
16
+ markObserved(promise: Values.Promise): void;
17
+ await(promise: Values.Promise): Effect.Effect<Exit.Exit<unknown, unknown>>;
18
18
  fork(effect: Effect.Effect<unknown, unknown, R>): Effect.Effect<void, never, R>;
19
19
  diagnostics(): Array<Diagnostic>;
20
20
  interrupt(): Effect.Effect<Array<Diagnostic>>;
21
21
  }
22
22
  export declare const selfResolutionError: (node?: AstNode) => InterpreterRuntimeError;
23
23
  export declare const resolvePromiseValue: <R>(runner: CallbackRunner<R>, value: unknown, node: AstNode, own?: {
24
- promise?: CodeModePromise;
24
+ promise?: Values.Promise;
25
25
  }) => Effect.Effect<unknown, unknown, R>;
26
- export declare const resolvePromise: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, value: unknown, node: AstNode) => Effect.Effect<CodeModePromise, never, R>;
26
+ export declare const resolvePromise: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, value: unknown, node: AstNode) => Effect.Effect<Values.Promise, never, R>;
27
27
  export declare const invokePromiseMethod: <R>(runner: CallbackRunner<R> & SyncIteratorRunner<R>, promises: PromiseRuntime<R>, ref: PromiseMethodReference, args: Array<unknown>, node: AstNode) => Effect.Effect<unknown, unknown, R>;
28
- export declare const invokePromiseInstanceMethod: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, ref: PromiseInstanceMethodReference, args: Array<unknown>, node: AstNode) => Effect.Effect<CodeModePromise, never, R>;
29
- export declare const constructPromise: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, executor: unknown, node: AstNode) => Effect.Effect<CodeModePromise, unknown, R>;
28
+ export declare const invokePromiseInstanceMethod: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, ref: PromiseInstanceMethodReference, args: Array<unknown>, node: AstNode) => Effect.Effect<Values.Promise, never, R>;
29
+ export declare const constructPromise: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, executor: unknown, node: AstNode) => Effect.Effect<Values.Promise, unknown, R>;
@@ -4,7 +4,7 @@ import { caughtErrorValue, normalizeError } from "./errors.js";
4
4
  import { applyCollectionCallback, isSupportedCallback } from "./methods.js";
5
5
  import { typeofValue } from "./references.js";
6
6
  import { createAggregateErrorValue } from "../stdlib/value.js";
7
- import { CodeModePromise } from "../values.js";
7
+ import { Values } from "../values.js";
8
8
  // Observation only controls rejection reporting; program completion interrupts all promise work.
9
9
  export class PromiseRuntime {
10
10
  scope;
@@ -21,7 +21,7 @@ export class PromiseRuntime {
21
21
  // Allocate before forking so reruns get distinct IDs and diagnostics retain creation order.
22
22
  const id = this.nextID++;
23
23
  return Effect.map(Effect.forkIn(effect, this.scope, { startImmediately: true }), (fiber) => {
24
- const promise = new CodeModePromise(fiber);
24
+ const promise = new Values.Promise(fiber);
25
25
  this.active.add(promise);
26
26
  this.ids.set(promise, id);
27
27
  fiber.addObserver((exit) => {
@@ -72,7 +72,7 @@ export const selfResolutionError = (node) => new InterpreterRuntimeError("Chaini
72
72
  export const resolvePromiseValue = (runner, value, node, own) => {
73
73
  if (own?.promise !== undefined && value === own.promise)
74
74
  return Effect.fail(selfResolutionError(node));
75
- if (value instanceof CodeModePromise)
75
+ if (value instanceof Values.Promise)
76
76
  return runner.settlePromise(value);
77
77
  if (value === null || typeof value !== "object" || !Object.hasOwn(value, "then"))
78
78
  return Effect.succeed(value);
@@ -99,7 +99,7 @@ export const resolvePromiseValue = (runner, value, node, own) => {
99
99
  });
100
100
  };
101
101
  export const resolvePromise = (runner, promises, value, node) => {
102
- if (value instanceof CodeModePromise)
102
+ if (value instanceof Values.Promise)
103
103
  return Effect.succeed(value);
104
104
  const box = {};
105
105
  return Effect.map(promises.create(resolvePromiseValue(runner, value, node, box)), (promise) => {
@@ -1,6 +1,6 @@
1
1
  import { AsyncIteratorSymbol, CodeModeFunction, CodeModeGenerator, CoercionFunction, ErrorConstructorReference, GlobalMethodReference, GlobalNamespace, GeneratorMethodReference, InterpreterRuntimeError, IntrinsicReference, IteratorSymbol, JsonMethodReference, PromiseCapabilityFunction, PromiseInstanceMethodReference, PromiseMethodReference, PromiseNamespace, SearchFunction, SymbolNamespace, UriFunction, } from "./model.js";
2
2
  import { ToolReference } from "../tool-runtime.js";
3
- import { isCodeModeValue, CodeModePromise } from "../values.js";
3
+ import { Values } from "../values.js";
4
4
  export const isRuntimeReference = (value) => value instanceof CodeModeFunction ||
5
5
  value instanceof CodeModeGenerator ||
6
6
  value instanceof GeneratorMethodReference ||
@@ -12,14 +12,14 @@ export const isRuntimeReference = (value) => value instanceof CodeModeFunction |
12
12
  value instanceof PromiseNamespace ||
13
13
  value instanceof PromiseMethodReference ||
14
14
  value instanceof PromiseInstanceMethodReference ||
15
- value instanceof CodeModePromise ||
15
+ value instanceof Values.Promise ||
16
16
  value instanceof CoercionFunction ||
17
17
  value instanceof UriFunction ||
18
18
  value instanceof SearchFunction ||
19
19
  value instanceof PromiseCapabilityFunction ||
20
20
  value instanceof ErrorConstructorReference ||
21
21
  value instanceof SymbolNamespace ||
22
- isCodeModeValue(value);
22
+ Values.isValue(value);
23
23
  function* childValues(value) {
24
24
  for (const key of Reflect.ownKeys(value)) {
25
25
  if (!Object.prototype.propertyIsEnumerable.call(value, key))
@@ -29,9 +29,9 @@ function* childValues(value) {
29
29
  yield Reflect.get(value, key);
30
30
  }
31
31
  }
32
- export const containsRuntimeReference = (value) => {
32
+ // Depth-first search over a value tree. `match` stops the walk; `skip` prunes a subtree without matching it.
33
+ const find = (value, match, skip, seen) => {
33
34
  const pending = [[value].values()];
34
- const seen = new Set();
35
35
  while (pending.length > 0) {
36
36
  const next = pending.at(-1).next();
37
37
  if (next.done) {
@@ -39,53 +39,23 @@ export const containsRuntimeReference = (value) => {
39
39
  continue;
40
40
  }
41
41
  const current = next.value;
42
- if (isRuntimeReference(current))
42
+ if (match(current))
43
43
  return true;
44
- if (current === null || typeof current !== "object" || seen.has(current))
44
+ if (current === null || typeof current !== "object" || skip(current) || seen.has(current))
45
45
  continue;
46
46
  seen.add(current);
47
47
  pending.push(childValues(current));
48
48
  }
49
49
  return false;
50
50
  };
51
+ const never = () => false;
52
+ export const containsRuntimeReference = (value) => find(value, isRuntimeReference, never, new Set());
51
53
  // CodeMode values are data here, not opaque interpreter references.
52
- export const containsOpaqueReference = (value) => {
53
- const pending = [[value].values()];
54
- const seen = new Set();
55
- while (pending.length > 0) {
56
- const next = pending.at(-1).next();
57
- if (next.done) {
58
- pending.pop();
59
- continue;
60
- }
61
- const current = next.value;
62
- if (isCodeModeValue(current))
63
- continue;
64
- if (isRuntimeReference(current))
65
- return true;
66
- if (current === null || typeof current !== "object" || seen.has(current))
67
- continue;
68
- seen.add(current);
69
- pending.push(childValues(current));
70
- }
71
- return false;
72
- };
54
+ export const containsOpaqueReference = (value) => find(value, (current) => !Values.isValue(current) && isRuntimeReference(current), Values.isValue, new Set());
73
55
  // Reject cycles before mutation so later boundary walks remain safe.
74
56
  export const rejectCircularInsertion = (container, value, label, node, seen = new Set()) => {
75
- const pending = [[value].values()];
76
- while (pending.length > 0) {
77
- const next = pending.at(-1).next();
78
- if (next.done) {
79
- pending.pop();
80
- continue;
81
- }
82
- const current = next.value;
83
- if (current === container)
84
- throw new InterpreterRuntimeError(`${label} contains a circular value.`, node, "InvalidDataValue");
85
- if (current === null || typeof current !== "object" || isRuntimeReference(current) || seen.has(current))
86
- continue;
87
- seen.add(current);
88
- pending.push(childValues(current));
57
+ if (find(value, (current) => current === container, isRuntimeReference, seen)) {
58
+ throw new InterpreterRuntimeError(`${label} contains a circular value.`, node, "InvalidDataValue");
89
59
  }
90
60
  };
91
61
  export const typeofValue = (value) => {
@@ -1,5 +1,5 @@
1
+ import type { Program } from "acorn";
1
2
  import { Effect } from "effect";
2
- import { type ProgramNode } from "./model.js";
3
3
  import { PromiseRuntime } from "./promises.js";
4
4
  export declare class Interpreter<R> {
5
5
  private scopes;
@@ -12,7 +12,7 @@ export declare class Interpreter<R> {
12
12
  private generatorAsync;
13
13
  private readonly runner;
14
14
  constructor(executeTool: (path: ReadonlyArray<string>, args: Array<unknown>) => Effect.Effect<unknown, unknown, R>, invokeSearch: (args: Array<unknown>) => Effect.Effect<unknown, unknown, R>, toolKeys: (path: ReadonlyArray<string>) => ReadonlyArray<string>, promises: PromiseRuntime<R>, logs?: Array<string>);
15
- run(program: ProgramNode): Effect.Effect<unknown, unknown, R>;
15
+ run(program: Program): Effect.Effect<unknown, unknown, R>;
16
16
  private createToolCallPromise;
17
17
  private createPromise;
18
18
  private settlePromise;
@@ -55,7 +55,6 @@ export declare class Interpreter<R> {
55
55
  private constructArray;
56
56
  private constructObject;
57
57
  private constructDate;
58
- private toDatePrimitive;
59
58
  private constructRegExp;
60
59
  private constructMap;
61
60
  private constructSet;