@earendil-works/pi-codemode 0.0.1 → 0.99.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 +184 -1
- package/dist/declarations.d.ts +53 -0
- package/dist/declarations.d.ts.map +1 -0
- package/dist/declarations.js +330 -0
- package/dist/declarations.js.map +1 -0
- package/dist/identifier.d.ts +6 -0
- package/dist/identifier.d.ts.map +1 -0
- package/dist/identifier.js +13 -0
- package/dist/identifier.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime/host.d.ts +35 -0
- package/dist/runtime/host.d.ts.map +1 -0
- package/dist/runtime/host.js +314 -0
- package/dist/runtime/host.js.map +1 -0
- package/dist/runtime/prelude-source.d.ts +31 -0
- package/dist/runtime/prelude-source.d.ts.map +1 -0
- package/dist/runtime/prelude-source.js +322 -0
- package/dist/runtime/prelude-source.js.map +1 -0
- package/dist/runtime/protocol.d.ts +69 -0
- package/dist/runtime/protocol.d.ts.map +1 -0
- package/dist/runtime/protocol.js +10 -0
- package/dist/runtime/protocol.js.map +1 -0
- package/dist/runtime/worker.d.ts +2 -0
- package/dist/runtime/worker.d.ts.map +1 -0
- package/dist/runtime/worker.js +137 -0
- package/dist/runtime/worker.js.map +1 -0
- package/dist/source.d.ts +35 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +92 -0
- package/dist/source.js.map +1 -0
- package/dist/types.d.ts +136 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/wasm.d.ts +12 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +24 -0
- package/dist/wasm.js.map +1 -0
- package/package.json +54 -4
package/dist/source.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codemode source format: JavaScript, optionally preceded by one options line.
|
|
3
|
+
*
|
|
4
|
+
* ```js
|
|
5
|
+
* // @options: {"max_output_tokens": 2000, "timeout_ms": 30000}
|
|
6
|
+
* const text = await tools.read({ path: "package.json" });
|
|
7
|
+
* text(JSON.parse(text).name);
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export const CODEMODE_OPTIONS_PREFIX = "// @options:";
|
|
11
|
+
const SUPPORTED_FIELDS = ["max_output_tokens", "timeout_ms"];
|
|
12
|
+
const SUPPORTED_FIELDS_TEXT = "`max_output_tokens` and `timeout_ms`";
|
|
13
|
+
/** Largest delay `setTimeout` supports, which bounds `timeout_ms`. */
|
|
14
|
+
const MAX_TIMEOUT_MS = 2_147_483_647;
|
|
15
|
+
/**
|
|
16
|
+
* Lark grammar for providers with grammar-constrained tool input. It only fixes the shape of the
|
|
17
|
+
* options line; the options JSON and the code are checked by {@link parseCodemodeSource}.
|
|
18
|
+
*/
|
|
19
|
+
export const CODEMODE_SOURCE_GRAMMAR = String.raw `
|
|
20
|
+
start: options_source | plain_source
|
|
21
|
+
options_source: OPTIONS_LINE NEWLINE SOURCE
|
|
22
|
+
plain_source: SOURCE
|
|
23
|
+
|
|
24
|
+
OPTIONS_LINE: /[ \t]*\/\/ @options:[^\r\n]*/
|
|
25
|
+
NEWLINE: /\r?\n/
|
|
26
|
+
SOURCE: /[\s\S]+/
|
|
27
|
+
`;
|
|
28
|
+
export class CodemodeSourceError extends Error {
|
|
29
|
+
constructor(message) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.name = "CodemodeSourceError";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function isSafeInteger(value) {
|
|
35
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
36
|
+
}
|
|
37
|
+
function parseOptions(directive) {
|
|
38
|
+
if (directive === "") {
|
|
39
|
+
throw new CodemodeSourceError(`@options must be a JSON object with supported fields ${SUPPORTED_FIELDS_TEXT}`);
|
|
40
|
+
}
|
|
41
|
+
let value;
|
|
42
|
+
try {
|
|
43
|
+
value = JSON.parse(directive);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
throw new CodemodeSourceError(`@options must be valid JSON with supported fields ${SUPPORTED_FIELDS_TEXT}: ${error instanceof Error ? error.message : String(error)}`);
|
|
47
|
+
}
|
|
48
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
49
|
+
throw new CodemodeSourceError(`@options must be a JSON object with supported fields ${SUPPORTED_FIELDS_TEXT}`);
|
|
50
|
+
}
|
|
51
|
+
const fields = value;
|
|
52
|
+
for (const key of Object.keys(fields)) {
|
|
53
|
+
if (!SUPPORTED_FIELDS.includes(key)) {
|
|
54
|
+
throw new CodemodeSourceError(`@options only supports ${SUPPORTED_FIELDS_TEXT}; got \`${key}\``);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const options = {};
|
|
58
|
+
const { max_output_tokens, timeout_ms } = fields;
|
|
59
|
+
if (max_output_tokens !== undefined) {
|
|
60
|
+
if (!isSafeInteger(max_output_tokens)) {
|
|
61
|
+
throw new CodemodeSourceError("@options field `max_output_tokens` must be a non-negative safe integer");
|
|
62
|
+
}
|
|
63
|
+
options.maxOutputTokens = max_output_tokens;
|
|
64
|
+
}
|
|
65
|
+
if (timeout_ms !== undefined) {
|
|
66
|
+
if (!isSafeInteger(timeout_ms) || timeout_ms === 0 || timeout_ms > MAX_TIMEOUT_MS) {
|
|
67
|
+
throw new CodemodeSourceError(`@options field \`timeout_ms\` must be a positive integer up to ${MAX_TIMEOUT_MS}`);
|
|
68
|
+
}
|
|
69
|
+
options.timeoutMs = timeout_ms;
|
|
70
|
+
}
|
|
71
|
+
return options;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Split an optional first-line `// @options: {...}` from the script. Throws
|
|
75
|
+
* {@link CodemodeSourceError} for empty input and invalid options.
|
|
76
|
+
*/
|
|
77
|
+
export function parseCodemodeSource(input) {
|
|
78
|
+
if (input.trim() === "") {
|
|
79
|
+
throw new CodemodeSourceError('Expected JavaScript source text (non-empty). Provide JS only, optionally with a first line `// @options: {"max_output_tokens": 1000}`.');
|
|
80
|
+
}
|
|
81
|
+
const newline = input.indexOf("\n");
|
|
82
|
+
const firstLine = (newline === -1 ? input : input.slice(0, newline)).replace(/\r$/, "");
|
|
83
|
+
const trimmed = firstLine.trimStart();
|
|
84
|
+
if (!trimmed.startsWith(CODEMODE_OPTIONS_PREFIX))
|
|
85
|
+
return { code: input, options: {} };
|
|
86
|
+
const code = newline === -1 ? "" : input.slice(newline);
|
|
87
|
+
if (code.trim() === "") {
|
|
88
|
+
throw new CodemodeSourceError("The @options line must be followed by JavaScript source on subsequent lines");
|
|
89
|
+
}
|
|
90
|
+
return { code, options: parseOptions(trimmed.slice(CODEMODE_OPTIONS_PREFIX.length).trim()) };
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Codemode source format: JavaScript, optionally preceded by one options line.\n *\n * ```js\n * // @options: {\"max_output_tokens\": 2000, \"timeout_ms\": 30000}\n * const text = await tools.read({ path: \"package.json\" });\n * text(JSON.parse(text).name);\n * ```\n */\n\nexport const CODEMODE_OPTIONS_PREFIX = \"// @options:\";\n\nconst SUPPORTED_FIELDS = [\"max_output_tokens\", \"timeout_ms\"] as const;\nconst SUPPORTED_FIELDS_TEXT = \"`max_output_tokens` and `timeout_ms`\";\n/** Largest delay `setTimeout` supports, which bounds `timeout_ms`. */\nconst MAX_TIMEOUT_MS = 2_147_483_647;\n\n/**\n * Lark grammar for providers with grammar-constrained tool input. It only fixes the shape of the\n * options line; the options JSON and the code are checked by {@link parseCodemodeSource}.\n */\nexport const CODEMODE_SOURCE_GRAMMAR = String.raw`\nstart: options_source | plain_source\noptions_source: OPTIONS_LINE NEWLINE SOURCE\nplain_source: SOURCE\n\nOPTIONS_LINE: /[ \\t]*\\/\\/ @options:[^\\r\\n]*/\nNEWLINE: /\\r?\\n/\nSOURCE: /[\\s\\S]+/\n`;\n\nexport interface CodemodeSourceOptions {\n\t/** Token budget for the script's output. */\n\tmaxOutputTokens?: number;\n\t/** Hard deadline for the whole script in milliseconds, including tool calls. */\n\ttimeoutMs?: number;\n}\n\nexport interface ParsedCodemodeSource {\n\t/** The script with the options line replaced by an empty line, so line numbers are unchanged. */\n\tcode: string;\n\toptions: CodemodeSourceOptions;\n}\n\nexport class CodemodeSourceError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CodemodeSourceError\";\n\t}\n}\n\nfunction isSafeInteger(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n}\n\nfunction parseOptions(directive: string): CodemodeSourceOptions {\n\tif (directive === \"\") {\n\t\tthrow new CodemodeSourceError(`@options must be a JSON object with supported fields ${SUPPORTED_FIELDS_TEXT}`);\n\t}\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(directive);\n\t} catch (error) {\n\t\tthrow new CodemodeSourceError(\n\t\t\t`@options must be valid JSON with supported fields ${SUPPORTED_FIELDS_TEXT}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t}\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new CodemodeSourceError(`@options must be a JSON object with supported fields ${SUPPORTED_FIELDS_TEXT}`);\n\t}\n\tconst fields = value as Record<string, unknown>;\n\tfor (const key of Object.keys(fields)) {\n\t\tif (!(SUPPORTED_FIELDS as readonly string[]).includes(key)) {\n\t\t\tthrow new CodemodeSourceError(`@options only supports ${SUPPORTED_FIELDS_TEXT}; got \\`${key}\\``);\n\t\t}\n\t}\n\tconst options: CodemodeSourceOptions = {};\n\tconst { max_output_tokens, timeout_ms } = fields;\n\tif (max_output_tokens !== undefined) {\n\t\tif (!isSafeInteger(max_output_tokens)) {\n\t\t\tthrow new CodemodeSourceError(\"@options field `max_output_tokens` must be a non-negative safe integer\");\n\t\t}\n\t\toptions.maxOutputTokens = max_output_tokens;\n\t}\n\tif (timeout_ms !== undefined) {\n\t\tif (!isSafeInteger(timeout_ms) || timeout_ms === 0 || timeout_ms > MAX_TIMEOUT_MS) {\n\t\t\tthrow new CodemodeSourceError(\n\t\t\t\t`@options field \\`timeout_ms\\` must be a positive integer up to ${MAX_TIMEOUT_MS}`,\n\t\t\t);\n\t\t}\n\t\toptions.timeoutMs = timeout_ms;\n\t}\n\treturn options;\n}\n\n/**\n * Split an optional first-line `// @options: {...}` from the script. Throws\n * {@link CodemodeSourceError} for empty input and invalid options.\n */\nexport function parseCodemodeSource(input: string): ParsedCodemodeSource {\n\tif (input.trim() === \"\") {\n\t\tthrow new CodemodeSourceError(\n\t\t\t'Expected JavaScript source text (non-empty). Provide JS only, optionally with a first line `// @options: {\"max_output_tokens\": 1000}`.',\n\t\t);\n\t}\n\tconst newline = input.indexOf(\"\\n\");\n\tconst firstLine = (newline === -1 ? input : input.slice(0, newline)).replace(/\\r$/, \"\");\n\tconst trimmed = firstLine.trimStart();\n\tif (!trimmed.startsWith(CODEMODE_OPTIONS_PREFIX)) return { code: input, options: {} };\n\tconst code = newline === -1 ? \"\" : input.slice(newline);\n\tif (code.trim() === \"\") {\n\t\tthrow new CodemodeSourceError(\"The @options line must be followed by JavaScript source on subsequent lines\");\n\t}\n\treturn { code, options: parseOptions(trimmed.slice(CODEMODE_OPTIONS_PREFIX.length).trim()) };\n}\n"]}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { CodemodeWasmModule } from "./wasm.ts";
|
|
2
|
+
export interface CodemodeToolContext {
|
|
3
|
+
/**
|
|
4
|
+
* Aborted when the script finishes (including unawaited calls), the
|
|
5
|
+
* execution times out, the caller aborts, or the sandbox is closed.
|
|
6
|
+
*/
|
|
7
|
+
signal: AbortSignal;
|
|
8
|
+
}
|
|
9
|
+
/** A JSON Schema document. Only used to render declarations; values are not validated against it. */
|
|
10
|
+
export type CodemodeJsonSchema = {
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
} | boolean;
|
|
13
|
+
export interface CodemodeTool {
|
|
14
|
+
/**
|
|
15
|
+
* The script calls tools as `tools.<id>(args)`, where `<id>` is the name with characters that
|
|
16
|
+
* are not valid in identifiers replaced by `_` (see `toCodemodeIdentifier`), and also as
|
|
17
|
+
* `tools["<name>"](args)`. Globals are called as `<name>(args)` and must be identifiers, or
|
|
18
|
+
* `<namespace>.<member>`, which groups them into a frozen namespace object.
|
|
19
|
+
*/
|
|
20
|
+
name: string;
|
|
21
|
+
/** Shown as a doc comment in {@link renderDeclarations}, and listed in `ALL_TOOLS` for tools. */
|
|
22
|
+
description?: string;
|
|
23
|
+
/** Schema of the single argument. Rendered as the parameter type; `unknown` when omitted. */
|
|
24
|
+
inputSchema?: CodemodeJsonSchema;
|
|
25
|
+
/** Schema of the resolved value. Rendered as the promise type; `unknown` when omitted. */
|
|
26
|
+
outputSchema?: CodemodeJsonSchema;
|
|
27
|
+
/** Globals only: `execute` receives all call arguments as an array instead of the first one. */
|
|
28
|
+
spread?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Globals only: TypeScript parameter list and return type for {@link renderDeclarations}, for
|
|
31
|
+
* example `(type: string, id?: string): Promise<Model[]>`. Replaces the rendering from the schemas.
|
|
32
|
+
*/
|
|
33
|
+
signature?: string;
|
|
34
|
+
/**
|
|
35
|
+
* `args` is whatever the script passed, after a JSON round trip. The return
|
|
36
|
+
* value must be JSON-serializable; a thrown error surfaces in the script as
|
|
37
|
+
* an `Error` with the same message.
|
|
38
|
+
*/
|
|
39
|
+
execute(args: unknown, context: CodemodeToolContext): Promise<unknown> | unknown;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* One item of the script's output, in the order the script produced it: `text()` and `console.*`
|
|
43
|
+
* produce text items, `image()` image items. `data` is base64.
|
|
44
|
+
*/
|
|
45
|
+
export type CodemodeOutputItem = {
|
|
46
|
+
type: "text";
|
|
47
|
+
text: string;
|
|
48
|
+
} | {
|
|
49
|
+
type: "image";
|
|
50
|
+
data: string;
|
|
51
|
+
mimeType: string;
|
|
52
|
+
};
|
|
53
|
+
export type CodemodeCallStatus = "ok" | "error" | "cancelled";
|
|
54
|
+
export interface CodemodeCall {
|
|
55
|
+
name: string;
|
|
56
|
+
status: CodemodeCallStatus;
|
|
57
|
+
durationMs: number;
|
|
58
|
+
}
|
|
59
|
+
export type CodemodeErrorKind =
|
|
60
|
+
/** The script threw or failed to parse. `name` and `stack` come from the script's error. */
|
|
61
|
+
"script"
|
|
62
|
+
/** The overall deadline expired. The worker was terminated. */
|
|
63
|
+
| "timeout"
|
|
64
|
+
/** The caller's signal fired or the sandbox was closed. The worker was terminated. */
|
|
65
|
+
| "aborted"
|
|
66
|
+
/** The worker or VM failed outside the script's control (for example a wasm trap or a missing worker file). */
|
|
67
|
+
| "sandbox";
|
|
68
|
+
export interface CodemodeError {
|
|
69
|
+
kind: CodemodeErrorKind;
|
|
70
|
+
name?: string;
|
|
71
|
+
message: string;
|
|
72
|
+
stack?: string;
|
|
73
|
+
}
|
|
74
|
+
/** Keys the script changed with `store()`. Only successful executions report writes. */
|
|
75
|
+
export interface CodemodeStoreWrites {
|
|
76
|
+
set: Record<string, unknown>;
|
|
77
|
+
/** Keys stored as `undefined`. */
|
|
78
|
+
delete: string[];
|
|
79
|
+
}
|
|
80
|
+
/** `output` is kept for failed executions too, up to the failure. `exit()` completes with `value: undefined`. */
|
|
81
|
+
export type CodemodeResult = {
|
|
82
|
+
ok: true;
|
|
83
|
+
value: unknown;
|
|
84
|
+
output: CodemodeOutputItem[];
|
|
85
|
+
calls: CodemodeCall[];
|
|
86
|
+
storeWrites: CodemodeStoreWrites;
|
|
87
|
+
} | {
|
|
88
|
+
ok: false;
|
|
89
|
+
error: CodemodeError;
|
|
90
|
+
output: CodemodeOutputItem[];
|
|
91
|
+
calls: CodemodeCall[];
|
|
92
|
+
};
|
|
93
|
+
export interface CodemodeSandboxOptions {
|
|
94
|
+
tools?: CodemodeTool[];
|
|
95
|
+
/**
|
|
96
|
+
* Functions exposed as top-level identifiers instead of on `tools`, for host helpers such as
|
|
97
|
+
* attaching an image to the result. They behave like tools (JSON round trip, promise result)
|
|
98
|
+
* but are not recorded in `result.calls`. Names must be identifiers and may not shadow the
|
|
99
|
+
* built-in globals (`tools`, `ALL_TOOLS`, `console`, `text`, `image`, `exit`, `store`, `load`).
|
|
100
|
+
*/
|
|
101
|
+
globals?: CodemodeTool[];
|
|
102
|
+
/**
|
|
103
|
+
* Overall deadline per execution, including time spent in tools. `Infinity` disables the
|
|
104
|
+
* deadline; the execution then only ends when the script settles or is aborted.
|
|
105
|
+
* Default: 300000.
|
|
106
|
+
*/
|
|
107
|
+
timeoutMs?: number;
|
|
108
|
+
/**
|
|
109
|
+
* Maximum memory the QuickJS VM may allocate. Allocations beyond it fail inside the script as
|
|
110
|
+
* `InternalError: out of memory`. Default: no limit beyond wasm32's 4 GiB address space.
|
|
111
|
+
*/
|
|
112
|
+
memoryLimitBytes?: number;
|
|
113
|
+
/**
|
|
114
|
+
* Compiled `quickjs-wasi/quickjs.wasm`, usually from {@link loadQuickJSWasm}. Default:
|
|
115
|
+
* `loadQuickJSWasm()`, the file in the installed `quickjs-wasi` package. Pass it when that file
|
|
116
|
+
* is not on disk, for example in a Bun compiled executable.
|
|
117
|
+
*/
|
|
118
|
+
wasm?: CodemodeWasmModule | Promise<CodemodeWasmModule>;
|
|
119
|
+
/**
|
|
120
|
+
* Worker entry that imports `@earendil-works/pi-codemode/worker`. Default: this package's own
|
|
121
|
+
* worker file. Pass it when this package is bundled, since the default is resolved relative to
|
|
122
|
+
* the module that creates the sandbox.
|
|
123
|
+
*/
|
|
124
|
+
workerUrl?: URL;
|
|
125
|
+
}
|
|
126
|
+
export interface CodemodeExecuteOptions {
|
|
127
|
+
signal?: AbortSignal;
|
|
128
|
+
/** Overrides the sandbox default for this execution. */
|
|
129
|
+
timeoutMs?: number;
|
|
130
|
+
/**
|
|
131
|
+
* Values the script reads with `load(key)`. Must be JSON-serializable. The script's own
|
|
132
|
+
* `store()` calls come back as `result.storeWrites`; persisting them is up to the caller.
|
|
133
|
+
*/
|
|
134
|
+
store?: Readonly<Record<string, unknown>>;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { CodemodeWasmModule } from \"./wasm.ts\";\n\nexport interface CodemodeToolContext {\n\t/**\n\t * Aborted when the script finishes (including unawaited calls), the\n\t * execution times out, the caller aborts, or the sandbox is closed.\n\t */\n\tsignal: AbortSignal;\n}\n\n/** A JSON Schema document. Only used to render declarations; values are not validated against it. */\nexport type CodemodeJsonSchema = { [key: string]: unknown } | boolean;\n\nexport interface CodemodeTool {\n\t/**\n\t * The script calls tools as `tools.<id>(args)`, where `<id>` is the name with characters that\n\t * are not valid in identifiers replaced by `_` (see `toCodemodeIdentifier`), and also as\n\t * `tools[\"<name>\"](args)`. Globals are called as `<name>(args)` and must be identifiers, or\n\t * `<namespace>.<member>`, which groups them into a frozen namespace object.\n\t */\n\tname: string;\n\t/** Shown as a doc comment in {@link renderDeclarations}, and listed in `ALL_TOOLS` for tools. */\n\tdescription?: string;\n\t/** Schema of the single argument. Rendered as the parameter type; `unknown` when omitted. */\n\tinputSchema?: CodemodeJsonSchema;\n\t/** Schema of the resolved value. Rendered as the promise type; `unknown` when omitted. */\n\toutputSchema?: CodemodeJsonSchema;\n\t/** Globals only: `execute` receives all call arguments as an array instead of the first one. */\n\tspread?: boolean;\n\t/**\n\t * Globals only: TypeScript parameter list and return type for {@link renderDeclarations}, for\n\t * example `(type: string, id?: string): Promise<Model[]>`. Replaces the rendering from the schemas.\n\t */\n\tsignature?: string;\n\t/**\n\t * `args` is whatever the script passed, after a JSON round trip. The return\n\t * value must be JSON-serializable; a thrown error surfaces in the script as\n\t * an `Error` with the same message.\n\t */\n\texecute(args: unknown, context: CodemodeToolContext): Promise<unknown> | unknown;\n}\n\n/**\n * One item of the script's output, in the order the script produced it: `text()` and `console.*`\n * produce text items, `image()` image items. `data` is base64.\n */\nexport type CodemodeOutputItem = { type: \"text\"; text: string } | { type: \"image\"; data: string; mimeType: string };\n\nexport type CodemodeCallStatus = \"ok\" | \"error\" | \"cancelled\";\n\nexport interface CodemodeCall {\n\tname: string;\n\tstatus: CodemodeCallStatus;\n\tdurationMs: number;\n}\n\nexport type CodemodeErrorKind =\n\t/** The script threw or failed to parse. `name` and `stack` come from the script's error. */\n\t| \"script\"\n\t/** The overall deadline expired. The worker was terminated. */\n\t| \"timeout\"\n\t/** The caller's signal fired or the sandbox was closed. The worker was terminated. */\n\t| \"aborted\"\n\t/** The worker or VM failed outside the script's control (for example a wasm trap or a missing worker file). */\n\t| \"sandbox\";\n\nexport interface CodemodeError {\n\tkind: CodemodeErrorKind;\n\tname?: string;\n\tmessage: string;\n\tstack?: string;\n}\n\n/** Keys the script changed with `store()`. Only successful executions report writes. */\nexport interface CodemodeStoreWrites {\n\tset: Record<string, unknown>;\n\t/** Keys stored as `undefined`. */\n\tdelete: string[];\n}\n\n/** `output` is kept for failed executions too, up to the failure. `exit()` completes with `value: undefined`. */\nexport type CodemodeResult =\n\t| {\n\t\t\tok: true;\n\t\t\tvalue: unknown;\n\t\t\toutput: CodemodeOutputItem[];\n\t\t\tcalls: CodemodeCall[];\n\t\t\tstoreWrites: CodemodeStoreWrites;\n\t }\n\t| { ok: false; error: CodemodeError; output: CodemodeOutputItem[]; calls: CodemodeCall[] };\n\nexport interface CodemodeSandboxOptions {\n\ttools?: CodemodeTool[];\n\t/**\n\t * Functions exposed as top-level identifiers instead of on `tools`, for host helpers such as\n\t * attaching an image to the result. They behave like tools (JSON round trip, promise result)\n\t * but are not recorded in `result.calls`. Names must be identifiers and may not shadow the\n\t * built-in globals (`tools`, `ALL_TOOLS`, `console`, `text`, `image`, `exit`, `store`, `load`).\n\t */\n\tglobals?: CodemodeTool[];\n\t/**\n\t * Overall deadline per execution, including time spent in tools. `Infinity` disables the\n\t * deadline; the execution then only ends when the script settles or is aborted.\n\t * Default: 300000.\n\t */\n\ttimeoutMs?: number;\n\t/**\n\t * Maximum memory the QuickJS VM may allocate. Allocations beyond it fail inside the script as\n\t * `InternalError: out of memory`. Default: no limit beyond wasm32's 4 GiB address space.\n\t */\n\tmemoryLimitBytes?: number;\n\t/**\n\t * Compiled `quickjs-wasi/quickjs.wasm`, usually from {@link loadQuickJSWasm}. Default:\n\t * `loadQuickJSWasm()`, the file in the installed `quickjs-wasi` package. Pass it when that file\n\t * is not on disk, for example in a Bun compiled executable.\n\t */\n\twasm?: CodemodeWasmModule | Promise<CodemodeWasmModule>;\n\t/**\n\t * Worker entry that imports `@earendil-works/pi-codemode/worker`. Default: this package's own\n\t * worker file. Pass it when this package is bundled, since the default is resolved relative to\n\t * the module that creates the sandbox.\n\t */\n\tworkerUrl?: URL;\n}\n\nexport interface CodemodeExecuteOptions {\n\tsignal?: AbortSignal;\n\t/** Overrides the sandbox default for this execution. */\n\ttimeoutMs?: number;\n\t/**\n\t * Values the script reads with `load(key)`. Must be JSON-serializable. The script's own\n\t * `store()` calls come back as `result.storeWrites`; persisting them is up to the caller.\n\t */\n\tstore?: Readonly<Record<string, unknown>>;\n}\n"]}
|
package/dist/wasm.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A compiled `WebAssembly.Module` of `quickjs-wasi/quickjs.wasm`. Typed opaquely because the Node
|
|
3
|
+
* type definitions do not declare the WebAssembly globals (they live in the DOM lib).
|
|
4
|
+
*/
|
|
5
|
+
export type CodemodeWasmModule = object;
|
|
6
|
+
/**
|
|
7
|
+
* Read and compile the QuickJS wasm once per path. `path` defaults to the file in the installed
|
|
8
|
+
* `quickjs-wasi` package; pass it when that file lives elsewhere, for example embedded in a Bun
|
|
9
|
+
* compiled executable. A failed load is retried on the next call.
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadQuickJSWasm(path?: string): Promise<CodemodeWasmModule>;
|
|
12
|
+
//# sourceMappingURL=wasm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasm.d.ts","sourceRoot":"","sources":["../src/wasm.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAQxC;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAc1E"}
|
package/dist/wasm.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
const modules = new Map();
|
|
4
|
+
/**
|
|
5
|
+
* Read and compile the QuickJS wasm once per path. `path` defaults to the file in the installed
|
|
6
|
+
* `quickjs-wasi` package; pass it when that file lives elsewhere, for example embedded in a Bun
|
|
7
|
+
* compiled executable. A failed load is retried on the next call.
|
|
8
|
+
*/
|
|
9
|
+
export function loadQuickJSWasm(path) {
|
|
10
|
+
const resolved = path ?? createRequire(import.meta.url).resolve("quickjs-wasi/quickjs.wasm");
|
|
11
|
+
let module = modules.get(resolved);
|
|
12
|
+
if (!module) {
|
|
13
|
+
const { WebAssembly } = globalThis;
|
|
14
|
+
module = readFile(resolved)
|
|
15
|
+
.then((bytes) => WebAssembly.compile(bytes))
|
|
16
|
+
.catch((error) => {
|
|
17
|
+
modules.delete(resolved);
|
|
18
|
+
throw error;
|
|
19
|
+
});
|
|
20
|
+
modules.set(resolved, module);
|
|
21
|
+
}
|
|
22
|
+
return module;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=wasm.js.map
|
package/dist/wasm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasm.js","sourceRoot":"","sources":["../src/wasm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAY5C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAuC,CAAC;AAE/D;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAa;IAC5C,MAAM,QAAQ,GAAG,IAAI,IAAI,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;IAC7F,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,EAAE,WAAW,EAAE,GAAG,UAA2D,CAAC;QACpF,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC;aACzB,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;aAC3C,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACzB,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\n\n/**\n * A compiled `WebAssembly.Module` of `quickjs-wasi/quickjs.wasm`. Typed opaquely because the Node\n * type definitions do not declare the WebAssembly globals (they live in the DOM lib).\n */\nexport type CodemodeWasmModule = object;\n\ninterface WebAssemblyGlobal {\n\tcompile(bytes: Uint8Array): Promise<CodemodeWasmModule>;\n}\n\nconst modules = new Map<string, Promise<CodemodeWasmModule>>();\n\n/**\n * Read and compile the QuickJS wasm once per path. `path` defaults to the file in the installed\n * `quickjs-wasi` package; pass it when that file lives elsewhere, for example embedded in a Bun\n * compiled executable. A failed load is retried on the next call.\n */\nexport function loadQuickJSWasm(path?: string): Promise<CodemodeWasmModule> {\n\tconst resolved = path ?? createRequire(import.meta.url).resolve(\"quickjs-wasi/quickjs.wasm\");\n\tlet module = modules.get(resolved);\n\tif (!module) {\n\t\tconst { WebAssembly } = globalThis as unknown as { WebAssembly: WebAssemblyGlobal };\n\t\tmodule = readFile(resolved)\n\t\t\t.then((bytes) => WebAssembly.compile(bytes))\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tmodules.delete(resolved);\n\t\t\t\tthrow error;\n\t\t\t});\n\t\tmodules.set(resolved, module);\n\t}\n\treturn module;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,14 +1,64 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earendil-works/pi-codemode",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.99.0",
|
|
4
|
+
"description": "Sandboxed JavaScript execution where the only capability is calling injected tools",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"source": "./src/index.ts",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./declarations": {
|
|
15
|
+
"source": "./src/declarations.ts",
|
|
16
|
+
"types": "./dist/declarations.d.ts",
|
|
17
|
+
"import": "./dist/declarations.js"
|
|
18
|
+
},
|
|
19
|
+
"./source": {
|
|
20
|
+
"source": "./src/source.ts",
|
|
21
|
+
"types": "./dist/source.d.ts",
|
|
22
|
+
"import": "./dist/source.js"
|
|
23
|
+
},
|
|
24
|
+
"./worker": {
|
|
25
|
+
"source": "./src/runtime/worker.ts",
|
|
26
|
+
"types": "./dist/runtime/worker.d.ts",
|
|
27
|
+
"import": "./dist/runtime/worker.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"clean": "shx rm -rf dist",
|
|
36
|
+
"build": "tsc -p tsconfig.build.json",
|
|
37
|
+
"test": "vitest --run",
|
|
38
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"pi",
|
|
42
|
+
"codemode",
|
|
43
|
+
"sandbox",
|
|
44
|
+
"quickjs",
|
|
45
|
+
"wasm"
|
|
46
|
+
],
|
|
47
|
+
"author": "Earendil Works",
|
|
5
48
|
"license": "MIT",
|
|
6
49
|
"repository": {
|
|
7
50
|
"type": "git",
|
|
8
51
|
"url": "git+https://github.com/earendil-works/pi.git",
|
|
9
52
|
"directory": "packages/codemode"
|
|
10
53
|
},
|
|
11
|
-
"
|
|
12
|
-
"
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=22.19.0"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"quickjs-wasi": "3.6.2"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"shx": "0.4.0",
|
|
62
|
+
"vitest": "4.1.11"
|
|
13
63
|
}
|
|
14
64
|
}
|