@opencode/codemode 0.0.0-beta-19296 → 0.0.0-beta-19365

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 (41) hide show
  1. package/README.md +6 -0
  2. package/dist/codemode.d.ts +8 -11
  3. package/dist/codemode.js +4 -8
  4. package/dist/data.d.ts +28 -0
  5. package/dist/data.js +130 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +1 -0
  8. package/dist/interpreter/errors.d.ts +1 -1
  9. package/dist/interpreter/errors.js +2 -2
  10. package/dist/interpreter/execute.d.ts +3 -3
  11. package/dist/interpreter/execute.js +9 -15
  12. package/dist/interpreter/methods.d.ts +9 -2
  13. package/dist/interpreter/methods.js +54 -76
  14. package/dist/interpreter/model.d.ts +12 -32
  15. package/dist/interpreter/model.js +0 -31
  16. package/dist/interpreter/promises.d.ts +8 -8
  17. package/dist/interpreter/promises.js +4 -4
  18. package/dist/interpreter/references.js +12 -42
  19. package/dist/interpreter/runtime.d.ts +2 -3
  20. package/dist/interpreter/runtime.js +255 -311
  21. package/dist/openapi/spec.js +1 -1
  22. package/dist/stdlib/console.js +14 -14
  23. package/dist/stdlib/date.d.ts +2 -2
  24. package/dist/stdlib/date.js +1 -1
  25. package/dist/stdlib/json.js +17 -26
  26. package/dist/stdlib/number.d.ts +1 -1
  27. package/dist/stdlib/number.js +4 -3
  28. package/dist/stdlib/object.js +11 -10
  29. package/dist/stdlib/regexp.d.ts +2 -2
  30. package/dist/stdlib/regexp.js +3 -3
  31. package/dist/stdlib/string.d.ts +1 -1
  32. package/dist/stdlib/string.js +1 -1
  33. package/dist/stdlib/url.d.ts +3 -3
  34. package/dist/stdlib/url.js +7 -6
  35. package/dist/stdlib/value.d.ts +2 -3
  36. package/dist/stdlib/value.js +14 -15
  37. package/dist/tool-runtime.d.ts +16 -15
  38. package/dist/tool-runtime.js +13 -150
  39. package/dist/values.d.ts +22 -16
  40. package/dist/values.js +23 -17
  41. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
1
  import { Cause, Effect, Exit, Formatter, Schema } from "effect";
2
+ import { fromData, toData, ToolRuntimeError } from "./data.js";
2
3
  import { toolError } from "./tool-error.js";
3
4
  import { decodeInput as decodeToolInput, decodeOutput as decodeToolOutput, identifierSegment, inputProperties, inputTypeScript, isEmptyInput, outputTypeScript, } from "./tool-schema.js";
4
5
  import { isNamespace } from "./namespace.js";
5
6
  import { isTool } from "./tool.js";
6
- import { CodeModeDate, CodeModeMap, CodeModePromise, CodeModeRegExp, CodeModeSet, CodeModeURL, CodeModeURLSearchParams, } from "./values.js";
7
- const compareText = (left, right) => (left < right ? -1 : left > right ? 1 : 0);
7
+ export const compareText = (left, right) => (left < right ? -1 : left > right ? 1 : 0);
8
8
  const defaultSearchLimit = 10;
9
9
  const PositiveInt = Schema.Int.check(Schema.isGreaterThan(0));
10
10
  const NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
@@ -35,143 +35,6 @@ export class ToolReference {
35
35
  this.path = path;
36
36
  }
37
37
  }
