@opencode/codemode 2.0.1 → 2.0.2

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 (61) hide show
  1. package/dist/data.d.ts +6 -5
  2. package/dist/data.js +44 -46
  3. package/dist/index.d.ts +0 -1
  4. package/dist/index.js +0 -1
  5. package/dist/interpreter/errors.d.ts +3 -4
  6. package/dist/interpreter/errors.js +40 -17
  7. package/dist/interpreter/execute.js +5 -3
  8. package/dist/interpreter/generators.d.ts +4 -0
  9. package/dist/interpreter/generators.js +25 -0
  10. package/dist/interpreter/globals.js +67 -46
  11. package/dist/interpreter/intrinsics.d.ts +8 -5
  12. package/dist/interpreter/intrinsics.js +59 -18
  13. package/dist/interpreter/model.d.ts +2 -32
  14. package/dist/interpreter/model.js +4 -38
  15. package/dist/interpreter/native.d.ts +19 -0
  16. package/dist/interpreter/native.js +40 -0
  17. package/dist/interpreter/objects.d.ts +105 -12
  18. package/dist/interpreter/objects.js +190 -66
  19. package/dist/interpreter/promises.d.ts +12 -13
  20. package/dist/interpreter/promises.js +52 -46
  21. package/dist/interpreter/references.d.ts +1 -0
  22. package/dist/interpreter/references.js +20 -33
  23. package/dist/interpreter/runner.d.ts +15 -13
  24. package/dist/interpreter/runner.js +19 -19
  25. package/dist/interpreter/runtime.d.ts +3 -3
  26. package/dist/interpreter/runtime.js +150 -314
  27. package/dist/stdlib/array.d.ts +4 -2
  28. package/dist/stdlib/array.js +423 -31
  29. package/dist/stdlib/collections.d.ts +3 -7
  30. package/dist/stdlib/collections.js +286 -114
  31. package/dist/stdlib/console.d.ts +3 -2
  32. package/dist/stdlib/console.js +35 -30
  33. package/dist/stdlib/date.d.ts +1 -7
  34. package/dist/stdlib/date.js +93 -188
  35. package/dist/stdlib/json.d.ts +2 -2
  36. package/dist/stdlib/json.js +24 -24
  37. package/dist/stdlib/math.d.ts +2 -2
  38. package/dist/stdlib/math.js +96 -76
  39. package/dist/stdlib/number.d.ts +3 -4
  40. package/dist/stdlib/number.js +94 -59
  41. package/dist/stdlib/object.d.ts +4 -4
  42. package/dist/stdlib/object.js +123 -49
  43. package/dist/stdlib/regexp.d.ts +6 -8
  44. package/dist/stdlib/regexp.js +71 -63
  45. package/dist/stdlib/string.d.ts +2 -2
  46. package/dist/stdlib/string.js +213 -50
  47. package/dist/stdlib/url.d.ts +5 -13
  48. package/dist/stdlib/url.js +196 -96
  49. package/dist/stdlib/value.d.ts +5 -4
  50. package/dist/stdlib/value.js +16 -16
  51. package/dist/stdlib/web.d.ts +4 -4
  52. package/dist/stdlib/web.js +8 -7
  53. package/dist/tool-runtime.d.ts +2 -1
  54. package/dist/tool-runtime.js +2 -2
  55. package/package.json +1 -1
  56. package/dist/interpreter/host.d.ts +0 -41
  57. package/dist/interpreter/host.js +0 -44
  58. package/dist/interpreter/methods.d.ts +0 -4
  59. package/dist/interpreter/methods.js +0 -837
  60. package/dist/values.d.ts +0 -37
  61. package/dist/values.js +0 -56
@@ -1,25 +1,25 @@
1
- import { sync } from "../interpreter/host.js";
2
- import { InterpreterRuntimeError } from "../interpreter/model.js";
3
1
  import { toProgram } from "../data.js";
4
- import { get, ProgramArray, ProgramError } from "../interpreter/objects.js";
5
- import { Values } from "../values.js";
2
+ import { fn } from "../interpreter/native.js";
3
+ import { InterpreterRuntimeError } from "../interpreter/model.js";
4
+ import { get, isWrapper, ProgramArray, ProgramDate, ProgramError, ProgramMap, ProgramRegExp, ProgramSet, ProgramURL, ProgramURLSearchParams, } from "../interpreter/objects.js";
6
5
  export const compoundOperators = new Set(["+=", "-=", "*=", "/=", "%=", "**=", "&=", "|=", "^=", "<<=", ">>=", ">>>="]);
