@opencode-ai/codemode 0.0.0-beta-17492

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +168 -0
  2. package/dist/codemode.d.ts +148 -0
  3. package/dist/codemode.js +70 -0
  4. package/dist/index.d.ts +5 -0
  5. package/dist/index.js +5 -0
  6. package/dist/interpreter/errors.d.ts +9 -0
  7. package/dist/interpreter/errors.js +91 -0
  8. package/dist/interpreter/execute.d.ts +4 -0
  9. package/dist/interpreter/execute.js +178 -0
  10. package/dist/interpreter/iterator.d.ts +13 -0
  11. package/dist/interpreter/iterator.js +4 -0
  12. package/dist/interpreter/methods.d.ts +17 -0
  13. package/dist/interpreter/methods.js +1026 -0
  14. package/dist/interpreter/model.d.ts +151 -0
  15. package/dist/interpreter/model.js +186 -0
  16. package/dist/interpreter/promises.d.ts +29 -0
  17. package/dist/interpreter/promises.js +253 -0
  18. package/dist/interpreter/references.d.ts +6 -0
  19. package/dist/interpreter/references.js +114 -0
  20. package/dist/interpreter/runtime.d.ts +98 -0
  21. package/dist/interpreter/runtime.js +2351 -0
  22. package/dist/interpreter/scope.d.ts +15 -0
  23. package/dist/interpreter/scope.js +79 -0
  24. package/dist/interpreter/transpile.node.d.ts +5 -0
  25. package/dist/interpreter/transpile.node.js +19 -0
  26. package/dist/interpreter/transpile.workerd.d.ts +5 -0
  27. package/dist/interpreter/transpile.workerd.js +6 -0
  28. package/dist/openapi/index.d.ts +7 -0
  29. package/dist/openapi/index.js +101 -0
  30. package/dist/openapi/runtime.d.ts +4 -0
  31. package/dist/openapi/runtime.js +283 -0
  32. package/dist/openapi/spec.d.ts +20 -0
  33. package/dist/openapi/spec.js +588 -0
  34. package/dist/openapi/types.d.ts +122 -0
  35. package/dist/openapi/types.js +2 -0
  36. package/dist/stdlib/collections.d.ts +4 -0
  37. package/dist/stdlib/collections.js +57 -0
  38. package/dist/stdlib/console.d.ts +2 -0
  39. package/dist/stdlib/console.js +126 -0
  40. package/dist/stdlib/date.d.ts +7 -0
  41. package/dist/stdlib/date.js +186 -0
  42. package/dist/stdlib/json.d.ts +6 -0
  43. package/dist/stdlib/json.js +124 -0
  44. package/dist/stdlib/math.d.ts +12 -0
  45. package/dist/stdlib/math.js +157 -0
  46. package/dist/stdlib/number.d.ts +6 -0
  47. package/dist/stdlib/number.js +76 -0
  48. package/dist/stdlib/object.d.ts +7 -0
  49. package/dist/stdlib/object.js +100 -0
  50. package/dist/stdlib/promise.d.ts +2 -0
  51. package/dist/stdlib/promise.js +1 -0
  52. package/dist/stdlib/regexp.d.ts +11 -0
  53. package/dist/stdlib/regexp.js +106 -0
  54. package/dist/stdlib/string.d.ts +4 -0
  55. package/dist/stdlib/string.js +48 -0
  56. package/dist/stdlib/url.d.ts +12 -0
  57. package/dist/stdlib/url.js +84 -0
  58. package/dist/stdlib/value.d.ts +12 -0
  59. package/dist/stdlib/value.js +120 -0
  60. package/dist/tool-error.d.ts +11 -0
  61. package/dist/tool-error.js +9 -0
  62. package/dist/tool-runtime.d.ts +68 -0
  63. package/dist/tool-runtime.js +390 -0
  64. package/dist/tool-schema.d.ts +15 -0
  65. package/dist/tool-schema.js +213 -0
  66. package/dist/tool.d.ts +55 -0
  67. package/dist/tool.js +21 -0
  68. package/dist/tools.d.ts +4 -0
  69. package/dist/tools.js +1 -0
  70. package/dist/values.d.ts +31 -0
  71. package/dist/values.js +50 -0
  72. package/package.json +46 -0
