@opencode/codemode 0.0.0-dev-19370 → 0.0.0-dev-19371

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.
@@ -8,7 +8,7 @@ import { ToolRuntime } from "../tool-runtime.js";
8
8
  import { normalizeError } from "./errors.js";
9
9
  import { InterpreterRuntimeError } from "./model.js";
10
10
  import { PromiseRuntime } from "./promises.js";
11
- import { Interpreter } from "./runtime.js";
11
+ import { Runtime } from "./runtime.js";
12
12
  export const executeProgram = (code, prepared, limits, hooks) => {
13
13
  if (code.trim().length === 0) {
14
14
  return Effect.succeed({
@@ -27,8 +27,7 @@ export const executeProgram = (code, prepared, limits, hooks) => {
27
27
  const base = Effect.acquireUseRelease(Scope.make("parallel"), (scope) => Effect.gen(function* () {
28
28
  const program = parseProgram(code);
29
29
  const promises = new PromiseRuntime(scope);
30
- const interpreter = new Interpreter(tools.execute, tools.search, tools.keys, promises, logs);
31
- const value = yield* interpreter.run(program);
30
+ const value = yield* new Runtime(tools.execute, tools.search, tools.keys, promises, logs).run(program);
32
31
  const result = toData(value, "Execution result", "result");
33
32
  returned = { value: result, promises };
34
33
  const warnings = yield* promises.interrupt();
@@ -1,86 +1,16 @@
1
1
  import type { Program } from "acorn";
2
2
  import { Effect } from "effect";
3
+ import { type Runner } from "./runner.js";
3
4
  import { PromiseRuntime } from "./promises.js";
4
- export declare class Interpreter<R> {
5
- private scopes;
6
- private readonly executeTool;
7
- private readonly invokeSearch;
8
- private readonly toolKeys;
9
- private readonly logs;
10
- private readonly promises;
11
- private generatorState?;
12
- private generatorAsync;
13
- private readonly runner;
14
- constructor(executeTool: (path: ReadonlyArray<string>, args: Array<unknown>) => Effect.Effect<unknown, unknown, R>, invokeSearch: (args: Array<unknown>) => Effect.Effect<unknown, unknown, R>, toolKeys: (path: ReadonlyArray<string>) => ReadonlyArray<string>, promises: PromiseRuntime<R>, logs?: Array<string>);
5
+ /** One program execution: the tool bridge, promise scheduler, captured logs, and the global scope built once. */
6
+ export declare class Runtime<R> {
7
+ readonly executeTool: (path: ReadonlyArray<string>, args: Array<unknown>) => Effect.Effect<unknown, unknown, R>;
8
+ readonly search: (args: Array<unknown>) => Effect.Effect<unknown, unknown, R>;
9
+ readonly toolKeys: (path: ReadonlyArray<string>) => ReadonlyArray<string>;
10
+ readonly promises: PromiseRuntime<R>;
11
+ readonly logs: Array<string>;
12
+ readonly runner: Runner<R>;
13
+ private readonly root;
14
+ constructor(executeTool: (path: ReadonlyArray<string>, args: Array<unknown>) => Effect.Effect<unknown, unknown, R>, search: (args: Array<unknown>) => Effect.Effect<unknown, unknown, R>, toolKeys: (path: ReadonlyArray<string>) => ReadonlyArray<string>, promises: PromiseRuntime<R>, logs?: Array<string>);
15
15
  run(program: Program): Effect.Effect<unknown, unknown, R>;
16
- private createToolCallPromise;
17
- private createPromise;
18
- private settlePromise;
19
- private evaluateStatement;
20
- private evaluateBlock;
21
- private createFunction;
22
- private hoistFunctions;
23
- private predeclareLexical;
24
- private predeclarePattern;
25
- private evaluateIfStatement;
26
- private evaluateSwitchStatement;
27
- private evaluateWhileStatement;
28
- private evaluateDoWhileStatement;
29
- private evaluateForStatement;
30
- private evaluateForOfStatement;
31
- private awaitValue;
32
- private awaitAsyncFromSyncValue;
33
- private syncIterator;
34
- private customIterator;
35
- private nextIteratorResult;
36
- private closeIterator;
37
- private requireIteratorObject;
38
- private requireIterator;
39
- private requireIteratorMethod;
40
- private enumerableKeys;
41
- private evaluateForInStatement;
42
- private evaluateBreakStatement;
43
- private evaluateContinueStatement;
44
- private evaluateLabeledStatement;
45
- private evaluateThrowStatement;
46
- private evaluateTryStatement;
47
- private evaluateVariableDeclaration;
48
- private declarePattern;
49
- private assignPattern;
50
- private destructureArrayPattern;
51
- private destructuringPropertyKey;
52
- private destructuringPropertyValue;
53
- private evaluateExpression;
54
- private evaluateNewExpression;
55
- private evaluateBinaryExpression;
56
- private applyBinaryOperator;
57
- private evaluateLogicalExpression;
58
- private evaluateUnaryExpression;
59
- private evaluateAssignmentExpression;
60
- private evaluateLogicalAssignment;
61
- private evaluateUpdateExpression;
62
- private evaluateCallExpression;
63
- private invokeCallable;
64
- private evaluateCallArguments;
65
- private invokeFunction;
66
- private createGenerator;
67
- private completeGeneratorRequests;
68
- private takeGeneratorRequest;
69
- private dequeueGeneratorRequest;
70
- private evaluateYieldExpression;
71
- private suspendGenerator;
72
- private delegateYield;
73
- private evaluateObjectExpression;
74
- private evaluateArrayExpression;
75
- private evaluateTemplateLiteral;
76
- private evaluateConditionalExpression;
77
- private applyCompoundAssignment;
78
- private getMemberReference;
79
- private readMember;
80
- private writeMember;
81
- private evaluateDeleteExpression;
82
- private modifyMember;
83
- private readReferenceValue;
84
- private assignToReference;
85
- private toPropertyKey;
86
16
  }
@@ -97,33 +97,47 @@ const copyIteratorSymbols = (source, target, consumed) => {
97
97
  }
98
98
  };
99
99
  const promiseResolutionNode = { type: "PromiseResolution", start: 0, end: 0 };
100
- export class Interpreter {
101
- scopes;
100
+ /** One program execution: the tool bridge, promise scheduler, captured logs, and the global scope built once. */
101
+ export class Runtime {
102
102
  executeTool;
103
- invokeSearch;
103
+ search;
104
104
  toolKeys;
105
- logs;
106
105
  promises;
107
- generatorState;
108
- generatorAsync = false;
109
- runner = {
110
- invokeFunction: (fn, args) => this.invokeFunction(fn, args),
111
- invokeCallable: (callable, args, node) => this.invokeCallable(callable, args, node),
112
- settlePromise: (promise) => this.settlePromise(promise),
113
- syncIterator: (value, node) => this.syncIterator(value, node),
114
- };
115
- constructor(executeTool, invokeSearch, toolKeys, promises, logs = []) {
116
- const globalScope = new Map();
117
- this.scopes = new ScopeStack([globalScope]);
106
+ logs;
107
+ runner;
108
+ root;
109
+ constructor(executeTool, search, toolKeys, promises, logs = []) {
118
110
  this.executeTool = executeTool;
119
- this.invokeSearch = invokeSearch;
111
+ this.search = search;
120
112
  this.toolKeys = toolKeys;
121
- this.logs = logs;
122
113
  this.promises = promises;
123
- const host = { runner: this.runner, promises, search: invokeSearch, toolKeys, logs };
124
- for (const [name, value] of globals(host))
114
+ this.logs = logs;
115
+ const globalScope = new Map();
116
+ // Calling back into the program never reads frame state, so any frame serves; the root is always alive.
117
+ this.root = new Frame(this, new ScopeStack([globalScope]));
118
+ this.runner = {
119
+ invokeFunction: (fn, args) => this.root.invokeFunction(fn, args),
120
+ invokeCallable: (callable, args, node) => this.root.invokeCallable(callable, args, node),
121
+ settlePromise: (promise) => this.root.settlePromise(promise),
122
+ syncIterator: (value, node) => this.root.syncIterator(value, node),
123
+ };
124
+ for (const [name, value] of globals(this))
125
125
  globalScope.set(name, { mutable: false, value });
126
126
  }
127
+ run(program) {
128
+ return this.root.run(program);
129
+ }
130
+ }
131
+ /** One activation: the top-level program or a single function call, evaluating against its own scope chain. */
132
+ class Frame {
133
+ runtime;
134
+ scopes;
135
+ generatorState;
136
+ generatorAsync = false;
137
+ constructor(runtime, scopes) {
138
+ this.runtime = runtime;
139
+ this.scopes = scopes;
140
+ }
127
141
  run(program) {
128
142
  const self = this;
129
143
  // Keep top-level declarations separate so they can shadow builtins.
@@ -147,20 +161,20 @@ export class Interpreter {
147
161
  }
148
162
  }
149
163
  // The implicit async body adopts returned promises before copy-out.
150
- value = yield* resolvePromiseValue(self.runner, value, program);
164
+ value = yield* resolvePromiseValue(self.runtime.runner, value, program);
151
165
  return value;
152
166
  }).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
153
167
  }
154
168
  // Fork at the call site so admission and hooks occur when the call is made.
155
169
  createToolCallPromise(path, args) {
156
- return this.createPromise(Effect.suspend(() => this.executeTool(path, args)));
170
+ return this.createPromise(Effect.suspend(() => this.runtime.executeTool(path, args)));
157
171
  }
158
172
  createPromise(effect) {
159
- return this.promises.create(effect);
173
+ return this.runtime.promises.create(effect);
160
174
  }
161
175
  // Fiber exits make settlement idempotent; yielding prevents inline continuation.
162
176
  settlePromise(promise) {
163
- const promises = this.promises;
177
+ const promises = this.runtime.promises;
164
178
  return Effect.suspend(() => {
165
179
  promises.markObserved(promise);
166
180
  return Effect.flatMap(promises.await(promise), (exit) => Effect.andThen(Effect.yieldNow, exit));
@@ -483,7 +497,7 @@ export class Interpreter {
483
497
  })));
484
498
  }
485
499
  awaitValue(value, node = promiseResolutionNode) {
486
- return Effect.flatMap(resolvePromise(this.runner, this.promises, value, node), (promise) => this.settlePromise(promise));
500
+ return Effect.flatMap(resolvePromise(this.runtime.runner, this.runtime.promises, value, node), (promise) => this.settlePromise(promise));
487
501
  }
488
502
  awaitAsyncFromSyncValue(iterator, value, node, closeOnRejection) {
489
503
  const self = this;
@@ -630,7 +644,7 @@ export class Interpreter {
630
644
  }
631
645
  enumerableKeys(value) {
632
646
  if (value instanceof ToolReference) {
633
- return [...this.toolKeys(value.path)];
647
+ return [...this.runtime.toolKeys(value.path)];
634
648
  }
635
649
  if (Array.isArray(value)) {
636
650
  return Object.keys(value);
@@ -1267,10 +1281,10 @@ export class Interpreter {
1267
1281
  return callable.generator.asynchronous ? yield* self.createPromise(requested) : yield* requested;
1268
1282
  }
1269
1283
  if (callable instanceof IntrinsicReference) {
1270
- return yield* invokeIntrinsic(self.runner, callable, args, node);
1284
+ return yield* invokeIntrinsic(self.runtime.runner, callable, args, node);
1271
1285
  }
1272
1286
  if (callable instanceof PromiseInstanceMethodReference) {
1273
- return yield* invokePromiseInstanceMethod(self.runner, self.promises, callable, args, node);
1287
+ return yield* invokePromiseInstanceMethod(self.runtime.runner, self.runtime.promises, callable, args, node);
1274
1288
  }
1275
1289
  if (callable instanceof HostFunction)
1276
1290
  return yield* callable.call(args, node);
@@ -1305,8 +1319,7 @@ export class Interpreter {
1305
1319
  });
1306
1320
  }
1307
1321
  invokeFunction(fn, args) {
1308
- const invocation = new Interpreter(this.executeTool, this.invokeSearch, this.toolKeys, this.promises, this.logs);
1309
- invocation.scopes = new ScopeStack([...fn.capturedScopes, new Map()]);
1322
+ const invocation = new Frame(this.runtime, new ScopeStack([...fn.capturedScopes, new Map()]));
1310
1323
  const run = Effect.gen(function* () {
1311
1324
  // Seed all parameters first so defaults cannot fall through to same-named outer bindings.
1312
1325
  const paramScope = invocation.scopes.current();
@@ -1334,7 +1347,7 @@ export class Interpreter {
1334
1347
  return run;
1335
1348
  // The initial yield assigns the promise before the body can self-resolve.
1336
1349
  const box = {};
1337
- return Effect.map(this.createPromise(Effect.flatMap(run, (value) => resolvePromiseValue(invocation.runner, value, fn.body, box))), (promise) => {
1350
+ return Effect.map(this.createPromise(Effect.flatMap(run, (value) => resolvePromiseValue(invocation.runtime.runner, value, fn.body, box))), (promise) => {
1338
1351
  box.promise = promise;
1339
1352
  return promise;
1340
1353
  });
@@ -1355,7 +1368,7 @@ export class Interpreter {
1355
1368
  if (state.draining)
1356
1369
  return Deferred.await(request.response);
1357
1370
  state.draining = true;
1358
- return Effect.andThen(this.promises.fork(invocation
1371
+ return Effect.andThen(this.runtime.promises.fork(invocation
1359
1372
  .completeGeneratorRequests(state, true)
1360
1373
  .pipe(Effect.ensuring(Effect.sync(() => (state.draining = false))))), Deferred.await(request.response));
1361
1374
  }
@@ -1393,7 +1406,7 @@ export class Interpreter {
1393
1406
  yield* invocation.completeGeneratorRequests(state, asynchronous);
1394
1407
  state.completed = true;
1395
1408
  });
1396
- return Effect.andThen(this.promises.fork(body), Deferred.await(request.response));
1409
+ return Effect.andThen(this.runtime.promises.fork(body), Deferred.await(request.response));
1397
1410
  }
1398
1411
  return Deferred.await(request.response);
1399
1412
  });
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-19370",
4
+ "version": "0.0.0-dev-19371",
5
5
  "description": "Effect-native confined code execution over schema-described tools",
6
6
  "type": "module",
7
7
  "license": "MIT",