@opencode/codemode 0.0.0-beta-19507 → 0.0.0-dev-19276

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 (65) hide show
  1. package/README.md +0 -6
  2. package/dist/codemode.d.ts +12 -9
  3. package/dist/codemode.js +9 -5
  4. package/dist/index.d.ts +0 -1
  5. package/dist/index.js +0 -1
  6. package/dist/interpreter/errors.d.ts +6 -4
  7. package/dist/interpreter/errors.js +10 -25
  8. package/dist/interpreter/execute.d.ts +3 -4
  9. package/dist/interpreter/execute.js +18 -11
  10. package/dist/interpreter/iterator.d.ts +13 -0
  11. package/dist/interpreter/iterator.js +4 -0
  12. package/dist/interpreter/methods.d.ts +16 -3
  13. package/dist/interpreter/methods.js +290 -101
  14. package/dist/interpreter/model.d.ts +79 -10
  15. package/dist/interpreter/model.js +102 -2
  16. package/dist/interpreter/promises.d.ts +13 -15
  17. package/dist/interpreter/promises.js +52 -70
  18. package/dist/interpreter/references.d.ts +0 -1
  19. package/dist/interpreter/references.js +77 -57
  20. package/dist/interpreter/runtime.d.ts +95 -16
  21. package/dist/interpreter/runtime.js +960 -549
  22. package/dist/openapi/spec.js +6 -3
  23. package/dist/stdlib/collections.d.ts +1 -6
  24. package/dist/stdlib/collections.js +1 -117
  25. package/dist/stdlib/console.d.ts +2 -3
  26. package/dist/stdlib/console.js +28 -39
  27. package/dist/stdlib/date.d.ts +4 -5
  28. package/dist/stdlib/date.js +12 -34
  29. package/dist/stdlib/json.d.ts +6 -3
  30. package/dist/stdlib/json.js +63 -40
  31. package/dist/stdlib/math.d.ts +7 -3
  32. package/dist/stdlib/math.js +153 -85
  33. package/dist/stdlib/number.d.ts +4 -2
  34. package/dist/stdlib/number.js +37 -30
  35. package/dist/stdlib/object.d.ts +6 -6
  36. package/dist/stdlib/object.js +87 -84
  37. package/dist/stdlib/promise.d.ts +2 -0
  38. package/dist/stdlib/promise.js +1 -0
  39. package/dist/stdlib/regexp.d.ts +7 -6
  40. package/dist/stdlib/regexp.js +34 -48
  41. package/dist/stdlib/string.d.ts +3 -1
  42. package/dist/stdlib/string.js +17 -20
  43. package/dist/stdlib/url.d.ts +6 -10
  44. package/dist/stdlib/url.js +25 -102
  45. package/dist/stdlib/value.d.ts +7 -8
  46. package/dist/stdlib/value.js +56 -56
  47. package/dist/tool-runtime.d.ts +15 -16
  48. package/dist/tool-runtime.js +150 -13
  49. package/dist/values.d.ts +16 -22
  50. package/dist/values.js +17 -23
  51. package/package.json +1 -1
  52. package/dist/data.d.ts +0 -25
  53. package/dist/data.js +0 -153
  54. package/dist/interpreter/globals.d.ts +0 -13
  55. package/dist/interpreter/globals.js +0 -63
  56. package/dist/interpreter/host.d.ts +0 -41
  57. package/dist/interpreter/host.js +0 -44
  58. package/dist/interpreter/objects.d.ts +0 -37
  59. package/dist/interpreter/objects.js +0 -151
  60. package/dist/interpreter/runner.d.ts +0 -24
  61. package/dist/interpreter/runner.js +0 -45
  62. package/dist/stdlib/array.d.ts +0 -3
  63. package/dist/stdlib/array.js +0 -68
  64. package/dist/stdlib/web.d.ts +0 -4
  65. package/dist/stdlib/web.js +0 -20
@@ -1,9 +1,9 @@
1
- import { sync, syncCall } from "../interpreter/host.js";
2
1
  import { InterpreterRuntimeError } from "../interpreter/model.js";
3
- import { ProgramArray, record, set } from "../interpreter/objects.js";
4
- import { Values } from "../values.js";
2
+ import { isBlockedMember } from "../tool-runtime.js";
3
+ import { CodeModeRegExp } from "../values.js";
5
4
  import { coerceToNumber, coerceToString } from "./value.js";
6
5
  export const regexpMethods = new Set(["test", "exec", "toString"]);