@@ -0,0 +1,151 @@
1
+ import type { Effect } from "effect";
2
+ import type { SafeObject } from "../tool-runtime.js";
3
+ import type { CodeModePromise, CodeModeRegExp, CodeModeURL } from "../values.js";
4
+ export type SourcePosition = {
5
+ line: number;
6
+ column: number;
7
+ };
8
+ export type SourceLocation = {
9
+ start: SourcePosition;
10
+ end: SourcePosition;
11
+ };
12
+ export type AstNode = {
13
+ type: string;
14
+ loc?: SourceLocation;
15
+ [key: string]: unknown;
16
+ };
17
+ export type ProgramNode = AstNode & {
18
+ type: "Program";
19
+ body: Array<AstNode>;
20
+ };
21
+ export type Binding = {
22
+ mutable: boolean;
23
+ value: unknown;
24
+ initialized?: boolean;
25
+ };
26
+ export type StatementResult = {
27
+ kind: "none";
28
+ } | {
29
+ kind: "return";
30
+ value: unknown;
31
+ } | {
32
+ kind: "break";
33
+ label?: string;
34
+ } | {
35
+ kind: "continue";
36
+ label?: string;
37
+ };
38
+ export type MemberReference = {
39
+ target: SafeObject | Array<unknown> | CodeModeRegExp | CodeModeURL;
40
+ key: PropertyKey;
41
+ };
42
+ export declare class CodeModeFunction {
43
+ readonly parameters: ReadonlyArray<AstNode>;
44
+ readonly body: AstNode;
45
+ readonly capturedScopes: ReadonlyArray<Map<string, Binding>>;
46
+ readonly async: boolean;
47
+ readonly generator: boolean;
48
+ constructor(parameters: ReadonlyArray<AstNode>, body: AstNode, capturedScopes: ReadonlyArray<Map<string, Binding>>, async: boolean, generator: boolean);
49
+ }
50
+ export type GeneratorRequestKind = "next" | "return" | "throw";
51
+ export declare class CodeModeGenerator {
52
+ readonly asynchronous: boolean;
53
+ readonly request: (kind: GeneratorRequestKind, value: unknown, node: AstNode) => Effect.Effect<unknown, unknown, unknown>;
54
+ constructor(asynchronous: boolean, request: (kind: GeneratorRequestKind, value: unknown, node: AstNode) => Effect.Effect<unknown, unknown, unknown>);
55
+ }
56
+ export declare class GeneratorMethodReference {
57
+ readonly generator: CodeModeGenerator;
58
+ readonly kind: GeneratorRequestKind | "iterator";
59
+ constructor(generator: CodeModeGenerator, kind: GeneratorRequestKind | "iterator");
60
+ }
61
+ export declare class IntrinsicReference {
62
+ readonly receiver: unknown;
63
+ readonly name: string;
64
+ constructor(receiver: unknown, name: string);
65
+ }
66
+ export declare class ComputedValue {
67
+ readonly value: unknown;
68
+ constructor(value: unknown);
69
+ }
70
+ export declare class PromiseNamespace {
71
+ }
72
+ export declare class SymbolNamespace {
73
+ }
74
+ export declare const AsyncIteratorSymbol: unique symbol;
75
+ export declare const IteratorSymbol: unique symbol;
76
+ export declare const IteratorSymbols: readonly [typeof AsyncIteratorSymbol, typeof IteratorSymbol];
77
+ export type PromiseMethodName = "all" | "allSettled" | "race" | "any" | "resolve" | "reject";
78
+ export declare class PromiseMethodReference {
79
+ readonly name: PromiseMethodName;
80
+ constructor(name: PromiseMethodName);
81
+ }
82
+ export type PromiseInstanceMethodName = "then" | "catch" | "finally";
83
+ export declare class PromiseInstanceMethodReference {
84
+ readonly promise: CodeModePromise;
85
+ readonly name: PromiseInstanceMethodName;
86
+ constructor(promise: CodeModePromise, name: PromiseInstanceMethodName);
87
+ }
88
+ export declare class PromiseCapabilityFunction {
89
+ readonly settle: (value: unknown) => void;
90
+ constructor(settle: (value: unknown) => void);
91
+ }
92
+ export type GlobalNamespaceName = "Object" | "Math" | "JSON" | "Array" | "console" | "Date" | "RegExp" | "Map" | "Set" | "URL" | "URLSearchParams";
93
+ export declare class GlobalNamespace {
94
+ readonly name: GlobalNamespaceName;
95
+ constructor(name: GlobalNamespaceName);
96
+ }
97
+ export declare class GlobalMethodReference {
98
+ readonly namespace: Exclude<GlobalNamespaceName, "JSON"> | "Number" | "String";
99
+ readonly name: string;
100
+ constructor(namespace: Exclude<GlobalNamespaceName, "JSON"> | "Number" | "String", name: string);
101
+ }
102
+ export declare class JsonMethodReference {
103
+ readonly name: "parse" | "stringify";
104
+ constructor(name: "parse" | "stringify");
105
+ }
106
+ export declare class CoercionFunction {
107
+ readonly name: "Number" | "String" | "Boolean" | "parseInt" | "parseFloat" | "isFinite" | "isNaN";
108
+ constructor(name: "Number" | "String" | "Boolean" | "parseInt" | "parseFloat" | "isFinite" | "isNaN");
109
+ }
110
+ export declare class UriFunction {
111
+ readonly name: "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent";
112
+ constructor(name: "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent");
113
+ }
114
+ export declare class SearchFunction {
115
+ }
116
+ export declare class ProgramThrow {
117
+ readonly value: unknown;
118
+ constructor(value: unknown);
119
+ }
120
+ export declare class GeneratorReturn {
121
+ readonly value: unknown;
122
+ constructor(value: unknown);
123
+ }
124
+ export declare class ErrorConstructorReference {
125
+ readonly name: string;
126
+ constructor(name: string);
127
+ }
128
+ export type DiagnosticKind = "ParseError" | "UnsupportedSyntax" | "UnknownTool" | "InvalidToolInput" | "InvalidToolOutput" | "InvalidDataValue" | "ToolCallLimitExceeded" | "TimeoutExceeded" | "ToolFailure" | "ExecutionFailure";
129
+ export declare const OptionalShortCircuit: unique symbol;
130
+ export declare const supportedSyntaxMessage = "Supported orchestration syntax: tools.* calls (they return promises - resolve them with await), data literals, destructuring, optional chaining, template literals, conditionals, switch, loops (incl. for...of and for...in over object/array/tools keys), arrow functions, spread, try/catch, array methods (map/filter/find/findIndex/some/every/reduce/flatMap/forEach/sort/slice/concat/indexOf/lastIndexOf/at/flat/reverse/includes/join), string methods (incl. match/matchAll/replace/split with regular expressions), Date/RegExp/Map/Set/URL/URLSearchParams, URI encoding helpers, Object/Math/JSON helpers, captured console.log/warn/error/dir/table, Promise.all/allSettled/race/any/resolve/reject over arrays mixing promises and plain values for parallel tool calls, promise chaining with .then/.catch/.finally, and new Promise((resolve, reject) => ...) construction.";
131
+ export declare class InterpreterRuntimeError extends Error {
132
+ readonly kind: DiagnosticKind;
133
+ readonly suggestions?: ReadonlyArray<string> | undefined;
134
+ readonly node?: AstNode;
135
+ errorName: string;
136
+ constructor(message: string, node?: AstNode, kind?: DiagnosticKind, suggestions?: ReadonlyArray<string> | undefined);
137
+ as(errorName: string): this;
138
+ }
139
+ export declare const unsupportedSyntax: (kind: string, node: AstNode) => InterpreterRuntimeError;
140
+ export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
141
+ export declare const asNode: (value: unknown, context: string) => AstNode;
142
+ export declare const getArray: (node: AstNode, key: string) => Array<unknown>;
143
+ export declare const getString: (node: AstNode, key: string) => string;
144
+ export declare const getBoolean: (node: AstNode, key: string) => boolean;
145
+ export declare const getOptionalNode: (node: AstNode, key: string) => AstNode | undefined;
146
+ export declare const getNode: (node: AstNode, key: string) => AstNode;
147
+ export declare const sourceLocation: (node: AstNode) => {
148
+ readonly line: number;
149
+ readonly column: number;
150
+ };
151
+ export declare const formatLocation: (node?: AstNode) => string;
@@ -0,0 +1,186 @@
1
+ export class CodeModeFunction {
2
+ parameters;
3
+ body;
4
+ capturedScopes;
5
+ async;
6
+ generator;
7
+ constructor(parameters, body, capturedScopes, async, generator) {
8
+ this.parameters = parameters;
9
+ this.body = body;
10
+ this.capturedScopes = capturedScopes;
11
+ this.async = async;
12
+ this.generator = generator;
13
+ }
14
+ }
15
+ export class CodeModeGenerator {
16
+ asynchronous;
17
+ request;
18
+ constructor(asynchronous, request) {
19
+ this.asynchronous = asynchronous;
20
+ this.request = request;
21
+ }
22
+ }
23
+ export class GeneratorMethodReference {
24
+ generator;
25
+ kind;
26
+ constructor(generator, kind) {
27
+ this.generator = generator;
28
+ this.kind = kind;
29
+ }
30
+ }
31
+ export class IntrinsicReference {
32
+ receiver;
33
+ name;
34
+ constructor(receiver, name) {
35
+ this.receiver = receiver;
36
+ this.name = name;
37
+ }
38
+ }
39
+ export class ComputedValue {
40
+ value;
41
+ constructor(value) {
42
+ this.value = value;
43
+ }
44
+ }
45
+ export class PromiseNamespace {
46
+ }
47
+ export class SymbolNamespace {
48
+ }
49
+ export const AsyncIteratorSymbol = Symbol("codemode.async-iterator");
50
+ export const IteratorSymbol = Symbol("codemode.iterator");
51
+ export const IteratorSymbols = [AsyncIteratorSymbol, IteratorSymbol];
52
+ export class PromiseMethodReference {
53
+ name;
54
+ constructor(name) {
55
+ this.name = name;
56
+ }
57
+ }
58
+ export class PromiseInstanceMethodReference {
59
+ promise;
60
+ name;
61
+ constructor(promise, name) {
62
+ this.promise = promise;
63
+ this.name = name;
64
+ }
65
+ }
66
+ export class PromiseCapabilityFunction {
67
+ settle;
68
+ constructor(settle) {
69
+ this.settle = settle;
70
+ }
71
+ }
72
+ export class GlobalNamespace {
73
+ name;
74
+ constructor(name) {
75
+ this.name = name;
76
+ }
77
+ }
78
+ export class GlobalMethodReference {
79
+ namespace;
80
+ name;
81
+ constructor(namespace, name) {
82
+ this.namespace = namespace;
83
+ this.name = name;
84
+ }
85
+ }
86
+ export class JsonMethodReference {
87
+ name;
88
+ constructor(name) {
89
+ this.name = name;
90
+ }
91
+ }
92
+ export class CoercionFunction {
93
+ name;
94
+ constructor(name) {
95
+ this.name = name;
96
+ }
97
+ }
98
+ export class UriFunction {
99
+ name;
100
+ constructor(name) {
101
+ this.name = name;
102
+ }
103
+ }
104
+ export class SearchFunction {
105
+ }
106
+ export class ProgramThrow {
107
+ value;
108
+ constructor(value) {
109
+ this.value = value;
110
+ }
111
+ }
112
+ export class GeneratorReturn {
113
+ value;
114
+ constructor(value) {
115
+ this.value = value;
116
+ }
117
+ }
118
+ export class ErrorConstructorReference {
119
+ name;
120
+ constructor(name) {
121
+ this.name = name;
122
+ }
123
+ }
124
+ export const OptionalShortCircuit = Symbol("codemode.optional-short-circuit");
125
+ export const supportedSyntaxMessage = "Supported orchestration syntax: tools.* calls (they return promises - resolve them with await), data literals, destructuring, optional chaining, template literals, conditionals, switch, loops (incl. for...of and for...in over object/array/tools keys), arrow functions, spread, try/catch, array methods (map/filter/find/findIndex/some/every/reduce/flatMap/forEach/sort/slice/concat/indexOf/lastIndexOf/at/flat/reverse/includes/join), string methods (incl. match/matchAll/replace/split with regular expressions), Date/RegExp/Map/Set/URL/URLSearchParams, URI encoding helpers, Object/Math/JSON helpers, captured console.log/warn/error/dir/table, Promise.all/allSettled/race/any/resolve/reject over arrays mixing promises and plain values for parallel tool calls, promise chaining with .then/.catch/.finally, and new Promise((resolve, reject) => ...) construction.";
126
+ export class InterpreterRuntimeError extends Error {
127
+ kind;
128
+ suggestions;
129
+ node;
130
+ errorName = "Error";
131
+ constructor(message, node, kind = "ExecutionFailure", suggestions) {
132
+ super(message);
133
+ this.kind = kind;
134
+ this.suggestions = suggestions;
135
+ this.name = "InterpreterRuntimeError";
136
+ if (node)
137
+ this.node = node;
138
+ }
139
+ as(errorName) {
140
+ this.errorName = errorName;
141
+ return this;
142
+ }
143
+ }
144
+ export const unsupportedSyntax = (kind, node) => new InterpreterRuntimeError(`Syntax '${kind}' is not supported. ${supportedSyntaxMessage}`, node, "UnsupportedSyntax", [supportedSyntaxMessage]);
145
+ export const isRecord = (value) => typeof value === "object" && value !== null;
146
+ export const asNode = (value, context) => {
147
+ if (!isRecord(value) || typeof value.type !== "string") {
148
+ throw new InterpreterRuntimeError(`Invalid AST node while reading ${context}.`);
149
+ }
150
+ return value;
151
+ };
152
+ export const getArray = (node, key) => {
153
+ const value = node[key];
154
+ if (!Array.isArray(value))
155
+ throw new InterpreterRuntimeError(`Expected '${key}' to be an array.`, node);
156
+ return value;
157
+ };
158
+ export const getString = (node, key) => {
159
+ const value = node[key];
160
+ if (typeof value !== "string")
161
+ throw new InterpreterRuntimeError(`Expected '${key}' to be a string.`, node);
162
+ return value;
163
+ };
164
+ export const getBoolean = (node, key) => {
165
+ const value = node[key];
166
+ if (typeof value !== "boolean")
167
+ throw new InterpreterRuntimeError(`Expected '${key}' to be a boolean.`, node);
168
+ return value;
169
+ };
170
+ export const getOptionalNode = (node, key) => {
171
+ const value = node[key];
172
+ if (value === undefined || value === null)
173
+ return undefined;
174
+ return asNode(value, key);
175
+ };
176
+ export const getNode = (node, key) => asNode(node[key], key);
177
+ export const sourceLocation = (node) => ({
178
+ line: Math.max(1, (node.loc?.start.line ?? 2) - 1),
179
+ column: Math.max(1, (node.loc?.start.column ?? 4) - 3),
180
+ });
181
+ export const formatLocation = (node) => {
182
+ if (!node?.loc)
183
+ return "";
184
+ const location = sourceLocation(node);
185
+ return ` (line ${location.line}, col ${location.column})`;
186
+ };
@@ -0,0 +1,29 @@
1
+ import { Effect, Exit, Scope } from "effect";
2
+ import type { Diagnostic } from "../codemode.js";
3
+ import { type AstNode, InterpreterRuntimeError, PromiseInstanceMethodReference, PromiseMethodReference } from "./model.js";
4
+ import { type CallbackRunner } from "./methods.js";
5
+ import { CodeModePromise } from "../values.js";
6
+ import type { SyncIteratorRunner } from "./iterator.js";
7
+ export declare class PromiseRuntime<R> {
8
+ private readonly scope;
9
+ private readonly active;
10
+ private readonly ids;
11
+ private readonly observed;
12
+ private readonly failures;
13
+ private nextID;
14
+ constructor(scope: Scope.Scope);
15
+ create(effect: Effect.Effect<unknown, unknown, R>): Effect.Effect<CodeModePromise, never, R>;
16
+ markObserved(promise: CodeModePromise): void;
17
+ await(promise: CodeModePromise): Effect.Effect<Exit.Exit<unknown, unknown>>;
18
+ fork(effect: Effect.Effect<unknown, unknown, R>): Effect.Effect<void, never, R>;
19
+ diagnostics(): Array<Diagnostic>;
20
+ interrupt(): Effect.Effect<Array<Diagnostic>>;
21
+ }
22
+ export declare const selfResolutionError: (node?: AstNode) => InterpreterRuntimeError;
23
+ export declare const resolvePromiseValue: <R>(runner: CallbackRunner<R>, value: unknown, node: AstNode, own?: {
24
+ promise?: CodeModePromise;
25
+ }) => Effect.Effect<unknown, unknown, R>;
26
+ export declare const resolvePromise: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, value: unknown, node: AstNode) => Effect.Effect<CodeModePromise, never, R>;
27
+ export declare const invokePromiseMethod: <R>(runner: CallbackRunner<R> & SyncIteratorRunner<R>, promises: PromiseRuntime<R>, ref: PromiseMethodReference, args: Array<unknown>, node: AstNode) => Effect.Effect<unknown, unknown, R>;
28
+ export declare const invokePromiseInstanceMethod: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, ref: PromiseInstanceMethodReference, args: Array<unknown>, node: AstNode) => Effect.Effect<CodeModePromise, never, R>;
29
+ export declare const constructPromise: <R>(runner: CallbackRunner<R>, promises: PromiseRuntime<R>, executor: unknown, node: AstNode) => Effect.Effect<CodeModePromise, unknown, R>;
@@ -0,0 +1,253 @@
1
+ import { Cause, Deferred, Effect, Exit, Fiber, Scope } from "effect";
2
+ import { CodeModeFunction, InterpreterRuntimeError, ProgramThrow, PromiseCapabilityFunction, PromiseInstanceMethodReference, PromiseMethodReference, } from "./model.js";
3
+ import { caughtErrorValue, normalizeError } from "./errors.js";
4
+ import { applyCollectionCallback, isSupportedCallback } from "./methods.js";
5
+ import { typeofValue } from "./references.js";
6
+ import { createAggregateErrorValue } from "../stdlib/value.js";
7
+ import { CodeModePromise } from "../values.js";
8
+ // Observation only controls rejection reporting; program completion interrupts all promise work.
9
+ export class PromiseRuntime {
10
+ scope;
11
+ active = new Set();
12
+ ids = new WeakMap();
13
+ observed = new WeakSet();
14
+ failures = new Map();
15
+ nextID = 0;
16
+ constructor(scope) {
17
+ this.scope = scope;
18
+ }
19
+ create(effect) {
20
+ return Effect.suspend(() => {
21
+ // Allocate before forking so reruns get distinct IDs and diagnostics retain creation order.
22
+ const id = this.nextID++;
23
+ return Effect.map(Effect.forkIn(effect, this.scope, { startImmediately: true }), (fiber) => {
24
+ const promise = new CodeModePromise(fiber);
25
+ this.active.add(promise);
26
+ this.ids.set(promise, id);
27
+ fiber.addObserver((exit) => {
28
+ this.active.delete(promise);
29
+ if (Exit.isSuccess(exit) || Cause.hasInterruptsOnly(exit.cause) || this.observed.has(promise)) {
30
+ this.ids.delete(promise);
31
+ return;
32
+ }
33
+ const failure = normalizeError(Cause.squash(exit.cause));
34
+ this.failures.set(id, {
35
+ ...failure,
36
+ message: `Unhandled rejection from an un-awaited promise: ${failure.message}`,
37
+ });
38
+ });
39
+ return promise;
40
+ });
41
+ });
42
+ }
43
+ // Observation must be recorded when responsibility transfers, before the consumer fiber runs.
44
+ markObserved(promise) {
45
+ this.observed.add(promise);
46
+ const id = this.ids.get(promise);
47
+ this.ids.delete(promise);
48
+ if (id !== undefined)
49
+ this.failures.delete(id);
50
+ }
51
+ await(promise) {
52
+ return Fiber.await(promise.fiber);
53
+ }
54
+ fork(effect) {
55
+ return Effect.asVoid(Effect.forkIn(effect, this.scope, { startImmediately: true }));
56
+ }
57
+ diagnostics() {
58
+ return [...this.failures].sort(([left], [right]) => left - right).map(([, failure]) => failure);
59
+ }
60
+ // Re-check because a straggler can create promises before its interruption lands.
61
+ interrupt() {
62
+ const self = this;
63
+ return Effect.gen(function* () {
64
+ while (self.active.size > 0) {
65
+ yield* Fiber.interruptAll([...self.active].map((promise) => promise.fiber));
66
+ }
67
+ return self.diagnostics();
68
+ });
69
+ }
70
+ }
71
+ export const selfResolutionError = (node) => new InterpreterRuntimeError("Chaining cycle detected: a promise cannot resolve with itself.", node).as("TypeError");
72
+ export const resolvePromiseValue = (runner, value, node, own) => {
73
+ if (own?.promise !== undefined && value === own.promise)
74
+ return Effect.fail(selfResolutionError(node));
75
+ if (value instanceof CodeModePromise)
76
+ return runner.settlePromise(value);
77
+ if (value === null || typeof value !== "object" || !Object.hasOwn(value, "then"))
78
+ return Effect.succeed(value);
79
+ const then = value.then;
80
+ if (typeofValue(then) !== "function")
81
+ return Effect.succeed(value);
82
+ return Effect.gen(function* () {
83
+ // Promise resolution invokes a thenable's method in a later job.
84
+ yield* Effect.yieldNow;
85
+ const deferred = Deferred.makeUnsafe();
86
+ const resolve = new PromiseCapabilityFunction((result) => {
87
+ Deferred.doneUnsafe(deferred, Exit.succeed(result));
88
+ });
89
+ const reject = new PromiseCapabilityFunction((reason) => {
90
+ Deferred.doneUnsafe(deferred, Exit.fail(new ProgramThrow(reason)));
91
+ });
92
+ const executed = yield* Effect.exit(runner.invokeCallable(then, [resolve, reject], node));
93
+ if (!Exit.isSuccess(executed)) {
94
+ if (Cause.hasInterruptsOnly(executed.cause))
95
+ return yield* Effect.failCause(executed.cause);
96
+ Deferred.doneUnsafe(deferred, Exit.fail(Cause.squash(executed.cause)));
97
+ }
98
+ return yield* resolvePromiseValue(runner, yield* Deferred.await(deferred), node, own);
99
+ });
100
+ };
101
+ export const resolvePromise = (runner, promises, value, node) => {
102
+ if (value instanceof CodeModePromise)
103
+ return Effect.succeed(value);
104
+ const box = {};
105
+ return Effect.map(promises.create(resolvePromiseValue(runner, value, node, box)), (promise) => {
106
+ box.promise = promise;
107
+ return promise;
108
+ });
109
+ };
110
+ export const invokePromiseMethod = (runner, promises, ref, args, node) => {
111
+ if (ref.name === "resolve") {
112
+ return resolvePromise(runner, promises, args[0], node);
113
+ }
114
+ if (ref.name === "reject") {
115
+ return promises.create(Effect.fail(new ProgramThrow(args[0])));
116
+ }
117
+ return promises.create(Effect.gen(function* () {
118
+ const cursor = yield* runner.syncIterator(args[0], node);
119
+ if (cursor === undefined) {
120
+ throw new InterpreterRuntimeError(`Promise.${ref.name} expects an array or other synchronous iterable.`, node).as("TypeError");
121
+ }
122
+ const items = [];
123
+ while (true) {
124
+ const step = yield* cursor.next;
125
+ if (step.done)
126
+ break;
127
+ const item = yield* resolvePromise(runner, promises, step.value, node);
128
+ promises.markObserved(item);
129
+ items.push(item);
130
+ }
131
+ if (ref.name === "all") {
132
+ return yield* settleAfterTurn(Effect.all(items.map((item) => Effect.flatten(promises.await(item))), { concurrency: "unbounded" }));
133
+ }
134
+ if (ref.name === "allSettled") {
135
+ const outcomes = [];
136
+ for (const item of items) {
137
+ const exit = yield* promises.await(item);
138
+ if (Exit.isSuccess(exit)) {
139
+ outcomes.push(Object.assign(Object.create(null), { status: "fulfilled", value: exit.value }));
140
+ continue;
141
+ }
142
+ if (Cause.hasInterruptsOnly(exit.cause))
143
+ return yield* Effect.failCause(exit.cause);
144
+ outcomes.push(Object.assign(Object.create(null), {
145
+ status: "rejected",
146
+ reason: caughtErrorValue(Cause.squash(exit.cause)),
147
+ }));
148
+ }
149
+ yield* Effect.yieldNow;
150
+ return outcomes;
151
+ }
152
+ if (ref.name === "race") {
153
+ if (items.length === 0) {
154
+ throw new InterpreterRuntimeError("Promise.race([]) would never settle; provide at least one promise or value.", node);
155
+ }
156
+ return yield* settleAfterTurn(Effect.flatten(Effect.raceAll(items.map((item) => promises.await(item)))));
157
+ }
158
+ const flipped = items.map((item) => Effect.flatMap(promises.await(item), (exit) => {
159
+ if (Exit.isSuccess(exit))
160
+ return Effect.fail(new PromiseAnyFulfilled(exit.value));
161
+ if (Cause.hasInterruptsOnly(exit.cause))
162
+ return Effect.failCause(exit.cause);
163
+ return Effect.succeed(caughtErrorValue(Cause.squash(exit.cause)));
164
+ }));
165
+ return yield* settleAfterTurn(Effect.all(flipped, { concurrency: "unbounded" }).pipe(Effect.flatMap((reasons) => Effect.fail(new ProgramThrow(createAggregateErrorValue(reasons, "All promises were rejected")))), Effect.catch((error) => error instanceof PromiseAnyFulfilled ? Effect.succeed(error.value) : Effect.fail(error))));
166
+ }));
167
+ };
168
+ export const invokePromiseInstanceMethod = (runner, promises, ref, args, node) => {
169
+ const method = `Promise.prototype.${ref.name}`;
170
+ promises.markObserved(ref.promise);
171
+ if (ref.name === "finally") {
172
+ return chainFinally(runner, promises, ref.promise, reactionHandler(args[0], method, node), method, node);
173
+ }
174
+ const onFulfilled = ref.name === "then" ? reactionHandler(args[0], method, node) : undefined;
175
+ const onRejected = reactionHandler(ref.name === "then" ? args[1] : args[0], method, node);
176
+ return chainReaction(runner, promises, ref.promise, onFulfilled, onRejected, method, node);
177
+ };
178
+ export const constructPromise = (runner, promises, executor, node) => {
179
+ if (!(executor instanceof CodeModeFunction)) {
180
+ throw new InterpreterRuntimeError("new Promise(...) expects an executor function (e.g. new Promise((resolve, reject) => { ... })).", node).as("TypeError");
181
+ }
182
+ return Effect.gen(function* () {
183
+ const deferred = Deferred.makeUnsafe();
184
+ const box = {};
185
+ const promise = yield* promises.create(Effect.flatMap(Deferred.await(deferred), (value) => resolvePromiseValue(runner, value, node, box)));
186
+ box.promise = promise;
187
+ const resolve = new PromiseCapabilityFunction((value) => {
188
+ Deferred.doneUnsafe(deferred, Exit.succeed(value));
189
+ });
190
+ const reject = new PromiseCapabilityFunction((value) => {
191
+ Deferred.doneUnsafe(deferred, Exit.fail(new ProgramThrow(value)));
192
+ });
193
+ const executed = yield* Effect.exit(runner.invokeFunction(executor, [resolve, reject]));
194
+ if (!Exit.isSuccess(executed)) {
195
+ if (Cause.hasInterruptsOnly(executed.cause))
196
+ return yield* Effect.failCause(executed.cause);
197
+ Deferred.doneUnsafe(deferred, Exit.fail(Cause.squash(executed.cause)));
198
+ }
199
+ return promise;
200
+ });
201
+ };
202
+ // Settle one reaction turn after the deciding member, after its existing reactions.
203
+ const settleAfterTurn = (body) => Effect.flatMap(Effect.exit(body), (exit) => Effect.andThen(Effect.yieldNow, exit));
204
+ class PromiseAnyFulfilled {
205
+ value;
206
+ constructor(value) {
207
+ this.value = value;
208
+ }
209
+ }
210
+ const reactionHandler = (value, method, node) => {
211
+ if (isSupportedCallback(value))
212
+ return value;
213
+ if (typeofValue(value) === "function") {
214
+ throw new InterpreterRuntimeError(`${method} cannot use this callable as a handler; wrap it in an arrow function, e.g. (value) => tools.ns.tool(value).`, node);
215
+ }
216
+ return undefined;
217
+ };
218
+ // Teardown bypasses handlers; settled reactions yield once so handlers never run inline.
219
+ const reactionExit = (promises, source) => Effect.gen(function* () {
220
+ const exit = yield* promises.await(source);
221
+ if (!Exit.isSuccess(exit) && Cause.hasInterruptsOnly(exit.cause))
222
+ return yield* Effect.failCause(exit.cause);
223
+ yield* Effect.yieldNow;
224
+ return exit;
225
+ });
226
+ const chainReaction = (runner, promises, source, onFulfilled, onRejected, method, node) => {
227
+ const box = {};
228
+ const body = Effect.gen(function* () {
229
+ const exit = yield* reactionExit(promises, source);
230
+ const handler = Exit.isSuccess(exit) ? onFulfilled : onRejected;
231
+ if (handler === undefined)
232
+ return yield* exit;
233
+ const input = Exit.isSuccess(exit) ? exit.value : caughtErrorValue(Cause.squash(exit.cause));
234
+ const result = yield* applyCollectionCallback(runner, handler, method, node)([input]);
235
+ return yield* resolvePromiseValue(runner, result, node, box);
236
+ });
237
+ return Effect.map(promises.create(body), (derived) => {
238
+ box.promise = derived;
239
+ return derived;
240
+ });
241
+ };
242
+ const chainFinally = (runner, promises, source, cleanup, method, node) => promises.create(Effect.gen(function* () {
243
+ const exit = yield* reactionExit(promises, source);
244
+ if (cleanup !== undefined) {
245
+ const result = yield* applyCollectionCallback(runner, cleanup, method, node)([]);
246
+ const intermediate = yield* promises.create(Effect.gen(function* () {
247
+ yield* runner.settlePromise(yield* resolvePromise(runner, promises, result, node));
248
+ return yield* exit;
249
+ }));
250
+ return yield* runner.settlePromise(intermediate);
251
+ }
252
+ return yield* exit;
253
+ }));
@@ -0,0 +1,6 @@
1
+ import { type AstNode } from "./model.js";
2
+ export declare const isRuntimeReference: (value: unknown) => boolean;
3
+ export declare const containsRuntimeReference: (value: unknown) => boolean;
4
+ export declare const containsOpaqueReference: (value: unknown) => boolean;
5
+ export declare const rejectCircularInsertion: (container: object, value: unknown, label: string, node: AstNode) => void;
6
+ export declare const typeofValue: (value: unknown) => string;