38
- const MAX_VALUE_DEPTH = 32;
39
- export class ToolRuntimeError extends Error {
40
- kind;
41
- suggestions;
42
- constructor(kind, message, suggestions = []) {
43
- super(message);
44
- this.kind = kind;
45
- this.suggestions = suggestions;
46
- this.name = "ToolRuntimeError";
47
- }
48
- }
49
- const blockedMemberNames = new Set(["__proto__", "constructor", "prototype"]);
50
- export const isBlockedMember = (name) => blockedMemberNames.has(name);
51
- // Checkpoint mode preserves CodeMode values; boundary mode JSON-normalizes them.
52
- export const copyIn = (value, label, preserveCodeModeValues = false) => copyBounded(value, label, 0, new Set(), preserveCodeModeValues);
53
- const copyBounded = (value, label, depth, seen, preserveCodeModeValues) => {
54
- if (depth > MAX_VALUE_DEPTH) {
55
- throw new ToolRuntimeError("InvalidDataValue", `${label} exceeds the maximum value depth of ${MAX_VALUE_DEPTH}.`);
56
- }
57
- if (value === null ||
58
- value === undefined ||
59
- typeof value === "string" ||
60
- typeof value === "boolean" ||
61
- typeof value === "number") {
62
- return value;
63
- }
64
- if (typeof value !== "object") {
65
- throw new ToolRuntimeError("InvalidDataValue", `${label} must contain data only.`);
66
- }
67
- if (value instanceof CodeModePromise) {
68
- throw new ToolRuntimeError("InvalidDataValue", `${label} contains an un-awaited Promise; await tool calls (e.g. \`const result = await tools.ns.tool(...)\`) before using their results.`);
69
- }
70
- if (preserveCodeModeValues) {
71
- if (value instanceof CodeModeDate ||
72
- value instanceof CodeModeRegExp ||
73
- value instanceof CodeModeMap ||
74
- value instanceof CodeModeSet ||
75
- value instanceof CodeModeURL ||
76
- value instanceof CodeModeURLSearchParams) {
77
- return value;
78
- }
79
- if (value instanceof Date)
80
- return new CodeModeDate(value.getTime());
81
- if (value instanceof RegExp)
82
- return new CodeModeRegExp(value.source, value.flags);
83
- if (value instanceof Map) {
84
- const wrapped = new CodeModeMap();
85
- for (const [key, item] of value.entries()) {
86
- wrapped.map.set(copyBounded(key, label, depth + 1, seen, true), copyBounded(item, label, depth + 1, seen, true));
87
- }
88
- return wrapped;
89
- }
90
- if (value instanceof Set) {
91
- const wrapped = new CodeModeSet();
92
- for (const item of value.values())
93
- wrapped.set.add(copyBounded(item, label, depth + 1, seen, true));
94
- return wrapped;
95
- }
96
- if (value instanceof URL)
97
- return new CodeModeURL(new URL(value.href));
98
- if (value instanceof URLSearchParams)
99
- return new CodeModeURLSearchParams(new URLSearchParams(value));
100
- }
101
- if (value instanceof CodeModeDate) {
102
- return Number.isFinite(value.time) ? new Date(value.time).toISOString() : null;
103
- }
104
- if (value instanceof Date) {
105
- return Number.isFinite(value.getTime()) ? value.toISOString() : null;
106
- }
107
- if (value instanceof CodeModeURL)
108
- return value.url.href;
109
- if (value instanceof URL)
110
- return value.href;
111
- if (value instanceof CodeModeRegExp ||
112
- value instanceof CodeModeMap ||
113
- value instanceof CodeModeSet ||
114
- value instanceof CodeModeURLSearchParams ||
115
- value instanceof RegExp ||
116
- value instanceof Map ||
117
- value instanceof Set ||
118
- value instanceof URLSearchParams) {
119
- return Object.create(null);
120
- }
121
- if (seen.has(value)) {
122
- throw new ToolRuntimeError("InvalidDataValue", `${label} contains a circular value.`);
123
- }
124
- seen.add(value);
125
- if (Array.isArray(value)) {
126
- const copied = value.map((item) => copyBounded(item, label, depth + 1, seen, preserveCodeModeValues));
127
- if (preserveCodeModeValues) {
128
- // Checkpoint copies retain array metadata that boundary copies omit.
129
- for (const [key, item] of Object.entries(value)) {
130
- if (Object.hasOwn(copied, key))
131
- continue;
132
- if (isBlockedMember(key)) {
133
- throw new ToolRuntimeError("InvalidDataValue", `${label} contains blocked property '${key}'.`);
134
- }
135
- Reflect.set(copied, key, copyBounded(item, label, depth + 1, seen, true));
136
- }
137
- }
138
- seen.delete(value);
139
- return copied;
140
- }
141
- const prototype = Object.getPrototypeOf(value);
142
- if (prototype !== Object.prototype && prototype !== null) {
143
- throw new ToolRuntimeError("InvalidDataValue", `${label} must contain plain objects only.`);
144
- }
145
- const copied = Object.create(null);
146
- for (const [key, item] of Object.entries(value)) {
147
- if (isBlockedMember(key)) {
148
- throw new ToolRuntimeError("InvalidDataValue", `${label} contains blocked property '${key}'.`);
149
- }
150
- copied[key] = copyBounded(item, label, depth + 1, seen, preserveCodeModeValues);
151
- }
152
- seen.delete(value);
153
- return copied;
154
- };
155
- export const copyOut = (value, mode) => {
156
- if (value === undefined && mode === "nullify")
157
- return null;
158
- if (typeof value === "number" && !Number.isFinite(value)) {
159
- return null;
160
- }
161
- if (Array.isArray(value)) {
162
- // Array.from densifies holes so sparse arrays normalize at the boundary like JSON does.
163
- return Array.from(value, (item) => {
164
- const copied = copyOut(item, mode);
165
- return copied === undefined && mode === "json" ? null : copied;
166
- });
167
- }
168
- if (value !== null && typeof value === "object" && !(value instanceof ToolReference)) {
169
- return Object.fromEntries(Object.entries(value)
170
- .map(([key, item]) => [key, copyOut(item, mode)])
171
- .filter(([, item]) => !(item === undefined && mode === "json")));
172
- }
173
- return value;
174
- };
175
38
  const toolTrie = (tools) => {
176
39
  const root = { children: new Map() };
177
40
  const insert = (node, group) => {
@@ -212,8 +75,6 @@ const describeTool = (visible) => ({
212
75
  ? `${toolExpression(visible.path)}(): Promise<${outputTypeScript(visible.tool, true)}>`
213
76
  : `${toolExpression(visible.path)}(input: ${inputTypeScript(visible.tool, true)}): Promise<${outputTypeScript(visible.tool, true)}>`,
214
77
  });
215
- // Discovery bytes are durable instructions, so order only after canonical-path collisions settle.
216
- const visibleTools = (tools) => flattenTools(toolTrie(tools)).sort((left, right) => compareText(left.path, right.path));
217
78
  const tokenize = (query) => query
218
79
  .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
219
80
  .toLowerCase()
@@ -290,10 +151,12 @@ const toSearchEntry = (visible) => ({
290
151
  .join("\n")
291
152
  .toLowerCase(),
292
153
  });
293
- export const searchIndex = (tools) => visibleTools(tools).map(toSearchEntry);
294
154
  export const prepare = (tools) => {
295
- const visible = visibleTools(tools);
155
+ const root = toolTrie(tools);
156
+ // Discovery bytes are durable instructions, so order only after canonical-path collisions settle.
157
+ const visible = flattenTools(root).sort((left, right) => compareText(left.path, right.path));
296
158
  return {
159
+ root,
297
160
  catalog: visible.map(describeTool),
298
161
  searchIndex: visible.map(toSearchEntry),
299
162
  };
@@ -320,10 +183,11 @@ const resolve = (root, path) => {
320
183
  }
321
184
  return node.tool;
322
185
  };
323
- export const make = (tools, maxToolCalls, searchIndex, hooks) => {
186
+ /** Per-execution call state over tools prepared once for the runtime. */
187
+ export const make = (prepared, maxToolCalls, hooks) => {
324
188
  const calls = [];
325
- const root = toolTrie(tools);
326
- const searchTool = makeSearchTool(searchIndex);
189
+ const root = prepared.root;
190
+ const searchTool = makeSearchTool(prepared.searchIndex);
327
191
  const observeEnd = (effect, call) => {
328
192
  const onEnd = hooks?.onToolCallEnd;
329
193
  if (onEnd === undefined)
@@ -370,19 +234,18 @@ export const make = (tools, maxToolCalls, searchIndex, hooks) => {
370
234
  .join("\n")));
371
235
  }));
372
236
  return yield* Effect.try({
373
- try: () => copyIn(decodeToolOutput(tool, raw), `Result from tool '${name}'`),
237
+ try: () => fromData(decodeToolOutput(tool, raw), `Result from tool '${name}'`),
374
238
  catch: (cause) => new ToolRuntimeError("InvalidToolOutput", `Invalid output from tool '${name}': ${cause}`),
375
239
  });
376
240
  }), call);
