@executor-js/codemode-core 0.0.1 → 0.1.0

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/README.md CHANGED
@@ -1,15 +1,15 @@
1
- # @executor/codemode-core
1
+ # @executor-js/codemode-core
2
2
 
3
3
  Core primitives for "code mode" — the pattern where an LLM writes TypeScript/JavaScript that calls into a pre-registered set of tools, executed in a sandbox. This package provides the shared type surface (`Tool`, `SandboxToolInvoker`, `CodeExecutor`), JSON Schema helpers, and error types used by every runtime that implements the contract.
4
4
 
5
- Most callers depend on this transitively through `@executor/execution` and a sandbox runtime like `@executor/runtime-quickjs`. Install directly when you're authoring a new runtime.
5
+ Most callers depend on this transitively through `@executor-js/execution` and a sandbox runtime like `@executor-js/runtime-quickjs`. Install directly when you're authoring a new runtime.
6
6
 
7
7
  ## Install
8
8
 
9
9
  ```sh
10
- bun add @executor/codemode-core
10
+ bun add @executor-js/codemode-core
11
11
  # or
12
- npm install @executor/codemode-core
12
+ npm install @executor-js/codemode-core
13
13
  ```
14
14
 
15
15
  ## Usage
@@ -17,19 +17,27 @@ npm install @executor/codemode-core
17
17
  Implement a runtime that satisfies `CodeExecutor`:
18
18
 
19
19
  ```ts
20
- import type { CodeExecutor, SandboxToolInvoker } from "@executor/codemode-core";
20
+ import type {
21
+ CodeExecutor,
22
+ ExecuteResult,
23
+ SandboxToolInvoker,
24
+ } from "@executor-js/codemode-core";
21
25
  import { Effect } from "effect";
22
26
 
23
27
  export const makeMyRuntime = (): CodeExecutor => ({
24
28
  execute: (code: string, invoker: SandboxToolInvoker) =>
25
29
  Effect.gen(function* () {
26
- // Spin up your sandbox, expose `invoker` as `tools.<path>(...)`, run the code,
27
- // collect logs, and return an ExecuteResult.
30
+ // Spin up your sandbox, expose `invoker` as `tools.<path>(...)`, run
31
+ // the code, collect logs, and return an ExecuteResult.
32
+ void code;
33
+ void invoker;
34
+ const result: ExecuteResult = { result: undefined, logs: [] };
35
+ return result;
28
36
  }),
29
37
  });
30
38
  ```
31
39
 
32
- The runtime is passed a `SandboxToolInvoker` that bridges sandbox-side tool calls back to the executor. The sandbox-visible API is whatever you decide — `@executor/runtime-quickjs` exposes a `tools` proxy object; a runtime targeting Cloudflare Workers might use something else.
40
+ The runtime is passed a `SandboxToolInvoker` that bridges sandbox-side tool calls back to the executor. The sandbox-visible API is whatever you decide — `@executor-js/runtime-quickjs` exposes a `tools` proxy object; a runtime targeting Cloudflare Workers might use something else.
33
41
 
34
42
  ## Status
35
43
 
@@ -1 +1 @@
1
- {"version":3,"file":"code-recovery.d.ts","sourceRoot":"","sources":["../src/code-recovery.ts"],"names":[],"mappings":"AAuIA,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,MASnD,CAAC"}
1
+ {"version":3,"file":"code-recovery.d.ts","sourceRoot":"","sources":["../src/code-recovery.ts"],"names":[],"mappings":"AAyIA,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,MASnD,CAAC"}
@@ -7,5 +7,22 @@ export declare class KernelCoreEffectError extends KernelCoreEffectError_base<{
7
7
  }> {
8
8
  }
9
9
  export declare const kernelCoreEffectError: (module: string, message: string) => KernelCoreEffectError;
10
+ declare const CodeExecutionError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
11
+ readonly _tag: "CodeExecutionError";
12
+ } & Readonly<A>;
13
+ /**
14
+ * Default failure type for any `CodeExecutor.execute` implementation —
15
+ * surfaces sandbox-level defects (isolate crash, module load failure,
16
+ * worker loader error) as a typed error so callers can handle them
17
+ * structurally instead of untyped `unknown`. Runtimes that want a
18
+ * narrower error shape can define their own `Data.TaggedError` subclass
19
+ * and parameterize `CodeExecutor<MyError>`.
20
+ */
21
+ export declare class CodeExecutionError extends CodeExecutionError_base<{
22
+ readonly runtime: string;
23
+ readonly message: string;
24
+ readonly cause?: unknown;
25
+ }> {
26
+ }
10
27
  export {};