6
+ export const regexpStatics = new Set(["escape"]);
7
7
  export const regexpProperties = new Set([
8
8
  "source",
9
9
  "flags",
@@ -17,13 +17,13 @@ export const regexpProperties = new Set([
17
17
  "unicodeSets",
18
18
  "dotAll",
19
19
  ]);
20
- const regexFailureReason = (error) => (error instanceof Error ? error.message : String(error)).replace(/^Invalid regular expression:\s*/i, "");
21
- const escapeRegexHint = 'To match special characters like ( ) [ ] { } + * ? . literally, escape them with a backslash (e.g. "\\\\(") or test for them with String.includes instead.';
20
+ export const regexFailureReason = (error) => (error instanceof Error ? error.message : String(error)).replace(/^Invalid regular expression:\s*/i, "");
21
+ export const escapeRegexHint = 'To match special characters like ( ) [ ] { } + * ? . literally, escape them with a backslash (e.g. "\\\\(") or test for them with String.includes instead.';
22
22
  export const toHostRegex = (arg, method, node, extraFlags = "") => {
23
23
  // Native parity: an undefined pattern behaves as an empty pattern.
24
24
  if (arg === undefined)
25
25
  return new RegExp("", extraFlags);
26
- if (arg instanceof Values.RegExp)
26
+ if (arg instanceof CodeModeRegExp)
27
27
  return arg.regex;
28
28
  if (typeof arg === "string") {
29
29
  try {
@@ -36,48 +36,29 @@ export const toHostRegex = (arg, method, node, extraFlags = "") => {
36
36
  throw new InterpreterRuntimeError(`String.${method} expects a regular expression (a /pattern/flags literal or new RegExp(...)) or a string pattern, not ${arg === null ? "null" : typeof arg}.`, node);
37
37
  };
38
38
  export const matchToValue = (match) => {
39
- const result = new ProgramArray(Array.from(match, (group) => group));
39
+ const result = Array.from(match, (group) => group);
40
40
  if (match.index !== undefined)
41
- set(result, "index", match.index);
42
- if (match.input !== undefined)
43
- set(result, "input", match.input);
44
- if (match.groups)
45
- set(result, "groups", record(match.groups));
41
+ result.index = match.index;
42
+ if (match.groups) {
43
+ const groups = Object.create(null);
44
+ for (const [key, group] of Object.entries(match.groups)) {
45
+ if (!isBlockedMember(key))
46
+ groups[key] = group;
47
+ }
48
+ result.groups = groups;
49
+ }
46
50
  if (match.indices)
47
- set(result, "indices", indicesToValue(match.indices));
51
+ result.indices = indicesToValue(match.indices);
48
52
  return result;
49
53
  };
50
- export const constructRegExp = (args, node) => {
51
- const first = args[0];
52
- const pattern = first instanceof Values.RegExp ? first.regex.source : first === undefined ? "" : coerceToString(first);
53
- const flagsArg = args[1];
54
- if (flagsArg !== undefined && typeof flagsArg !== "string") {
55
- throw new InterpreterRuntimeError(`RegExp flags must be a string of flag characters (e.g. "g", "gi"), not ${flagsArg === null ? "null" : typeof flagsArg}.`, node).as("SyntaxError");
56
- }
57
- const flags = flagsArg ?? (first instanceof Values.RegExp ? first.regex.flags : "");
58
- try {
59
- return new Values.RegExp(pattern, flags);
60
- }
61
- catch (error) {
62
- const reason = regexFailureReason(error);
63
- throw new InterpreterRuntimeError(/flag/i.test(reason)
64
- ? `new RegExp(...) received invalid flags ${JSON.stringify(flags)} (${reason}). Valid flags are d, g, i, m, s, u, v, and y.`
65
- : `new RegExp(...) received ${JSON.stringify(pattern)}, which is not a valid regular expression pattern (${reason}). ${escapeRegexHint}`, node).as("SyntaxError");
54
+ export const invokeRegExpStatic = (name, args, node) => {
55
+ if (name !== "escape")
56
+ throw new InterpreterRuntimeError(`RegExp.${name} is not available.`, node);
57
+ if (typeof args[0] !== "string") {
58
+ throw new InterpreterRuntimeError("RegExp.escape expects a string.", node).as("TypeError");
66
59
  }
60
+ return RegExp.escape(args[0]);
67
61
  };
68
- // RegExp constructs identically with or without new, like JS.
69
- export const regexpGlobal = sync("RegExp", constructRegExp, {
70
- construct: syncCall(constructRegExp),
71
- instanceOf: (value) => value instanceof Values.RegExp,
72
- members: {
73
- escape: sync("RegExp.escape", (args, node) => {
74
- if (typeof args[0] !== "string") {
75
- throw new InterpreterRuntimeError("RegExp.escape expects a string.", node).as("TypeError");
76
- }
77
- return RegExp.escape(args[0]);
78
- }),
79
- },
80
- });
81
62
  export const invokeRegExpMethod = (value, name, args, node) => {
82
63
  switch (name) {
83
64
  case "test":
@@ -110,11 +91,16 @@ const toLength = (value) => {
110
91
  return Math.min(Math.floor(number), Number.MAX_SAFE_INTEGER);
111
92
  };
112
93
  const indicesToValue = (indices) => {
113
- const range = (pair) => (pair === undefined ? undefined : new ProgramArray([...pair]));
114
- const result = new ProgramArray(Array.from(indices, range));
115
- const groups = indices.groups;
116
- set(result, "groups", groups === undefined
117
- ? undefined
118
- : record(Object.fromEntries(Object.entries(groups).map(([key, pair]) => [key, range(pair)]))));
94
+ const result = Array.from(indices, (range) => (range === undefined ? undefined : [...range]));
95
+ if (indices.groups) {
96
+ const groups = Object.create(null);
97
+ for (const [key, range] of Object.entries(indices.groups)) {
98
+ if (!isBlockedMember(key))
99
+ groups[key] = range === undefined ? undefined : [...range];
100
+ }
101
+ result.groups = groups;
102
+ return result;
103
+ }
104
+ result.groups = undefined;
119
105
  return result;
120
106
  };
@@ -1,2 +1,4 @@
1
1
  export declare const stringMethods: Set<string>;
2
- export declare const stringGlobal: import("../interpreter/host.js").HostFunction<never>;
2
+ export declare const stringStatics: Set<string>;
3
+ export declare const invokeStringStatic: (name: string, args: Array<unknown>, node: AstNode) => unknown;
4
+ import { type AstNode } from "../interpreter/model.js";
@@ -1,18 +1,12 @@
1
- import { sync } from "../interpreter/host.js";
2
- import { InterpreterRuntimeError } from "../interpreter/model.js";
3
- import { coercion } from "./value.js";
4
1
  export const stringMethods = new Set([
5
2
  "toLowerCase",
6
3
  "toUpperCase",
7
4
  "trim",
8
5
  "trimStart",
9
6
  "trimEnd",
10
- "trimLeft",
11
- "trimRight",
12
7
  "split",
13
8
  "slice",
14
9
  "substring",
15
- "substr",
16
10
  "includes",
17
11
  "startsWith",
18
12
  "endsWith",
@@ -34,18 +28,21 @@ export const stringMethods = new Set([
34
28
  "search",
35
29
  "localeCompare",
36
30
  "normalize",
37
- "isWellFormed",
38
- "toWellFormed",
39
31
  ]);
40
- const codeUnits = (name, op) => sync(`String.${name}`, (args, node) => op(...args.map((arg) => {
41
- if (typeof arg !== "number")
42
- throw new InterpreterRuntimeError(`String.${name} expects number arguments.`, node);
43
- return arg;
44
- })));
45
- export const stringGlobal = coercion("String", {
46
- instanceOf: () => false,
47
- members: {
48
- fromCharCode: codeUnits("fromCharCode", String.fromCharCode),
49
- fromCodePoint: codeUnits("fromCodePoint", String.fromCodePoint),
50
- },
51
- });
32
+ export const stringStatics = new Set(["fromCharCode", "fromCodePoint"]);
33
+ export const invokeStringStatic = (name, args, node) => {
34
+ const codes = args.map((arg) => {
35
+ if (typeof arg !== "number")
36
+ throw new InterpreterRuntimeError(`String.${name} expects number arguments.`, node);
37
+ return arg;
38
+ });
39
+ switch (name) {
40
+ case "fromCharCode":
41
+ return String.fromCharCode(...codes);
42
+ case "fromCodePoint":
43
+ return String.fromCodePoint(...codes);
44
+ default:
45
+ throw new InterpreterRuntimeError(`String.${name} is not available.`, node);
46
+ }
47
+ };
48
+ import { InterpreterRuntimeError } from "../interpreter/model.js";
@@ -1,16 +1,12 @@
1
- import { HostFunction } from "../interpreter/host.js";
2
- import { type AstNode } from "../interpreter/model.js";
3
- import { type Runner } from "../interpreter/runner.js";
4
- import { Values } from "../values.js";
5
1
  export declare const urlProperties: Set<string>;
6
2
  export declare const urlWritableProperties: Set<string>;
7
3
  export declare const urlMethods: Set<string>;
4
+ export declare const urlStatics: Set<string>;
8
5
  export declare const urlSearchParamsMethods: Set<string>;
9
6
  export declare const uriArgument: (value: unknown, label: string) => string;
10
- type UriFunction = "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent";
11
- export declare const uriGlobal: (name: UriFunction) => HostFunction<never>;
7
+ export declare const invokeUriFunction: (ref: UriFunction, args: Array<unknown>, node: AstNode) => string;
12
8
  export declare const urlArgument: (value: unknown, label: string) => string;
13
- export declare const urlGlobal: HostFunction<never>;
14
- export declare const urlSearchParamsGlobal: <R>(runner: Runner<R>) => HostFunction<R>;
15
- export declare const invokeURLMethod: (value: Values.URL, name: string, node: AstNode) => string;
16
- export {};
9
+ export declare const invokeURLStatic: (name: string, args: Array<unknown>, node: AstNode) => unknown;
10
+ export declare const invokeURLMethod: (value: CodeModeURL, name: string, node: AstNode) => string;
11
+ import { type AstNode, UriFunction } from "../interpreter/model.js";
12
+ import { CodeModeURL } from "../values.js";
@@ -1,12 +1,3 @@
1
- import { Effect } from "effect";
2
- import { toProgram } from "../data.js";
3
- import { HostFunction, requiresNew, sync, syncCall } from "../interpreter/host.js";
4
- import { InterpreterRuntimeError } from "../interpreter/model.js";
5
- import { ownEntries, ProgramObject } from "../interpreter/objects.js";
6
- import { isRuntimeReference } from "../interpreter/references.js";
7
- import { preserveConsumerError } from "../interpreter/runner.js";
8
- import { Values } from "../values.js";
9
- import { coerceToString } from "./value.js";
10
1
  export const urlProperties = new Set([
11
2
  "href",
12
3
  "origin",
@@ -33,6 +24,7 @@ export const urlWritableProperties = new Set([
33
24
  "hash",
34
25
  ]);
35
26
  export const urlMethods = new Set(["toString", "toJSON"]);
27
+ export const urlStatics = new Set(["canParse", "parse"]);
36
28
  export const urlSearchParamsMethods = new Set([
37
29
  "append",
38
30
  "delete",
@@ -47,115 +39,46 @@ export const urlSearchParamsMethods = new Set([
47
39
  "entries",
48
40
  "toString",
49
41
  ]);
50
- export const uriArgument = (value, label) => coerceToString(toProgram(value, label));
51
- const uriFunctions = {
52
- encodeURI,
53
- encodeURIComponent,
54
- decodeURI,
55
- decodeURIComponent,
56
- };
57
- export const uriGlobal = (name) => sync(name, (args, node) => {
58
- const value = uriArgument(args[0], `${name} input`);
42
+ export const uriArgument = (value, label) => coerceToString(boundedData(value, label));
43
+ export const invokeUriFunction = (ref, args, node) => {
44
+ const value = uriArgument(args[0], `${ref.name} input`);
59
45
  try {
60
- return uriFunctions[name](value);
46
+ switch (ref.name) {
47
+ case "encodeURI":
48
+ return encodeURI(value);
49
+ case "encodeURIComponent":
50
+ return encodeURIComponent(value);
51
+ case "decodeURI":
52
+ return decodeURI(value);
53
+ case "decodeURIComponent":
54
+ return decodeURIComponent(value);
55
+ }
61
56
  }
62
57
  catch (error) {
63
- throw new InterpreterRuntimeError(`${name} received malformed URI data: ${error instanceof Error ? error.message : String(error)}`, node).as("URIError");
58
+ throw new InterpreterRuntimeError(`${ref.name} received malformed URI data: ${error instanceof Error ? error.message : String(error)}`, node).as("URIError");
64
59
  }
65
- });
66
- export const urlArgument = (value, label) => value instanceof Values.URL ? value.url.href : uriArgument(value, label);
67
- const urlStatic = (name) => sync(`URL.${name}`, (args, node) => {
68
- if (args.length === 0) {
60
+ };
61
+ export const urlArgument = (value, label) => value instanceof CodeModeURL ? value.url.href : uriArgument(value, label);
62
+ export const invokeURLStatic = (name, args, node) => {
63
+ if (!urlStatics.has(name))
64
+ throw new InterpreterRuntimeError(`URL.${name} is not available.`, node);
65
+ if (args.length === 0)
69
66
  throw new InterpreterRuntimeError(`URL.${name} requires a URL argument.`, node).as("TypeError");
70
- }
71
67
  const input = urlArgument(args[0], `URL.${name} input`);
72
68
  const base = args[1] === undefined ? undefined : urlArgument(args[1], `URL.${name} base`);
73
69
  try {
74
70
  const url = new URL(input, base);
75
- return name === "canParse" ? true : new Values.URL(url);
71
+ return name === "canParse" ? true : new CodeModeURL(url);
76
72
  }
77
73
  catch {
78
74
  return name === "canParse" ? false : null;
79
75
  }
80
- });
81
- const constructURL = (args, node) => {
82
- if (args.length === 0) {
83
- throw new InterpreterRuntimeError("new URL(...) requires a URL string and an optional base URL.", node).as("TypeError");
84
- }
85
- const input = urlArgument(args[0], "new URL input");
86
- const base = args[1] === undefined ? undefined : urlArgument(args[1], "new URL base");
87
- try {
88
- return new Values.URL(new URL(input, base));
89
- }
90
- catch {
91
- throw new InterpreterRuntimeError(`new URL(...) received an invalid URL${base === undefined ? "" : " or base URL"}.`, node).as("TypeError");
92
- }
93
- };
94
- export const urlGlobal = new HostFunction({
95
- name: "URL",
96
- call: requiresNew("URL"),
97
- construct: syncCall(constructURL),
98
- instanceOf: (value) => value instanceof Values.URL,
99
- members: { canParse: urlStatic("canParse"), parse: urlStatic("parse") },
100
- });
101
- const readURLSearchParamsPair = (runner, value, node) => Effect.gen(function* () {
102
- const cursor = yield* runner.syncIterator(value, node);
103
- if (cursor === undefined) {
104
- throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node).as("TypeError");
105
- }
106
- const items = [];
107
- while (true) {
108
- const step = yield* cursor.next;
109
- if (step.done)
110
- return items;
111
- items.push(yield* preserveConsumerError(cursor, Effect.sync(() => uriArgument(step.value, "URLSearchParams pair value"))));
112
- }
113
- });
114
- const constructURLSearchParams = (runner, init, node) => {
115
- if (init === undefined)
116
- return Effect.succeed(new Values.URLSearchParams(new URLSearchParams()));
117
- if (init instanceof Values.URLSearchParams) {
118
- return Effect.succeed(new Values.URLSearchParams(new URLSearchParams(init.params)));
119
- }
120
- if (typeof init === "string")
121
- return Effect.succeed(new Values.URLSearchParams(new URLSearchParams(init)));
122
- if (init === null || typeof init === "number" || typeof init === "boolean") {
123
- return Effect.succeed(new Values.URLSearchParams(new URLSearchParams(coerceToString(init))));
124
- }
125
- return Effect.gen(function* () {
126
- const cursor = yield* runner.syncIterator(init, node);
127
- if (cursor !== undefined) {
128
- const entries = [];
129
- while (true) {
130
- const step = yield* cursor.next;
131
- if (step.done) {
132
- if (entries.some((entry) => entry.length !== 2)) {
133
- throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node).as("TypeError");
134
- }
135
- return new Values.URLSearchParams(new URLSearchParams(entries.map((entry) => [entry[0] ?? "", entry[1] ?? ""])));
136
- }
137
- entries.push(yield* preserveConsumerError(cursor, readURLSearchParamsPair(runner, step.value, node)));
138
- }
139
- }
140
- if (isRuntimeReference(init)) {
141
- throw new InterpreterRuntimeError("new URLSearchParams(...) expects a query string, data object, or synchronous iterable pairs.", node).as("TypeError");
142
- }
143
- if (Values.isValue(init))
144
- return new Values.URLSearchParams(new URLSearchParams());
145
- if (!(init instanceof ProgramObject)) {
146
- throw new InterpreterRuntimeError("new URLSearchParams(...) expects a query string, data object, iterable pairs, or URLSearchParams.", node).as("TypeError");
147
- }
148
- return new Values.URLSearchParams(new URLSearchParams(Object.fromEntries(ownEntries(init).map(([key, value]) => [key, coerceToString(value)]))));
149
- });
150
76
  };
151
- export const urlSearchParamsGlobal = (runner) => new HostFunction({
152
- name: "URLSearchParams",
153
- call: requiresNew("URLSearchParams"),
154
- construct: (args, node) => constructURLSearchParams(runner, args[0], node),
155
- instanceOf: (value) => value instanceof Values.URLSearchParams,
156
- });
157
77
  export const invokeURLMethod = (value, name, node) => {
158
78
  if (name === "toString" || name === "toJSON")
159
79
  return value.url.href;
160
80
  throw new InterpreterRuntimeError(`URL method '${name}' is not available.`, node);
161
81
  };
82
+ import { InterpreterRuntimeError, UriFunction } from "../interpreter/model.js";
83
+ import { CodeModeURL } from "../values.js";
84
+ import { boundedData, coerceToString } from "./value.js";
@@ -1,13 +1,12 @@
1
- import { type HostFunction, type SyncOptions } from "../interpreter/host.js";
2
- import { ProgramError } from "../interpreter/objects.js";
3
1
  export declare const errorConstructors: Set<string>;
2
+ export declare const valueConstructors: Set<string>;
4
3
  export declare const compoundOperators: Set<string>;
5
- export declare const createErrorValue: (name: string, message: string) => ProgramError;
6
- export declare const createAggregateErrorValue: (errors: Array<unknown>, message: string) => ProgramError;
4
+ export declare const createErrorValue: (name: string, message: string) => SafeObject;
5
+ export declare const createAggregateErrorValue: (errors: Array<unknown>, message: string) => SafeObject;
7
6
  export declare const errorBrandName: (value: unknown) => string | undefined;
7
+ export declare const boundedData: (value: unknown, label: string) => unknown;
8
8
  export declare const coerceToString: (value: unknown) => string;
9
9
  export declare const coerceToNumber: (value: unknown) => number;
10
- type Coercion = "Number" | "String" | "Boolean" | "parseInt" | "parseFloat" | "isFinite" | "isNaN";
11
- /** A global coercion function such as `Number` or `parseInt`. */
12
- export declare const coercion: (name: Coercion, options?: SyncOptions) => HostFunction;
13
- export {};
10
+ export declare const invokeCoercion: (ref: CoercionFunction, args: Array<unknown>, node: AstNode) => unknown;
11
+ import { type AstNode, CoercionFunction } from "../interpreter/model.js";
12
+ import { type SafeObject } from "../tool-runtime.js";
@@ -1,8 +1,3 @@
1
- import { sync } from "../interpreter/host.js";
2
- import { InterpreterRuntimeError } from "../interpreter/model.js";
3
- import { toProgram } from "../data.js";
4
- import { get, ProgramArray, ProgramError, set } from "../interpreter/objects.js";
5
- import { Values } from "../values.js";
6
1
  export const errorConstructors = new Set([
7
2
  "Error",
8
3
  "TypeError",
@@ -13,108 +8,113 @@ export const errorConstructors = new Set([
13
8
  "URIError",
14
9
  "AggregateError",
15
10
  ]);
11
+ export const valueConstructors = new Set(["Date", "RegExp", "Map", "Set", "URL", "URLSearchParams"]);
16
12
  export const compoundOperators = new Set(["+=", "-=", "*=", "/=", "%=", "**=", "&=", "|=", "^=", "<<=", ">>=", ">>>="]);
13
+ const ErrorBrand = Symbol("codemode.error");
17
14
  export const createErrorValue = (name, message) => {
18
- const value = new ProgramError(name);
19
- set(value, "name", name);
20
- set(value, "message", message);
15
+ const value = Object.assign(Object.create(null), { name, message });
16
+ Object.defineProperty(value, ErrorBrand, { value: name });
21
17
  return value;
22
18
  };
23
- export const createAggregateErrorValue = (errors, message) => {
24
- const value = createErrorValue("AggregateError", message);
25
- set(value, "errors", new ProgramArray(errors));
26
- return value;
27
- };
28
- export const errorBrandName = (value) => value instanceof ProgramError ? value.errorName : undefined;
19
+ export const createAggregateErrorValue = (errors, message) => Object.assign(createErrorValue("AggregateError", message), { errors });
20
+ export const errorBrandName = (value) => value !== null && typeof value === "object"
21
+ ? value[ErrorBrand]
22
+ : undefined;
23
+ export const boundedData = (value, label) => copyIn(value, label, true);
29
24
  export const coerceToString = (value) => {
30
25
  if (value === null)
31
26
  return "null";
32
27
  if (value === undefined)
33
28
  return "undefined";
34
- if (value instanceof Values.Date)
29
+ if (value instanceof CodeModeDate)
35
30
  return Number.isFinite(value.time) ? new Date(value.time).toISOString() : "Invalid Date";
36
- if (value instanceof Values.RegExp)
31
+ if (value instanceof CodeModeRegExp)
37
32
  return `/${value.regex.source}/${value.regex.flags}`;
38
- if (value instanceof Values.Map)
33
+ if (value instanceof CodeModeMap)
39
34
  return "[object Map]";
40
- if (value instanceof Values.Set)
35
+ if (value instanceof CodeModeSet)
41
36
  return "[object Set]";
42
- if (value instanceof Values.URL)
37
+ if (value instanceof CodeModeURL)
43
38
  return value.url.href;
44
- if (value instanceof Values.URLSearchParams)
39
+ if (value instanceof CodeModeURLSearchParams)
45
40
  return value.params.toString();
46
- if (value instanceof ProgramError) {
41
+ if (errorBrandName(value) !== undefined) {
47
42
  // Match Error.prototype.toString: "name: message", or just one when the other is empty.
48
- const name = get(value, "name");
49
- const message = get(value, "message");
50
- const shownName = typeof name === "string" ? name : "Error";
51
- const shownMessage = typeof message === "string" ? message : "";
52
- if (shownMessage === "")
53
- return shownName;
54
- if (shownName === "")
55
- return shownMessage;
56
- return `${shownName}: ${shownMessage}`;
43
+ const error = value;
44
+ const name = typeof error.name === "string" ? error.name : "Error";
45
+ const message = typeof error.message === "string" ? error.message : "";
46
+ if (message === "")
47
+ return name;
48
+ if (name === "")
49
+ return message;
50
+ return `${name}: ${message}`;
57
51
  }
58
- if (value instanceof ProgramArray) {
59
- return value.items.map((item) => (item === null || item === undefined ? "" : coerceToString(item))).join(",");
52
+ if (typeof value === "object") {
53
+ return Array.isArray(value)
54
+ ? value.map((item) => (item === null || item === undefined ? "" : coerceToString(item))).join(",")
55
+ : "[object Object]";
60
56
  }
61
- if (typeof value === "object")
62
- return "[object Object]";
63
57
  return String(value);
64
58
  };
65
59
  export const coerceToNumber = (value) => {
66
- if (value instanceof Values.Date)
60
+ if (value instanceof CodeModeDate)
67
61
  return value.time;
68
- if (Values.isValue(value))
62
+ if (isCodeModeValue(value))
69
63
  return Number.NaN;
70
- if (value instanceof ProgramArray)
64
+ // Arrays coerce through our own string coercion: host Number(array) joins with host
65
+ // ToPrimitive, which throws on the null-prototype objects the interpreter produces.
66
+ if (Array.isArray(value))
71
67
  return Number(coerceToString(value));
72
68
  return value !== null && typeof value === "object" ? Number.NaN : Number(value);
73
69
  };
74
- const coerce = (name, args, node) => {
70
+ export const invokeCoercion = (ref, args, node) => {
75
71
  // Native: Number() is 0 and String() is "", unlike their undefined-argument forms; the
76
72
  // other coercers match native through the undefined-argument path below.
77
73
  if (args.length === 0) {
78
- if (name === "Number")
74
+ if (ref.name === "Number")
79
75
  return 0;
80
- if (name === "String")
76
+ if (ref.name === "String")
81
77
  return "";
82
78
  }
83
79
  const raw = args[0];
84
- if (Values.isValue(raw)) {
85
- if (name === "Boolean")
80
+ // Error values are plain SafeObjects; the boundedData path below would strip their brand.
81
+ if (ref.name === "String" && errorBrandName(raw) !== undefined)
82
+ return coerceToString(raw);
83
+ if (isCodeModeValue(raw)) {
84
+ if (ref.name === "Boolean")
86
85
  return true;
87
- if (name === "Number")
86
+ if (ref.name === "Number")
88
87
  return coerceToNumber(raw);
89
- if (name === "String")
88
+ if (ref.name === "String")
90
89
  return coerceToString(raw);
91
- if (name === "isFinite")
90
+ if (ref.name === "isFinite")
92
91
  return Number.isFinite(coerceToNumber(raw));
93
- if (name === "isNaN")
92
+ if (ref.name === "isNaN")
94
93
  return Number.isNaN(coerceToNumber(raw));
95
- if (name === "parseInt")
94
+ if (ref.name === "parseInt")
96
95
  return parseInt(coerceToString(raw));
97
96
  return parseFloat(coerceToString(raw));
98
97
  }
99
- const value = toProgram(raw, `${name} input`);
100
- if (name === "Number")
98
+ const value = boundedData(raw, `${ref.name} input`);
99
+ if (ref.name === "Number")
101
100
  return coerceToNumber(value);
102
- if (name === "Boolean")
101
+ if (ref.name === "Boolean")
103
102
  return Boolean(value);
104
- if (name === "isFinite")
103
+ if (ref.name === "isFinite")
105
104
  return Number.isFinite(coerceToNumber(value));
106
- if (name === "isNaN")
105
+ if (ref.name === "isNaN")
107
106
  return Number.isNaN(coerceToNumber(value));
108
- if (name === "parseInt") {
107
+ if (ref.name === "parseInt") {
109
108
  const radix = args[1];
110
109
  if (radix !== undefined && typeof radix !== "number") {
111
110
  throw new InterpreterRuntimeError("parseInt expects a numeric radix.", node);
112
111
  }
113
112
  return parseInt(coerceToString(value), radix);
114
113
  }
115
- if (name === "parseFloat")
114
+ if (ref.name === "parseFloat")
116
115
  return parseFloat(coerceToString(value));
117
116
  return coerceToString(value);
118
117
  };
119
- /** A global coercion function such as `Number` or `parseInt`. */
120
- export const coercion = (name, options = {}) => sync(name, (args, node) => toProgram(coerce(name, args, node), `${name} result`), options);
118
+ import { CoercionFunction, InterpreterRuntimeError } from "../interpreter/model.js";
119
+ import { copyIn } from "../tool-runtime.js";
120
+ import { isCodeModeValue, CodeModeDate, CodeModeMap, CodeModeRegExp, CodeModeSet, CodeModeURL, CodeModeURLSearchParams, } from "../values.js";
@@ -1,8 +1,5 @@
1
1
  import { Effect } from "effect";
2
- import { type Namespace } from "./namespace.js";
3
- import { type Tool } from "./tool.js";
4
2
  import type { Tools } from "./tools.js";
5
- export declare const compareText: (left: string, right: string) => 1 | -1 | 0;
6
3
  export type Services<T> = ServicesOf<T, []>;
7
4
  type ServicesOf<T, Depth extends ReadonlyArray<unknown>> = Depth["length"] extends 8 ? never : T extends {
8
5
  readonly _tag: "CodeModeTool";
@@ -25,9 +22,7 @@ export type ToolCallEnded = {
25
22
  readonly message?: string;
26
23
  };
27
24
  export type ToolCallHooks<R = never> = {
28
- /** Observes decoded tool input immediately before tool execution. */
29
25
  readonly onToolCallStart?: ((call: ToolCallStarted) => Effect.Effect<void, never, R>) | undefined;
30
- /** Observes each admitted tool call as it succeeds, fails, or is interrupted. */
31
26
  readonly onToolCallEnd?: ((call: ToolCallEnded) => Effect.Effect<void, never, R>) | undefined;
32
27
  };
33
28
  export type ToolDescription = {
@@ -35,19 +30,22 @@ export type ToolDescription = {
35
30
  readonly description: string;
36
31
  readonly signature: string;
37
32
  };
33
+ export type SafeObject = Record<string, unknown>;
38
34
  export declare const toolExpression: (path: string) => string;
39
35
  export declare class ToolReference {
40
36
  readonly path: ReadonlyArray<string>;
41
37
  constructor(path: ReadonlyArray<string>);
42
38
  }
43
- type ToolNode<R> = {
44
- tool?: Tool<R>;
45
- namespace?: Namespace<R>;
46
- readonly children: Map<string, ToolNode<R>>;
47
- };
48
- /** Tools indexed once per runtime: the lookup trie plus the model-facing catalog and search index. */
49
- export type Prepared<R = never> = {
50
- readonly root: ToolNode<R>;
39
+ export declare class ToolRuntimeError extends Error {
40
+ readonly kind: "UnknownTool" | "InvalidToolInput" | "InvalidToolOutput" | "InvalidDataValue" | "ToolCallLimitExceeded";
41
+ readonly suggestions: ReadonlyArray<string>;
42
+ constructor(kind: "UnknownTool" | "InvalidToolInput" | "InvalidToolOutput" | "InvalidDataValue" | "ToolCallLimitExceeded", message: string, suggestions?: ReadonlyArray<string>);
43
+ }
44
+ export declare const isBlockedMember: (name: string) => boolean;
45
+ export declare const copyIn: (value: unknown, label: string, preserveCodeModeValues?: boolean) => unknown;
46
+ export type CopyOutMode = "json" | "nullify";
47
+ export declare const copyOut: (value: unknown, mode: CopyOutMode) => unknown;
48
+ export type DiscoveryPlan = {
51
49
  readonly catalog: ReadonlyArray<ToolDescription>;
52
50
  readonly searchIndex: ReadonlyArray<SearchEntry>;
53
51
  };
@@ -57,13 +55,14 @@ export type SearchEntry = {
57
55
  };
58
56
  /** Exact callable signature of the built-in `search` function, for host-owned instructions. */
59
57
  export declare const searchSignature: string;
60
- export declare const prepare: <R>(tools: Tools<R>) => Prepared<R>;
58
+ export declare const searchIndex: <R>(tools: Tools<R>) => ReadonlyArray<SearchEntry>;
59
+ export declare const prepare: <R>(tools: Tools<R>) => DiscoveryPlan;
61
60
  export type ToolRuntime<R = never> = {
61
+ readonly root: ToolReference;
62
62
  readonly calls: Array<ToolCall>;
63
63
  readonly execute: (path: ReadonlyArray<string>, args: Array<unknown>) => Effect.Effect<unknown, unknown, R>;
64
64
  readonly search: (args: Array<unknown>) => Effect.Effect<unknown, unknown, R>;
65
65
  readonly keys: (path: ReadonlyArray<string>) => ReadonlyArray<string>;
66
66
  };
67
- /** Per-execution call state over tools prepared once for the runtime. */
68
- export declare const make: <R>(prepared: Prepared<R>, maxToolCalls: number | undefined, hooks?: ToolCallHooks<R>) => ToolRuntime<R>;
67
+ export declare const make: <R>(tools: Tools<R>, maxToolCalls: number | undefined, searchIndex: ReadonlyArray<SearchEntry>, hooks?: ToolCallHooks<R>) => ToolRuntime<R>;
69
68
  export * as ToolRuntime from "./tool-runtime.js";