377
241
  });
378
242
  return {
379
- root: new ToolReference([]),
380
243
  calls,
381
244
  keys: (path) => namespaceKeys(root, path),
382
- search: (args) => Effect.suspend(() => executeTool("search", searchTool, args.map((arg) => copyOut(copyIn(arg, "Arguments for tool 'search'"), "json")))),
245
+ search: (args) => Effect.suspend(() => executeTool("search", searchTool, args.map((arg) => toData(arg, "Arguments for tool 'search'")))),
383
246
  execute: (path, args) => Effect.gen(function* () {
384
247
  const name = canonicalSegments(path).join(".");
385
- const externalArgs = args.map((arg) => copyOut(copyIn(arg, `Arguments for tool '${name}'`), "json"));
248
+ const externalArgs = args.map((arg) => toData(arg, `Arguments for tool '${name}'`));
386
249
  const tool = resolve(root, path);
387
250
  return yield* executeTool(name, tool, externalArgs);
388
251
  }),
package/dist/values.d.ts CHANGED
@@ -1,31 +1,37 @@
1
+ export * as Values from "./values.js";
1
2
  import type { Fiber } from "effect";
2
- export declare class CodeModePromise {
3
+ /**
4
+ * Runtime values the interpreter recognizes by class. Each wraps the host value it stands for,
5
+ * so hosts construct these to hand a value to a program and receive them back unchanged.
6
+ */
7
+ export declare class Promise {
3
8
  readonly fiber: Fiber.Fiber<unknown, unknown>;
4
9
  constructor(fiber: Fiber.Fiber<unknown, unknown>);
5
10
  }
6
- export declare class CodeModeDate {
11
+ export declare class Date {
7
12
  time: number;
8
13
  constructor(time: number);
9
14
  }
10
- export declare class CodeModeRegExp {
11
- readonly regex: RegExp;
15
+ export declare class RegExp {
16
+ readonly regex: globalThis.RegExp;
12
17
  constructor(pattern: string, flags: string);
13
18
  get lastIndex(): unknown;
14
19
  set lastIndex(value: unknown);
15
20
  }
16
- export declare class CodeModeMap {
17
- readonly map: Map<unknown, unknown>;
21
+ export declare class Map {
22
+ readonly map: globalThis.Map<unknown, unknown>;
18
23
  }
19
- export declare class CodeModeSet {
20
- readonly set: Set<unknown>;
24
+ export declare class Set {
25
+ readonly set: globalThis.Set<unknown>;
21
26
  }
22
- export declare class CodeModeURLSearchParams {
23
- readonly params: URLSearchParams;
24
- constructor(params: URLSearchParams);
27
+ export declare class URLSearchParams {
28
+ readonly params: globalThis.URLSearchParams;
29
+ constructor(params: globalThis.URLSearchParams);
25
30
  }
26
- export declare class CodeModeURL {
27
- readonly url: URL;
28
- readonly searchParams: CodeModeURLSearchParams;
29
- constructor(url: URL);
31
+ export declare class URL {
32
+ readonly url: globalThis.URL;
33
+ readonly searchParams: URLSearchParams;
34
+ constructor(url: globalThis.URL);
30
35
  }
31
- export declare const isCodeModeValue: (value: unknown) => value is CodeModeDate | CodeModeRegExp | CodeModeMap | CodeModeSet | CodeModeURL | CodeModeURLSearchParams;
36
+ /** Data-like runtime values; excludes Promise, which never crosses a boundary. */
37
+ export declare const isValue: (value: unknown) => value is Date | RegExp | Map | Set | URL | URLSearchParams;
package/dist/values.js CHANGED
@@ -1,19 +1,24 @@
1
- export class CodeModePromise {
1
+ export * as Values from "./values.js";
2
+ /**
3
+ * Runtime values the interpreter recognizes by class. Each wraps the host value it stands for,
4
+ * so hosts construct these to hand a value to a program and receive them back unchanged.
5
+ */
6
+ export class Promise {
2
7
  fiber;
3
8
  constructor(fiber) {
4
9
  this.fiber = fiber;
5
10
  }
6
11
  }
7
- export class CodeModeDate {
12
+ export class Date {
8
13
  time;
9
14
  constructor(time) {
10
15
  this.time = time;
11
16
  }
12
17
  }
13
- export class CodeModeRegExp {
18
+ export class RegExp {
14
19
  regex;
15
20
  constructor(pattern, flags) {
16
- this.regex = new RegExp(pattern, flags);
21
+ this.regex = new globalThis.RegExp(pattern, flags);
17
22
  }
18
23
  get lastIndex() {
19
24
  return Reflect.get(this.regex, "lastIndex");
@@ -22,29 +27,30 @@ export class CodeModeRegExp {
22
27
  Reflect.set(this.regex, "lastIndex", value);
23
28
  }
24
29
  }
25
- export class CodeModeMap {
26
- map = new Map();
30
+ export class Map {
31
+ map = new globalThis.Map();
27
32
  }
28
- export class CodeModeSet {
29
- set = new Set();
33
+ export class Set {
34
+ set = new globalThis.Set();
30
35
  }
31
- export class CodeModeURLSearchParams {
36
+ export class URLSearchParams {
32
37
  params;
33
38
  constructor(params) {
34
39
  this.params = params;
35
40
  }
36
41
  }
37
- export class CodeModeURL {
42
+ export class URL {
38
43
  url;
39
44
  searchParams;
40
45
  constructor(url) {
41
46
  this.url = url;
42
- this.searchParams = new CodeModeURLSearchParams(url.searchParams);
47
+ this.searchParams = new URLSearchParams(url.searchParams);
43
48
  }
44
49
  }
45
- export const isCodeModeValue = (value) => value instanceof CodeModeDate ||
46
- value instanceof CodeModeRegExp ||
47
- value instanceof CodeModeMap ||
48
- value instanceof CodeModeSet ||
49
- value instanceof CodeModeURL ||
50
- value instanceof CodeModeURLSearchParams;
50
+ /** Data-like runtime values; excludes Promise, which never crosses a boundary. */
51
+ export const isValue = (value) => value instanceof Date ||
52
+ value instanceof RegExp ||
53
+ value instanceof Map ||
54
+ value instanceof Set ||
55
+ value instanceof URL ||
56
+ value instanceof URLSearchParams;
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-beta-19296",
4
+ "version": "0.0.0-beta-19365",
5
5
  "description": "Effect-native confined code execution over schema-described tools",
6
6
  "type": "module",
7
7
  "license": "MIT",