@opencode/codemode 0.0.0-dev-19631 → 0.0.0-dev-19633
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.
- package/dist/codemode.js +1 -1
- package/dist/data.d.ts +3 -3
- package/dist/data.js +37 -31
- package/dist/interpreter/callback.d.ts +20 -0
- package/dist/interpreter/{runner.js → callback.js} +10 -10
- package/dist/interpreter/errors.d.ts +5 -5
- package/dist/interpreter/errors.js +21 -22
- package/dist/interpreter/execute.d.ts +2 -2
- package/dist/interpreter/execute.js +11 -11
- package/dist/interpreter/extensions.d.ts +2 -2
- package/dist/interpreter/extensions.js +42 -36
- package/dist/interpreter/generators.d.ts +2 -3
- package/dist/interpreter/generators.js +8 -8
- package/dist/interpreter/globals.d.ts +2 -12
- package/dist/interpreter/globals.js +41 -37
- package/dist/interpreter/interpreter.d.ts +31 -0
- package/dist/interpreter/{runtime.js → interpreter.js} +118 -117
- package/dist/interpreter/intrinsics.d.ts +5 -5
- package/dist/interpreter/intrinsics.js +16 -10
- package/dist/interpreter/model.d.ts +3 -3
- package/dist/interpreter/model.js +1 -1
- package/dist/interpreter/native.d.ts +9 -9
- package/dist/interpreter/native.js +9 -9
- package/dist/interpreter/objects.d.ts +51 -46
- package/dist/interpreter/objects.js +57 -40
- package/dist/interpreter/promises.d.ts +13 -13
- package/dist/interpreter/promises.js +70 -70
- package/dist/interpreter/references.js +17 -15
- package/dist/openapi/types.d.ts +1 -1
- package/dist/stdlib/array.d.ts +3 -3
- package/dist/stdlib/array.js +31 -31
- package/dist/stdlib/bytes.d.ts +10 -0
- package/dist/stdlib/bytes.js +228 -0
- package/dist/stdlib/collections.d.ts +4 -4
- package/dist/stdlib/collections.js +55 -55
- package/dist/stdlib/console.d.ts +3 -3
- package/dist/stdlib/console.js +24 -22
- package/dist/stdlib/date.d.ts +2 -2
- package/dist/stdlib/date.js +19 -19
- package/dist/stdlib/json.d.ts +3 -3
- package/dist/stdlib/json.js +24 -24
- package/dist/stdlib/math.d.ts +3 -3
- package/dist/stdlib/math.js +7 -7
- package/dist/stdlib/number.d.ts +3 -3
- package/dist/stdlib/number.js +11 -11
- package/dist/stdlib/object.d.ts +5 -5
- package/dist/stdlib/object.js +41 -39
- package/dist/stdlib/regexp.d.ts +6 -6
- package/dist/stdlib/regexp.js +24 -24
- package/dist/stdlib/string.d.ts +2 -2
- package/dist/stdlib/string.js +24 -24
- package/dist/stdlib/url.d.ts +6 -6
- package/dist/stdlib/url.js +39 -39
- package/dist/stdlib/value.d.ts +3 -3
- package/dist/stdlib/value.js +18 -14
- package/dist/stdlib/web.d.ts +4 -4
- package/dist/stdlib/web.js +19 -5
- package/dist/tool-runtime.d.ts +2 -2
- package/dist/tool-runtime.js +2 -2
- package/package.json +1 -1
- package/dist/interpreter/runner.d.ts +0 -27
- package/dist/interpreter/runtime.d.ts +0 -19
package/dist/codemode.js
CHANGED
|
@@ -72,6 +72,6 @@ export const make = (options = {}) => {
|
|
|
72
72
|
}
|
|
73
73
|
return {
|
|
74
74
|
catalog: prepared.catalog,
|
|
75
|
-
execute: (code) => executeProgram(code, prepared, limits, options, (
|
|
75
|
+
execute: (code) => executeProgram(code, prepared, limits, options, (ctx) => extensionGlobals(ctx, extensions)),
|
|
76
76
|
};
|
|
77
77
|
};
|
package/dist/data.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * as Data from "./data.js";
|
|
2
2
|
import type { DiagnosticKind } from "./codemode.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { Builtins } from "./interpreter/intrinsics.js";
|
|
4
4
|
export declare const MAX_VALUE_DEPTH = 32;
|
|
5
5
|
export declare class ToolRuntimeError extends Error {
|
|
6
6
|
readonly kind: Extract<DiagnosticKind, "UnknownTool" | "InvalidToolInput" | "InvalidToolOutput" | "InvalidDataValue" | "ToolCallLimitExceeded">;
|
|
@@ -12,12 +12,12 @@ export declare class ToolRuntimeError extends Error {
|
|
|
12
12
|
* Map, Set, URL, and URLSearchParams become their built-in wrappers, and host objects and arrays
|
|
13
13
|
* are copied.
|
|
14
14
|
*/
|
|
15
|
-
export declare const toProgram: (
|
|
15
|
+
export declare const toProgram: (builtins: Builtins, value: unknown, label: string) => unknown;
|
|
16
16
|
/**
|
|
17
17
|
* Brings host data into the program: Date and URL become strings, other host collections become
|
|
18
18
|
* empty objects, and objects become program copies. Used for tool results and parsed JSON.
|
|
19
19
|
*/
|
|
20
|
-
export declare const fromData: (
|
|
20
|
+
export declare const fromData: (builtins: Builtins, value: unknown, label: string) => unknown;
|
|
21
21
|
/**
|
|
22
22
|
* Takes a program value out as plain JSON: runtime values serialize like `JSON.stringify` would,
|
|
23
23
|
* non-finite numbers become null, and array holes become null. `undefined` object properties are
|
package/dist/data.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * as Data from "./data.js";
|
|
2
|
-
import { Callable, define, entries, get, isWrapper, parseArrayIndex,
|
|
2
|
+
import { Callable, define, entries, get, isWrapper, parseArrayIndex, Arr, Bytes, DateObj, ErrorObj, GeneratorObj, Handle, MapObj, Obj, PromiseObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, } from "./interpreter/objects.js";
|
|
3
3
|
export const MAX_VALUE_DEPTH = 32;
|
|
4
4
|
export class ToolRuntimeError extends Error {
|
|
5
5
|
kind;
|
|
@@ -16,12 +16,12 @@ export class ToolRuntimeError extends Error {
|
|
|
16
16
|
* Map, Set, URL, and URLSearchParams become their built-in wrappers, and host objects and arrays
|
|
17
17
|
* are copied.
|
|
18
18
|
*/
|
|
19
|
-
export const toProgram = (
|
|
19
|
+
export const toProgram = (builtins, value, label) => copy(value, label, "program", 0, new Set(), builtins);
|
|
20
20
|
/**
|
|
21
21
|
* Brings host data into the program: Date and URL become strings, other host collections become
|
|
22
22
|
* empty objects, and objects become program copies. Used for tool results and parsed JSON.
|
|
23
23
|
*/
|
|
24
|
-
export const fromData = (
|
|
24
|
+
export const fromData = (builtins, value, label) => copy(value, label, "data", 0, new Set(), builtins);
|
|
25
25
|
/**
|
|
26
26
|
* Takes a program value out as plain JSON: runtime values serialize like `JSON.stringify` would,
|
|
27
27
|
* non-finite numbers become null, and array holes become null. `undefined` object properties are
|
|
@@ -34,8 +34,8 @@ export const fromData = (protos, value, label) => copy(value, label, "data", 0,
|
|
|
34
34
|
* behavior.
|
|
35
35
|
*/
|
|
36
36
|
export const toData = (value, label, undefinedAs = "json", boundary = true) => copy(value, label, undefinedAs, 0, new Set(), undefined, boundary);
|
|
37
|
-
const copy = (value, label, mode, depth, seen,
|
|
38
|
-
const next = (item) => copy(item, label, mode, depth + 1, seen,
|
|
37
|
+
const copy = (value, label, mode, depth, seen, builtins, boundary = true) => {
|
|
38
|
+
const next = (item) => copy(item, label, mode, depth + 1, seen, builtins, boundary);
|
|
39
39
|
if (depth > MAX_VALUE_DEPTH) {
|
|
40
40
|
throw new ToolRuntimeError("InvalidDataValue", `${label} exceeds the maximum value depth of ${MAX_VALUE_DEPTH}.`);
|
|
41
41
|
}
|
|
@@ -48,57 +48,63 @@ const copy = (value, label, mode, depth, seen, protos, boundary = true) => {
|
|
|
48
48
|
if (typeof value !== "object") {
|
|
49
49
|
throw new ToolRuntimeError("InvalidDataValue", `${label} must contain data only.`);
|
|
50
50
|
}
|
|
51
|
-
if (value instanceof
|
|
51
|
+
if (value instanceof PromiseObj) {
|
|
52
52
|
throw new ToolRuntimeError("InvalidDataValue", `${label} contains an un-awaited Promise; await tool calls (e.g. \`const result = await tools.ns.tool(...)\`) before using their results.`);
|
|
53
53
|
}
|
|
54
|
-
if ((value instanceof Callable || value instanceof
|
|
54
|
+
if ((value instanceof Callable || value instanceof GeneratorObj) && mode !== "program") {
|
|
55
55
|
throw new ToolRuntimeError("InvalidDataValue", `${label} must contain data only.`);
|
|
56
56
|
}
|
|
57
|
-
if (value instanceof
|
|
57
|
+
if (value instanceof Handle && mode !== "program") {
|
|
58
58
|
throw new ToolRuntimeError("InvalidDataValue", `${label} contains a ${value.instance.constructor.name}, which only extension functions accept.`);
|
|
59
59
|
}
|
|
60
60
|
// Host-produced input never holds program objects; one arriving here would come back as a host object.
|
|
61
|
-
if (value instanceof
|
|
61
|
+
if (value instanceof Obj && mode === "data") {
|
|
62
62
|
throw new ToolRuntimeError("InvalidDataValue", `${label} must be host data, not a program value.`);
|
|
63
63
|
}
|
|
64
|
-
if (
|
|
65
|
-
if (value instanceof
|
|
64
|
+
if (builtins !== undefined && mode === "program") {
|
|
65
|
+
if (value instanceof Obj)
|
|
66
66
|
return value;
|
|
67
67
|
if (value instanceof Date)
|
|
68
|
-
return new
|
|
68
|
+
return new DateObj(builtins.Date, value.getTime());
|
|
69
69
|
if (value instanceof RegExp)
|
|
70
|
-
return new
|
|
70
|
+
return new RegExpObj(builtins.RegExp, value.source, value.flags);
|
|
71
71
|
if (value instanceof Map) {
|
|
72
|
-
const wrapped = new
|
|
72
|
+
const wrapped = new MapObj(builtins.Map);
|
|
73
73
|
for (const [key, item] of value.entries())
|
|
74
74
|
wrapped.map.set(next(key), next(item));
|
|
75
75
|
return wrapped;
|
|
76
76
|
}
|
|
77
77
|
if (value instanceof Set) {
|
|
78
|
-
const wrapped = new
|
|
78
|
+
const wrapped = new SetObj(builtins.Set);
|
|
79
79
|
for (const item of value.values())
|
|
80
80
|
wrapped.set.add(next(item));
|
|
81
81
|
return wrapped;
|
|
82
82
|
}
|
|
83
83
|
if (value instanceof URL)
|
|
84
|
-
return new
|
|
84
|
+
return new URLObj(builtins.URL, builtins.URLSearchParams, new URL(value.href));
|
|
85
85
|
if (value instanceof URLSearchParams)
|
|
86
|
-
return new
|
|
86
|
+
return new URLSearchParamsObj(builtins.URLSearchParams, new URLSearchParams(value));
|
|
87
87
|
}
|
|
88
|
-
if (value instanceof
|
|
88
|
+
if (value instanceof DateObj)
|
|
89
89
|
return Number.isFinite(value.time) ? new Date(value.time).toISOString() : null;
|
|
90
90
|
if (value instanceof Date)
|
|
91
91
|
return Number.isFinite(value.getTime()) ? value.toISOString() : null;
|
|
92
|
-
if (value instanceof
|
|
92
|
+
if (value instanceof URLObj)
|
|
93
93
|
return value.url.href;
|
|
94
94
|
if (value instanceof URL)
|
|
95
95
|
return value.href;
|
|
96
|
-
if (
|
|
97
|
-
if (
|
|
96
|
+
if (value instanceof Bytes) {
|
|
97
|
+
if (boundary) {
|
|
98
|
+
throw new ToolRuntimeError("InvalidDataValue", `${label} contains a Uint8Array; pass text instead, e.g. \`new TextDecoder().decode(bytes)\` or \`bytes.toBase64()\`.`);
|
|
99
|
+
}
|
|
100
|
+
return Object.fromEntries(value.bytes.entries());
|
|
101
|
+
}
|
|
102
|
+
if (boundary && builtins === undefined) {
|
|
103
|
+
if (value instanceof RegExpObj)
|
|
98
104
|
return String(value.regex);
|
|
99
|
-
if (value instanceof
|
|
105
|
+
if (value instanceof URLSearchParamsObj)
|
|
100
106
|
return value.params.toString();
|
|
101
|
-
if (value instanceof
|
|
107
|
+
if (value instanceof SetObj) {
|
|
102
108
|
if (seen.has(value))
|
|
103
109
|
throw new ToolRuntimeError("InvalidDataValue", `${label} contains a circular value.`);
|
|
104
110
|
seen.add(value);
|
|
@@ -113,21 +119,21 @@ const copy = (value, label, mode, depth, seen, protos, boundary = true) => {
|
|
|
113
119
|
value instanceof Map ||
|
|
114
120
|
value instanceof Set ||
|
|
115
121
|
value instanceof URLSearchParams) {
|
|
116
|
-
return
|
|
122
|
+
return builtins !== undefined ? new Obj(builtins.Object) : {};
|
|
117
123
|
}
|
|
118
124
|
if (seen.has(value)) {
|
|
119
125
|
throw new ToolRuntimeError("InvalidDataValue", `${label} contains a circular value.`);
|
|
120
126
|
}
|
|
121
127
|
seen.add(value);
|
|
122
|
-
if (value instanceof
|
|
128
|
+
if (value instanceof Arr) {
|
|
123
129
|
const copied = Array.from(value.items, (item) => next(item) ?? null);
|
|
124
130
|
seen.delete(value);
|
|
125
131
|
return copied;
|
|
126
132
|
}
|
|
127
|
-
if (value instanceof
|
|
133
|
+
if (value instanceof Obj) {
|
|
128
134
|
const copied = {};
|
|
129
135
|
// Errors serialize as { name, message, ...own }: both may be inherited, and neither is enumerable in JS.
|
|
130
|
-
if (value instanceof
|
|
136
|
+
if (value instanceof ErrorObj) {
|
|
131
137
|
defineHost(copied, "name", next(get(value, "name")));
|
|
132
138
|
defineHost(copied, "message", next(get(value, "message")));
|
|
133
139
|
}
|
|
@@ -143,8 +149,8 @@ const copy = (value, label, mode, depth, seen, protos, boundary = true) => {
|
|
|
143
149
|
return copied;
|
|
144
150
|
}
|
|
145
151
|
if (Array.isArray(value)) {
|
|
146
|
-
if (
|
|
147
|
-
const copied = new
|
|
152
|
+
if (builtins !== undefined) {
|
|
153
|
+
const copied = new Arr(builtins.Array, value.map(next));
|
|
148
154
|
for (const [key, item] of Object.entries(value)) {
|
|
149
155
|
if (parseArrayIndex(key) === undefined)
|
|
150
156
|
define(copied, key, next(item));
|
|
@@ -160,8 +166,8 @@ const copy = (value, label, mode, depth, seen, protos, boundary = true) => {
|
|
|
160
166
|
if (prototype !== Object.prototype && prototype !== null) {
|
|
161
167
|
throw new ToolRuntimeError("InvalidDataValue", `${label} must contain plain objects only.`);
|
|
162
168
|
}
|
|
163
|
-
if (
|
|
164
|
-
const copied = new
|
|
169
|
+
if (builtins !== undefined) {
|
|
170
|
+
const copied = new Obj(builtins.Object);
|
|
165
171
|
for (const [key, item] of Object.entries(value))
|
|
166
172
|
define(copied, key, next(item));
|
|
167
173
|
seen.delete(value);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { Interpreter } from "./interpreter.js";
|
|
3
|
+
import { Callable } from "./objects.js";
|
|
4
|
+
export type IteratorCursor<R> = {
|
|
5
|
+
readonly next: Effect.Effect<{
|
|
6
|
+
readonly done: boolean;
|
|
7
|
+
readonly value: unknown;
|
|
8
|
+
}, unknown, R>;
|
|
9
|
+
readonly close: Effect.Effect<void, unknown, R>;
|
|
10
|
+
};
|
|
11
|
+
export declare const preserveConsumerError: <A, R>(cursor: IteratorCursor<R>, effect: Effect.Effect<A, unknown, R>) => Effect.Effect<A, unknown, R>;
|
|
12
|
+
/**
|
|
13
|
+
* ToPrimitive: calls `valueOf`/`toString` in hint order and returns the first primitive result. Dates treat the
|
|
14
|
+
* default hint as "string", like their `Symbol.toPrimitive`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const toPrimitive: <R>(ctx: Interpreter<R>, value: unknown, hint: "number" | "string" | "default") => Effect.Effect<unknown, unknown, R>;
|
|
17
|
+
export declare const toPrimitiveString: <R>(ctx: Interpreter<R>, value: unknown) => Effect.Effect<string, unknown, R>;
|
|
18
|
+
export declare const toPrimitiveNumber: <R>(ctx: Interpreter<R>, value: unknown) => Effect.Effect<number, unknown, R>;
|
|
19
|
+
export declare const isSupportedCallback: (value: unknown) => value is Callable;
|
|
20
|
+
export declare const applyCollectionCallback: <R>(ctx: Interpreter<R>, callback: unknown, name: string) => ((args: Array<unknown>) => Effect.Effect<unknown, unknown, R>);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Effect, Exit } from "effect";
|
|
2
2
|
import { coerceToNumber, coerceToString } from "../stdlib/value.js";
|
|
3
3
|
import { typeError } from "./model.js";
|
|
4
|
-
import { Callable, get,
|
|
4
|
+
import { Callable, get, Native, DateObj, Obj } from "./objects.js";
|
|
5
5
|
import { typeofValue } from "./references.js";
|
|
6
6
|
export const preserveConsumerError = (cursor, effect) => Effect.flatMap(Effect.exit(effect), (exit) => Exit.isSuccess(exit)
|
|
7
7
|
? Effect.succeed(exit.value)
|
|
@@ -10,36 +10,36 @@ export const preserveConsumerError = (cursor, effect) => Effect.flatMap(Effect.e
|
|
|
10
10
|
* ToPrimitive: calls `valueOf`/`toString` in hint order and returns the first primitive result. Dates treat the
|
|
11
11
|
* default hint as "string", like their `Symbol.toPrimitive`.
|
|
12
12
|
*/
|
|
13
|
-
export const toPrimitive = (
|
|
14
|
-
if (!(value instanceof
|
|
13
|
+
export const toPrimitive = (ctx, value, hint) => {
|
|
14
|
+
if (!(value instanceof Obj))
|
|
15
15
|
return Effect.succeed(value);
|
|
16
|
-
const asString = hint === "string" || (hint === "default" && value instanceof
|
|
16
|
+
const asString = hint === "string" || (hint === "default" && value instanceof DateObj);
|
|
17
17
|
const order = asString ? ["toString", "valueOf"] : ["valueOf", "toString"];
|
|
18
18
|
return Effect.gen(function* () {
|
|
19
19
|
for (const method of order) {
|
|
20
20
|
const callable = get(value, method);
|
|
21
21
|
if (!(callable instanceof Callable))
|
|
22
22
|
continue;
|
|
23
|
-
const result = yield*
|
|
23
|
+
const result = yield* ctx.call(callable, value, []);
|
|
24
24
|
if (result === null || (typeof result !== "object" && typeof result !== "function"))
|
|
25
25
|
return result;
|
|
26
26
|
}
|
|
27
27
|
throw typeError("Cannot convert object to primitive value.");
|
|
28
28
|
});
|
|
29
29
|
};
|
|
30
|
-
export const toPrimitiveString = (
|
|
31
|
-
export const toPrimitiveNumber = (
|
|
30
|
+
export const toPrimitiveString = (ctx, value) => Effect.map(toPrimitive(ctx, value, "string"), coerceToString);
|
|
31
|
+
export const toPrimitiveNumber = (ctx, value) => Effect.map(toPrimitive(ctx, value, "number"), coerceToNumber);
|
|
32
32
|
// The single acceptance list for callbacks: collections, sort, string replacers,
|
|
33
33
|
// Array.from mappers, and promise reactions all admit exactly these callables.
|
|
34
34
|
// Admission means dispatchable, not necessarily invocable: new-requiring
|
|
35
35
|
// constructors pass the gate and throw a TypeError on call, like JS.
|
|
36
|
-
export const isSupportedCallback = (value) => value instanceof Callable && !(value instanceof
|
|
37
|
-
export const applyCollectionCallback = (
|
|
36
|
+
export const isSupportedCallback = (value) => value instanceof Callable && !(value instanceof Native && !value.callback);
|
|
37
|
+
export const applyCollectionCallback = (ctx, callback, name) => {
|
|
38
38
|
if (!isSupportedCallback(callback)) {
|
|
39
39
|
if (typeofValue(callback) === "function") {
|
|
40
40
|
throw typeError(`${name} cannot use this callable as a callback; wrap it in an arrow function, e.g. (value) => tools.ns.tool(value).`);
|
|
41
41
|
}
|
|
42
42
|
throw typeError(`${name} expects a function callback.`);
|
|
43
43
|
}
|
|
44
|
-
return (callbackArgs) =>
|
|
44
|
+
return (callbackArgs) => ctx.call(callback, undefined, callbackArgs);
|
|
45
45
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Diagnostic } from "../codemode.js";
|
|
2
2
|
import { type AstNode } from "./model.js";
|
|
3
3
|
import { type ErrorType } from "./intrinsics.js";
|
|
4
|
-
import { type
|
|
5
|
-
import {
|
|
4
|
+
import { type Native, ErrorObj, Obj } from "./objects.js";
|
|
5
|
+
import type { Interpreter } from "./interpreter.js";
|
|
6
6
|
export declare const normalizeError: (error: unknown) => Diagnostic;
|
|
7
7
|
/**
|
|
8
8
|
* Gives a failure the source location of the expression that raised it, keeping the first one attached. Host errors
|
|
@@ -10,7 +10,7 @@ export declare const normalizeError: (error: unknown) => Diagnostic;
|
|
|
10
10
|
*/
|
|
11
11
|
export declare const locate: (error: unknown, node?: AstNode) => unknown;
|
|
12
12
|
/** The program value a handler receives for a failure; one failure always yields the same value. */
|
|
13
|
-
export declare const materialize: <R>(
|
|
14
|
-
export declare const createAggregateErrorValue: <R>(
|
|
13
|
+
export declare const materialize: <R>(ctx: Interpreter<R>, thrown: unknown) => unknown;
|
|
14
|
+
export declare const createAggregateErrorValue: <R>(ctx: Interpreter<R>, errors: Array<unknown>, message: string, proto?: Obj) => ErrorObj;
|
|
15
15
|
/** An error constructor such as `Error` or `TypeError`; callable with or without `new`, like JS. */
|
|
16
|
-
export declare const errorGlobal: <R>(type: ErrorType,
|
|
16
|
+
export declare const errorGlobal: <R>(type: ErrorType, ctx: Interpreter<R>) => Native<R>;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { ToolError } from "../tool-error.js";
|
|
3
3
|
import { toData, ToolRuntimeError } from "../data.js";
|
|
4
|
-
import { formatLocation, PendingThrow,
|
|
4
|
+
import { formatLocation, PendingThrow, Throw, sourceLocation, typeError } from "./model.js";
|
|
5
5
|
import { containsRuntimeReference } from "./references.js";
|
|
6
6
|
import { createErrorValue, isErrorType } from "./intrinsics.js";
|
|
7
7
|
import { constructor, methods, prototypeFrom, receiver } from "./native.js";
|
|
8
|
-
import { define, get, hidden,
|
|
9
|
-
import {} from "./runner.js";
|
|
8
|
+
import { define, get, hidden, Arr, ErrorObj, Obj } from "./objects.js";
|
|
10
9
|
import { coerceToString } from "../stdlib/value.js";
|
|
11
10
|
export const normalizeError = (error) => {
|
|
12
11
|
if (error instanceof PendingThrow) {
|
|
@@ -27,9 +26,9 @@ export const normalizeError = (error) => {
|
|
|
27
26
|
if (error instanceof ToolError) {
|
|
28
27
|
return { kind: "ToolFailure", message: error.message };
|
|
29
28
|
}
|
|
30
|
-
if (error instanceof
|
|
29
|
+
if (error instanceof Throw) {
|
|
31
30
|
const value = error.value;
|
|
32
|
-
if (value instanceof
|
|
31
|
+
if (value instanceof ErrorObj) {
|
|
33
32
|
return value.host ? normalizeError(value.host) : { kind: "ExecutionFailure", message: errorToString(value) };
|
|
34
33
|
}
|
|
35
34
|
let message;
|
|
@@ -83,19 +82,19 @@ export const locate = (error, node) => {
|
|
|
83
82
|
return error;
|
|
84
83
|
};
|
|
85
84
|
/** The program value a handler receives for a failure; one failure always yields the same value. */
|
|
86
|
-
export const materialize = (
|
|
87
|
-
if (thrown instanceof
|
|
85
|
+
export const materialize = (ctx, thrown) => {
|
|
86
|
+
if (thrown instanceof Throw)
|
|
88
87
|
return thrown.value;
|
|
89
|
-
const
|
|
88
|
+
const builtins = ctx.builtins;
|
|
90
89
|
if (thrown instanceof PendingThrow) {
|
|
91
90
|
if (thrown.value === undefined) {
|
|
92
|
-
thrown.value = createErrorValue(
|
|
91
|
+
thrown.value = createErrorValue(builtins[thrown.type], thrown.message);
|
|
93
92
|
thrown.value.host = thrown;
|
|
94
93
|
}
|
|
95
94
|
return thrown.value;
|
|
96
95
|
}
|
|
97
96
|
const type = thrown instanceof Error && isErrorType(thrown.name) ? thrown.name : "Error";
|
|
98
|
-
return createErrorValue(
|
|
97
|
+
return createErrorValue(builtins[type], normalizeError(thrown).message);
|
|
99
98
|
};
|
|
100
99
|
/** Error.prototype.toString: `name: message`, omitting whichever side is empty. */
|
|
101
100
|
const errorToString = (self) => {
|
|
@@ -109,43 +108,43 @@ const errorToString = (self) => {
|
|
|
109
108
|
return shownMessage;
|
|
110
109
|
return `${shownName}: ${shownMessage}`;
|
|
111
110
|
};
|
|
112
|
-
export const createAggregateErrorValue = (
|
|
111
|
+
export const createAggregateErrorValue = (ctx, errors, message, proto = ctx.builtins.AggregateError) => {
|
|
113
112
|
const value = createErrorValue(proto, message);
|
|
114
|
-
define(value, "errors", new
|
|
113
|
+
define(value, "errors", new Arr(ctx.builtins.Array, errors), { ...hidden });
|
|
115
114
|
return value;
|
|
116
115
|
};
|
|
117
|
-
const constructAggregateErrorValue = (
|
|
118
|
-
const cursor = yield*
|
|
116
|
+
const constructAggregateErrorValue = (ctx, args, proto) => Effect.gen(function* () {
|
|
117
|
+
const cursor = yield* ctx.iterate(args[0]);
|
|
119
118
|
if (cursor === undefined)
|
|
120
119
|
throw typeError("new AggregateError(...) expects a synchronous iterable of errors.");
|
|
121
120
|
const errors = [];
|
|
122
121
|
while (true) {
|
|
123
122
|
const step = yield* cursor.next;
|
|
124
123
|
if (step.done) {
|
|
125
|
-
return createAggregateErrorValue(
|
|
124
|
+
return createAggregateErrorValue(ctx, errors, args[1] === undefined ? "" : coerceToString(args[1]), proto);
|
|
126
125
|
}
|
|
127
126
|
errors.push(step.value);
|
|
128
127
|
}
|
|
129
128
|
});
|
|
130
129
|
/** An error constructor such as `Error` or `TypeError`; callable with or without `new`, like JS. */
|
|
131
|
-
export const errorGlobal = (type,
|
|
132
|
-
const
|
|
133
|
-
const prototype =
|
|
130
|
+
export const errorGlobal = (type, ctx) => {
|
|
131
|
+
const builtins = ctx.builtins;
|
|
132
|
+
const prototype = builtins[type];
|
|
134
133
|
const construct = (args, newTarget) => {
|
|
135
134
|
const proto = prototypeFrom(newTarget, prototype);
|
|
136
135
|
return type === "AggregateError"
|
|
137
|
-
? constructAggregateErrorValue(
|
|
136
|
+
? constructAggregateErrorValue(ctx, args, proto)
|
|
138
137
|
: Effect.sync(() => createErrorValue(proto, args[0] === undefined ? undefined : coerceToString(args[0])));
|
|
139
138
|
};
|
|
140
|
-
const ctor = constructor(
|
|
139
|
+
const ctor = constructor(builtins, prototype, {
|
|
141
140
|
name: type,
|
|
142
141
|
length: type === "AggregateError" ? 2 : 1,
|
|
143
142
|
call: (_, args) => construct(args, ctor),
|
|
144
143
|
construct,
|
|
145
144
|
});
|
|
146
145
|
if (type === "Error") {
|
|
147
|
-
methods(
|
|
148
|
-
["toString", 0, (thisValue) => errorToString(receiver(
|
|
146
|
+
methods(builtins, prototype, [
|
|
147
|
+
["toString", 0, (thisValue) => errorToString(receiver(Obj, thisValue, "Error.prototype.toString"))],
|
|
149
148
|
]);
|
|
150
149
|
}
|
|
151
150
|
return ctor;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import type { ResolvedExecutionLimits, Result } from "../codemode.js";
|
|
3
3
|
import { ToolRuntime } from "../tool-runtime.js";
|
|
4
|
-
import
|
|
5
|
-
export declare const executeProgram: <R>(code: string, prepared: ToolRuntime.Prepared<R>, limits: ResolvedExecutionLimits, hooks: ToolRuntime.ToolCallHooks<R>,
|
|
4
|
+
import { Interpreter } from "./interpreter.js";
|
|
5
|
+
export declare const executeProgram: <R>(code: string, prepared: ToolRuntime.Prepared<R>, limits: ResolvedExecutionLimits, hooks: ToolRuntime.ToolCallHooks<R>, globals?: (ctx: Interpreter<R>) => ReadonlyArray<readonly [string, unknown]>) => Effect.Effect<Result, never, R>;
|
|
@@ -6,11 +6,11 @@ import { transpile } from "#transpile";
|
|
|
6
6
|
import { toData } from "../data.js";
|
|
7
7
|
import { ToolRuntime } from "../tool-runtime.js";
|
|
8
8
|
import { normalizeError } from "./errors.js";
|
|
9
|
-
import {
|
|
9
|
+
import { createBuiltins } from "./intrinsics.js";
|
|
10
10
|
import { PendingThrow } from "./model.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
export const executeProgram = (code, prepared, limits, hooks,
|
|
11
|
+
import { Pending } from "./promises.js";
|
|
12
|
+
import { Interpreter } from "./interpreter.js";
|
|
13
|
+
export const executeProgram = (code, prepared, limits, hooks, globals) => {
|
|
14
14
|
if (code.trim().length === 0) {
|
|
15
15
|
return Effect.succeed({
|
|
16
16
|
ok: false,
|
|
@@ -20,19 +20,19 @@ export const executeProgram = (code, prepared, limits, hooks, extraGlobals) => {
|
|
|
20
20
|
}
|
|
21
21
|
// Allocate execution state inside suspension so reused Effects never share it.
|
|
22
22
|
return Effect.suspend(() => {
|
|
23
|
-
const
|
|
24
|
-
const tools = ToolRuntime.make(prepared,
|
|
23
|
+
const builtins = createBuiltins();
|
|
24
|
+
const tools = ToolRuntime.make(prepared, builtins, limits.maxToolCalls, hooks);
|
|
25
25
|
const logs = [];
|
|
26
26
|
const logged = () => (logs.length > 0 ? { logs: [...logs] } : {});
|
|
27
27
|
// Set only after copy-out so timeouts cannot report invalid values as completed.
|
|
28
28
|
let returned;
|
|
29
29
|
const base = Effect.acquireUseRelease(Scope.make("parallel"), (scope) => Effect.gen(function* () {
|
|
30
30
|
const program = parseProgram(code);
|
|
31
|
-
const
|
|
32
|
-
const value = yield* new
|
|
31
|
+
const pending = new Pending(scope, builtins.Promise);
|
|
32
|
+
const value = yield* new Interpreter({ tools, pending, builtins, logs, globals }).run(program);
|
|
33
33
|
const result = toData(value, "Execution result", "result");
|
|
34
|
-
returned = { value: result,
|
|
35
|
-
const warnings = yield*
|
|
34
|
+
returned = { value: result, pending };
|
|
35
|
+
const warnings = yield* pending.interrupt();
|
|
36
36
|
return {
|
|
37
37
|
ok: true,
|
|
38
38
|
value: result,
|
|
@@ -64,7 +64,7 @@ export const executeProgram = (code, prepared, limits, hooks, extraGlobals) => {
|
|
|
64
64
|
kind: "TimeoutExceeded",
|
|
65
65
|
message: `The program returned, but background work was still running at the ${timeoutMs}ms timeout and was interrupted. Await all started promises.`,
|
|
66
66
|
},
|
|
67
|
-
...returned.
|
|
67
|
+
...returned.pending.diagnostics(),
|
|
68
68
|
],
|
|
69
69
|
...logged(),
|
|
70
70
|
toolCalls: tools.calls,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Extension } from "../extension.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { Interpreter } from "./interpreter.js";
|
|
3
3
|
/**
|
|
4
4
|
* The global bindings of one run's extensions. Everything crossing the boundary is converted: plain data is
|
|
5
5
|
* copied, built-in wrappers are copied, instances of exposed classes travel as handles, and a host Promise becomes
|
|
6
6
|
* a program promise. Prototypes, constructors, and handle identity are all per run.
|
|
7
7
|
*/
|
|
8
|
-
export declare const extensionGlobals: <R>(
|
|
8
|
+
export declare const extensionGlobals: <R>(ctx: Interpreter<R>, extensions: ReadonlyArray<Extension>) => ReadonlyArray<readonly [string, unknown]>;
|