11
28
  //# sourceMappingURL=effect-errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"effect-errors.d.ts","sourceRoot":"","sources":["../src/effect-errors.ts"],"names":[],"mappings":";;;AAEA,qBAAa,qBAAsB,SAAQ,2BAA0C;IACnF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAEL,eAAO,MAAM,qBAAqB,GAAI,QAAQ,MAAM,EAAE,SAAS,MAAM,0BACrB,CAAC"}
1
+ {"version":3,"file":"effect-errors.d.ts","sourceRoot":"","sources":["../src/effect-errors.ts"],"names":[],"mappings":";;;AAEA,qBAAa,qBAAsB,SAAQ,2BAA0C;IACnF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAEL,eAAO,MAAM,qBAAqB,GAAI,QAAQ,MAAM,EAAE,SAAS,MAAM,0BACrB,CAAC;;;;AAEjD;;;;;;;GAOG;AACH,qBAAa,kBAAmB,SAAQ,wBAAuC;IAC7E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;CAAG"}
package/dist/index.js CHANGED
@@ -18,6 +18,8 @@ import * as Data from "effect/Data";
18
18
  var KernelCoreEffectError = class extends Data.TaggedError("KernelCoreEffectError") {
19
19
  };
20
20
  var kernelCoreEffectError = (module, message) => new KernelCoreEffectError({ module, message });
21
+ var CodeExecutionError = class extends Data.TaggedError("CodeExecutionError") {
22
+ };
21
23
 
22
24
  // src/validation.ts
23
25
  var getSchemaValidator = (schema) => {
@@ -216,6 +218,7 @@ var recoverExecutionBody = (code) => {
216
218
  }
217
219
  };