6
+ /** The built-in string form of a value, without consulting program-defined `toString` methods. */
7
7
  export const coerceToString = (value) => {
8
8
  if (value === null)
9
9
  return "null";
10
10
  if (value === undefined)
11
11
  return "undefined";
12
- if (value instanceof Values.Date)
12
+ if (value instanceof ProgramDate)
13
13
  return Number.isFinite(value.time) ? new Date(value.time).toISOString() : "Invalid Date";
14
- if (value instanceof Values.RegExp)
14
+ if (value instanceof ProgramRegExp)
15
15
  return `/${value.regex.source}/${value.regex.flags}`;
16
- if (value instanceof Values.Map)
16
+ if (value instanceof ProgramMap)
17
17
  return "[object Map]";
18
- if (value instanceof Values.Set)
18
+ if (value instanceof ProgramSet)
19
19
  return "[object Set]";
20
- if (value instanceof Values.URL)
20
+ if (value instanceof ProgramURL)
21
21
  return value.url.href;
22
- if (value instanceof Values.URLSearchParams)
22
+ if (value instanceof ProgramURLSearchParams)
23
23
  return value.params.toString();
24
24
  if (value instanceof ProgramError) {
25
25
  // Match Error.prototype.toString: "name: message", or just one when the other is empty.
@@ -41,15 +41,15 @@ export const coerceToString = (value) => {
41
41
  return String(value);
42
42
  };
43
43
  export const coerceToNumber = (value) => {
44
- if (value instanceof Values.Date)
44
+ if (value instanceof ProgramDate)
45
45
  return value.time;
46
- if (Values.isValue(value))
46
+ if (isWrapper(value))
47
47
  return Number.NaN;
48
48
  if (value instanceof ProgramArray)
49
49
  return Number(coerceToString(value));
50
50
  return value !== null && typeof value === "object" ? Number.NaN : Number(value);
51
51
  };
52
- const coerce = (name, args, node) => {
52
+ const coerce = (runner, name, args, node) => {
53
53
  // Native: Number() is 0 and String() is "", unlike their undefined-argument forms; the
54
54
  // other coercers match native through the undefined-argument path below.
55
55
  if (args.length === 0) {
@@ -59,7 +59,7 @@ const coerce = (name, args, node) => {
59
59
  return "";
60
60
  }
61
61
  const raw = args[0];
62
- if (Values.isValue(raw)) {
62
+ if (isWrapper(raw)) {
63
63
  if (name === "Boolean")
64
64
  return true;
65
65
  if (name === "Number")
@@ -74,7 +74,7 @@ const coerce = (name, args, node) => {
74
74
  return parseInt(coerceToString(raw));
75
75
  return parseFloat(coerceToString(raw));
76
76
  }
77
- const value = toProgram(raw, `${name} input`);
77
+ const value = toProgram(runner.prototypes, raw, `${name} input`);
78
78
  if (name === "Number")
79
79
  return coerceToNumber(value);
80
80
  if (name === "Boolean")
@@ -95,4 +95,4 @@ const coerce = (name, args, node) => {
95
95
  return coerceToString(value);
96
96
  };
97
97
  /** A global coercion function such as `Number` or `parseInt`. */
98
- export const coercion = (name, options = {}) => sync(name, (args, node) => toProgram(coerce(name, args, node), `${name} result`), options);
98
+ export const coercion = (runner, name, length = 1) => fn(runner.prototypes, name, length, (_, args, node) => toProgram(runner.prototypes, coerce(runner, name, args, node), `${name} result`));
@@ -1,4 +1,4 @@
1
- import { HostNamespace } from "../interpreter/host.js";
2
- export declare const atobGlobal: import("../interpreter/host.js").HostFunction<never>;
3
- export declare const btoaGlobal: import("../interpreter/host.js").HostFunction<never>;
4
- export declare const cryptoGlobal: HostNamespace;
1
+ import { ProgramObject } from "../interpreter/objects.js";
2
+ import type { Runner } from "../interpreter/runner.js";
3
+ export declare const base64Global: <R>(runner: Runner<R>, name: "atob" | "btoa") => import("../interpreter/objects.js").NativeFunction<R>;
4
+ export declare const cryptoGlobal: <R>(runner: Runner<R>) => ProgramObject;
@@ -1,9 +1,10 @@
1
- import { HostNamespace, sync } from "../interpreter/host.js";
1
+ import { fn, methods } from "../interpreter/native.js";
2
2
  import { InterpreterRuntimeError } from "../interpreter/model.js";
3
+ import { ProgramObject } from "../interpreter/objects.js";
3
4
  import { coerceToString } from "./value.js";
4
5
  // WebIDL DOMString conversion: a missing argument is a TypeError, anything else stringifies. Invalid input is a
5
6
  // TypeError as well; browsers throw a DOMException named InvalidCharacterError, which CodeMode does not have.
6
- const base64 = (name) => sync(name, (args, node) => {
7
+ export const base64Global = (runner, name) => fn(runner.prototypes, name, 1, (_, args, node) => {
7
8
  if (args.length === 0)
8
9
  throw new InterpreterRuntimeError(`${name} requires 1 argument (a string)`, node);
9
10
  const input = coerceToString(args[0]);
@@ -14,8 +15,8 @@ const base64 = (name) => sync(name, (args, node) => {
14
15
  throw new InterpreterRuntimeError("The string contains invalid characters.", node);
15
16
  }
16
17
  });
17
- export const atobGlobal = base64("atob");
18
- export const btoaGlobal = base64("btoa");
19
- export const cryptoGlobal = new HostNamespace("crypto", {
20
- randomUUID: sync("crypto.randomUUID", () => crypto.randomUUID()),
21
- });
18
+ export const cryptoGlobal = (runner) => {
19
+ const object = new ProgramObject(runner.prototypes.Object);
20
+ methods(runner.prototypes, object, [["randomUUID", 0, () => crypto.randomUUID()]]);
21
+ return object;
22
+ };
@@ -1,4 +1,5 @@
1
1
  import { Effect } from "effect";
2
+ import type { Prototypes } from "./interpreter/intrinsics.js";
2
3
  import { type Namespace } from "./namespace.js";
3
4
  import { type Tool } from "./tool.js";
4
5
  import type { Tools } from "./tools.js";
@@ -65,5 +66,5 @@ export type ToolRuntime<R = never> = {
65
66
  readonly keys: (path: ReadonlyArray<string>) => ReadonlyArray<string>;
66
67
  };
67
68
  /** Per-execution call state over tools prepared once for the runtime. */
68
- export declare const make: <R>(prepared: Prepared<R>, maxToolCalls: number | undefined, hooks?: ToolCallHooks<R>) => ToolRuntime<R>;
69
+ export declare const make: <R>(prepared: Prepared<R>, prototypes: Prototypes, maxToolCalls: number | undefined, hooks?: ToolCallHooks<R>) => ToolRuntime<R>;
69
70
  export * as ToolRuntime from "./tool-runtime.js";
@@ -184,7 +184,7 @@ const resolve = (root, path) => {
184
184
  return node.tool;
185
185
  };
186
186
  /** Per-execution call state over tools prepared once for the runtime. */
187
- export const make = (prepared, maxToolCalls, hooks) => {
187
+ export const make = (prepared, prototypes, maxToolCalls, hooks) => {
188
188
  const calls = [];
189
189
  const root = prepared.root;
190
190
  const searchTool = makeSearchTool(prepared.searchIndex);
@@ -234,7 +234,7 @@ export const make = (prepared, maxToolCalls, hooks) => {
234
234
  .join("\n")));
235
235
  }));
236
236
  return yield* Effect.try({
237
- try: () => fromData(decodeToolOutput(tool, raw), `Result from tool '${name}'`),
237
+ try: () => fromData(prototypes, decodeToolOutput(tool, raw), `Result from tool '${name}'`),
238
238
  catch: (cause) => new ToolRuntimeError("InvalidToolOutput", `Invalid output from tool '${name}': ${cause}`),
239
239
  });
240
240
  }), call);
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": "2.0.1",
4
+ "version": "2.0.2",
5
5
  "description": "Effect-native confined code execution over schema-described tools",
6
6
  "type": "module",
7
7
  "license": "MIT",
@@ -1,41 +0,0 @@
1
- import { Effect } from "effect";
2
- import { type AstNode } from "./model.js";
3
- export type HostCall<R> = (args: Array<unknown>, node: AstNode) => Effect.Effect<unknown, unknown, R>;
4
- type HostMember = (key: PropertyKey, node: AstNode) => unknown;
5
- type HostFunctionOptions<R> = {
6
- readonly name: string;
7
- readonly call: HostCall<R>;
8
- /** `new name(...)`; without it `new` is unsupported syntax. */
9
- readonly construct?: HostCall<R>;
10
- /** Static members read through `name.key`; unknown keys read as `undefined` unless the function decides otherwise. */
11
- readonly members?: Record<string, unknown> | HostMember;
12
- /** `value instanceof name`; without it the operator rejects this right-hand side. */
13
- readonly instanceOf?: (value: unknown) => boolean;
14
- /** Whether callback sites (array methods, replacers, promise reactions) admit this function. Defaults to true. */
15
- readonly callback?: boolean;
16
- };
17
- /** A host-implemented function value. `typeof` is "function". */
18
- export declare class HostFunction<R = never> {
19
- readonly name: string;
20
- readonly call: HostCall<R>;
21
- readonly construct: HostCall<R> | undefined;
22
- readonly member: HostMember;
23
- readonly instanceOf: ((value: unknown) => boolean) | undefined;
24
- readonly callback: boolean;
25
- constructor(options: HostFunctionOptions<R>);
26
- }
27
- /** A host-implemented object of static members. `typeof` is "object" and it is not callable. */
28
- export declare class HostNamespace {
29
- readonly name: string;
30
- readonly member: HostMember;
31
- constructor(name: string, members: Record<string, unknown> | HostMember);
32
- }
33
- export type SyncOptions = Omit<HostFunctionOptions<never>, "name" | "call">;
34
- type SyncImpl = (args: Array<unknown>, node: AstNode) => unknown;
35
- /** Lifts a synchronous implementation, which may throw `InterpreterRuntimeError`, into a host call. */
36
- export declare const syncCall: (impl: SyncImpl) => HostCall<never>;
37
- /** A synchronous host function. */
38
- export declare const sync: (name: string, impl: SyncImpl, options?: SyncOptions) => HostFunction<never>;
39
- /** The `call` of a constructor that JS requires to be invoked with `new`. */
40
- export declare const requiresNew: (name: string) => HostCall<never>;
41
- export {};
@@ -1,44 +0,0 @@
1
- import { Effect } from "effect";
2
- import { InterpreterRuntimeError } from "./model.js";
3
- /** A host-implemented function value. `typeof` is "function". */
4
- export class HostFunction {
5
- name;
6
- call;
7
- construct;
8
- member;
9
- instanceOf;
10
- callback;
11
- constructor(options) {
12
- this.name = options.name;
13
- this.call = options.call;
14
- this.construct = options.construct;
15
- this.member = memberLookup(options.members);
16
- this.instanceOf = options.instanceOf;
17
- this.callback = options.callback ?? true;
18
- }
19
- }
20
- /** A host-implemented object of static members. `typeof` is "object" and it is not callable. */
21
- export class HostNamespace {
22
- name;
23
- member;
24
- constructor(name, members) {
25
- this.name = name;
26
- this.member = memberLookup(members);
27
- }
28
- }
29
- const memberLookup = (members) => {
30
- if (members === undefined)
31
- return () => undefined;
32
- if (typeof members === "function")
33
- return members;
34
- const table = new Map(Object.entries(members));
35
- return (key) => (typeof key === "string" ? table.get(key) : undefined);
36
- };
37
- /** Lifts a synchronous implementation, which may throw `InterpreterRuntimeError`, into a host call. */
38
- export const syncCall = (impl) => (args, node) => Effect.sync(() => impl(args, node));
39
- /** A synchronous host function. */
40
- export const sync = (name, impl, options = {}) => new HostFunction({ name, call: syncCall(impl), ...options });
41
- /** The `call` of a constructor that JS requires to be invoked with `new`. */
42
- export const requiresNew = (name) => (_, node) => Effect.sync(() => {
43
- throw new InterpreterRuntimeError(`Constructor ${name} requires 'new'.`, node);
44
- });
@@ -1,4 +0,0 @@
1
- import { Effect } from "effect";
2
- import { type AstNode, IntrinsicReference } from "./model.js";
3
- import { type Runner } from "./runner.js";
4
- export declare const invokeIntrinsic: <R>(runner: Runner<R>, ref: IntrinsicReference, args: Array<unknown>, node: AstNode) => Effect.Effect<unknown, unknown, R>;