@opencode/codemode 2.0.3 → 2.0.5
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/README.md +5 -2
- package/dist/codemode.d.ts +7 -2
- package/dist/codemode.js +15 -2
- package/dist/data.d.ts +14 -21
- package/dist/data.js +72 -140
- package/dist/extension.d.ts +11 -0
- package/dist/extension.js +9 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/interpreter/callback.d.ts +20 -0
- package/dist/interpreter/{runner.js → callback.js} +14 -14
- package/dist/interpreter/errors.d.ts +12 -5
- package/dist/interpreter/errors.js +66 -54
- package/dist/interpreter/execute.d.ts +2 -2
- package/dist/interpreter/execute.js +15 -15
- package/dist/interpreter/extensions.d.ts +8 -0
- package/dist/interpreter/extensions.js +160 -0
- package/dist/interpreter/generators.d.ts +2 -3
- package/dist/interpreter/generators.js +10 -10
- package/dist/interpreter/globals.d.ts +4 -12
- package/dist/interpreter/globals.js +56 -49
- package/dist/interpreter/interpreter.d.ts +34 -0
- package/dist/interpreter/{runtime.js → interpreter.js} +250 -215
- package/dist/interpreter/intrinsics.d.ts +5 -5
- package/dist/interpreter/intrinsics.js +16 -10
- package/dist/interpreter/limits.d.ts +10 -0
- package/dist/interpreter/limits.js +19 -0
- package/dist/interpreter/model.d.ts +27 -14
- package/dist/interpreter/model.js +22 -14
- package/dist/interpreter/native.d.ts +12 -13
- package/dist/interpreter/native.js +17 -16
- package/dist/interpreter/objects.d.ts +55 -48
- package/dist/interpreter/objects.js +64 -44
- package/dist/interpreter/promises.d.ts +13 -15
- package/dist/interpreter/promises.js +89 -85
- package/dist/interpreter/references.d.ts +1 -2
- package/dist/interpreter/references.js +18 -16
- package/dist/interpreter/scope.js +6 -6
- package/dist/openapi/types.d.ts +1 -1
- package/dist/stdlib/array.d.ts +3 -4
- package/dist/stdlib/array.js +115 -110
- 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 +89 -89
- package/dist/stdlib/console.d.ts +5 -3
- package/dist/stdlib/console.js +30 -37
- package/dist/stdlib/date.d.ts +2 -2
- package/dist/stdlib/date.js +35 -35
- package/dist/stdlib/json.d.ts +3 -3
- package/dist/stdlib/json.js +29 -67
- package/dist/stdlib/math.d.ts +3 -3
- package/dist/stdlib/math.js +17 -21
- package/dist/stdlib/number.d.ts +3 -3
- package/dist/stdlib/number.js +32 -36
- package/dist/stdlib/object.d.ts +5 -5
- package/dist/stdlib/object.js +59 -62
- package/dist/stdlib/regexp.d.ts +7 -8
- package/dist/stdlib/regexp.js +40 -48
- package/dist/stdlib/string.d.ts +2 -2
- package/dist/stdlib/string.js +110 -88
- package/dist/stdlib/url.d.ts +4 -6
- package/dist/stdlib/url.js +86 -90
- package/dist/stdlib/value.d.ts +3 -3
- package/dist/stdlib/value.js +26 -24
- package/dist/stdlib/web.d.ts +4 -4
- package/dist/stdlib/web.js +22 -8
- package/dist/tool-runtime.d.ts +38 -19
- package/dist/tool-runtime.js +70 -48
- package/package.json +1 -1
- package/dist/interpreter/runner.d.ts +0 -28
- package/dist/interpreter/runtime.d.ts +0 -19
package/dist/stdlib/url.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { toProgram, ToolRuntimeError } from "../data.js";
|
|
3
2
|
import { constructor, fn, methods, prototypeFrom, receiver, requiresNew } from "../interpreter/native.js";
|
|
4
|
-
import {
|
|
5
|
-
import { defineAccessor, entries, isWrapper,
|
|
3
|
+
import { PendingThrow, typeError, uriError } from "../interpreter/model.js";
|
|
4
|
+
import { defineAccessor, entries, isWrapper, Arr, Obj, URLObj, URLSearchParamsObj } from "../interpreter/objects.js";
|
|
6
5
|
import { isRuntimeReference } from "../interpreter/references.js";
|
|
7
|
-
import { applyCollectionCallback, preserveConsumerError } from "../interpreter/
|
|
6
|
+
import { applyCollectionCallback, preserveConsumerError } from "../interpreter/callback.js";
|
|
8
7
|
import { coerceToString } from "./value.js";
|
|
9
8
|
const urlProperties = [
|
|
10
9
|
"href",
|
|
@@ -19,64 +18,63 @@ const urlProperties = [
|
|
|
19
18
|
"search",
|
|
20
19
|
"hash",
|
|
21
20
|
];
|
|
22
|
-
export const uriArgument = (protos, value, label) => coerceToString(toProgram(protos, value, label));
|
|
23
21
|
const uriFunctions = {
|
|
24
22
|
encodeURI,
|
|
25
23
|
encodeURIComponent,
|
|
26
24
|
decodeURI,
|
|
27
25
|
decodeURIComponent,
|
|
28
26
|
};
|
|
29
|
-
export const uriGlobal = (
|
|
30
|
-
const value =
|
|
27
|
+
export const uriGlobal = (ctx, name) => fn(ctx.builtins, name, 1, (_, args) => {
|
|
28
|
+
const value = coerceToString(args[0]);
|
|
31
29
|
try {
|
|
32
30
|
return uriFunctions[name](value);
|
|
33
31
|
}
|
|
34
32
|
catch (error) {
|
|
35
|
-
throw uriError(`${name} received malformed URI data: ${error instanceof Error ? error.message : String(error)}
|
|
33
|
+
throw uriError(`${name} received malformed URI data: ${error instanceof Error ? error.message : String(error)}`);
|
|
36
34
|
}
|
|
37
35
|
});
|
|
38
|
-
const urlArgument = (
|
|
39
|
-
export const urlGlobal = (
|
|
40
|
-
const
|
|
41
|
-
const proto =
|
|
42
|
-
const construct = (args, into
|
|
36
|
+
const urlArgument = (value) => (value instanceof URLObj ? value.url.href : coerceToString(value));
|
|
37
|
+
export const urlGlobal = (ctx) => {
|
|
38
|
+
const builtins = ctx.builtins;
|
|
39
|
+
const proto = builtins.URL;
|
|
40
|
+
const construct = (args, into) => {
|
|
43
41
|
if (args.length === 0) {
|
|
44
|
-
throw
|
|
42
|
+
throw typeError("new URL(...) requires a URL string and an optional base URL.");
|
|
45
43
|
}
|
|
46
|
-
const input = urlArgument(
|
|
47
|
-
const base = args[1] === undefined ? undefined : urlArgument(
|
|
44
|
+
const input = urlArgument(args[0]);
|
|
45
|
+
const base = args[1] === undefined ? undefined : urlArgument(args[1]);
|
|
48
46
|
try {
|
|
49
|
-
return new
|
|
47
|
+
return new URLObj(into, builtins.URLSearchParams, new URL(input, base));
|
|
50
48
|
}
|
|
51
49
|
catch {
|
|
52
|
-
throw
|
|
50
|
+
throw typeError(`new URL(...) received an invalid URL${base === undefined ? "" : " or base URL"}.`);
|
|
53
51
|
}
|
|
54
52
|
};
|
|
55
|
-
const url = constructor(
|
|
53
|
+
const url = constructor(builtins, proto, {
|
|
56
54
|
name: "URL",
|
|
57
55
|
length: 1,
|
|
58
56
|
call: requiresNew("URL"),
|
|
59
|
-
construct: (args, newTarget
|
|
57
|
+
construct: (args, newTarget) => Effect.sync(() => construct(args, prototypeFrom(newTarget, proto))),
|
|
60
58
|
});
|
|
61
59
|
const parse = (name) => [
|
|
62
60
|
name,
|
|
63
61
|
1,
|
|
64
|
-
(_, args
|
|
62
|
+
(_, args) => {
|
|
65
63
|
if (args.length === 0)
|
|
66
|
-
throw
|
|
67
|
-
const input = urlArgument(
|
|
68
|
-
const base = args[1] === undefined ? undefined : urlArgument(
|
|
64
|
+
throw typeError(`URL.${name} requires a URL argument.`);
|
|
65
|
+
const input = urlArgument(args[0]);
|
|
66
|
+
const base = args[1] === undefined ? undefined : urlArgument(args[1]);
|
|
69
67
|
try {
|
|
70
68
|
const parsed = new URL(input, base);
|
|
71
|
-
return name === "canParse" ? true : new
|
|
69
|
+
return name === "canParse" ? true : new URLObj(proto, builtins.URLSearchParams, parsed);
|
|
72
70
|
}
|
|
73
71
|
catch {
|
|
74
72
|
return name === "canParse" ? false : null;
|
|
75
73
|
}
|
|
76
74
|
},
|
|
77
75
|
];
|
|
78
|
-
methods(
|
|
79
|
-
const self = (thisValue, name
|
|
76
|
+
methods(builtins, url, [parse("canParse"), parse("parse")]);
|
|
77
|
+
const self = (thisValue, name) => receiver(URLObj, thisValue, `URL.prototype.${name}`);
|
|
80
78
|
for (const name of urlProperties) {
|
|
81
79
|
defineAccessor(proto, name, (thisValue) => self(thisValue, name).url[name], name === "origin"
|
|
82
80
|
? undefined
|
|
@@ -84,40 +82,40 @@ export const urlGlobal = (runner) => {
|
|
|
84
82
|
const target = self(thisValue, name);
|
|
85
83
|
try {
|
|
86
84
|
;
|
|
87
|
-
target.url[name] =
|
|
85
|
+
target.url[name] = coerceToString(value);
|
|
88
86
|
}
|
|
89
87
|
catch (error) {
|
|
90
|
-
if (error instanceof
|
|
88
|
+
if (error instanceof PendingThrow)
|
|
91
89
|
throw error;
|
|
92
|
-
throw
|
|
90
|
+
throw typeError(`URL.${name} received an invalid value.`);
|
|
93
91
|
}
|
|
94
92
|
});
|
|
95
93
|
}
|
|
96
94
|
defineAccessor(proto, "searchParams", (thisValue) => self(thisValue, "searchParams").searchParams);
|
|
97
|
-
methods(
|
|
98
|
-
["toString", 0, (thisValue
|
|
99
|
-
["toJSON", 0, (thisValue
|
|
95
|
+
methods(builtins, proto, [
|
|
96
|
+
["toString", 0, (thisValue) => self(thisValue, "toString").url.href],
|
|
97
|
+
["toJSON", 0, (thisValue) => self(thisValue, "toJSON").url.href],
|
|
100
98
|
]);
|
|
101
99
|
return url;
|
|
102
100
|
};
|
|
103
|
-
const readPair = (
|
|
104
|
-
const cursor = yield*
|
|
101
|
+
const readPair = (ctx, value) => Effect.gen(function* () {
|
|
102
|
+
const cursor = yield* ctx.iterate(value);
|
|
105
103
|
if (cursor === undefined) {
|
|
106
|
-
throw
|
|
104
|
+
throw typeError("new URLSearchParams(...) expects iterable [name, value] pairs.");
|
|
107
105
|
}
|
|
108
106
|
const items = [];
|
|
109
107
|
while (true) {
|
|
110
108
|
const step = yield* cursor.next;
|
|
111
109
|
if (step.done)
|
|
112
110
|
return items;
|
|
113
|
-
items.push(yield* preserveConsumerError(cursor, Effect.sync(() =>
|
|
111
|
+
items.push(yield* preserveConsumerError(cursor, Effect.sync(() => coerceToString(step.value))));
|
|
114
112
|
}
|
|
115
113
|
});
|
|
116
|
-
const constructURLSearchParams = (
|
|
117
|
-
const wrap = (params) => new
|
|
114
|
+
const constructURLSearchParams = (ctx, init, proto) => {
|
|
115
|
+
const wrap = (params) => new URLSearchParamsObj(proto, params);
|
|
118
116
|
if (init === undefined)
|
|
119
117
|
return Effect.succeed(wrap(new URLSearchParams()));
|
|
120
|
-
if (init instanceof
|
|
118
|
+
if (init instanceof URLSearchParamsObj)
|
|
121
119
|
return Effect.succeed(wrap(new URLSearchParams(init.params)));
|
|
122
120
|
if (typeof init === "string")
|
|
123
121
|
return Effect.succeed(wrap(new URLSearchParams(init)));
|
|
@@ -125,130 +123,128 @@ const constructURLSearchParams = (runner, init, proto, node) => {
|
|
|
125
123
|
return Effect.succeed(wrap(new URLSearchParams(coerceToString(init))));
|
|
126
124
|
}
|
|
127
125
|
return Effect.gen(function* () {
|
|
128
|
-
const cursor = yield*
|
|
126
|
+
const cursor = yield* ctx.iterate(init);
|
|
129
127
|
if (cursor !== undefined) {
|
|
130
128
|
const pairs = [];
|
|
131
129
|
while (true) {
|
|
132
130
|
const step = yield* cursor.next;
|
|
133
131
|
if (step.done) {
|
|
134
132
|
if (pairs.some((entry) => entry.length !== 2)) {
|
|
135
|
-
throw
|
|
133
|
+
throw typeError("new URLSearchParams(...) expects iterable [name, value] pairs.");
|
|
136
134
|
}
|
|
137
135
|
return wrap(new URLSearchParams(pairs.map((entry) => [entry[0] ?? "", entry[1] ?? ""])));
|
|
138
136
|
}
|
|
139
|
-
pairs.push(yield* preserveConsumerError(cursor, readPair(
|
|
137
|
+
pairs.push(yield* preserveConsumerError(cursor, readPair(ctx, step.value)));
|
|
140
138
|
}
|
|
141
139
|
}
|
|
142
140
|
if (isRuntimeReference(init)) {
|
|
143
|
-
throw
|
|
141
|
+
throw typeError("new URLSearchParams(...) expects a query string, data object, or synchronous iterable pairs.");
|
|
144
142
|
}
|
|
145
143
|
if (isWrapper(init))
|
|
146
144
|
return wrap(new URLSearchParams());
|
|
147
|
-
if (!(init instanceof
|
|
148
|
-
throw
|
|
145
|
+
if (!(init instanceof Obj)) {
|
|
146
|
+
throw typeError("new URLSearchParams(...) expects a query string, data object, iterable pairs, or URLSearchParams.");
|
|
149
147
|
}
|
|
150
148
|
return wrap(new URLSearchParams(Object.fromEntries(entries(init).map(([key, value]) => [key, coerceToString(value)]))));
|
|
151
149
|
});
|
|
152
150
|
};
|
|
153
|
-
export const urlSearchParamsGlobal = (
|
|
154
|
-
const
|
|
155
|
-
const proto =
|
|
156
|
-
const searchParams = constructor(
|
|
151
|
+
export const urlSearchParamsGlobal = (ctx) => {
|
|
152
|
+
const builtins = ctx.builtins;
|
|
153
|
+
const proto = builtins.URLSearchParams;
|
|
154
|
+
const searchParams = constructor(builtins, proto, {
|
|
157
155
|
name: "URLSearchParams",
|
|
158
156
|
call: requiresNew("URLSearchParams"),
|
|
159
|
-
construct: (args, newTarget
|
|
157
|
+
construct: (args, newTarget) => constructURLSearchParams(ctx, args[0], prototypeFrom(newTarget, proto)),
|
|
160
158
|
});
|
|
161
|
-
const self = (thisValue, name
|
|
162
|
-
const wrap = (items) => new
|
|
163
|
-
const arg = (
|
|
164
|
-
const requireArgs = (name, args, count
|
|
159
|
+
const self = (thisValue, name) => receiver(URLSearchParamsObj, thisValue, `URLSearchParams.prototype.${name}`);
|
|
160
|
+
const wrap = (items) => new Arr(builtins.Array, items);
|
|
161
|
+
const arg = (args, index) => coerceToString(args[index]);
|
|
162
|
+
const requireArgs = (name, args, count) => {
|
|
165
163
|
if (args.length < count) {
|
|
166
|
-
throw
|
|
164
|
+
throw typeError(`URLSearchParams.${name} requires ${count} argument${count === 1 ? "" : "s"}.`);
|
|
167
165
|
}
|
|
168
166
|
};
|
|
169
167
|
defineAccessor(proto, "size", (thisValue) => self(thisValue, "size").params.size);
|
|
170
|
-
methods(
|
|
168
|
+
methods(builtins, proto, [
|
|
171
169
|
[
|
|
172
170
|
"append",
|
|
173
171
|
2,
|
|
174
|
-
(thisValue, args
|
|
175
|
-
requireArgs("append", args, 2
|
|
176
|
-
self(thisValue, "append"
|
|
172
|
+
(thisValue, args) => {
|
|
173
|
+
requireArgs("append", args, 2);
|
|
174
|
+
self(thisValue, "append").params.append(arg(args, 0), arg(args, 1));
|
|
177
175
|
return undefined;
|
|
178
176
|
},
|
|
179
177
|
],
|
|
180
178
|
[
|
|
181
179
|
"delete",
|
|
182
180
|
1,
|
|
183
|
-
(thisValue, args
|
|
184
|
-
requireArgs("delete", args, 1
|
|
185
|
-
const params = self(thisValue, "delete"
|
|
181
|
+
(thisValue, args) => {
|
|
182
|
+
requireArgs("delete", args, 1);
|
|
183
|
+
const params = self(thisValue, "delete").params;
|
|
186
184
|
if (args[1] !== undefined)
|
|
187
|
-
params.delete(arg(
|
|
185
|
+
params.delete(arg(args, 0), arg(args, 1));
|
|
188
186
|
else
|
|
189
|
-
params.delete(arg(
|
|
187
|
+
params.delete(arg(args, 0));
|
|
190
188
|
return undefined;
|
|
191
189
|
},
|
|
192
190
|
],
|
|
193
191
|
[
|
|
194
192
|
"get",
|
|
195
193
|
1,
|
|
196
|
-
(thisValue, args
|
|
197
|
-
requireArgs("get", args, 1
|
|
198
|
-
return self(thisValue, "get"
|
|
194
|
+
(thisValue, args) => {
|
|
195
|
+
requireArgs("get", args, 1);
|
|
196
|
+
return self(thisValue, "get").params.get(arg(args, 0));
|
|
199
197
|
},
|
|
200
198
|
],
|
|
201
199
|
[
|
|
202
200
|
"getAll",
|
|
203
201
|
1,
|
|
204
|
-
(thisValue, args
|
|
205
|
-
requireArgs("getAll", args, 1
|
|
206
|
-
return wrap(self(thisValue, "getAll"
|
|
202
|
+
(thisValue, args) => {
|
|
203
|
+
requireArgs("getAll", args, 1);
|
|
204
|
+
return wrap(self(thisValue, "getAll").params.getAll(arg(args, 0)));
|
|
207
205
|
},
|
|
208
206
|
],
|
|
209
207
|
[
|
|
210
208
|
"has",
|
|
211
209
|
1,
|
|
212
|
-
(thisValue, args
|
|
213
|
-
requireArgs("has", args, 1
|
|
214
|
-
const params = self(thisValue, "has"
|
|
215
|
-
return args[1] !== undefined
|
|
216
|
-
? params.has(arg("has", args, 0), arg("has", args, 1))
|
|
217
|
-
: params.has(arg("has", args, 0));
|
|
210
|
+
(thisValue, args) => {
|
|
211
|
+
requireArgs("has", args, 1);
|
|
212
|
+
const params = self(thisValue, "has").params;
|
|
213
|
+
return args[1] !== undefined ? params.has(arg(args, 0), arg(args, 1)) : params.has(arg(args, 0));
|
|
218
214
|
},
|
|
219
215
|
],
|
|
220
216
|
[
|
|
221
217
|
"set",
|
|
222
218
|
2,
|
|
223
|
-
(thisValue, args
|
|
224
|
-
requireArgs("set", args, 2
|
|
225
|
-
self(thisValue, "set"
|
|
219
|
+
(thisValue, args) => {
|
|
220
|
+
requireArgs("set", args, 2);
|
|
221
|
+
self(thisValue, "set").params.set(arg(args, 0), arg(args, 1));
|
|
226
222
|
return undefined;
|
|
227
223
|
},
|
|
228
224
|
],
|
|
229
225
|
[
|
|
230
226
|
"sort",
|
|
231
227
|
0,
|
|
232
|
-
(thisValue
|
|
233
|
-
self(thisValue, "sort"
|
|
228
|
+
(thisValue) => {
|
|
229
|
+
self(thisValue, "sort").params.sort();
|
|
234
230
|
return undefined;
|
|
235
231
|
},
|
|
236
232
|
],
|
|
237
|
-
["keys", 0, (thisValue
|
|
238
|
-
["values", 0, (thisValue
|
|
233
|
+
["keys", 0, (thisValue) => wrap(Array.from(self(thisValue, "keys").params.keys()))],
|
|
234
|
+
["values", 0, (thisValue) => wrap(Array.from(self(thisValue, "values").params.values()))],
|
|
239
235
|
[
|
|
240
236
|
"entries",
|
|
241
237
|
0,
|
|
242
|
-
(thisValue
|
|
238
|
+
(thisValue) => wrap(Array.from(self(thisValue, "entries").params.entries(), ([key, value]) => wrap([key, value]))),
|
|
243
239
|
],
|
|
244
|
-
["toString", 0, (thisValue
|
|
240
|
+
["toString", 0, (thisValue) => self(thisValue, "toString").params.toString()],
|
|
245
241
|
[
|
|
246
242
|
"forEach",
|
|
247
243
|
1,
|
|
248
|
-
(thisValue, args
|
|
249
|
-
requireArgs("forEach", args, 1
|
|
250
|
-
const target = self(thisValue, "forEach"
|
|
251
|
-
const apply = applyCollectionCallback(
|
|
244
|
+
(thisValue, args) => {
|
|
245
|
+
requireArgs("forEach", args, 1);
|
|
246
|
+
const target = self(thisValue, "forEach");
|
|
247
|
+
const apply = applyCollectionCallback(ctx, args[0], "URLSearchParams.forEach");
|
|
252
248
|
return Effect.gen(function* () {
|
|
253
249
|
for (const [key, value] of Array.from(target.params.entries()))
|
|
254
250
|
yield* apply([value, key, target]);
|
package/dist/stdlib/value.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import type {
|
|
1
|
+
import { type Native } from "../interpreter/objects.js";
|
|
2
|
+
import type { Interpreter } from "../interpreter/interpreter.js";
|
|
3
3
|
export declare const compoundOperators: Set<string>;
|
|
4
4
|
/** The built-in string form of a value, without consulting program-defined `toString` methods. */
|
|
5
5
|
export declare const coerceToString: (value: unknown) => string;
|
|
6
6
|
export declare const coerceToNumber: (value: unknown) => number;
|
|
7
7
|
export type Coercion = "Number" | "String" | "Boolean" | "parseInt" | "parseFloat" | "isFinite" | "isNaN";
|
|
8
8
|
/** A global coercion function such as `Number` or `parseInt`. */
|
|
9
|
-
export declare const coercion: <R>(
|
|
9
|
+
export declare const coercion: <R>(ctx: Interpreter<R>, name: Coercion, length?: number) => Native<R>;
|
package/dist/stdlib/value.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { toProgram } from "../data.js";
|
|
2
1
|
import { fn } from "../interpreter/native.js";
|
|
3
|
-
import {
|
|
4
|
-
import { get, isWrapper,
|
|
2
|
+
import { typeError } from "../interpreter/model.js";
|
|
3
|
+
import { get, isWrapper, Arr, Bytes, DateObj, ErrorObj, MapObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, } from "../interpreter/objects.js";
|
|
5
4
|
export const compoundOperators = new Set(["+=", "-=", "*=", "/=", "%=", "**=", "&=", "|=", "^=", "<<=", ">>=", ">>>="]);
|
|
6
5
|
/** The built-in string form of a value, without consulting program-defined `toString` methods. */
|
|
7
6
|
export const coerceToString = (value) => {
|
|
@@ -9,19 +8,21 @@ export const coerceToString = (value) => {
|
|
|
9
8
|
return "null";
|
|
10
9
|
if (value === undefined)
|
|
11
10
|
return "undefined";
|
|
12
|
-
if (value instanceof
|
|
11
|
+
if (value instanceof DateObj)
|
|
13
12
|
return Number.isFinite(value.time) ? new Date(value.time).toISOString() : "Invalid Date";
|
|
14
|
-
if (value instanceof
|
|
13
|
+
if (value instanceof RegExpObj)
|
|
15
14
|
return `/${value.regex.source}/${value.regex.flags}`;
|
|
16
|
-
if (value instanceof
|
|
15
|
+
if (value instanceof MapObj)
|
|
17
16
|
return "[object Map]";
|
|
18
|
-
if (value instanceof
|
|
17
|
+
if (value instanceof SetObj)
|
|
19
18
|
return "[object Set]";
|
|
20
|
-
if (value instanceof
|
|
19
|
+
if (value instanceof URLObj)
|
|
21
20
|
return value.url.href;
|
|
22
|
-
if (value instanceof
|
|
21
|
+
if (value instanceof URLSearchParamsObj)
|
|
23
22
|
return value.params.toString();
|
|
24
|
-
if (value instanceof
|
|
23
|
+
if (value instanceof Bytes)
|
|
24
|
+
return value.bytes.join(",");
|
|
25
|
+
if (value instanceof ErrorObj) {
|
|
25
26
|
// Match Error.prototype.toString: "name: message", or just one when the other is empty.
|
|
26
27
|
const name = get(value, "name");
|
|
27
28
|
const message = get(value, "message");
|
|
@@ -33,7 +34,7 @@ export const coerceToString = (value) => {
|
|
|
33
34
|
return shownMessage;
|
|
34
35
|
return `${shownName}: ${shownMessage}`;
|
|
35
36
|
}
|
|
36
|
-
if (value instanceof
|
|
37
|
+
if (value instanceof Arr) {
|
|
37
38
|
return value.items.map((item) => (item === null || item === undefined ? "" : coerceToString(item))).join(",");
|
|
38
39
|
}
|
|
39
40
|
if (typeof value === "object")
|
|
@@ -41,15 +42,17 @@ export const coerceToString = (value) => {
|
|
|
41
42
|
return String(value);
|
|
42
43
|
};
|
|
43
44
|
export const coerceToNumber = (value) => {
|
|
44
|
-
if (value instanceof
|
|
45
|
+
if (value instanceof DateObj)
|
|
45
46
|
return value.time;
|
|
47
|
+
if (value instanceof Bytes)
|
|
48
|
+
return Number(coerceToString(value));
|
|
46
49
|
if (isWrapper(value))
|
|
47
50
|
return Number.NaN;
|
|
48
|
-
if (value instanceof
|
|
51
|
+
if (value instanceof Arr)
|
|
49
52
|
return Number(coerceToString(value));
|
|
50
53
|
return value !== null && typeof value === "object" ? Number.NaN : Number(value);
|
|
51
54
|
};
|
|
52
|
-
const coerce = (
|
|
55
|
+
const coerce = (ctx, name, args) => {
|
|
53
56
|
// Native: Number() is 0 and String() is "", unlike their undefined-argument forms; the
|
|
54
57
|
// other coercers match native through the undefined-argument path below.
|
|
55
58
|
if (args.length === 0) {
|
|
@@ -74,25 +77,24 @@ const coerce = (runner, name, args, node) => {
|
|
|
74
77
|
return parseInt(coerceToString(raw));
|
|
75
78
|
return parseFloat(coerceToString(raw));
|
|
76
79
|
}
|
|
77
|
-
const value = toProgram(runner.prototypes, raw, `${name} input`);
|
|
78
80
|
if (name === "Number")
|
|
79
|
-
return coerceToNumber(
|
|
81
|
+
return coerceToNumber(raw);
|
|
80
82
|
if (name === "Boolean")
|
|
81
|
-
return Boolean(
|
|
83
|
+
return Boolean(raw);
|
|
82
84
|
if (name === "isFinite")
|
|
83
|
-
return Number.isFinite(coerceToNumber(
|
|
85
|
+
return Number.isFinite(coerceToNumber(raw));
|
|
84
86
|
if (name === "isNaN")
|
|
85
|
-
return Number.isNaN(coerceToNumber(
|
|
87
|
+
return Number.isNaN(coerceToNumber(raw));
|
|
86
88
|
if (name === "parseInt") {
|
|
87
89
|
const radix = args[1];
|
|
88
90
|
if (radix !== undefined && typeof radix !== "number") {
|
|
89
|
-
throw
|
|
91
|
+
throw typeError("parseInt expects a numeric radix.");
|
|
90
92
|
}
|
|
91
|
-
return parseInt(coerceToString(
|
|
93
|
+
return parseInt(coerceToString(raw), radix);
|
|
92
94
|
}
|
|
93
95
|
if (name === "parseFloat")
|
|
94
|
-
return parseFloat(coerceToString(
|
|
95
|
-
return coerceToString(
|
|
96
|
+
return parseFloat(coerceToString(raw));
|
|
97
|
+
return coerceToString(raw);
|
|
96
98
|
};
|
|
97
99
|
/** A global coercion function such as `Number` or `parseInt`. */
|
|
98
|
-
export const coercion = (
|
|
100
|
+
export const coercion = (ctx, name, length = 1) => fn(ctx.builtins, name, length, (_, args) => coerce(ctx, name, args));
|
package/dist/stdlib/web.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
3
|
-
export declare const base64Global: <R>(
|
|
4
|
-
export declare const cryptoGlobal: <R>(
|
|
1
|
+
import { Obj } from "../interpreter/objects.js";
|
|
2
|
+
import type { Interpreter } from "../interpreter/interpreter.js";
|
|
3
|
+
export declare const base64Global: <R>(ctx: Interpreter<R>, name: "atob" | "btoa") => import("../interpreter/objects.js").Native<R>;
|
|
4
|
+
export declare const cryptoGlobal: <R>(ctx: Interpreter<R>) => Obj;
|
package/dist/stdlib/web.js
CHANGED
|
@@ -1,22 +1,36 @@
|
|
|
1
1
|
import { fn, methods } from "../interpreter/native.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { typeError } from "../interpreter/model.js";
|
|
3
|
+
import { Bytes, Obj } from "../interpreter/objects.js";
|
|
4
|
+
import { describeValue } from "../interpreter/references.js";
|
|
4
5
|
import { coerceToString } from "./value.js";
|
|
5
6
|
// WebIDL DOMString conversion: a missing argument is a TypeError, anything else stringifies. Invalid input is a
|
|
6
7
|
// TypeError as well; browsers throw a DOMException named InvalidCharacterError, which CodeMode does not have.
|
|
7
|
-
export const base64Global = (
|
|
8
|
+
export const base64Global = (ctx, name) => fn(ctx.builtins, name, 1, (_, args) => {
|
|
8
9
|
if (args.length === 0)
|
|
9
|
-
throw
|
|
10
|
+
throw typeError(`${name} requires 1 argument (a string)`);
|
|
10
11
|
const input = coerceToString(args[0]);
|
|
11
12
|
try {
|
|
12
13
|
return name === "atob" ? atob(input) : btoa(input);
|
|
13
14
|
}
|
|
14
15
|
catch {
|
|
15
|
-
throw
|
|
16
|
+
throw typeError("The string contains invalid characters.");
|
|
16
17
|
}
|
|
17
18
|
});
|
|
18
|
-
export const cryptoGlobal = (
|
|
19
|
-
const object = new
|
|
20
|
-
methods(
|
|
19
|
+
export const cryptoGlobal = (ctx) => {
|
|
20
|
+
const object = new Obj(ctx.builtins.Object);
|
|
21
|
+
methods(ctx.builtins, object, [
|
|
22
|
+
["randomUUID", 0, () => crypto.randomUUID()],
|
|
23
|
+
[
|
|
24
|
+
"getRandomValues",
|
|
25
|
+
1,
|
|
26
|
+
(_, args) => {
|
|
27
|
+
if (!(args[0] instanceof Bytes)) {
|
|
28
|
+
throw typeError(`crypto.getRandomValues expects a Uint8Array, received ${describeValue(args[0])}.`);
|
|
29
|
+
}
|
|
30
|
+
crypto.getRandomValues(args[0].bytes);
|
|
31
|
+
return args[0];
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
]);
|
|
21
35
|
return object;
|
|
22
36
|
};
|
package/dist/tool-runtime.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import type {
|
|
2
|
+
import type { Json } from "./data.js";
|
|
3
|
+
import type { DiagnosticKind } from "./codemode.js";
|
|
3
4
|
import { type Namespace } from "./namespace.js";
|
|
4
5
|
import { type Tool } from "./tool.js";
|
|
5
6
|
import type { Tools } from "./tools.js";
|
|
6
|
-
export declare const compareText: (left: string, right: string) =>
|
|
7
|
+
export declare const compareText: (left: string, right: string) => 0 | 1 | -1;
|
|
7
8
|
export type Services<T> = ServicesOf<T, []>;
|
|
8
9
|
type ServicesOf<T, Depth extends ReadonlyArray<unknown>> = Depth["length"] extends 8 ? never : T extends {
|
|
9
10
|
readonly _tag: "CodeModeTool";
|
|
@@ -12,25 +13,36 @@ type ServicesOf<T, Depth extends ReadonlyArray<unknown>> = Depth["length"] exten
|
|
|
12
13
|
export type ToolCall = {
|
|
13
14
|
readonly name: string;
|
|
14
15
|
};
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
/** A tool call the program is making, with its decoded input. */
|
|
17
|
+
export type ToolInvocation = {
|
|
17
18
|
readonly name: string;
|
|
18
19
|
readonly input: unknown;
|
|
19
20
|
};
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
/** A call the program is making to an extension global, with its arguments. */
|
|
22
|
+
export type ExtensionInvocation = {
|
|
23
|
+
readonly extension: string;
|
|
22
24
|
readonly name: string;
|
|
23
|
-
readonly
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
readonly args: ReadonlyArray<unknown>;
|
|
26
|
+
};
|
|
27
|
+
/** How a call ended; `after` hooks observe it and cannot change it. */
|
|
28
|
+
export type CallResult = {
|
|
29
|
+
readonly status: "success";
|
|
30
|
+
readonly value: unknown;
|
|
31
|
+
} | {
|
|
32
|
+
readonly status: "failure";
|
|
33
|
+
readonly error: unknown;
|
|
34
|
+
} | {
|
|
35
|
+
readonly status: "interrupted";
|
|
27
36
|
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
readonly
|
|
31
|
-
|
|
32
|
-
readonly
|
|
37
|
+
/** Hooks around every call the program makes into the host. A failing `before` denies the call. */
|
|
38
|
+
export type Hooks<R = never> = {
|
|
39
|
+
readonly "tool.before"?: ((call: ToolInvocation) => Effect.Effect<void, unknown, R>) | undefined;
|
|
40
|
+
readonly "tool.after"?: ((call: ToolInvocation, result: CallResult) => Effect.Effect<void, never, R>) | undefined;
|
|
41
|
+
readonly "extension.before"?: ((call: ExtensionInvocation) => Effect.Effect<void, unknown, R>) | undefined;
|
|
42
|
+
readonly "extension.after"?: ((call: ExtensionInvocation, result: CallResult) => Effect.Effect<void, never, R>) | undefined;
|
|
33
43
|
};
|
|
44
|
+
/** Runs `before`, then `run`, then `after` with how it ended, including when interrupted. */
|
|
45
|
+
export declare const hooked: <Call, A, R>(call: Call, before: ((call: Call) => Effect.Effect<void, unknown, R>) | undefined, after: ((call: Call, result: CallResult) => Effect.Effect<void, never, R>) | undefined, run: Effect.Effect<A, unknown, R>) => Effect.Effect<A, unknown, R>;
|
|
34
46
|
export type ToolDescription = {
|
|
35
47
|
readonly path: string;
|
|
36
48
|
readonly description: string;
|
|
@@ -46,7 +58,7 @@ type ToolNode<R> = {
|
|
|
46
58
|
namespace?: Namespace<R>;
|
|
47
59
|
readonly children: Map<string, ToolNode<R>>;
|
|
48
60
|
};
|
|
49
|
-
/** Tools indexed once per runtime
|
|
61
|
+
/** Tools indexed once per runtime, with discovery materialized on demand. */
|
|
50
62
|
export type Prepared<R = never> = {
|
|
51
63
|
readonly root: ToolNode<R>;
|
|
52
64
|
readonly catalog: ReadonlyArray<ToolDescription>;
|
|
@@ -59,12 +71,19 @@ export type SearchEntry = {
|
|
|
59
71
|
/** Exact callable signature of the built-in `search` function, for host-owned instructions. */
|
|
60
72
|
export declare const searchSignature: string;
|
|
61
73
|
export declare const prepare: <R>(tools: Tools<R>) => Prepared<R>;
|
|
74
|
+
export declare class ToolRuntimeError extends Error {
|
|
75
|
+
readonly kind: Extract<DiagnosticKind, "UnknownTool" | "InvalidToolInput" | "InvalidToolOutput" | "ToolCallLimitExceeded">;
|
|
76
|
+
readonly suggestions: ReadonlyArray<string>;
|
|
77
|
+
constructor(kind: Extract<DiagnosticKind, "UnknownTool" | "InvalidToolInput" | "InvalidToolOutput" | "ToolCallLimitExceeded">, message: string, suggestions?: ReadonlyArray<string>);
|
|
78
|
+
}
|
|
79
|
+
/** The tool bridge of one execution. Arguments arrive and results leave as JSON; program values never enter. */
|
|
62
80
|
export type ToolRuntime<R = never> = {
|
|
63
81
|
readonly calls: Array<ToolCall>;
|
|
64
|
-
readonly
|
|
65
|
-
readonly
|
|
82
|
+
readonly hooks: Hooks<R>;
|
|
83
|
+
readonly execute: (path: ReadonlyArray<string>, args: Array<Json | undefined>) => Effect.Effect<Json | undefined, unknown, R>;
|
|
84
|
+
readonly search: (args: Array<Json | undefined>) => Effect.Effect<Json | undefined, unknown, R>;
|
|
66
85
|
readonly keys: (path: ReadonlyArray<string>) => ReadonlyArray<string>;
|
|
67
86
|
};
|
|
68
87
|
/** Per-execution call state over tools prepared once for the runtime. */
|
|
69
|
-
export declare const make: <R>(prepared: Prepared<R>,
|
|
88
|
+
export declare const make: <R>(prepared: Prepared<R>, maxToolCalls: number | undefined, hooks?: Hooks<R>) => ToolRuntime<R>;
|
|
70
89
|
export * as ToolRuntime from "./tool-runtime.js";
|