218
220
  export {
221
+ CodeExecutionError,
219
222
  KernelCoreEffectError,
220
223
  asToolPath,
221
224
  kernelCoreEffectError,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/validation.ts","../src/effect-errors.ts","../src/json-schema.ts","../src/code-recovery.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type * as Effect from \"effect/Effect\";\n\n/** Branded tool path */\nexport type ToolPath = string & { readonly __toolPath: unique symbol };\n\nexport const asToolPath = (value: string): ToolPath => value as ToolPath;\n\n/** Standard Schema alias */\nexport type StandardSchema<Input = unknown, Output = unknown> = StandardSchemaV1<Input, Output>;\n\n/** A tool that can be invoked */\nexport interface Tool {\n readonly path: ToolPath;\n readonly description?: string;\n readonly inputSchema: StandardSchema;\n readonly outputSchema?: StandardSchema;\n readonly execute: (input: unknown) => unknown | Promise<unknown>;\n}\n\n/** Invoke a tool by path from inside a sandbox */\nexport interface SandboxToolInvoker {\n invoke(input: { path: string; args: unknown }): Effect.Effect<unknown, unknown>;\n}\n\n/** Result of executing code in a sandbox */\nexport type ExecuteResult = {\n result: unknown;\n error?: string;\n logs?: string[];\n};\n\n/** Executes code in a sandboxed runtime with tool access */\nexport interface CodeExecutor {\n execute(code: string, toolInvoker: SandboxToolInvoker): Effect.Effect<ExecuteResult, unknown>;\n}\n\n/** Accept-anything schema for tools with no input validation */\nexport const unknownInputSchema: StandardSchema = {\n \"~standard\": {\n version: 1,\n vendor: \"@executor/codemode-core\",\n validate: (value: unknown) => ({\n value,\n }),\n },\n};\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport * as Effect from \"effect/Effect\";\n\nimport { kernelCoreEffectError } from \"./effect-errors\";\n\nconst getSchemaValidator = (\n schema: unknown,\n):\n | ((\n value: unknown,\n ) => StandardSchemaV1.Result<unknown> | Promise<StandardSchemaV1.Result<unknown>>)\n | null => {\n if (!schema || (typeof schema !== \"object\" && typeof schema !== \"function\")) {\n return null;\n }\n\n const standard = (schema as { \"~standard\"?: unknown })[\"~standard\"];\n if (!standard || typeof standard !== \"object\") {\n return null;\n }\n\n const validate = (standard as { validate?: unknown }).validate;\n return typeof validate === \"function\"\n ? (validate as (\n value: unknown,\n ) => StandardSchemaV1.Result<unknown> | Promise<StandardSchemaV1.Result<unknown>>)\n : null;\n};\n\nconst formatIssuePath = (\n path: ReadonlyArray<PropertyKey | StandardSchemaV1.PathSegment> | undefined,\n): string => {\n if (!path || path.length === 0) {\n return \"$\";\n }\n\n return path\n .map((segment) =>\n typeof segment === \"object\" && segment !== null && \"key\" in segment\n ? String(segment.key)\n : String(segment),\n )\n .join(\".\");\n};\n\nconst formatIssues = (issues: ReadonlyArray<StandardSchemaV1.Issue>): string =>\n issues.map((issue) => `${formatIssuePath(issue.path)}: ${issue.message}`).join(\"; \");\n\n/** Validate a value against a Standard Schema */\nexport const validateInput = (input: {\n schema: unknown;\n value: unknown;\n path: string;\n}): Effect.Effect<unknown, Error> => {\n const validate = getSchemaValidator(input.schema);\n if (!validate) {\n return Effect.fail(\n kernelCoreEffectError(\n \"validation\",\n `Tool ${input.path} has no Standard Schema validator on inputSchema`,\n ),\n );\n }\n\n return Effect.tryPromise({\n try: () => Promise.resolve(validate(input.value)),\n catch: (cause) =>\n kernelCoreEffectError(\"validation\", `Validation error for ${input.path}: ${String(cause)}`),\n }).pipe(\n Effect.flatMap((result) => {\n if (\"issues\" in result && result.issues) {\n return Effect.fail(\n kernelCoreEffectError(\n \"validation\",\n `Input validation failed for ${input.path}: ${formatIssues(result.issues)}`,\n ),\n );\n }\n return Effect.succeed(result.value);\n }),\n );\n};\n","import * as Data from \"effect/Data\";\n\nexport class KernelCoreEffectError extends Data.TaggedError(\"KernelCoreEffectError\")<{\n readonly module: string;\n readonly message: string;\n}> {}\n\nexport const kernelCoreEffectError = (module: string, message: string) =>\n new KernelCoreEffectError({ module, message });\n","import type { ErrorObject } from \"ajv\";\nimport Ajv2020 from \"ajv/dist/2020\";\nimport addFormats from \"ajv-formats\";\n\nimport type { StandardSchema } from \"./types\";\nimport { unknownInputSchema } from \"./types\";\n\nconst ajv = new Ajv2020({\n allErrors: true,\n strict: false,\n validateSchema: false,\n allowUnionTypes: true,\n});\n\naddFormats(ajv);\n\nconst decodePointerSegment = (segment: string): PropertyKey => {\n const decoded = segment.replaceAll(\"~1\", \"/\").replaceAll(\"~0\", \"~\");\n return /^\\d+$/.test(decoded) ? Number(decoded) : decoded;\n};\n\nconst pointerToPath = (pointer: string | undefined): ReadonlyArray<PropertyKey> | undefined => {\n if (!pointer || pointer.length === 0 || pointer === \"/\") {\n return undefined;\n }\n\n return pointer\n .split(\"/\")\n .slice(1)\n .filter((segment) => segment.length > 0)\n .map(decodePointerSegment);\n};\n\nconst toIssueMessage = (error: ErrorObject): string => {\n const keyword = error.keyword.trim();\n const message = (error.message ?? \"Invalid value\").trim();\n return keyword.length > 0 ? `${keyword}: ${message}` : message;\n};\n\nexport const standardSchemaFromJsonSchema = (\n schema: unknown,\n options?: {\n vendor?: string;\n fallback?: StandardSchema;\n },\n): StandardSchema => {\n try {\n const validate = ajv.compile(schema as Record<string, unknown>);\n\n return {\n \"~standard\": {\n version: 1,\n vendor: options?.vendor ?? \"json-schema\",\n validate: (value: unknown) => {\n const valid = validate(value);\n if (valid) {\n return { value };\n }\n\n const issues = (validate.errors ?? []).map((error) => ({\n message: toIssueMessage(error),\n path: pointerToPath(error.instancePath),\n }));\n\n return {\n issues: issues.length > 0 ? issues : [{ message: \"Invalid value\" }],\n };\n },\n },\n };\n } catch {\n return options?.fallback ?? unknownInputSchema;\n }\n};\n","import { parse } from \"@babel/parser\";\n\nconst FENCED_CODE_BLOCK = /```(?:[^\\n`]*)?\\s*\\n([\\s\\S]*?)```/i;\nconst FUNCTION_DECLARATION =\n /^(?:async\\s+)?function(?:\\s+([a-zA-Z_$][a-zA-Z0-9_$]*))?\\s*\\(/;\nconst CALLABLE_ERROR = \"Code must evaluate to a function\";\n\nconst extractCandidateSource = (code: string): string => {\n const trimmed = code.trim();\n if (!trimmed) return \"\";\n\n const fenced = trimmed.match(FENCED_CODE_BLOCK)?.[1];\n return (fenced ?? trimmed).trim();\n};\n\nconst wrapCallableBody = (source: string): string =>\n [\n \"const __fn = (\",\n source,\n \");\",\n `if (typeof __fn !== \"function\") throw new Error(${JSON.stringify(CALLABLE_ERROR)});`,\n \"return await __fn();\",\n ].join(\"\\n\");\n\nconst wrapNamedFunctionBody = (source: string, name: string): string =>\n [source, `return await ${name}();`].join(\"\\n\");\n\nconst wrapAnonymousFunctionBody = (source: string): string => `return await (${source})();`;\n\nconst sliceNode = (\n source: string,\n node: {\n start?: number | null;\n end?: number | null;\n },\n): string => {\n const start = node.start ?? 0;\n const end = node.end ?? source.length;\n return source.slice(start, end);\n};\n\nconst unwrapExpression = (expression: { type: string; expression?: unknown }): unknown => {\n switch (expression.type) {\n case \"ParenthesizedExpression\":\n case \"TSAsExpression\":\n case \"TSSatisfiesExpression\":\n case \"TSTypeAssertion\":\n case \"TSNonNullExpression\":\n case \"TSInstantiationExpression\":\n return expression.expression ? unwrapExpression(expression.expression as { type: string }) : expression;\n default:\n return expression;\n }\n};\n\nconst renderExportDefaultBody = (\n source: string,\n declaration: {\n type: string;\n start?: number | null;\n end?: number | null;\n id?: { name?: string | null } | null;\n expression?: unknown;\n },\n): string => {\n if (declaration.type === \"FunctionDeclaration\") {\n const fnSource = sliceNode(source, declaration);\n const name = declaration.id?.name;\n return name ? wrapNamedFunctionBody(fnSource, name) : wrapAnonymousFunctionBody(fnSource);\n }\n\n const expression = unwrapExpression(declaration as { type: string; expression?: unknown }) as {\n type?: string;\n };\n const expressionSource = sliceNode(source, declaration);\n\n if (expression?.type === \"ArrowFunctionExpression\" || expression?.type === \"FunctionExpression\") {\n return wrapCallableBody(expressionSource);\n }\n\n return `return (${expressionSource});`;\n};\n\nconst renderParsedBody = (source: string): string => {\n const program = parse(source, {\n sourceType: \"module\",\n allowAwaitOutsideFunction: true,\n allowReturnOutsideFunction: true,\n allowImportExportEverywhere: true,\n plugins: [\"typescript\"],\n }).program;\n\n if (program.body.length !== 1) return source;\n\n const [statement] = program.body;\n if (!statement) return source;\n\n switch (statement.type) {\n case \"ExpressionStatement\": {\n const expression = unwrapExpression(statement.expression as { type: string; expression?: unknown }) as {\n type?: string;\n };\n return expression?.type === \"ArrowFunctionExpression\" || expression?.type === \"FunctionExpression\"\n ? wrapCallableBody(source)\n : source;\n }\n case \"FunctionDeclaration\":\n return statement.id?.name ? wrapNamedFunctionBody(source, statement.id.name) : source;\n case \"ExportDefaultDeclaration\":\n return renderExportDefaultBody(source, statement.declaration as never);\n default:\n return source;\n }\n};\n\nconst renderHeuristicBody = (source: string): string => {\n const withoutDefaultExport = source.replace(/^export\\s+default\\s+/, \"\").trim();\n\n if (\n (withoutDefaultExport.startsWith(\"async\") || withoutDefaultExport.startsWith(\"(\")) &&\n withoutDefaultExport.includes(\"=>\")\n ) {\n return wrapCallableBody(withoutDefaultExport);\n }\n\n if (FUNCTION_DECLARATION.test(withoutDefaultExport)) {\n const name = withoutDefaultExport.match(FUNCTION_DECLARATION)?.[1];\n return name\n ? wrapNamedFunctionBody(withoutDefaultExport, name)\n : wrapAnonymousFunctionBody(withoutDefaultExport);\n }\n\n return withoutDefaultExport;\n};\n\nexport const recoverExecutionBody = (code: string): string => {\n const source = extractCandidateSource(code);\n if (!source) return \"\";\n\n try {\n return renderParsedBody(source);\n } catch {\n return renderHeuristicBody(source);\n }\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/types.ts","../src/validation.ts","../src/effect-errors.ts","../src/json-schema.ts","../src/code-recovery.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type * as Cause from \"effect/Cause\";\nimport type * as Effect from \"effect/Effect\";\n\nimport type { CodeExecutionError } from \"./effect-errors\";\n\n/** Branded tool path */\nexport type ToolPath = string & { readonly __toolPath: unique symbol };\n\nexport const asToolPath = (value: string): ToolPath => value as ToolPath;\n\n/** Standard Schema alias */\nexport type StandardSchema<Input = unknown, Output = unknown> = StandardSchemaV1<Input, Output>;\n\n/** A tool that can be invoked */\nexport interface Tool {\n readonly path: ToolPath;\n readonly description?: string;\n readonly inputSchema: StandardSchema;\n readonly outputSchema?: StandardSchema;\n readonly execute: (input: unknown) => unknown | Promise<unknown>;\n}\n\n/** Invoke a tool by path from inside a sandbox */\nexport interface SandboxToolInvoker {\n invoke(input: { path: string; args: unknown }): Effect.Effect<unknown, unknown, never>;\n}\n\n/** Result of executing code in a sandbox */\nexport type ExecuteResult = {\n result: unknown;\n error?: string;\n logs?: string[];\n};\n\n/**\n * Executes code in a sandboxed runtime with tool access.\n *\n * Error channel is constrained to Effect's `YieldableError` (the base\n * shape `Data.TaggedError(...)` produces) so callers always get a\n * structurally tagged error, never untyped `unknown`. Defaults to\n * `CodeExecutionError`; runtimes can parameterize with their own\n * `Data.TaggedError` subclass — e.g. `CodeExecutor<WorkerLoaderError>`.\n */\nexport interface CodeExecutor<E extends Cause.YieldableError = CodeExecutionError> {\n execute(code: string, toolInvoker: SandboxToolInvoker): Effect.Effect<ExecuteResult, E>;\n}\n\n/** Accept-anything schema for tools with no input validation */\nexport const unknownInputSchema: StandardSchema = {\n \"~standard\": {\n version: 1,\n vendor: \"@executor-js/codemode-core\",\n validate: (value: unknown) => ({\n value,\n }),\n },\n};\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport * as Effect from \"effect/Effect\";\n\nimport { kernelCoreEffectError } from \"./effect-errors\";\n\nconst getSchemaValidator = (\n schema: unknown,\n):\n | ((\n value: unknown,\n ) => StandardSchemaV1.Result<unknown> | Promise<StandardSchemaV1.Result<unknown>>)\n | null => {\n if (!schema || (typeof schema !== \"object\" && typeof schema !== \"function\")) {\n return null;\n }\n\n const standard = (schema as { \"~standard\"?: unknown })[\"~standard\"];\n if (!standard || typeof standard !== \"object\") {\n return null;\n }\n\n const validate = (standard as { validate?: unknown }).validate;\n return typeof validate === \"function\"\n ? (validate as (\n value: unknown,\n ) => StandardSchemaV1.Result<unknown> | Promise<StandardSchemaV1.Result<unknown>>)\n : null;\n};\n\nconst formatIssuePath = (\n path: ReadonlyArray<PropertyKey | StandardSchemaV1.PathSegment> | undefined,\n): string => {\n if (!path || path.length === 0) {\n return \"$\";\n }\n\n return path\n .map((segment) =>\n typeof segment === \"object\" && segment !== null && \"key\" in segment\n ? String(segment.key)\n : String(segment),\n )\n .join(\".\");\n};\n\nconst formatIssues = (issues: ReadonlyArray<StandardSchemaV1.Issue>): string =>\n issues.map((issue) => `${formatIssuePath(issue.path)}: ${issue.message}`).join(\"; \");\n\n/** Validate a value against a Standard Schema */\nexport const validateInput = (input: {\n schema: unknown;\n value: unknown;\n path: string;\n}): Effect.Effect<unknown, Error> => {\n const validate = getSchemaValidator(input.schema);\n if (!validate) {\n return Effect.fail(\n kernelCoreEffectError(\n \"validation\",\n `Tool ${input.path} has no Standard Schema validator on inputSchema`,\n ),\n );\n }\n\n return Effect.tryPromise({\n try: () => Promise.resolve(validate(input.value)),\n catch: (cause) =>\n kernelCoreEffectError(\"validation\", `Validation error for ${input.path}: ${String(cause)}`),\n }).pipe(\n Effect.flatMap((result) => {\n if (\"issues\" in result && result.issues) {\n return Effect.fail(\n kernelCoreEffectError(\n \"validation\",\n `Input validation failed for ${input.path}: ${formatIssues(result.issues)}`,\n ),\n );\n }\n return Effect.succeed(result.value);\n }),\n );\n};\n","import * as Data from \"effect/Data\";\n\nexport class KernelCoreEffectError extends Data.TaggedError(\"KernelCoreEffectError\")<{\n readonly module: string;\n readonly message: string;\n}> {}\n\nexport const kernelCoreEffectError = (module: string, message: string) =>\n new KernelCoreEffectError({ module, message });\n\n/**\n * Default failure type for any `CodeExecutor.execute` implementation —\n * surfaces sandbox-level defects (isolate crash, module load failure,\n * worker loader error) as a typed error so callers can handle them\n * structurally instead of untyped `unknown`. Runtimes that want a\n * narrower error shape can define their own `Data.TaggedError` subclass\n * and parameterize `CodeExecutor<MyError>`.\n */\nexport class CodeExecutionError extends Data.TaggedError(\"CodeExecutionError\")<{\n readonly runtime: string;\n readonly message: string;\n readonly cause?: unknown;\n}> {}\n","import type { ErrorObject } from \"ajv\";\nimport Ajv2020 from \"ajv/dist/2020\";\nimport addFormats from \"ajv-formats\";\n\nimport type { StandardSchema } from \"./types\";\nimport { unknownInputSchema } from \"./types\";\n\nconst ajv = new Ajv2020({\n allErrors: true,\n strict: false,\n validateSchema: false,\n allowUnionTypes: true,\n});\n\naddFormats(ajv);\n\nconst decodePointerSegment = (segment: string): PropertyKey => {\n const decoded = segment.replaceAll(\"~1\", \"/\").replaceAll(\"~0\", \"~\");\n return /^\\d+$/.test(decoded) ? Number(decoded) : decoded;\n};\n\nconst pointerToPath = (pointer: string | undefined): ReadonlyArray<PropertyKey> | undefined => {\n if (!pointer || pointer.length === 0 || pointer === \"/\") {\n return undefined;\n }\n\n return pointer\n .split(\"/\")\n .slice(1)\n .filter((segment) => segment.length > 0)\n .map(decodePointerSegment);\n};\n\nconst toIssueMessage = (error: ErrorObject): string => {\n const keyword = error.keyword.trim();\n const message = (error.message ?? \"Invalid value\").trim();\n return keyword.length > 0 ? `${keyword}: ${message}` : message;\n};\n\nexport const standardSchemaFromJsonSchema = (\n schema: unknown,\n options?: {\n vendor?: string;\n fallback?: StandardSchema;\n },\n): StandardSchema => {\n try {\n const validate = ajv.compile(schema as Record<string, unknown>);\n\n return {\n \"~standard\": {\n version: 1,\n vendor: options?.vendor ?? \"json-schema\",\n validate: (value: unknown) => {\n const valid = validate(value);\n if (valid) {\n return { value };\n }\n\n const issues = (validate.errors ?? []).map((error) => ({\n message: toIssueMessage(error),\n path: pointerToPath(error.instancePath),\n }));\n\n return {\n issues: issues.length > 0 ? issues : [{ message: \"Invalid value\" }],\n };\n },\n },\n };\n } catch {\n return options?.fallback ?? unknownInputSchema;\n }\n};\n","import { parse } from \"@babel/parser\";\n\nconst FENCED_CODE_BLOCK = /```(?:[^\\n`]*)?\\s*\\n([\\s\\S]*?)```/i;\nconst FUNCTION_DECLARATION =\n /^(?:async\\s+)?function(?:\\s+([a-zA-Z_$][a-zA-Z0-9_$]*))?\\s*\\(/;\nconst CALLABLE_ERROR = \"Code must evaluate to a function\";\n\nconst extractCandidateSource = (code: string): string => {\n const trimmed = code.trim();\n if (!trimmed) return \"\";\n\n const fenced = trimmed.match(FENCED_CODE_BLOCK)?.[1];\n return (fenced ?? trimmed).trim();\n};\n\nconst wrapCallableBody = (source: string): string =>\n [\n \"const __fn = (\",\n source,\n \");\",\n `if (typeof __fn !== \"function\") throw new Error(${JSON.stringify(CALLABLE_ERROR)});`,\n \"return await __fn();\",\n ].join(\"\\n\");\n\nconst wrapNamedFunctionBody = (source: string, name: string): string =>\n [source, `return await ${name}();`].join(\"\\n\");\n\nconst wrapAnonymousFunctionBody = (source: string): string => `return await (${source})();`;\n\nconst sliceNode = (\n source: string,\n node: {\n start?: number | null;\n end?: number | null;\n },\n): string => {\n const start = node.start ?? 0;\n const end = node.end ?? source.length;\n return source.slice(start, end);\n};\n\nconst unwrapExpression = (expression: { type: string; expression?: unknown }): unknown => {\n switch (expression.type) {\n case \"ParenthesizedExpression\":\n case \"TSAsExpression\":\n case \"TSSatisfiesExpression\":\n case \"TSTypeAssertion\":\n case \"TSNonNullExpression\":\n case \"TSInstantiationExpression\":\n return expression.expression ? unwrapExpression(expression.expression as { type: string }) : expression;\n default:\n return expression;\n }\n};\n\nconst renderExportDefaultBody = (\n source: string,\n declaration: ExportDefaultDeclarationNode,\n): string => {\n if (declaration.type === \"FunctionDeclaration\") {\n const fnSource = sliceNode(source, declaration);\n const name = declaration.id?.name;\n return name ? wrapNamedFunctionBody(fnSource, name) : wrapAnonymousFunctionBody(fnSource);\n }\n\n const expression = unwrapExpression(declaration) as {\n type?: string;\n };\n const expressionSource = sliceNode(source, declaration);\n\n if (expression?.type === \"ArrowFunctionExpression\" || expression?.type === \"FunctionExpression\") {\n return wrapCallableBody(expressionSource);\n }\n\n return `return (${expressionSource});`;\n};\n\ntype ExportDefaultDeclarationNode = {\n type: string;\n start?: number | null;\n end?: number | null;\n id?: { name?: string | null } | null;\n expression?: unknown;\n};\n\nconst renderParsedBody = (source: string): string => {\n const program = parse(source, {\n sourceType: \"module\",\n allowAwaitOutsideFunction: true,\n allowReturnOutsideFunction: true,\n allowImportExportEverywhere: true,\n plugins: [\"typescript\"],\n }).program;\n\n if (program.body.length !== 1) return source;\n\n const [statement] = program.body;\n if (!statement) return source;\n\n switch (statement.type) {\n case \"ExpressionStatement\": {\n const expression = unwrapExpression(statement.expression as { type: string; expression?: unknown }) as {\n type?: string;\n };\n return expression?.type === \"ArrowFunctionExpression\" || expression?.type === \"FunctionExpression\"\n ? wrapCallableBody(source)\n : source;\n }\n case \"FunctionDeclaration\":\n return statement.id?.name ? wrapNamedFunctionBody(source, statement.id.name) : source;\n case \"ExportDefaultDeclaration\":\n return renderExportDefaultBody(source, statement.declaration);\n default:\n return source;\n }\n};\n\nconst renderHeuristicBody = (source: string): string => {\n const withoutDefaultExport = source.replace(/^export\\s+default\\s+/, \"\").trim();\n\n if (\n (withoutDefaultExport.startsWith(\"async\") || withoutDefaultExport.startsWith(\"(\")) &&\n withoutDefaultExport.includes(\"=>\")\n ) {\n return wrapCallableBody(withoutDefaultExport);\n }\n\n if (FUNCTION_DECLARATION.test(withoutDefaultExport)) {\n const name = withoutDefaultExport.match(FUNCTION_DECLARATION)?.[1];\n return name\n ? wrapNamedFunctionBody(withoutDefaultExport, name)\n : wrapAnonymousFunctionBody(withoutDefaultExport);\n }\n\n return withoutDefaultExport;\n};\n\nexport const recoverExecutionBody = (code: string): string => {\n const source = extractCandidateSource(code);\n if (!source) return \"\";\n\n try {\n return renderParsedBody(source);\n } catch {\n return renderHeuristicBody(source);\n }\n};\n"],"mappings":"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","names":[]}
