@opencode/codemode 0.0.0-dev-19435 → 0.0.0-dev-19437
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.d.ts +1 -1
- package/dist/codemode.js +1 -1
- package/dist/interpreter/promises.d.ts +3 -0
- package/dist/interpreter/promises.js +13 -16
- package/dist/interpreter/runtime.js +29 -68
- package/dist/stdlib/object.js +6 -16
- package/package.json +1 -1
package/dist/codemode.d.ts
CHANGED
|
@@ -136,7 +136,7 @@ export declare const Result: Schema.Union<readonly [Schema.Struct<{
|
|
|
136
136
|
export type Result = typeof Result.Type;
|
|
137
137
|
/** Reusable confined runtime over explicit tools. */
|
|
138
138
|
export type Runtime<R = never> = {
|
|
139
|
-
readonly catalog:
|
|
139
|
+
readonly catalog: ReadonlyArray<ToolDescription>;
|
|
140
140
|
readonly execute: (code: string) => Effect.Effect<Result, never, R>;
|
|
141
141
|
};
|
|
142
142
|
/** Executes one Effect-native CodeMode program without constructing a reusable runtime. */
|
package/dist/codemode.js
CHANGED
|
@@ -60,7 +60,7 @@ export const make = (options = {}) => {
|
|
|
60
60
|
const prepared = ToolRuntime.prepare((options.tools ?? {}));
|
|
61
61
|
const limits = resolveExecutionLimits(options.limits);
|
|
62
62
|
return {
|
|
63
|
-
catalog:
|
|
63
|
+
catalog: prepared.catalog,
|
|
64
64
|
execute: (code) => executeProgram(code, prepared, limits, options),
|
|
65
65
|
};
|
|
66
66
|
};
|
|
@@ -12,6 +12,9 @@ export declare class PromiseRuntime<R> {
|
|
|
12
12
|
private readonly failures;
|
|
13
13
|
private nextID;
|
|
14
14
|
constructor(scope: Scope.Scope);
|
|
15
|
+
createWithSelf(body: (self: {
|
|
16
|
+
promise?: Values.Promise;
|
|
17
|
+
}) => Effect.Effect<unknown, unknown, R>): Effect.Effect<Values.Promise, never, R>;
|
|
15
18
|
create(effect: Effect.Effect<unknown, unknown, R>): Effect.Effect<Values.Promise, never, R>;
|
|
16
19
|
markObserved(promise: Values.Promise): void;
|
|
17
20
|
await(promise: Values.Promise): Effect.Effect<Exit.Exit<unknown, unknown>>;
|
|
@@ -22,6 +22,14 @@ export class PromiseRuntime {
|
|
|
22
22
|
constructor(scope) {
|
|
23
23
|
this.scope = scope;
|
|
24
24
|
}
|
|
25
|
+
// Resolution bodies need the promise's own identity to reject `resolve(promise)` self-resolution.
|
|
26
|
+
createWithSelf(body) {
|
|
27
|
+
const self = {};
|
|
28
|
+
return Effect.map(this.create(body(self)), (promise) => {
|
|
29
|
+
self.promise = promise;
|
|
30
|
+
return promise;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
25
33
|
create(effect) {
|
|
26
34
|
return Effect.suspend(() => {
|
|
27
35
|
// Allocate before forking so reruns get distinct IDs and diagnostics retain creation order.
|
|
@@ -103,11 +111,7 @@ export const resolvePromiseValue = (runner, value, node, own) => {
|
|
|
103
111
|
export const resolvePromise = (runner, promises, value, node) => {
|
|
104
112
|
if (value instanceof Values.Promise)
|
|
105
113
|
return Effect.succeed(value);
|
|
106
|
-
|
|
107
|
-
return Effect.map(promises.create(resolvePromiseValue(runner, value, node, box)), (promise) => {
|
|
108
|
-
box.promise = promise;
|
|
109
|
-
return promise;
|
|
110
|
-
});
|
|
114
|
+
return promises.createWithSelf((self) => resolvePromiseValue(runner, value, node, self));
|
|
111
115
|
};
|
|
112
116
|
const promiseStatics = ["all", "allSettled", "race", "any", "resolve", "reject"];
|
|
113
117
|
const invokePromiseMethod = (runner, promises, name, args, node) => {
|
|
@@ -184,9 +188,7 @@ const constructPromise = (runner, promises, executor, node) => {
|
|
|
184
188
|
}
|
|
185
189
|
return Effect.gen(function* () {
|
|
186
190
|
const deferred = Deferred.makeUnsafe();
|
|
187
|
-
const
|
|
188
|
-
const promise = yield* promises.create(Effect.flatMap(Deferred.await(deferred), (value) => resolvePromiseValue(runner, value, node, box)));
|
|
189
|
-
box.promise = promise;
|
|
191
|
+
const promise = yield* promises.createWithSelf((self) => Effect.flatMap(Deferred.await(deferred), (value) => resolvePromiseValue(runner, value, node, self)));
|
|
190
192
|
const resolve = capability("resolve", (value) => Deferred.doneUnsafe(deferred, Exit.succeed(value)));
|
|
191
193
|
const reject = capability("reject", (value) => Deferred.doneUnsafe(deferred, Exit.fail(new ProgramThrow(value))));
|
|
192
194
|
const executed = yield* Effect.exit(runner.invokeFunction(executor, [resolve, reject]));
|
|
@@ -223,20 +225,15 @@ const reactionExit = (promises, source) => Effect.gen(function* () {
|
|
|
223
225
|
return exit;
|
|
224
226
|
});
|
|
225
227
|
const chainReaction = (runner, promises, source, onFulfilled, onRejected, method, node) => {
|
|
226
|
-
|
|
227
|
-
const body = Effect.gen(function* () {
|
|
228
|
+
return promises.createWithSelf((self) => Effect.gen(function* () {
|
|
228
229
|
const exit = yield* reactionExit(promises, source);
|
|
229
230
|
const handler = Exit.isSuccess(exit) ? onFulfilled : onRejected;
|
|
230
231
|
if (handler === undefined)
|
|
231
232
|
return yield* exit;
|
|
232
233
|
const input = Exit.isSuccess(exit) ? exit.value : caughtErrorValue(Cause.squash(exit.cause));
|
|
233
234
|
const result = yield* applyCollectionCallback(runner, handler, method, node)([input]);
|
|
234
|
-
return yield* resolvePromiseValue(runner, result, node,
|
|
235
|
-
});
|
|
236
|
-
return Effect.map(promises.create(body), (derived) => {
|
|
237
|
-
box.promise = derived;
|
|
238
|
-
return derived;
|
|
239
|
-
});
|
|
235
|
+
return yield* resolvePromiseValue(runner, result, node, self);
|
|
236
|
+
}));
|
|
240
237
|
};
|
|
241
238
|
const chainFinally = (runner, promises, source, cleanup, method, node) => promises.create(Effect.gen(function* () {
|
|
242
239
|
const exit = yield* reactionExit(promises, source);
|
|
@@ -19,6 +19,20 @@ import { uriArgument, urlMethods, urlProperties, urlSearchParamsMethods, urlWrit
|
|
|
19
19
|
import { enumerableSource } from "../stdlib/object.js";
|
|
20
20
|
import { coerceToNumber, coerceToString, compoundOperators, errorBrandName } from "../stdlib/value.js";
|
|
21
21
|
import { Values } from "../values.js";
|
|
22
|
+
// What a loop does with its body's result: exit with a StatementResult, or undefined to keep iterating.
|
|
23
|
+
// Unlabelled break ends this loop; a label the loop does not carry propagates outward.
|
|
24
|
+
const loopExit = (result, labels) => {
|
|
25
|
+
if (result.kind === "return")
|
|
26
|
+
return result;
|
|
27
|
+
if (result.kind === "break") {
|
|
28
|
+
if (result.label !== undefined && !labels?.has(result.label))
|
|
29
|
+
return result;
|
|
30
|
+
return { kind: "none" };
|
|
31
|
+
}
|
|
32
|
+
if (result.kind === "continue" && result.label !== undefined && !labels?.has(result.label))
|
|
33
|
+
return result;
|
|
34
|
+
return undefined;
|
|
35
|
+
};
|
|
22
36
|
const calleeDescription = (callee) => {
|
|
23
37
|
if (callee?.type === "Identifier")
|
|
24
38
|
return callee.name;
|
|
@@ -352,20 +366,9 @@ class Frame {
|
|
|
352
366
|
const self = this;
|
|
353
367
|
return Effect.gen(function* () {
|
|
354
368
|
while (yield* self.evaluateExpression(node.test)) {
|
|
355
|
-
const
|
|
356
|
-
if (
|
|
357
|
-
|
|
358
|
-
return result;
|
|
359
|
-
continue;
|
|
360
|
-
}
|
|
361
|
-
if (result.kind === "break") {
|
|
362
|
-
if (result.label !== undefined && !labels?.has(result.label))
|
|
363
|
-
return result;
|
|
364
|
-
return { kind: "none" };
|
|
365
|
-
}
|
|
366
|
-
if (result.kind === "return") {
|
|
367
|
-
return result;
|
|
368
|
-
}
|
|
369
|
+
const exit = loopExit(yield* self.evaluateStatement(node.body), labels);
|
|
370
|
+
if (exit !== undefined)
|
|
371
|
+
return exit;
|
|
369
372
|
}
|
|
370
373
|
return { kind: "none" };
|
|
371
374
|
});
|
|
@@ -374,20 +377,9 @@ class Frame {
|
|
|
374
377
|
const self = this;
|
|
375
378
|
return Effect.gen(function* () {
|
|
376
379
|
do {
|
|
377
|
-
const
|
|
378
|
-
if (
|
|
379
|
-
|
|
380
|
-
return result;
|
|
381
|
-
continue;
|
|
382
|
-
}
|
|
383
|
-
if (result.kind === "break") {
|
|
384
|
-
if (result.label !== undefined && !labels?.has(result.label))
|
|
385
|
-
return result;
|
|
386
|
-
return { kind: "none" };
|
|
387
|
-
}
|
|
388
|
-
if (result.kind === "return") {
|
|
389
|
-
return result;
|
|
390
|
-
}
|
|
380
|
+
const exit = loopExit(yield* self.evaluateStatement(node.body), labels);
|
|
381
|
+
if (exit !== undefined)
|
|
382
|
+
return exit;
|
|
391
383
|
} while (yield* self.evaluateExpression(node.test));
|
|
392
384
|
return { kind: "none" };
|
|
393
385
|
});
|
|
@@ -422,24 +414,13 @@ class Frame {
|
|
|
422
414
|
};
|
|
423
415
|
nextIteration();
|
|
424
416
|
while (testNode ? yield* self.evaluateExpression(testNode) : true) {
|
|
425
|
-
const
|
|
426
|
-
if (
|
|
427
|
-
return
|
|
428
|
-
}
|
|
429
|
-
if (result.kind === "break") {
|
|
430
|
-
if (result.label !== undefined && !labels?.has(result.label))
|
|
431
|
-
return result;
|
|
432
|
-
return { kind: "none" };
|
|
433
|
-
}
|
|
434
|
-
if (result.kind === "continue" && result.label !== undefined && !labels?.has(result.label))
|
|
435
|
-
return result;
|
|
417
|
+
const exit = loopExit(yield* self.evaluateStatement(node.body), labels);
|
|
418
|
+
if (exit !== undefined)
|
|
419
|
+
return exit;
|
|
436
420
|
nextIteration();
|
|
437
421
|
if (updateNode) {
|
|
438
422
|
yield* self.evaluateExpression(updateNode);
|
|
439
423
|
}
|
|
440
|
-
if (result.kind === "continue") {
|
|
441
|
-
continue;
|
|
442
|
-
}
|
|
443
424
|
}
|
|
444
425
|
return { kind: "none" };
|
|
445
426
|
}).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
|
|
@@ -499,20 +480,10 @@ class Frame {
|
|
|
499
480
|
}
|
|
500
481
|
return yield* Effect.failCause(bodyExit.cause);
|
|
501
482
|
}
|
|
502
|
-
const
|
|
503
|
-
if (
|
|
504
|
-
yield* close();
|
|
505
|
-
return result;
|
|
506
|
-
}
|
|
507
|
-
if (result.kind === "break") {
|
|
508
|
-
yield* close();
|
|
509
|
-
if (result.label !== undefined && !labels?.has(result.label))
|
|
510
|
-
return result;
|
|
511
|
-
return { kind: "none" };
|
|
512
|
-
}
|
|
513
|
-
if (result.kind === "continue" && result.label !== undefined && !labels?.has(result.label)) {
|
|
483
|
+
const exit = loopExit(bodyExit.value, labels);
|
|
484
|
+
if (exit !== undefined) {
|
|
514
485
|
yield* close();
|
|
515
|
-
return
|
|
486
|
+
return exit;
|
|
516
487
|
}
|
|
517
488
|
}
|
|
518
489
|
}).pipe(Effect.ensuring(Effect.sync(() => {
|
|
@@ -705,19 +676,9 @@ class Frame {
|
|
|
705
676
|
if (declared)
|
|
706
677
|
self.scopes.pop();
|
|
707
678
|
})));
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
if (result.kind === "break") {
|
|
712
|
-
if (result.label !== undefined && !labels?.has(result.label))
|
|
713
|
-
return result;
|
|
714
|
-
return { kind: "none" };
|
|
715
|
-
}
|
|
716
|
-
if (result.kind === "continue") {
|
|
717
|
-
if (result.label !== undefined && !labels?.has(result.label))
|
|
718
|
-
return result;
|
|
719
|
-
continue;
|
|
720
|
-
}
|
|
679
|
+
const exit = loopExit(result, labels);
|
|
680
|
+
if (exit !== undefined)
|
|
681
|
+
return exit;
|
|
721
682
|
}
|
|
722
683
|
return { kind: "none" };
|
|
723
684
|
}).pipe(Effect.ensuring(Effect.sync(() => {
|
package/dist/stdlib/object.js
CHANGED
|
@@ -97,13 +97,6 @@ const constructObject = (args, node) => {
|
|
|
97
97
|
return first;
|
|
98
98
|
throw new InterpreterRuntimeError(`Object(${typeof first}) wrapper objects are not supported; use the primitive value directly.`, node);
|
|
99
99
|
};
|
|
100
|
-
// Tool references are not data; only Object.keys(tools) reads them, for tool names.
|
|
101
|
-
const rejectTools = (name, args, node) => {
|
|
102
|
-
if (!(args[0] instanceof ToolReference))
|
|
103
|
-
return;
|
|
104
|
-
throw new InterpreterRuntimeError(`Object.${name}(...) cannot read tool references: they are not plain data. Use Object.keys(tools) for names, or search({ query }) for signatures.`, node, "InvalidDataValue");
|
|
105
|
-
};
|
|
106
|
-
const objectStatic = (name, impl) => sync(`Object.${name}`, impl);
|
|
107
100
|
// Object constructs identically with or without new, like JS. Only `keys` copies its result into the
|
|
108
101
|
// program; `values`, `entries`, `assign`, and `fromEntries` hand back the program's own values.
|
|
109
102
|
export const objectGlobal = (runner, toolKeys) => new HostFunction({
|
|
@@ -115,22 +108,19 @@ export const objectGlobal = (runner, toolKeys) => new HostFunction({
|
|
|
115
108
|
keys: sync("Object.keys", (args, node) => toProgram(args[0] instanceof ToolReference
|
|
116
109
|
? [...toolKeys(args[0].path)]
|
|
117
110
|
: Object.keys(enumerableSource("Object.keys(...)", args[0], node)), "Object.keys result")),
|
|
118
|
-
values:
|
|
119
|
-
entries:
|
|
120
|
-
hasOwn:
|
|
121
|
-
is:
|
|
111
|
+
values: sync("Object.values", (args, node) => Object.values(enumerableSource("Object.values(...)", args[0], node))),
|
|
112
|
+
entries: sync("Object.entries", (args, node) => Object.entries(enumerableSource("Object.entries(...)", args[0], node)).map(([key, item]) => [key, item])),
|
|
113
|
+
hasOwn: sync("Object.hasOwn", (args, node) => Object.hasOwn(enumerableSource("Object.hasOwn(...)", args[0], node), args[1] === AsyncIteratorSymbol || args[1] === IteratorSymbol ? args[1] : String(args[1]))),
|
|
114
|
+
is: sync("Object.is", (args, node) => {
|
|
122
115
|
if (containsOpaqueReference(args[0]) || containsOpaqueReference(args[1])) {
|
|
123
116
|
throw new InterpreterRuntimeError("Object.is requires data values.", node, "InvalidDataValue");
|
|
124
117
|
}
|
|
125
118
|
return Object.is(args[0], args[1]);
|
|
126
119
|
}),
|
|
127
|
-
assign:
|
|
120
|
+
assign: sync("Object.assign", objectAssign),
|
|
128
121
|
fromEntries: new HostFunction({
|
|
129
122
|
name: "Object.fromEntries",
|
|
130
|
-
call: (args, node) => Effect.suspend(() =>
|
|
131
|
-
rejectTools("fromEntries", args, node);
|
|
132
|
-
return objectFromEntries(runner, args[0], node);
|
|
133
|
-
}),
|
|
123
|
+
call: (args, node) => Effect.suspend(() => objectFromEntries(runner, args[0], node)),
|
|
134
124
|
}),
|
|
135
125
|
groupBy: groupBy(runner, "Object"),
|
|
136
126
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@opencode/codemode",
|
|
4
|
-
"version": "0.0.0-dev-
|
|
4
|
+
"version": "0.0.0-dev-19437",
|
|
5
5
|
"description": "Effect-native confined code execution over schema-described tools",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|