@opencode/codemode 2.0.11 → 2.0.13
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/data.d.ts +5 -4
- package/dist/interpreter/callback.d.ts +11 -14
- package/dist/interpreter/callback.js +23 -7
- package/dist/interpreter/errors.d.ts +3 -3
- package/dist/interpreter/errors.js +2 -2
- package/dist/interpreter/execute.d.ts +2 -1
- package/dist/interpreter/extensions.d.ts +2 -1
- package/dist/interpreter/extensions.js +7 -35
- package/dist/interpreter/globals.d.ts +2 -1
- package/dist/interpreter/globals.js +1 -1
- package/dist/interpreter/interpreter.d.ts +9 -20
- package/dist/interpreter/interpreter.js +124 -122
- package/dist/interpreter/intrinsics.d.ts +4 -2
- package/dist/interpreter/intrinsics.js +12 -0
- package/dist/interpreter/model.d.ts +7 -8
- package/dist/interpreter/model.js +3 -3
- package/dist/interpreter/native.d.ts +5 -5
- package/dist/interpreter/objects.d.ts +148 -47
- package/dist/interpreter/objects.js +224 -26
- package/dist/interpreter/promises.d.ts +7 -7
- package/dist/interpreter/promises.js +32 -11
- package/dist/interpreter/references.d.ts +8 -7
- package/dist/interpreter/references.js +10 -46
- package/dist/interpreter/scope.d.ts +5 -4
- package/dist/stdlib/array.d.ts +2 -1
- package/dist/stdlib/array.js +37 -52
- package/dist/stdlib/bytes.js +14 -24
- package/dist/stdlib/collections.js +52 -30
- package/dist/stdlib/console.d.ts +2 -2
- package/dist/stdlib/console.js +6 -50
- package/dist/stdlib/date.js +6 -2
- package/dist/stdlib/headers.js +10 -22
- package/dist/stdlib/iterator.d.ts +1 -1
- package/dist/stdlib/iterator.js +294 -6
- package/dist/stdlib/json.js +3 -5
- package/dist/stdlib/math.js +5 -17
- package/dist/stdlib/number.js +9 -21
- package/dist/stdlib/object.d.ts +3 -4
- package/dist/stdlib/object.js +7 -18
- package/dist/stdlib/regexp.d.ts +3 -3
- package/dist/stdlib/regexp.js +1 -2
- package/dist/stdlib/string.js +12 -20
- package/dist/stdlib/url.d.ts +2 -1
- package/dist/stdlib/url.js +6 -16
- package/dist/stdlib/value.d.ts +0 -3
- package/dist/stdlib/value.js +2 -74
- package/dist/stdlib/web.js +1 -2
- package/dist/tool-runtime.d.ts +2 -0
- package/dist/tool-runtime.js +39 -27
- package/package.json +1 -1
package/dist/stdlib/json.js
CHANGED
|
@@ -2,10 +2,10 @@ import { Effect } from "effect";
|
|
|
2
2
|
import { methods } from "../interpreter/native.js";
|
|
3
3
|
import { applyCollectionCallback } from "../interpreter/callback.js";
|
|
4
4
|
import { checkStringLength } from "../interpreter/limits.js";
|
|
5
|
-
import { syntaxError
|
|
5
|
+
import { syntaxError } from "../interpreter/model.js";
|
|
6
6
|
import { typeofValue } from "../interpreter/references.js";
|
|
7
7
|
import { fromJson, toJson } from "../data.js";
|
|
8
|
-
import { get, keys, Arr, Obj, record, remove, set } from "../interpreter/objects.js";
|
|
8
|
+
import { get, keys, Arr, Obj, coerceToString, record, remove, set } from "../interpreter/objects.js";
|
|
9
9
|
export const jsonGlobal = (ctx) => {
|
|
10
10
|
const json = new Obj(ctx.builtins.Object);
|
|
11
11
|
methods(ctx.builtins, json, [
|
|
@@ -15,9 +15,7 @@ export const jsonGlobal = (ctx) => {
|
|
|
15
15
|
return json;
|
|
16
16
|
};
|
|
17
17
|
const parse = (ctx, args) => {
|
|
18
|
-
const text = args[0];
|
|
19
|
-
if (typeof text !== "string")
|
|
20
|
-
throw typeError("JSON.parse expects a string.");
|
|
18
|
+
const text = coerceToString(args[0]);
|
|
21
19
|
const parsed = (() => {
|
|
22
20
|
try {
|
|
23
21
|
return fromJson(ctx, JSON.parse(text));
|
package/dist/stdlib/math.js
CHANGED
|
@@ -1,32 +1,20 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { constants, methods } from "../interpreter/native.js";
|
|
3
3
|
import { typeError } from "../interpreter/model.js";
|
|
4
|
-
import { Obj } from "../interpreter/objects.js";
|
|
4
|
+
import { Obj, coerceToNumber } from "../interpreter/objects.js";
|
|
5
5
|
import { preserveConsumerError } from "../interpreter/callback.js";
|
|
6
6
|
// Validate only the arguments a method consumes; like JS, extras are ignored
|
|
7
7
|
// (so built-ins work as callbacks receiving (element, index, array)).
|
|
8
|
-
const
|
|
9
|
-
if (index >= args.length)
|
|
10
|
-
return Number.NaN;
|
|
11
|
-
const arg = args[index];
|
|
12
|
-
if (typeof arg !== "number")
|
|
13
|
-
throw typeError(`Math.${name} expects number arguments.`);
|
|
14
|
-
return arg;
|
|
15
|
-
};
|
|
16
|
-
const unary = (name, op) => [name, 1, (_, args) => op(number(name, args, 0))];
|
|
8
|
+
const unary = (name, op) => [name, 1, (_, args) => op(coerceToNumber(args[0]))];
|
|
17
9
|
const binary = (name, op) => [
|
|
18
10
|
name,
|
|
19
11
|
2,
|
|
20
|
-
(_, args) => op(
|
|
12
|
+
(_, args) => op(coerceToNumber(args[0]), coerceToNumber(args[1])),
|
|
21
13
|
];
|
|
22
14
|
const variadic = (name, op) => [
|
|
23
15
|
name,
|
|
24
16
|
2,
|
|
25
|
-
(_, args) => op(...args.map(
|
|
26
|
-
if (typeof arg !== "number")
|
|
27
|
-
throw typeError(`Math.${name} expects number arguments.`);
|
|
28
|
-
return arg;
|
|
29
|
-
})),
|
|
17
|
+
(_, args) => op(...args.map(coerceToNumber)),
|
|
30
18
|
];
|
|
31
19
|
export const mathGlobal = (ctx) => {
|
|
32
20
|
const builtins = ctx.builtins;
|
|
@@ -91,7 +79,7 @@ export const mathGlobal = (ctx) => {
|
|
|
91
79
|
const step = yield* cursor.next;
|
|
92
80
|
if (step.done)
|
|
93
81
|
return Math.sumPrecise(numbers);
|
|
94
|
-
yield* preserveConsumerError(cursor, Effect.sync(() => {
|
|
82
|
+
yield* preserveConsumerError(cursor.close, Effect.sync(() => {
|
|
95
83
|
if (typeof step.value !== "number") {
|
|
96
84
|
throw typeError("Math.sumPrecise expects an iterable of numbers.");
|
|
97
85
|
}
|
package/dist/stdlib/number.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { constructor, constants, methods } from "../interpreter/native.js";
|
|
2
|
+
import { coerceToNumber, coerceToString } from "../interpreter/objects.js";
|
|
2
3
|
import { rangeError, typeError } from "../interpreter/model.js";
|
|
3
|
-
import { coercion
|
|
4
|
+
import { coercion } from "./value.js";
|
|
4
5
|
export const numberGlobal = (ctx) => {
|
|
5
6
|
const builtins = ctx.builtins;
|
|
6
7
|
const number = constructor(builtins, builtins.Number, {
|
|
@@ -27,11 +28,7 @@ export const numberGlobal = (ctx) => {
|
|
|
27
28
|
"parseInt",
|
|
28
29
|
2,
|
|
29
30
|
(_, args) => {
|
|
30
|
-
|
|
31
|
-
if (radix !== undefined && typeof radix !== "number") {
|
|
32
|
-
throw typeError("Number.parseInt expects a numeric radix.");
|
|
33
|
-
}
|
|
34
|
-
return parseInt(coerceToString(args[0]), radix);
|
|
31
|
+
return parseInt(coerceToString(args[0]), coerceToNumber(args[1]));
|
|
35
32
|
},
|
|
36
33
|
],
|
|
37
34
|
["parseFloat", 1, (_, args) => parseFloat(coerceToString(args[0]))],
|
|
@@ -41,26 +38,17 @@ export const numberGlobal = (ctx) => {
|
|
|
41
38
|
return thisValue;
|
|
42
39
|
throw typeError(`Number.prototype.${name} requires that 'this' be a Number.`);
|
|
43
40
|
};
|
|
44
|
-
const optNum = (
|
|
45
|
-
if (arg === undefined)
|
|
46
|
-
return undefined;
|
|
47
|
-
if (typeof arg !== "number")
|
|
48
|
-
throw typeError(`Number.${name} expects a number argument.`);
|
|
49
|
-
return arg;
|
|
50
|
-
};
|
|
41
|
+
const optNum = (arg) => (arg === undefined ? undefined : coerceToNumber(arg));
|
|
51
42
|
methods(builtins, builtins.Number, [
|
|
52
|
-
["toFixed", 1, (thisValue, args) => self(thisValue, "toFixed").toFixed(optNum(
|
|
53
|
-
[
|
|
54
|
-
|
|
55
|
-
1,
|
|
56
|
-
(thisValue, args) => self(thisValue, "toExponential").toExponential(optNum("toExponential", args[0])),
|
|
57
|
-
],
|
|
43
|
+
["toFixed", 1, (thisValue, args) => self(thisValue, "toFixed").toFixed(optNum(args[0]))],
|
|
44
|
+
["toLocaleString", 0, (thisValue) => self(thisValue, "toLocaleString").toLocaleString("en-US")],
|
|
45
|
+
["toExponential", 1, (thisValue, args) => self(thisValue, "toExponential").toExponential(optNum(args[0]))],
|
|
58
46
|
[
|
|
59
47
|
"toPrecision",
|
|
60
48
|
1,
|
|
61
49
|
(thisValue, args) => {
|
|
62
50
|
const value = self(thisValue, "toPrecision");
|
|
63
|
-
const digits = optNum(
|
|
51
|
+
const digits = optNum(args[0]);
|
|
64
52
|
return digits === undefined ? value.toString() : value.toPrecision(digits);
|
|
65
53
|
},
|
|
66
54
|
],
|
|
@@ -69,7 +57,7 @@ export const numberGlobal = (ctx) => {
|
|
|
69
57
|
1,
|
|
70
58
|
(thisValue, args) => {
|
|
71
59
|
const value = self(thisValue, "toString");
|
|
72
|
-
const radix = optNum(
|
|
60
|
+
const radix = optNum(args[0]);
|
|
73
61
|
if (radix !== undefined && (radix < 2 || radix > 36)) {
|
|
74
62
|
throw rangeError("Number.toString radix must be between 2 and 36.");
|
|
75
63
|
}
|
package/dist/stdlib/object.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type AstNode } from "../interpreter/model.js";
|
|
2
|
-
import { Obj } from "../interpreter/objects.js";
|
|
2
|
+
import { Obj, type Value } from "../interpreter/objects.js";
|
|
3
3
|
import type { Interpreter } from "../interpreter/interpreter.js";
|
|
4
|
-
export declare const enumerableSource: <R>(ctx: Interpreter<R>, label: string, value:
|
|
5
|
-
export declare const objectAssign: <R>(ctx: Interpreter<R>, args: Array<
|
|
6
|
-
export declare const classTag: (value: unknown) => string;
|
|
4
|
+
export declare const enumerableSource: <R>(ctx: Interpreter<R>, label: string, value: Value, node?: AstNode) => Obj;
|
|
5
|
+
export declare const objectAssign: <R>(ctx: Interpreter<R>, args: Array<Value>) => Value;
|
|
7
6
|
export declare const objectGlobal: <R>(ctx: Interpreter<R>) => import("../interpreter/objects.js").Native<R>;
|
package/dist/stdlib/object.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { constructor, methods, receiver } from "../interpreter/native.js";
|
|
3
3
|
import { AsyncIteratorSymbol, invalidData, IteratorSymbol, rangeError, typeError, } from "../interpreter/model.js";
|
|
4
|
-
import {
|
|
4
|
+
import { define, entries, enumerableKeys, getOwn, hasOwn, hasPrototype, hidden, keys, own, Arr, Obj, PromiseObj, set, coerceToString, } from "../interpreter/objects.js";
|
|
5
5
|
import { containsOpaqueReference, describeValue, rejectCircularInsertion } from "../interpreter/references.js";
|
|
6
|
-
import { preserveConsumerError } from "../interpreter/callback.js";
|
|
6
|
+
import { invoke, preserveConsumerError } from "../interpreter/callback.js";
|
|
7
7
|
import { ToolReference } from "../tool-runtime.js";
|
|
8
8
|
import { groupBy } from "./collections.js";
|
|
9
|
-
import { coerceToString } from "./value.js";
|
|
10
9
|
// ToObject for enumeration.
|
|
11
10
|
export const enumerableSource = (ctx, label, value, node) => {
|
|
12
11
|
if (value === null || value === undefined) {
|
|
@@ -57,7 +56,7 @@ const objectFromEntries = (ctx, source) => {
|
|
|
57
56
|
const step = yield* cursor.next;
|
|
58
57
|
if (step.done)
|
|
59
58
|
return out;
|
|
60
|
-
yield* preserveConsumerError(cursor, Effect.sync(() => {
|
|
59
|
+
yield* preserveConsumerError(cursor.close, Effect.sync(() => {
|
|
61
60
|
if (!(step.value instanceof Obj) || containsOpaqueReference(step.value)) {
|
|
62
61
|
throw typeError("Object.fromEntries expects [key, value] entry objects.");
|
|
63
62
|
}
|
|
@@ -66,23 +65,13 @@ const objectFromEntries = (ctx, source) => {
|
|
|
66
65
|
}
|
|
67
66
|
});
|
|
68
67
|
};
|
|
69
|
-
|
|
68
|
+
const classTag = (value) => {
|
|
70
69
|
if (value === null)
|
|
71
70
|
return "Null";
|
|
72
71
|
if (value === undefined)
|
|
73
72
|
return "Undefined";
|
|
74
|
-
if (value instanceof
|
|
75
|
-
return
|
|
76
|
-
if (value instanceof Callable)
|
|
77
|
-
return "Function";
|
|
78
|
-
if (value instanceof ErrorObj)
|
|
79
|
-
return "Error";
|
|
80
|
-
if (value instanceof DateObj)
|
|
81
|
-
return "Date";
|
|
82
|
-
if (value instanceof RegExpObj)
|
|
83
|
-
return "RegExp";
|
|
84
|
-
if (value instanceof Bytes)
|
|
85
|
-
return "Uint8Array";
|
|
73
|
+
if (value instanceof Obj)
|
|
74
|
+
return value.tag;
|
|
86
75
|
if (typeof value === "string")
|
|
87
76
|
return "String";
|
|
88
77
|
if (typeof value === "number")
|
|
@@ -161,7 +150,7 @@ export const objectGlobal = (ctx) => {
|
|
|
161
150
|
true,
|
|
162
151
|
],
|
|
163
152
|
["toString", 0, (thisValue) => `[object ${classTag(thisValue)}]`],
|
|
164
|
-
["toLocaleString", 0, (thisValue) =>
|
|
153
|
+
["toLocaleString", 0, (thisValue) => invoke(ctx, thisValue, "toString", "Object.prototype.toLocaleString")],
|
|
165
154
|
[
|
|
166
155
|
"valueOf",
|
|
167
156
|
0,
|
package/dist/stdlib/regexp.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Builtins } from "../interpreter/intrinsics.js";
|
|
2
|
-
import { Arr, Obj, RegExpObj } from "../interpreter/objects.js";
|
|
2
|
+
import { Arr, Obj, RegExpObj, type Value } from "../interpreter/objects.js";
|
|
3
3
|
import type { Interpreter } from "../interpreter/interpreter.js";
|
|
4
|
-
export declare const toHostRegex: (arg:
|
|
4
|
+
export declare const toHostRegex: (arg: Value, method: string, extraFlags?: string) => RegExp;
|
|
5
5
|
export declare const matchToValue: (builtins: Builtins, match: RegExpMatchArray) => Arr;
|
|
6
|
-
export declare const constructRegExp: (builtins: Builtins, args: Array<
|
|
6
|
+
export declare const constructRegExp: (builtins: Builtins, args: Array<Value>, proto?: Obj) => RegExpObj;
|
|
7
7
|
export declare const regexpGlobal: <R>(ctx: Interpreter<R>) => import("../interpreter/objects.js").Native<R>;
|
package/dist/stdlib/regexp.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { constructor, methods, prototypeFrom, receiver } from "../interpreter/native.js";
|
|
3
3
|
import { syntaxError, typeError } from "../interpreter/model.js";
|
|
4
|
-
import { define, defineAccessor, Arr, Obj, RegExpObj, record } from "../interpreter/objects.js";
|
|
5
|
-
import { coerceToNumber, coerceToString } from "./value.js";
|
|
4
|
+
import { define, defineAccessor, Arr, Obj, RegExpObj, record, coerceToNumber, coerceToString, } from "../interpreter/objects.js";
|
|
6
5
|
const flagProperties = [
|
|
7
6
|
"hasIndices",
|
|
8
7
|
"global",
|
package/dist/stdlib/string.js
CHANGED
|
@@ -2,11 +2,11 @@ import { Effect } from "effect";
|
|
|
2
2
|
import { constructor, fn, methods } from "../interpreter/native.js";
|
|
3
3
|
import { checkArrayLength, checkStringLength } from "../interpreter/limits.js";
|
|
4
4
|
import { invalidData, IteratorSymbol, rangeError, typeError } from "../interpreter/model.js";
|
|
5
|
-
import { define, hidden, Arr,
|
|
5
|
+
import { define, hidden, Arr, hostIterator, RegExpObj, record, coerceToNumber, coerceToString, } from "../interpreter/objects.js";
|
|
6
6
|
import { containsOpaqueReference, typeofValue } from "../interpreter/references.js";
|
|
7
7
|
import { applyCollectionCallback, isSupportedCallback } from "../interpreter/callback.js";
|
|
8
8
|
import { matchToValue, toHostRegex } from "./regexp.js";
|
|
9
|
-
import {
|
|
9
|
+
import { coercion } from "./value.js";
|
|
10
10
|
// console is intercepted by the interpreter before reaching here.
|
|
11
11
|
const requireDataArgument = (name, index, arg) => {
|
|
12
12
|
if (containsOpaqueReference(arg)) {
|
|
@@ -23,17 +23,16 @@ const replaceWithCallback = (ctx, value, name, args) => {
|
|
|
23
23
|
const builtins = ctx.builtins;
|
|
24
24
|
const apply = applyCollectionCallback(ctx, args[1], `String.${name}`);
|
|
25
25
|
const matches = [];
|
|
26
|
+
// The host calls back with (match, ...captures, offset, string, groups?); only groups is not already a Value.
|
|
26
27
|
const collect = (...callbackArgs) => {
|
|
27
28
|
const match = callbackArgs[0];
|
|
28
|
-
const
|
|
29
|
-
const hasGroups = groups !== null && typeof groups === "object";
|
|
29
|
+
const hasGroups = typeof callbackArgs.at(-1) === "object";
|
|
30
30
|
const offset = callbackArgs[callbackArgs.length - (hasGroups ? 3 : 2)];
|
|
31
31
|
if (typeof match !== "string" || typeof offset !== "number") {
|
|
32
32
|
throw typeError(`String.${name} produced an invalid replacement match.`);
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
matches.push({ match, offset, args: callbackArgs });
|
|
34
|
+
const args = callbackArgs.map((arg) => (typeof arg === "object" ? record(builtins.Object, arg) : arg));
|
|
35
|
+
matches.push({ match, offset, args });
|
|
37
36
|
return match;
|
|
38
37
|
};
|
|
39
38
|
const pattern = args[0];
|
|
@@ -57,7 +56,7 @@ const replaceWithCallback = (ctx, value, name, args) => {
|
|
|
57
56
|
let end = 0;
|
|
58
57
|
for (const match of matches) {
|
|
59
58
|
const replacement = yield* apply(match.args);
|
|
60
|
-
output.push(value.slice(end, match.offset),
|
|
59
|
+
output.push(value.slice(end, match.offset), coerceToString(replacement));
|
|
61
60
|
end = match.offset + match.match.length;
|
|
62
61
|
}
|
|
63
62
|
output.push(value.slice(end));
|
|
@@ -74,12 +73,7 @@ export const stringGlobal = (ctx) => {
|
|
|
74
73
|
const codeUnits = (name, op) => [
|
|
75
74
|
name,
|
|
76
75
|
1,
|
|
77
|
-
(_, args) => op(...args.map(
|
|
78
|
-
if (typeof arg !== "number") {
|
|
79
|
-
throw typeError(`String.${name} expects number arguments.`);
|
|
80
|
-
}
|
|
81
|
-
return arg;
|
|
82
|
-
})),
|
|
76
|
+
(_, args) => op(...args.map(coerceToNumber)),
|
|
83
77
|
];
|
|
84
78
|
methods(builtins, string, [
|
|
85
79
|
codeUnits("fromCharCode", String.fromCharCode),
|
|
@@ -103,11 +97,7 @@ export const stringGlobal = (ctx) => {
|
|
|
103
97
|
throw typeError(`String.${name} cannot take a regular expression; use regex.test(string) or String.search instead.`);
|
|
104
98
|
}
|
|
105
99
|
};
|
|
106
|
-
const simple = (name, length, op) => [
|
|
107
|
-
name,
|
|
108
|
-
length,
|
|
109
|
-
(thisValue, args) => op(self(thisValue, name), args),
|
|
110
|
-
];
|
|
100
|
+
const simple = (name, length, op) => [name, length, (thisValue, args) => op(self(thisValue, name), args)];
|
|
111
101
|
const replace = (name) => simple(name, 2, (value, args) => {
|
|
112
102
|
if (isSupportedCallback(args[1]))
|
|
113
103
|
return replaceWithCallback(ctx, value, name, args);
|
|
@@ -130,6 +120,8 @@ export const stringGlobal = (ctx) => {
|
|
|
130
120
|
simple("valueOf", 0, (value) => value),
|
|
131
121
|
simple("toLowerCase", 0, (value) => value.toLowerCase()),
|
|
132
122
|
simple("toUpperCase", 0, (value) => value.toUpperCase()),
|
|
123
|
+
simple("toLocaleLowerCase", 0, (value) => value.toLowerCase()),
|
|
124
|
+
simple("toLocaleUpperCase", 0, (value) => value.toUpperCase()),
|
|
133
125
|
simple("trim", 0, (value) => value.trim()),
|
|
134
126
|
simple("trimStart", 0, (value) => value.trimStart()),
|
|
135
127
|
simple("trimLeft", 0, (value) => value.trimStart()),
|
|
@@ -232,6 +224,6 @@ export const stringGlobal = (ctx) => {
|
|
|
232
224
|
return joined;
|
|
233
225
|
}),
|
|
234
226
|
]);
|
|
235
|
-
define(builtins.String, IteratorSymbol, fn(builtins, "[Symbol.iterator]", 0, (thisValue) =>
|
|
227
|
+
define(builtins.String, IteratorSymbol, fn(builtins, "[Symbol.iterator]", 0, (thisValue) => hostIterator(builtins, self(thisValue, "[Symbol.iterator]")[Symbol.iterator]())), hidden);
|
|
236
228
|
return string;
|
|
237
229
|
};
|
package/dist/stdlib/url.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
+
import { type Value } from "../interpreter/objects.js";
|
|
2
3
|
import type { Interpreter } from "../interpreter/interpreter.js";
|
|
3
4
|
type UriFunction = "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent";
|
|
4
5
|
export declare const uriGlobal: <R>(ctx: Interpreter<R>, name: UriFunction) => import("../interpreter/objects.js").Native<R>;
|
|
@@ -7,6 +8,6 @@ export declare const urlGlobal: <R>(ctx: Interpreter<R>) => import("../interpret
|
|
|
7
8
|
* Reads a synchronous iterable of `[name, value]` pairs as strings; `undefined` when `init` is not iterable. As in
|
|
8
9
|
* WebIDL, the whole sequence is converted before any pair's length is checked.
|
|
9
10
|
*/
|
|
10
|
-
export declare const readPairs: <R>(ctx: Interpreter<R>, init:
|
|
11
|
+
export declare const readPairs: <R>(ctx: Interpreter<R>, init: Value, label: string) => Effect.Effect<Array<[string, string]> | undefined, unknown, R>;
|
|
11
12
|
export declare const urlSearchParamsGlobal: <R>(ctx: Interpreter<R>) => import("../interpreter/objects.js").Native<R>;
|
|
12
13
|
export {};
|
package/dist/stdlib/url.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { constructor, fn, methods, prototypeFrom, receiver, requiresNew } from "../interpreter/native.js";
|
|
3
3
|
import { IteratorSymbol, PendingThrow, typeError, uriError } from "../interpreter/model.js";
|
|
4
|
-
import { define, defineAccessor, entries, get, hidden,
|
|
5
|
-
import { isRuntimeReference } from "../interpreter/references.js";
|
|
4
|
+
import { define, defineAccessor, entries, get, hidden, Arr, hostIterator, Obj, URLObj, URLSearchParamsObj, coerceToString, isRuntimeReference, } from "../interpreter/objects.js";
|
|
6
5
|
import { applyCollectionCallback, preserveConsumerError } from "../interpreter/callback.js";
|
|
7
|
-
import { coerceToString } from "./value.js";
|
|
8
6
|
const urlProperties = [
|
|
9
7
|
"href",
|
|
10
8
|
"origin",
|
|
@@ -107,7 +105,7 @@ const readPair = (ctx, value, label) => Effect.gen(function* () {
|
|
|
107
105
|
const step = yield* cursor.next;
|
|
108
106
|
if (step.done)
|
|
109
107
|
return items;
|
|
110
|
-
items.push(yield* preserveConsumerError(cursor, Effect.sync(() => coerceToString(step.value))));
|
|
108
|
+
items.push(yield* preserveConsumerError(cursor.close, Effect.sync(() => coerceToString(step.value))));
|
|
111
109
|
}
|
|
112
110
|
});
|
|
113
111
|
/**
|
|
@@ -126,7 +124,7 @@ export const readPairs = (ctx, init, label) => Effect.gen(function* () {
|
|
|
126
124
|
throw typeError(`${label} expects iterable [name, value] pairs.`);
|
|
127
125
|
return pairs;
|
|
128
126
|
}
|
|
129
|
-
pairs.push(yield* preserveConsumerError(cursor, readPair(ctx, step.value, label)));
|
|
127
|
+
pairs.push(yield* preserveConsumerError(cursor.close, readPair(ctx, step.value, label)));
|
|
130
128
|
}
|
|
131
129
|
});
|
|
132
130
|
const constructURLSearchParams = (ctx, init, proto) => {
|
|
@@ -147,8 +145,6 @@ const constructURLSearchParams = (ctx, init, proto) => {
|
|
|
147
145
|
if (isRuntimeReference(init)) {
|
|
148
146
|
throw typeError("new URLSearchParams(...) expects a query string, data object, or synchronous iterable pairs.");
|
|
149
147
|
}
|
|
150
|
-
if (isWrapper(init))
|
|
151
|
-
return wrap(new URLSearchParams());
|
|
152
148
|
if (!(init instanceof Obj)) {
|
|
153
149
|
throw typeError("new URLSearchParams(...) expects a query string, data object, iterable pairs, or URLSearchParams.");
|
|
154
150
|
}
|
|
@@ -237,15 +233,9 @@ export const urlSearchParamsGlobal = (ctx) => {
|
|
|
237
233
|
return undefined;
|
|
238
234
|
},
|
|
239
235
|
],
|
|
240
|
-
["keys", 0, (thisValue) =>
|
|
241
|
-
["values", 0, (thisValue) =>
|
|
242
|
-
[
|
|
243
|
-
"entries",
|
|
244
|
-
0,
|
|
245
|
-
(thisValue) => new IteratorObj(builtins.Iterator, self(thisValue, "entries")
|
|
246
|
-
.params.entries()
|
|
247
|
-
.map(([key, value]) => wrap([key, value]))),
|
|
248
|
-
],
|
|
236
|
+
["keys", 0, (thisValue) => hostIterator(builtins, self(thisValue, "keys").params.keys())],
|
|
237
|
+
["values", 0, (thisValue) => hostIterator(builtins, self(thisValue, "values").params.values())],
|
|
238
|
+
["entries", 0, (thisValue) => hostIterator(builtins, self(thisValue, "entries").iterator(builtins))],
|
|
249
239
|
["toString", 0, (thisValue) => self(thisValue, "toString").params.toString()],
|
|
250
240
|
[
|
|
251
241
|
"forEach",
|
package/dist/stdlib/value.d.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { type Native } from "../interpreter/objects.js";
|
|
2
2
|
import type { Interpreter } from "../interpreter/interpreter.js";
|
|
3
3
|
export declare const compoundOperators: Set<string>;
|
|
4
|
-
/** The built-in string form of a value, without consulting program-defined `toString` methods. */
|
|
5
|
-
export declare const coerceToString: (value: unknown) => string;
|
|
6
|
-
export declare const coerceToNumber: (value: unknown) => number;
|
|
7
4
|
export type Coercion = "Number" | "String" | "Boolean" | "parseInt" | "parseFloat" | "isFinite" | "isNaN";
|
|
8
5
|
/** A global coercion function such as `Number` or `parseInt`. */
|
|
9
6
|
export declare const coercion: <R>(ctx: Interpreter<R>, name: Coercion, length?: number) => Native<R>;
|
package/dist/stdlib/value.js
CHANGED
|
@@ -1,59 +1,6 @@
|
|
|
1
1
|
import { fn } from "../interpreter/native.js";
|
|
2
|
-
import {
|
|
3
|
-
import { get, isWrapper, Arr, Bytes, DateObj, ErrorObj, MapObj, RegExpObj, SetObj, URLObj, URLSearchParamsObj, HeadersObj, } from "../interpreter/objects.js";
|
|
2
|
+
import { coerceToNumber, coerceToString } from "../interpreter/objects.js";
|
|
4
3
|
export const compoundOperators = new Set(["+=", "-=", "*=", "/=", "%=", "**=", "&=", "|=", "^=", "<<=", ">>=", ">>>="]);
|
|
5
|
-
/** The built-in string form of a value, without consulting program-defined `toString` methods. */
|
|
6
|
-
export const coerceToString = (value) => {
|
|
7
|
-
if (value === null)
|
|
8
|
-
return "null";
|
|
9
|
-
if (value === undefined)
|
|
10
|
-
return "undefined";
|
|
11
|
-
if (value instanceof DateObj)
|
|
12
|
-
return Number.isFinite(value.time) ? new Date(value.time).toISOString() : "Invalid Date";
|
|
13
|
-
if (value instanceof RegExpObj)
|
|
14
|
-
return `/${value.regex.source}/${value.regex.flags}`;
|
|
15
|
-
if (value instanceof MapObj)
|
|
16
|
-
return "[object Map]";
|
|
17
|
-
if (value instanceof SetObj)
|
|
18
|
-
return "[object Set]";
|
|
19
|
-
if (value instanceof URLObj)
|
|
20
|
-
return value.url.href;
|
|
21
|
-
if (value instanceof URLSearchParamsObj)
|
|
22
|
-
return value.params.toString();
|
|
23
|
-
if (value instanceof HeadersObj)
|
|
24
|
-
return "[object Headers]";
|
|
25
|
-
if (value instanceof Bytes)
|
|
26
|
-
return value.bytes.join(",");
|
|
27
|
-
if (value instanceof ErrorObj) {
|
|
28
|
-
// Match Error.prototype.toString: "name: message", or just one when the other is empty.
|
|
29
|
-
const name = get(value, "name");
|
|
30
|
-
const message = get(value, "message");
|
|
31
|
-
const shownName = typeof name === "string" ? name : "Error";
|
|
32
|
-
const shownMessage = typeof message === "string" ? message : "";
|
|
33
|
-
if (shownMessage === "")
|
|
34
|
-
return shownName;
|
|
35
|
-
if (shownName === "")
|
|
36
|
-
return shownMessage;
|
|
37
|
-
return `${shownName}: ${shownMessage}`;
|
|
38
|
-
}
|
|
39
|
-
if (value instanceof Arr) {
|
|
40
|
-
return value.items.map((item) => (item === null || item === undefined ? "" : coerceToString(item))).join(",");
|
|
41
|
-
}
|
|
42
|
-
if (typeof value === "object")
|
|
43
|
-
return "[object Object]";
|
|
44
|
-
return String(value);
|
|
45
|
-
};
|
|
46
|
-
export const coerceToNumber = (value) => {
|
|
47
|
-
if (value instanceof DateObj)
|
|
48
|
-
return value.time;
|
|
49
|
-
if (value instanceof Bytes)
|
|
50
|
-
return Number(coerceToString(value));
|
|
51
|
-
if (isWrapper(value))
|
|
52
|
-
return Number.NaN;
|
|
53
|
-
if (value instanceof Arr)
|
|
54
|
-
return Number(coerceToString(value));
|
|
55
|
-
return value !== null && typeof value === "object" ? Number.NaN : Number(value);
|
|
56
|
-
};
|
|
57
4
|
const coerce = (ctx, name, args) => {
|
|
58
5
|
// Native: Number() is 0 and String() is "", unlike their undefined-argument forms; the
|
|
59
6
|
// other coercers match native through the undefined-argument path below.
|
|
@@ -64,21 +11,6 @@ const coerce = (ctx, name, args) => {
|
|
|
64
11
|
return "";
|
|
65
12
|
}
|
|
66
13
|
const raw = args[0];
|
|
67
|
-
if (isWrapper(raw)) {
|
|
68
|
-
if (name === "Boolean")
|
|
69
|
-
return true;
|
|
70
|
-
if (name === "Number")
|
|
71
|
-
return coerceToNumber(raw);
|
|
72
|
-
if (name === "String")
|
|
73
|
-
return coerceToString(raw);
|
|
74
|
-
if (name === "isFinite")
|
|
75
|
-
return Number.isFinite(coerceToNumber(raw));
|
|
76
|
-
if (name === "isNaN")
|
|
77
|
-
return Number.isNaN(coerceToNumber(raw));
|
|
78
|
-
if (name === "parseInt")
|
|
79
|
-
return parseInt(coerceToString(raw));
|
|
80
|
-
return parseFloat(coerceToString(raw));
|
|
81
|
-
}
|
|
82
14
|
if (name === "Number")
|
|
83
15
|
return coerceToNumber(raw);
|
|
84
16
|
if (name === "Boolean")
|
|
@@ -88,11 +20,7 @@ const coerce = (ctx, name, args) => {
|
|
|
88
20
|
if (name === "isNaN")
|
|
89
21
|
return Number.isNaN(coerceToNumber(raw));
|
|
90
22
|
if (name === "parseInt") {
|
|
91
|
-
|
|
92
|
-
if (radix !== undefined && typeof radix !== "number") {
|
|
93
|
-
throw typeError("parseInt expects a numeric radix.");
|
|
94
|
-
}
|
|
95
|
-
return parseInt(coerceToString(raw), radix);
|
|
23
|
+
return parseInt(coerceToString(raw), coerceToNumber(args[1]));
|
|
96
24
|
}
|
|
97
25
|
if (name === "parseFloat")
|
|
98
26
|
return parseFloat(coerceToString(raw));
|
package/dist/stdlib/web.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { fn, methods } from "../interpreter/native.js";
|
|
2
2
|
import { typeError } from "../interpreter/model.js";
|
|
3
|
-
import { Bytes, Obj } from "../interpreter/objects.js";
|
|
3
|
+
import { Bytes, Obj, coerceToString } from "../interpreter/objects.js";
|
|
4
4
|
import { describeValue } from "../interpreter/references.js";
|
|
5
|
-
import { coerceToString } from "./value.js";
|
|
6
5
|
// WebIDL DOMString conversion: a missing argument is a TypeError, anything else stringifies. Invalid input is a
|
|
7
6
|
// TypeError as well; browsers throw a DOMException named InvalidCharacterError, which CodeMode does not have.
|
|
8
7
|
export const base64Global = (ctx, name) => fn(ctx.builtins, name, 1, (_, args) => {
|
package/dist/tool-runtime.d.ts
CHANGED
|
@@ -66,6 +66,8 @@ export type Prepared<R = never> = {
|
|
|
66
66
|
};
|
|
67
67
|
export type SearchEntry = {
|
|
68
68
|
readonly description: ToolDescription;
|
|
69
|
+
/** The path split into words, so `zones` matches `get_zones` as a word rather than as a substring of `timezones`. */
|
|
70
|
+
readonly pathWords: ReadonlyArray<string>;
|
|
69
71
|
readonly searchText: string;
|
|
70
72
|
};
|
|
71
73
|
/** Exact callable signature of the built-in `search` function, for host-owned instructions. */
|
package/dist/tool-runtime.js
CHANGED
|
@@ -90,7 +90,7 @@ const describeTool = (visible) => {
|
|
|
90
90
|
// Joining the final fragments avoids retaining the rendering's intermediate string ropes in JSC.
|
|
91
91
|
return (signature ??= [
|
|
92
92
|
toolExpression(visible.path),
|
|
93
|
-
isEmptyInput(visible.tool) ? "()" : `(
|
|
93
|
+
isEmptyInput(visible.tool) ? "()" : `(${inputTypeScript(visible.tool, true)})`,
|
|
94
94
|
`: Promise<${outputTypeScript(visible.tool, true)}>`,
|
|
95
95
|
].join(""));
|
|
96
96
|
},
|
|
@@ -109,6 +109,24 @@ const termForms = (term) => {
|
|
|
109
109
|
forms.push(term.slice(0, -1));
|
|
110
110
|
return forms;
|
|
111
111
|
};
|
|
112
|
+
const rank = (entries, query) => {
|
|
113
|
+
const terms = tokenize(query).map(termForms);
|
|
114
|
+
return entries
|
|
115
|
+
.map((entry) => {
|
|
116
|
+
const path = entry.description.path.toLowerCase();
|
|
117
|
+
const description = entry.description.description.toLowerCase();
|
|
118
|
+
const score = terms.reduce((total, forms) => total +
|
|
119
|
+
(forms.some((form) => path === form || path.endsWith(`.${form}`)) ? 20 : 0) +
|
|
120
|
+
(forms.some((form) => entry.pathWords.includes(form)) ? 12 : 0) +
|
|
121
|
+
(forms.some((form) => path.includes(form)) ? 8 : 0) +
|
|
122
|
+
(forms.some((form) => description.includes(form)) ? 4 : 0) +
|
|
123
|
+
(forms.some((form) => entry.searchText.includes(form)) ? 2 : 0), 0);
|
|
124
|
+
return { entry, score };
|
|
125
|
+
})
|
|
126
|
+
.filter(({ score }) => terms.length === 0 || score > 0)
|
|
127
|
+
.sort((left, right) => right.score - left.score || compareText(left.entry.description.path, right.entry.description.path))
|
|
128
|
+
.map(({ entry }) => entry);
|
|
129
|
+
};
|
|
112
130
|
const makeSearchTool = (searchIndex) => ({
|
|
113
131
|
_tag: "CodeModeTool",
|
|
114
132
|
description: "Search available tools",
|
|
@@ -118,32 +136,22 @@ const makeSearchTool = (searchIndex) => ({
|
|
|
118
136
|
const request = input;
|
|
119
137
|
const query = request.query ?? "";
|
|
120
138
|
const offset = request.offset ?? 0;
|
|
121
|
-
|
|
139
|
+
let ns = request.namespace;
|
|
140
|
+
if (ns !== undefined && !searchIndex.some((entry) => entry.description.path.startsWith("tools."))) {
|
|
141
|
+
if (ns === "tools")
|
|
142
|
+
ns = undefined;
|
|
143
|
+
else if (ns.startsWith("tools."))
|
|
144
|
+
ns = ns.slice("tools.".length);
|
|
145
|
+
}
|
|
146
|
+
const scoped = ns === undefined
|
|
122
147
|
? searchIndex
|
|
123
|
-
: searchIndex.filter((entry) => entry.description.path ===
|
|
124
|
-
entry.description.path.startsWith(`${request.namespace}.`));
|
|
148
|
+
: searchIndex.filter((entry) => entry.description.path === ns || entry.description.path.startsWith(`${ns}.`));
|
|
125
149
|
const trimmed = query.trim();
|
|
126
150
|
const pathQuery = trimmed.startsWith("tools.") ? trimmed.slice("tools.".length) : trimmed;
|
|
127
151
|
const exact = pathQuery === ""
|
|
128
152
|
? undefined
|
|
129
153
|
: scoped.find((entry) => entry.description.path === pathQuery || toolExpression(entry.description.path) === trimmed);
|
|
130
|
-
const
|
|
131
|
-
const ranked = exact !== undefined
|
|
132
|
-
? [exact]
|
|
133
|
-
: scoped
|
|
134
|
-
.map((entry) => {
|
|
135
|
-
const path = entry.description.path.toLowerCase();
|
|
136
|
-
const description = entry.description.description.toLowerCase();
|
|
137
|
-
const score = terms.reduce((total, forms) => total +
|
|
138
|
-
(forms.some((form) => path === form || path.endsWith(`.${form}`)) ? 20 : 0) +
|
|
139
|
-
(forms.some((form) => path.includes(form)) ? 8 : 0) +
|
|
140
|
-
(forms.some((form) => description.includes(form)) ? 4 : 0) +
|
|
141
|
-
(forms.some((form) => entry.searchText.includes(form)) ? 2 : 0), 0);
|
|
142
|
-
return { entry, score };
|
|
143
|
-
})
|
|
144
|
-
.filter(({ score }) => terms.length === 0 || score > 0)
|
|
145
|
-
.sort((left, right) => right.score - left.score || compareText(left.entry.description.path, right.entry.description.path))
|
|
146
|
-
.map(({ entry }) => entry);
|
|
154
|
+
const ranked = exact !== undefined ? [exact] : rank(scoped, query);
|
|
147
155
|
const items = ranked.slice(offset, offset + (request.limit ?? defaultSearchLimit)).map(({ description }) => ({
|
|
148
156
|
...description,
|
|
149
157
|
path: toolExpression(description.path),
|
|
@@ -159,10 +167,11 @@ const makeSearchTool = (searchIndex) => ({
|
|
|
159
167
|
/** Exact callable signature of the built-in `search` function, for host-owned instructions. */
|
|
160
168
|
export const searchSignature = (() => {
|
|
161
169
|
const tool = makeSearchTool([]);
|
|
162
|
-
return `search(
|
|
170
|
+
return `search(${inputTypeScript(tool, true)}): ${outputTypeScript(tool, true)}`;
|
|
163
171
|
})();
|
|
164
172
|
const toSearchEntry = (visible) => ({
|
|
165
173
|
description: describeTool(visible),
|
|
174
|
+
pathWords: tokenize(visible.path),
|
|
166
175
|
searchText: [
|
|
167
176
|
visible.path,
|
|
168
177
|
visible.tool.description,
|
|
@@ -199,13 +208,16 @@ const namespaceKeys = (root, path) => {
|
|
|
199
208
|
}
|
|
200
209
|
return Array.from(node.children.keys());
|
|
201
210
|
};
|
|
202
|
-
const resolve = (root, path) => {
|
|
211
|
+
const resolve = (root, path, index) => {
|
|
203
212
|
const segments = canonicalSegments(path);
|
|
204
213
|
const node = lookup(root, segments);
|
|
205
214
|
if (node === undefined) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
]
|
|
215
|
+
const name = segments.join(".");
|
|
216
|
+
const ns = segments.length > 1 && root.children.has(segments[0]) ? segments[0] : undefined;
|
|
217
|
+
const closest = rank(ns ? index.filter((entry) => entry.description.path.startsWith(`${ns}.`)) : index, ns ? segments.slice(1).join(" ") : name)[0];
|
|
218
|
+
throw new ToolRuntimeError("UnknownTool", closest
|
|
219
|
+
? `Unknown tool '${name}'. Did you mean ${toolExpression(closest.description.path)}?`
|
|
220
|
+
: `Unknown tool '${name}'.`, ["Use search to find available tools."]);
|
|
209
221
|
}
|
|
210
222
|
if (node.tool === undefined) {
|
|
211
223
|
throw new ToolRuntimeError("UnknownTool", `Tool '${segments.join(".")}' is not callable.`);
|
|
@@ -269,7 +281,7 @@ export const make = (prepared, maxToolCalls, hooks = {}) => {
|
|
|
269
281
|
// Models often write `tools.search(...)` for the bare `search(...)`; honor it unless a tool owns that path.
|
|
270
282
|
if (segments.length === 1 && segments[0] === "search" && lookup(root, segments) === undefined)
|
|
271
283
|
return executeTool("search", makeSearchTool(prepared.searchIndex), args);
|
|
272
|
-
return executeTool(segments.join("."), resolve(root, path), args);
|
|
284
|
+
return executeTool(segments.join("."), resolve(root, path, prepared.searchIndex), args);
|
|
273
285
|
}),
|
|
274
286
|
};
|
|
275
287
|
};
|