package/dist/types.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import type { StandardSchemaV1 } from "@standard-schema/spec";
2
+ import type * as Cause from "effect/Cause";
2
3
  import type * as Effect from "effect/Effect";
4
+ import type { CodeExecutionError } from "./effect-errors";
3
5
  /** Branded tool path */
4
6
  export type ToolPath = string & {
5
7
  readonly __toolPath: unique symbol;
@@ -20,7 +22,7 @@ export interface SandboxToolInvoker {
20
22
  invoke(input: {
21
23
  path: string;
22
24
  args: unknown;
23
- }): Effect.Effect<unknown, unknown>;
25
+ }): Effect.Effect<unknown, unknown, never>;
24
26
  }
25
27
  /** Result of executing code in a sandbox */
26
28
  export type ExecuteResult = {
@@ -28,9 +30,17 @@ export type ExecuteResult = {
28
30
  error?: string;
29
31
  logs?: string[];
30
32
  };
31
- /** Executes code in a sandboxed runtime with tool access */
32
- export interface CodeExecutor {
33
- execute(code: string, toolInvoker: SandboxToolInvoker): Effect.Effect<ExecuteResult, unknown>;
33
+ /**
34
+ * Executes code in a sandboxed runtime with tool access.
35
+ *
36
+ * Error channel is constrained to Effect's `YieldableError` (the base
37
+ * shape `Data.TaggedError(...)` produces) so callers always get a
38
+ * structurally tagged error, never untyped `unknown`. Defaults to
39
+ * `CodeExecutionError`; runtimes can parameterize with their own
40
+ * `Data.TaggedError` subclass — e.g. `CodeExecutor<WorkerLoaderError>`.
41
+ */
42
+ export interface CodeExecutor<E extends Cause.YieldableError = CodeExecutionError> {
43
+ execute(code: string, toolInvoker: SandboxToolInvoker): Effect.Effect<ExecuteResult, E>;
34
44
  }
35
45
  /** Accept-anything schema for tools with no input validation */
36
46
  export declare const unknownInputSchema: StandardSchema;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAE7C,wBAAwB;AACxB,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,MAAM,CAAA;CAAE,CAAC;AAEvE,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,KAAG,QAA6B,CAAC;AAEzE,4BAA4B;AAC5B,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,OAAO,IAAI,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAEhG,iCAAiC;AACjC,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IACrC,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAClE;AAED,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;CACjF;AAED,4CAA4C;AAC5C,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,4DAA4D;AAC5D,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;CAC/F;AAED,gEAAgE;AAChE,eAAO,MAAM,kBAAkB,EAAE,cAQhC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAE7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,wBAAwB;AACxB,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,MAAM,CAAA;CAAE,CAAC;AAEvE,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,KAAG,QAA6B,CAAC;AAEzE,4BAA4B;AAC5B,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,OAAO,IAAI,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAEhG,iCAAiC;AACjC,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IACrC,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAClE;AAED,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;CACxF;AAED,4CAA4C;AAC5C,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,KAAK,CAAC,cAAc,GAAG,kBAAkB;IAC/E,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;CACzF;AAED,gEAAgE;AAChE,eAAO,MAAM,kBAAkB,EAAE,cAQhC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@executor-js/codemode-core",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "homepage": "https://github.com/RhysSullivan/executor/tree/main/packages/kernel/core",
5
5
  "bugs": {
6
6
  "url": "https://github.com/RhysSullivan/executor/issues"
@@ -38,13 +38,13 @@
38
38
  "@standard-schema/spec": "^1.0.0",
39
39
  "ajv": "^8.17.1",
40
40
  "ajv-formats": "^3.0.1",
41
- "effect": "^3.21.0"
41
+ "effect": "4.0.0-beta.59"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^24.3.1",
45
45
  "bun-types": "^1.2.22",
46
46
  "tsup": "^8.5.0",
47
47
  "typescript": "^5.9.3",
48
- "vitest": "^4.1.3"
48
+ "vitest": "^4.1.5"
49
49
  }
50
50
  }