@rafads/runtime-quickjs 1.5.38
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 +59 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +361 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# @rafads/runtime-quickjs
|
|
2
|
+
|
|
3
|
+
[QuickJS](https://github.com/justjake/quickjs-emscripten) sandbox runtime for `@rafads/execution`. Runs untrusted TypeScript/JavaScript in a WASM-backed interpreter with configurable timeout, memory limit, and stack size — safe enough to execute LLM-generated code that calls your registered tools.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
bun add @rafads/execution @rafads/runtime-quickjs
|
|
9
|
+
# or
|
|
10
|
+
npm install @rafads/execution @rafads/runtime-quickjs
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Pass a `makeQuickJsExecutor()` as the `codeExecutor` when building the execution engine:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { createExecutor } from "@rafads/sdk";
|
|
19
|
+
import { createExecutionEngine } from "@rafads/execution";
|
|
20
|
+
import { makeQuickJsExecutor } from "@rafads/runtime-quickjs";
|
|
21
|
+
|
|
22
|
+
const executor = await createExecutor({ onElicitation: "accept-all" });
|
|
23
|
+
|
|
24
|
+
const engine = createExecutionEngine({
|
|
25
|
+
executor,
|
|
26
|
+
codeExecutor: makeQuickJsExecutor({
|
|
27
|
+
timeoutMs: 2_000,
|
|
28
|
+
memoryLimitBytes: 32 * 1024 * 1024,
|
|
29
|
+
maxStackSizeBytes: 1 * 1024 * 1024,
|
|
30
|
+
}),
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Options
|
|
35
|
+
|
|
36
|
+
| Option | Default | Description |
|
|
37
|
+
| ------------------- | ---------- | --------------------------------- |
|
|
38
|
+
| `timeoutMs` | `300_000` | Max wall-clock time per execution |
|
|
39
|
+
| `memoryLimitBytes` | `64 * 1MB` | Max memory the VM can allocate |
|
|
40
|
+
| `maxStackSizeBytes` | `1 * 1MB` | Max call-stack depth |
|
|
41
|
+
|
|
42
|
+
### Swapping the QuickJS build
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { setQuickJSModule } from "@rafads/runtime-quickjs";
|
|
46
|
+
import { newQuickJSWASMModule } from "quickjs-emscripten";
|
|
47
|
+
|
|
48
|
+
setQuickJSModule(await newQuickJSWASMModule());
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Use this when you want a different WASM variant (e.g. debug builds, QuickJS-NG) than the default bundled one. `newQuickJSWASMModule()` defaults to the release-sync variant; pass a different `@jitl/quickjs-*` variant to swap it.
|
|
52
|
+
|
|
53
|
+
## Status
|
|
54
|
+
|
|
55
|
+
Pre-`1.0`. APIs may still change between beta releases. Part of the [executor monorepo](https://github.com/UsefulSoftwareCo/executor).
|
|
56
|
+
|
|
57
|
+
## License
|
|
58
|
+
|
|
59
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type CodeExecutor } from "@rafads/codemode-core";
|
|
2
|
+
import { type QuickJSWASMModule } from "quickjs-emscripten";
|
|
3
|
+
export type QuickJsExecutorOptions = {
|
|
4
|
+
timeoutMs?: number;
|
|
5
|
+
memoryLimitBytes?: number;
|
|
6
|
+
maxStackSizeBytes?: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const setQuickJSModule: (mod: QuickJSWASMModule) => void;
|
|
9
|
+
declare const QuickJsExecutionError_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 & {
|
|
10
|
+
readonly _tag: "QuickJsExecutionError";
|
|
11
|
+
} & Readonly<A>;
|
|
12
|
+
declare class QuickJsExecutionError extends QuickJsExecutionError_base<{
|
|
13
|
+
readonly message: string;
|
|
14
|
+
}> {
|
|
15
|
+
}
|
|
16
|
+
export declare const makeQuickJsExecutor: (options?: QuickJsExecutorOptions) => CodeExecutor<QuickJsExecutionError>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EAIlB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAOL,KAAK,iBAAiB,EACvB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAKF,eAAO,MAAM,gBAAgB,GAAI,KAAK,iBAAiB,SAEtD,CAAC;;;;AAKF,cAAM,qBAAsB,SAAQ,2BAA0C;IAC5E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAwcL,eAAO,MAAM,mBAAmB,GAC9B,UAAS,sBAA2B,KACnC,YAAY,CAAC,qBAAqB,CAGnC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import {
|
|
3
|
+
recoverExecutionBody,
|
|
4
|
+
stripTypeScript
|
|
5
|
+
} from "@rafads/codemode-core";
|
|
6
|
+
import * as Data from "effect/Data";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
import {
|
|
9
|
+
getQuickJS,
|
|
10
|
+
shouldInterruptAfterDeadline
|
|
11
|
+
} from "quickjs-emscripten";
|
|
12
|
+
var preloadedModule = null;
|
|
13
|
+
var setQuickJSModule = (mod) => {
|
|
14
|
+
preloadedModule = mod;
|
|
15
|
+
};
|
|
16
|
+
var resolveQuickJS = () => preloadedModule ? Promise.resolve(preloadedModule) : getQuickJS();
|
|
17
|
+
var QuickJsExecutionError = class extends Data.TaggedError("QuickJsExecutionError") {
|
|
18
|
+
};
|
|
19
|
+
var DEFAULT_TIMEOUT_MS = 5 * 6e4;
|
|
20
|
+
var DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;
|
|
21
|
+
var DEFAULT_MAX_STACK_SIZE_BYTES = 1 * 1024 * 1024;
|
|
22
|
+
var EXECUTION_FILENAME = "executor-quickjs-runtime.js";
|
|
23
|
+
var toError = (cause) => cause instanceof Error ? cause : new Error(String(cause));
|
|
24
|
+
var sandboxDefectMessage = (cause) => {
|
|
25
|
+
if (cause !== null && typeof cause === "object") {
|
|
26
|
+
const tagged = cause;
|
|
27
|
+
if (tagged._tag === "ExecutionToolError" && typeof tagged.message === "string") {
|
|
28
|
+
return tagged.message;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return "Internal tool error";
|
|
32
|
+
};
|
|
33
|
+
var toErrorMessage = (cause) => {
|
|
34
|
+
if (typeof cause === "object" && cause !== null) {
|
|
35
|
+
const message = "message" in cause && typeof cause.message === "string" ? cause.message : void 0;
|
|
36
|
+
if (message) {
|
|
37
|
+
return message;
|
|
38
|
+
}
|
|
39
|
+
const stack = "stack" in cause && typeof cause.stack === "string" ? cause.stack : void 0;
|
|
40
|
+
if (stack) {
|
|
41
|
+
return stack;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const error = toError(cause);
|
|
45
|
+
return error.stack ?? error.message;
|
|
46
|
+
};
|
|
47
|
+
var serializeJson = (value, label) => {
|
|
48
|
+
if (typeof value === "undefined") {
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
return JSON.stringify(value);
|
|
53
|
+
} catch (cause) {
|
|
54
|
+
throw new Error(`${label} is not JSON serializable: ${toError(cause).message}`);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
var looksLikeInterruptedError = (message) => /\binterrupted\b/i.test(message);
|
|
58
|
+
var timeoutMessage = (timeoutMs) => `QuickJS execution timed out after ${timeoutMs}ms`;
|
|
59
|
+
var normalizeExecutionError = (cause, deadlineMs, timeoutMs) => {
|
|
60
|
+
const message = toErrorMessage(cause);
|
|
61
|
+
return Date.now() >= deadlineMs && looksLikeInterruptedError(message) ? timeoutMessage(timeoutMs) : message;
|
|
62
|
+
};
|
|
63
|
+
var buildExecutionSource = (code) => {
|
|
64
|
+
const body = stripTypeScript(recoverExecutionBody(code));
|
|
65
|
+
return [
|
|
66
|
+
'"use strict";',
|
|
67
|
+
"const __invokeTool = __executor_invokeTool;",
|
|
68
|
+
"const __log = __executor_log;",
|
|
69
|
+
"try { delete globalThis.__executor_invokeTool; } catch {}",
|
|
70
|
+
"try { delete globalThis.__executor_log; } catch {}",
|
|
71
|
+
"const __formatLogArg = (value) => {",
|
|
72
|
+
" if (typeof value === 'string') return value;",
|
|
73
|
+
" try {",
|
|
74
|
+
" return JSON.stringify(value);",
|
|
75
|
+
" } catch {",
|
|
76
|
+
" return String(value);",
|
|
77
|
+
" }",
|
|
78
|
+
"};",
|
|
79
|
+
"const __formatLogLine = (args) => args.map(__formatLogArg).join(' ');",
|
|
80
|
+
"const __outputs = [];",
|
|
81
|
+
"globalThis.__executor_outputs = __outputs;",
|
|
82
|
+
"const __formatOutputText = (value) => {",
|
|
83
|
+
" if (typeof value === 'undefined') return 'undefined';",
|
|
84
|
+
" if (value === null) return 'null';",
|
|
85
|
+
" if (typeof value === 'string') return value;",
|
|
86
|
+
" try {",
|
|
87
|
+
" return JSON.stringify(value);",
|
|
88
|
+
" } catch {",
|
|
89
|
+
" return String(value);",
|
|
90
|
+
" }",
|
|
91
|
+
"};",
|
|
92
|
+
"const __isToolFile = (value) => value && typeof value === 'object' && value._tag === 'ToolFile' && typeof value.mimeType === 'string' && value.encoding === 'base64' && typeof value.data === 'string' && typeof value.byteLength === 'number';",
|
|
93
|
+
"const __isMcpTextContentBlock = (value) => value && typeof value === 'object' && value.type === 'text' && typeof value.text === 'string';",
|
|
94
|
+
"const __isMcpImageContentBlock = (value) => value && typeof value === 'object' && value.type === 'image' && typeof value.data === 'string' && typeof value.mimeType === 'string';",
|
|
95
|
+
"const __isMcpAudioContentBlock = (value) => value && typeof value === 'object' && value.type === 'audio' && typeof value.data === 'string' && typeof value.mimeType === 'string';",
|
|
96
|
+
"const __isMcpResourceContentBlock = (value) => value && typeof value === 'object' && value.type === 'resource' && value.resource && typeof value.resource === 'object' && typeof value.resource.uri === 'string' && (typeof value.resource.text === 'string' || typeof value.resource.blob === 'string');",
|
|
97
|
+
"const __isMcpResourceLinkContentBlock = (value) => value && typeof value === 'object' && value.type === 'resource_link' && typeof value.uri === 'string' && typeof value.name === 'string';",
|
|
98
|
+
"const __isMcpContentBlock = (value) => __isMcpTextContentBlock(value) || __isMcpImageContentBlock(value) || __isMcpAudioContentBlock(value) || __isMcpResourceContentBlock(value) || __isMcpResourceLinkContentBlock(value);",
|
|
99
|
+
"const emit = (value) => {",
|
|
100
|
+
" if (__isToolFile(value)) {",
|
|
101
|
+
" __outputs.push({ type: 'file', file: value });",
|
|
102
|
+
" return;",
|
|
103
|
+
" }",
|
|
104
|
+
" if (__isMcpContentBlock(value)) {",
|
|
105
|
+
" __outputs.push({ type: 'content', content: value });",
|
|
106
|
+
" return;",
|
|
107
|
+
" }",
|
|
108
|
+
" __outputs.push({ type: 'content', content: { type: 'text', text: __formatOutputText(value) } });",
|
|
109
|
+
"};",
|
|
110
|
+
"const __toolsEnumerationError = (path) => new Error(",
|
|
111
|
+
" (path.length === 0 ? 'tools' : 'tools.' + path.join('.')) +",
|
|
112
|
+
` ' is a lazy proxy and cannot be enumerated. Use tools.search({ query: "..." }) to find tools, tools.search({ namespace: "<integration>", query: "" }) to list every tool in an integration, or tools.executor.coreTools.connections.list({}) to list saved connections.',`,
|
|
113
|
+
");",
|
|
114
|
+
"const __makeToolsProxy = (path = []) => new Proxy(() => undefined, {",
|
|
115
|
+
" get(_target, prop) {",
|
|
116
|
+
" if (prop === 'then' || typeof prop === 'symbol') {",
|
|
117
|
+
" return undefined;",
|
|
118
|
+
" }",
|
|
119
|
+
" return __makeToolsProxy([...path, String(prop)]);",
|
|
120
|
+
" },",
|
|
121
|
+
" ownKeys() {",
|
|
122
|
+
" throw __toolsEnumerationError(path);",
|
|
123
|
+
" },",
|
|
124
|
+
" getOwnPropertyDescriptor() {",
|
|
125
|
+
" throw __toolsEnumerationError(path);",
|
|
126
|
+
" },",
|
|
127
|
+
" apply(_target, _thisArg, args) {",
|
|
128
|
+
" const toolPath = path.join('.');",
|
|
129
|
+
" if (!toolPath) {",
|
|
130
|
+
" throw new Error('Tool path missing in invocation');",
|
|
131
|
+
" }",
|
|
132
|
+
" return Promise.resolve(__invokeTool(toolPath, args[0])).then((raw) => raw === undefined ? undefined : JSON.parse(raw));",
|
|
133
|
+
" },",
|
|
134
|
+
"});",
|
|
135
|
+
"const tools = __makeToolsProxy();",
|
|
136
|
+
"const console = {",
|
|
137
|
+
" log: (...args) => __log('log', __formatLogLine(args)),",
|
|
138
|
+
" warn: (...args) => __log('warn', __formatLogLine(args)),",
|
|
139
|
+
" error: (...args) => __log('error', __formatLogLine(args)),",
|
|
140
|
+
" info: (...args) => __log('info', __formatLogLine(args)),",
|
|
141
|
+
" debug: (...args) => __log('debug', __formatLogLine(args)),",
|
|
142
|
+
"};",
|
|
143
|
+
"const fetch = (..._args) => {",
|
|
144
|
+
" throw new Error('fetch is disabled in QuickJS executor');",
|
|
145
|
+
"};",
|
|
146
|
+
"(async () => {",
|
|
147
|
+
body,
|
|
148
|
+
"})()"
|
|
149
|
+
].join("\n");
|
|
150
|
+
};
|
|
151
|
+
var readPropDump = (context2, handle, key) => {
|
|
152
|
+
const prop = context2.getProp(handle, key);
|
|
153
|
+
try {
|
|
154
|
+
return context2.dump(prop);
|
|
155
|
+
} finally {
|
|
156
|
+
prop.dispose();
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
var readOutputItems = (context2) => {
|
|
160
|
+
const output = readPropDump(context2, context2.global, "__executor_outputs");
|
|
161
|
+
return Array.isArray(output) && output.length > 0 ? output : void 0;
|
|
162
|
+
};
|
|
163
|
+
var readResultState = (context2, handle) => ({
|
|
164
|
+
settled: readPropDump(context2, handle, "settled") === true,
|
|
165
|
+
value: readPropDump(context2, handle, "v"),
|
|
166
|
+
error: readPropDump(context2, handle, "e")
|
|
167
|
+
});
|
|
168
|
+
var createLogBridge = (context2, logs) => context2.newFunction("__executor_log", (levelHandle, lineHandle) => {
|
|
169
|
+
const level = context2.getString(levelHandle);
|
|
170
|
+
const line = context2.getString(lineHandle);
|
|
171
|
+
logs.push(`[${level}] ${line}`);
|
|
172
|
+
return context2.undefined;
|
|
173
|
+
});
|
|
174
|
+
var createToolBridge = (context2, toolInvoker, pendingDeferreds, runPromise) => context2.newFunction("__executor_invokeTool", (pathHandle, argsHandle) => {
|
|
175
|
+
const path = context2.getString(pathHandle);
|
|
176
|
+
const args = argsHandle === void 0 || context2.typeof(argsHandle) === "undefined" ? void 0 : context2.dump(argsHandle);
|
|
177
|
+
const deferred = context2.newPromise();
|
|
178
|
+
pendingDeferreds.add(deferred);
|
|
179
|
+
deferred.settled.finally(() => {
|
|
180
|
+
pendingDeferreds.delete(deferred);
|
|
181
|
+
});
|
|
182
|
+
void runPromise(toolInvoker.invoke({ path, args })).then(
|
|
183
|
+
(value) => {
|
|
184
|
+
if (!deferred.alive) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const serialized = serializeJson(value, `Tool result for ${path}`);
|
|
188
|
+
if (typeof serialized === "undefined") {
|
|
189
|
+
deferred.resolve();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const valueHandle = context2.newString(serialized);
|
|
193
|
+
deferred.resolve(valueHandle);
|
|
194
|
+
valueHandle.dispose();
|
|
195
|
+
},
|
|
196
|
+
(cause) => {
|
|
197
|
+
if (!deferred.alive) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const message = sandboxDefectMessage(cause);
|
|
201
|
+
try {
|
|
202
|
+
console.error("[executor:quickjs] tool dispatch defect", { path, cause });
|
|
203
|
+
} catch {
|
|
204
|
+
}
|
|
205
|
+
const errorHandle = context2.newError(message);
|
|
206
|
+
deferred.reject(errorHandle);
|
|
207
|
+
errorHandle.dispose();
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
return deferred.handle;
|
|
211
|
+
});
|
|
212
|
+
var drainJobs = (context2, runtime, deadlineMs, timeoutMs) => {
|
|
213
|
+
while (runtime.hasPendingJob()) {
|
|
214
|
+
if (Date.now() >= deadlineMs) {
|
|
215
|
+
throw new Error(timeoutMessage(timeoutMs));
|
|
216
|
+
}
|
|
217
|
+
const pending = runtime.executePendingJobs();
|
|
218
|
+
if (pending.error) {
|
|
219
|
+
const error = context2.dump(pending.error);
|
|
220
|
+
pending.error.dispose();
|
|
221
|
+
throw toError(error);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
var waitForDeferreds = async (pendingDeferreds, deadlineMs, timeoutMs) => {
|
|
226
|
+
const remainingMs = deadlineMs - Date.now();
|
|
227
|
+
if (remainingMs <= 0) {
|
|
228
|
+
throw new Error(timeoutMessage(timeoutMs));
|
|
229
|
+
}
|
|
230
|
+
let timer;
|
|
231
|
+
try {
|
|
232
|
+
await Promise.race([
|
|
233
|
+
Promise.race([...pendingDeferreds].map((deferred) => deferred.settled)),
|
|
234
|
+
new Promise((_, reject) => {
|
|
235
|
+
timer = setTimeout(() => reject(new Error(timeoutMessage(timeoutMs))), remainingMs);
|
|
236
|
+
})
|
|
237
|
+
]);
|
|
238
|
+
} finally {
|
|
239
|
+
if (timer !== void 0) {
|
|
240
|
+
clearTimeout(timer);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
var drainAsync = async (context2, runtime, pendingDeferreds, deadlineMs, timeoutMs) => {
|
|
245
|
+
drainJobs(context2, runtime, deadlineMs, timeoutMs);
|
|
246
|
+
while (pendingDeferreds.size > 0) {
|
|
247
|
+
await waitForDeferreds(pendingDeferreds, deadlineMs, timeoutMs);
|
|
248
|
+
drainJobs(context2, runtime, deadlineMs, timeoutMs);
|
|
249
|
+
}
|
|
250
|
+
drainJobs(context2, runtime, deadlineMs, timeoutMs);
|
|
251
|
+
};
|
|
252
|
+
var evaluateInQuickJs = async (options, code, toolInvoker, runPromise) => {
|
|
253
|
+
const timeoutMs = Math.max(100, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
254
|
+
const deadlineMs = Date.now() + timeoutMs;
|
|
255
|
+
const logs = [];
|
|
256
|
+
const pendingDeferreds = /* @__PURE__ */ new Set();
|
|
257
|
+
const QuickJS = await resolveQuickJS();
|
|
258
|
+
const runtime = QuickJS.newRuntime();
|
|
259
|
+
try {
|
|
260
|
+
runtime.setMemoryLimit(options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES);
|
|
261
|
+
runtime.setMaxStackSize(options.maxStackSizeBytes ?? DEFAULT_MAX_STACK_SIZE_BYTES);
|
|
262
|
+
runtime.setInterruptHandler(shouldInterruptAfterDeadline(deadlineMs));
|
|
263
|
+
const context2 = runtime.newContext();
|
|
264
|
+
try {
|
|
265
|
+
const logBridge = createLogBridge(context2, logs);
|
|
266
|
+
context2.setProp(context2.global, "__executor_log", logBridge);
|
|
267
|
+
logBridge.dispose();
|
|
268
|
+
const toolBridge = createToolBridge(context2, toolInvoker, pendingDeferreds, runPromise);
|
|
269
|
+
context2.setProp(context2.global, "__executor_invokeTool", toolBridge);
|
|
270
|
+
toolBridge.dispose();
|
|
271
|
+
const evaluated = context2.evalCode(buildExecutionSource(code), EXECUTION_FILENAME);
|
|
272
|
+
if (evaluated.error) {
|
|
273
|
+
const error = context2.dump(evaluated.error);
|
|
274
|
+
evaluated.error.dispose();
|
|
275
|
+
return {
|
|
276
|
+
result: null,
|
|
277
|
+
error: normalizeExecutionError(error, deadlineMs, timeoutMs),
|
|
278
|
+
logs
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
context2.setProp(context2.global, "__executor_result", evaluated.value);
|
|
282
|
+
evaluated.value.dispose();
|
|
283
|
+
const stateResult = context2.evalCode(
|
|
284
|
+
"(function(p){ var s = { v: void 0, e: void 0, settled: false }; var formatError = function(e){ if (e && typeof e === 'object') { var message = typeof e.message === 'string' ? e.message : ''; var stack = typeof e.stack === 'string' ? e.stack : ''; if (message && stack) { return stack.indexOf(message) === -1 ? message + '\\n' + stack : stack; } if (message) return message; if (stack) return stack; } return String(e); }; p.then(function(v){ s.v = v; s.settled = true; }, function(e){ s.e = formatError(e); s.settled = true; }); return s; })(__executor_result)"
|
|
285
|
+
);
|
|
286
|
+
if (stateResult.error) {
|
|
287
|
+
const error = context2.dump(stateResult.error);
|
|
288
|
+
stateResult.error.dispose();
|
|
289
|
+
return {
|
|
290
|
+
result: null,
|
|
291
|
+
error: normalizeExecutionError(error, deadlineMs, timeoutMs),
|
|
292
|
+
logs
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
const stateHandle = stateResult.value;
|
|
296
|
+
try {
|
|
297
|
+
await drainAsync(context2, runtime, pendingDeferreds, deadlineMs, timeoutMs);
|
|
298
|
+
const state = readResultState(context2, stateHandle);
|
|
299
|
+
if (!state.settled) {
|
|
300
|
+
return {
|
|
301
|
+
result: null,
|
|
302
|
+
error: timeoutMessage(timeoutMs),
|
|
303
|
+
output: readOutputItems(context2),
|
|
304
|
+
logs
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
if (typeof state.error !== "undefined") {
|
|
308
|
+
return {
|
|
309
|
+
result: null,
|
|
310
|
+
error: normalizeExecutionError(state.error, deadlineMs, timeoutMs),
|
|
311
|
+
output: readOutputItems(context2),
|
|
312
|
+
logs
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
result: state.value,
|
|
317
|
+
output: readOutputItems(context2),
|
|
318
|
+
logs
|
|
319
|
+
};
|
|
320
|
+
} finally {
|
|
321
|
+
stateHandle.dispose();
|
|
322
|
+
}
|
|
323
|
+
} finally {
|
|
324
|
+
for (const deferred of pendingDeferreds) {
|
|
325
|
+
if (deferred.alive) {
|
|
326
|
+
deferred.dispose();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
pendingDeferreds.clear();
|
|
330
|
+
context2.dispose();
|
|
331
|
+
}
|
|
332
|
+
} catch (cause) {
|
|
333
|
+
return {
|
|
334
|
+
result: null,
|
|
335
|
+
error: normalizeExecutionError(cause, deadlineMs, timeoutMs),
|
|
336
|
+
logs
|
|
337
|
+
};
|
|
338
|
+
} finally {
|
|
339
|
+
runtime.dispose();
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
var runInQuickJs = (options, code, toolInvoker) => Effect.gen(function* () {
|
|
343
|
+
const context2 = yield* Effect.context();
|
|
344
|
+
const runPromise = Effect.runPromiseWith(context2);
|
|
345
|
+
return yield* Effect.tryPromise({
|
|
346
|
+
try: () => evaluateInQuickJs(options, code, toolInvoker, runPromise),
|
|
347
|
+
catch: (cause) => new QuickJsExecutionError({ message: String(cause) })
|
|
348
|
+
});
|
|
349
|
+
}).pipe(
|
|
350
|
+
Effect.withSpan("executor.code.exec.quickjs", {
|
|
351
|
+
attributes: { "executor.runtime": "quickjs" }
|
|
352
|
+
})
|
|
353
|
+
);
|
|
354
|
+
var makeQuickJsExecutor = (options = {}) => ({
|
|
355
|
+
execute: (code, toolInvoker) => runInQuickJs(options, code, toolInvoker)
|
|
356
|
+
});
|
|
357
|
+
export {
|
|
358
|
+
makeQuickJsExecutor,
|
|
359
|
+
setQuickJSModule
|
|
360
|
+
};
|
|
361
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n recoverExecutionBody,\n stripTypeScript,\n type CodeExecutor,\n type ExecuteOutputItem,\n type ExecuteResult,\n type SandboxToolInvoker,\n} from \"@rafads/codemode-core\";\nimport * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\nimport {\n getQuickJS,\n shouldInterruptAfterDeadline,\n type QuickJSContext,\n type QuickJSDeferredPromise,\n type QuickJSHandle,\n type QuickJSRuntime,\n type QuickJSWASMModule,\n} from \"quickjs-emscripten\";\n\nexport type QuickJsExecutorOptions = {\n timeoutMs?: number;\n memoryLimitBytes?: number;\n maxStackSizeBytes?: number;\n};\n\n// Allow pre-loading a QuickJS module (e.g. with custom WASM bytes for compiled binaries)\nlet preloadedModule: QuickJSWASMModule | null = null;\n\nexport const setQuickJSModule = (mod: QuickJSWASMModule) => {\n preloadedModule = mod;\n};\n\nconst resolveQuickJS = (): Promise<QuickJSWASMModule> =>\n preloadedModule ? Promise.resolve(preloadedModule) : getQuickJS();\n\nclass QuickJsExecutionError extends Data.TaggedError(\"QuickJsExecutionError\")<{\n readonly message: string;\n}> {}\n\n// Large OpenAPI specs can take longer to parse inside QuickJS, so keep the\n// default execution budget at five minutes unless a caller opts into less.\nconst DEFAULT_TIMEOUT_MS = 5 * 60_000;\nconst DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;\nconst DEFAULT_MAX_STACK_SIZE_BYTES = 1 * 1024 * 1024;\nconst EXECUTION_FILENAME = \"executor-quickjs-runtime.js\";\n\nconst toError = (cause: unknown): Error =>\n cause instanceof Error ? cause : new Error(String(cause));\n\n// Defect surfaced to the sandbox when a tool dispatch reaches the\n// reject path. Two sources reach here:\n// - `ExecutionToolError` emitted by the execution package — message\n// is already either the canonical\n// `Internal tool error [<corrId>]` opaque generic (plugin defects\n// passed through `makeExecutorToolInvoker`'s catchCause) or an\n// intentional public string (validators in engine.ts:\n// \"tools.search expects an object: ...\").\n// - Anything else — assume infra defect and emit a bare opaque\n// generic.\n// `_tag === \"ExecutionToolError\"` is the in-band signal that the\n// message was generated by code we control and is safe to pass\n// through; we never read `.cause` / `.stack`.\nconst sandboxDefectMessage = (cause: unknown): string => {\n if (cause !== null && typeof cause === \"object\") {\n const tagged = cause as { readonly _tag?: unknown; readonly message?: unknown };\n // oxlint-disable-next-line executor/no-manual-tag-check, executor/no-unknown-error-message -- boundary: QuickJS reject path receives an already-rendered ExecutionToolError; we pass its in-band public message through and otherwise emit the opaque generic\n if (tagged._tag === \"ExecutionToolError\" && typeof tagged.message === \"string\") {\n return tagged.message;\n }\n }\n return \"Internal tool error\";\n};\n\nconst toErrorMessage = (cause: unknown): string => {\n if (typeof cause === \"object\" && cause !== null) {\n const message =\n \"message\" in cause && typeof cause.message === \"string\" ? cause.message : undefined;\n\n if (message) {\n return message;\n }\n\n const stack = \"stack\" in cause && typeof cause.stack === \"string\" ? cause.stack : undefined;\n\n if (stack) {\n return stack;\n }\n }\n\n const error = toError(cause);\n return error.stack ?? error.message;\n};\n\nconst serializeJson = (value: unknown, label: string): string | undefined => {\n if (typeof value === \"undefined\") {\n return undefined;\n }\n\n try {\n return JSON.stringify(value);\n } catch (cause) {\n throw new Error(`${label} is not JSON serializable: ${toError(cause).message}`);\n }\n};\n\nconst looksLikeInterruptedError = (message: string): boolean => /\\binterrupted\\b/i.test(message);\n\nconst timeoutMessage = (timeoutMs: number): string =>\n `QuickJS execution timed out after ${timeoutMs}ms`;\n\nconst normalizeExecutionError = (cause: unknown, deadlineMs: number, timeoutMs: number): string => {\n const message = toErrorMessage(cause);\n return Date.now() >= deadlineMs && looksLikeInterruptedError(message)\n ? timeoutMessage(timeoutMs)\n : message;\n};\n\nconst buildExecutionSource = (code: string): string => {\n // QuickJS evaluates plain JavaScript only; strip any TS type syntax\n // first. A parse failure here throws a SyntaxError which the outer\n // `Effect.tryPromise` maps to `QuickJsExecutionError` with the\n // sucrase-formatted message intact.\n const body = stripTypeScript(recoverExecutionBody(code));\n\n return [\n '\"use strict\";',\n \"const __invokeTool = __executor_invokeTool;\",\n \"const __log = __executor_log;\",\n \"try { delete globalThis.__executor_invokeTool; } catch {}\",\n \"try { delete globalThis.__executor_log; } catch {}\",\n \"const __formatLogArg = (value) => {\",\n \" if (typeof value === 'string') return value;\",\n \" try {\",\n \" return JSON.stringify(value);\",\n \" } catch {\",\n \" return String(value);\",\n \" }\",\n \"};\",\n \"const __formatLogLine = (args) => args.map(__formatLogArg).join(' ');\",\n \"const __outputs = [];\",\n \"globalThis.__executor_outputs = __outputs;\",\n \"const __formatOutputText = (value) => {\",\n \" if (typeof value === 'undefined') return 'undefined';\",\n \" if (value === null) return 'null';\",\n \" if (typeof value === 'string') return value;\",\n \" try {\",\n \" return JSON.stringify(value);\",\n \" } catch {\",\n \" return String(value);\",\n \" }\",\n \"};\",\n \"const __isToolFile = (value) => value && typeof value === 'object' && value._tag === 'ToolFile' && typeof value.mimeType === 'string' && value.encoding === 'base64' && typeof value.data === 'string' && typeof value.byteLength === 'number';\",\n \"const __isMcpTextContentBlock = (value) => value && typeof value === 'object' && value.type === 'text' && typeof value.text === 'string';\",\n \"const __isMcpImageContentBlock = (value) => value && typeof value === 'object' && value.type === 'image' && typeof value.data === 'string' && typeof value.mimeType === 'string';\",\n \"const __isMcpAudioContentBlock = (value) => value && typeof value === 'object' && value.type === 'audio' && typeof value.data === 'string' && typeof value.mimeType === 'string';\",\n \"const __isMcpResourceContentBlock = (value) => value && typeof value === 'object' && value.type === 'resource' && value.resource && typeof value.resource === 'object' && typeof value.resource.uri === 'string' && (typeof value.resource.text === 'string' || typeof value.resource.blob === 'string');\",\n \"const __isMcpResourceLinkContentBlock = (value) => value && typeof value === 'object' && value.type === 'resource_link' && typeof value.uri === 'string' && typeof value.name === 'string';\",\n \"const __isMcpContentBlock = (value) => __isMcpTextContentBlock(value) || __isMcpImageContentBlock(value) || __isMcpAudioContentBlock(value) || __isMcpResourceContentBlock(value) || __isMcpResourceLinkContentBlock(value);\",\n \"const emit = (value) => {\",\n \" if (__isToolFile(value)) {\",\n \" __outputs.push({ type: 'file', file: value });\",\n \" return;\",\n \" }\",\n \" if (__isMcpContentBlock(value)) {\",\n \" __outputs.push({ type: 'content', content: value });\",\n \" return;\",\n \" }\",\n \" __outputs.push({ type: 'content', content: { type: 'text', text: __formatOutputText(value) } });\",\n \"};\",\n \"const __toolsEnumerationError = (path) => new Error(\",\n \" (path.length === 0 ? 'tools' : 'tools.' + path.join('.')) +\",\n ' \\' is a lazy proxy and cannot be enumerated. Use tools.search({ query: \"...\" }) to find tools, tools.search({ namespace: \"<integration>\", query: \"\" }) to list every tool in an integration, or tools.executor.coreTools.connections.list({}) to list saved connections.\\',',\n \");\",\n \"const __makeToolsProxy = (path = []) => new Proxy(() => undefined, {\",\n \" get(_target, prop) {\",\n \" if (prop === 'then' || typeof prop === 'symbol') {\",\n \" return undefined;\",\n \" }\",\n \" return __makeToolsProxy([...path, String(prop)]);\",\n \" },\",\n \" ownKeys() {\",\n \" throw __toolsEnumerationError(path);\",\n \" },\",\n \" getOwnPropertyDescriptor() {\",\n \" throw __toolsEnumerationError(path);\",\n \" },\",\n \" apply(_target, _thisArg, args) {\",\n \" const toolPath = path.join('.');\",\n \" if (!toolPath) {\",\n \" throw new Error('Tool path missing in invocation');\",\n \" }\",\n \" return Promise.resolve(__invokeTool(toolPath, args[0])).then((raw) => raw === undefined ? undefined : JSON.parse(raw));\",\n \" },\",\n \"});\",\n \"const tools = __makeToolsProxy();\",\n \"const console = {\",\n \" log: (...args) => __log('log', __formatLogLine(args)),\",\n \" warn: (...args) => __log('warn', __formatLogLine(args)),\",\n \" error: (...args) => __log('error', __formatLogLine(args)),\",\n \" info: (...args) => __log('info', __formatLogLine(args)),\",\n \" debug: (...args) => __log('debug', __formatLogLine(args)),\",\n \"};\",\n \"const fetch = (..._args) => {\",\n \" throw new Error('fetch is disabled in QuickJS executor');\",\n \"};\",\n \"(async () => {\",\n body,\n \"})()\",\n ].join(\"\\n\");\n};\n\nconst readPropDump = (context: QuickJSContext, handle: QuickJSHandle, key: string): unknown => {\n const prop = context.getProp(handle, key);\n try {\n return context.dump(prop);\n } finally {\n prop.dispose();\n }\n};\n\nconst readOutputItems = (context: QuickJSContext): ExecuteOutputItem[] | undefined => {\n const output = readPropDump(context, context.global, \"__executor_outputs\");\n return Array.isArray(output) && output.length > 0 ? (output as ExecuteOutputItem[]) : undefined;\n};\n\nconst readResultState = (\n context: QuickJSContext,\n handle: QuickJSHandle,\n): {\n settled: boolean;\n value: unknown;\n error: unknown;\n} => ({\n settled: readPropDump(context, handle, \"settled\") === true,\n value: readPropDump(context, handle, \"v\"),\n error: readPropDump(context, handle, \"e\"),\n});\n\nconst createLogBridge = (context: QuickJSContext, logs: string[]): QuickJSHandle =>\n context.newFunction(\"__executor_log\", (levelHandle, lineHandle) => {\n const level = context.getString(levelHandle);\n const line = context.getString(lineHandle);\n logs.push(`[${level}] ${line}`);\n return context.undefined;\n });\n\ntype RunPromise = <A, E>(effect: Effect.Effect<A, E>) => Promise<A>;\n\nconst createToolBridge = (\n context: QuickJSContext,\n toolInvoker: SandboxToolInvoker,\n pendingDeferreds: Set<QuickJSDeferredPromise>,\n runPromise: RunPromise,\n): QuickJSHandle =>\n context.newFunction(\"__executor_invokeTool\", (pathHandle, argsHandle) => {\n const path = context.getString(pathHandle);\n const args =\n argsHandle === undefined || context.typeof(argsHandle) === \"undefined\"\n ? undefined\n : context.dump(argsHandle);\n const deferred = context.newPromise();\n pendingDeferreds.add(deferred);\n deferred.settled.finally(() => {\n pendingDeferreds.delete(deferred);\n });\n\n void runPromise(toolInvoker.invoke({ path, args })).then(\n (value) => {\n if (!deferred.alive) {\n return;\n }\n\n const serialized = serializeJson(value, `Tool result for ${path}`);\n if (typeof serialized === \"undefined\") {\n deferred.resolve();\n return;\n }\n\n const valueHandle = context.newString(serialized);\n deferred.resolve(valueHandle);\n valueHandle.dispose();\n },\n (cause) => {\n if (!deferred.alive) {\n return;\n }\n\n // The reject path is reserved for true infra defects. The\n // upstream tool-invoker has already replaced the message with\n // an opaque generic plus a correlation id, but defensively log\n // the cause here and emit a stable generic if upstream changes.\n const message = sandboxDefectMessage(cause);\n try {\n console.error(\"[executor:quickjs] tool dispatch defect\", { path, cause });\n } catch {\n /* ignore logger failures */\n }\n const errorHandle = context.newError(message);\n deferred.reject(errorHandle);\n errorHandle.dispose();\n },\n );\n\n return deferred.handle;\n });\n\nconst drainJobs = (\n context: QuickJSContext,\n runtime: QuickJSRuntime,\n deadlineMs: number,\n timeoutMs: number,\n): void => {\n while (runtime.hasPendingJob()) {\n if (Date.now() >= deadlineMs) {\n throw new Error(timeoutMessage(timeoutMs));\n }\n\n const pending = runtime.executePendingJobs();\n if (pending.error) {\n const error = context.dump(pending.error);\n pending.error.dispose();\n throw toError(error);\n }\n }\n};\n\nconst waitForDeferreds = async (\n pendingDeferreds: ReadonlySet<QuickJSDeferredPromise>,\n deadlineMs: number,\n timeoutMs: number,\n): Promise<void> => {\n const remainingMs = deadlineMs - Date.now();\n if (remainingMs <= 0) {\n throw new Error(timeoutMessage(timeoutMs));\n }\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n Promise.race([...pendingDeferreds].map((deferred) => deferred.settled)),\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(timeoutMessage(timeoutMs))), remainingMs);\n }),\n ]);\n } finally {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n }\n};\n\nconst drainAsync = async (\n context: QuickJSContext,\n runtime: QuickJSRuntime,\n pendingDeferreds: ReadonlySet<QuickJSDeferredPromise>,\n deadlineMs: number,\n timeoutMs: number,\n): Promise<void> => {\n drainJobs(context, runtime, deadlineMs, timeoutMs);\n\n while (pendingDeferreds.size > 0) {\n await waitForDeferreds(pendingDeferreds, deadlineMs, timeoutMs);\n drainJobs(context, runtime, deadlineMs, timeoutMs);\n }\n\n drainJobs(context, runtime, deadlineMs, timeoutMs);\n};\n\nconst evaluateInQuickJs = async (\n options: QuickJsExecutorOptions,\n code: string,\n toolInvoker: SandboxToolInvoker,\n runPromise: RunPromise,\n): Promise<ExecuteResult> => {\n const timeoutMs = Math.max(100, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n const deadlineMs = Date.now() + timeoutMs;\n const logs: string[] = [];\n const pendingDeferreds = new Set<QuickJSDeferredPromise>();\n const QuickJS = await resolveQuickJS();\n const runtime = QuickJS.newRuntime();\n\n try {\n runtime.setMemoryLimit(options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES);\n runtime.setMaxStackSize(options.maxStackSizeBytes ?? DEFAULT_MAX_STACK_SIZE_BYTES);\n\n runtime.setInterruptHandler(shouldInterruptAfterDeadline(deadlineMs));\n\n const context = runtime.newContext();\n try {\n const logBridge = createLogBridge(context, logs);\n context.setProp(context.global, \"__executor_log\", logBridge);\n logBridge.dispose();\n\n const toolBridge = createToolBridge(context, toolInvoker, pendingDeferreds, runPromise);\n context.setProp(context.global, \"__executor_invokeTool\", toolBridge);\n toolBridge.dispose();\n\n const evaluated = context.evalCode(buildExecutionSource(code), EXECUTION_FILENAME);\n if (evaluated.error) {\n const error = context.dump(evaluated.error);\n evaluated.error.dispose();\n return {\n result: null,\n error: normalizeExecutionError(error, deadlineMs, timeoutMs),\n logs,\n } satisfies ExecuteResult;\n }\n\n context.setProp(context.global, \"__executor_result\", evaluated.value);\n evaluated.value.dispose();\n\n const stateResult = context.evalCode(\n \"(function(p){ var s = { v: void 0, e: void 0, settled: false }; var formatError = function(e){ if (e && typeof e === 'object') { var message = typeof e.message === 'string' ? e.message : ''; var stack = typeof e.stack === 'string' ? e.stack : ''; if (message && stack) { return stack.indexOf(message) === -1 ? message + '\\\\n' + stack : stack; } if (message) return message; if (stack) return stack; } return String(e); }; p.then(function(v){ s.v = v; s.settled = true; }, function(e){ s.e = formatError(e); s.settled = true; }); return s; })(__executor_result)\",\n );\n if (stateResult.error) {\n const error = context.dump(stateResult.error);\n stateResult.error.dispose();\n return {\n result: null,\n error: normalizeExecutionError(error, deadlineMs, timeoutMs),\n logs,\n } satisfies ExecuteResult;\n }\n\n const stateHandle = stateResult.value;\n try {\n await drainAsync(context, runtime, pendingDeferreds, deadlineMs, timeoutMs);\n const state = readResultState(context, stateHandle);\n if (!state.settled) {\n return {\n result: null,\n error: timeoutMessage(timeoutMs),\n output: readOutputItems(context),\n logs,\n } satisfies ExecuteResult;\n }\n\n if (typeof state.error !== \"undefined\") {\n return {\n result: null,\n error: normalizeExecutionError(state.error, deadlineMs, timeoutMs),\n output: readOutputItems(context),\n logs,\n } satisfies ExecuteResult;\n }\n\n return {\n result: state.value,\n output: readOutputItems(context),\n logs,\n } satisfies ExecuteResult;\n } finally {\n stateHandle.dispose();\n }\n } finally {\n for (const deferred of pendingDeferreds) {\n if (deferred.alive) {\n deferred.dispose();\n }\n }\n\n pendingDeferreds.clear();\n context.dispose();\n }\n } catch (cause) {\n return {\n result: null,\n error: normalizeExecutionError(cause, deadlineMs, timeoutMs),\n logs,\n } satisfies ExecuteResult;\n } finally {\n runtime.dispose();\n }\n};\n\nconst runInQuickJs = (\n options: QuickJsExecutorOptions,\n code: string,\n toolInvoker: SandboxToolInvoker,\n): Effect.Effect<ExecuteResult, QuickJsExecutionError> =>\n Effect.gen(function* () {\n const context = yield* Effect.context<never>();\n const runPromise = Effect.runPromiseWith(context);\n return yield* Effect.tryPromise({\n try: () => evaluateInQuickJs(options, code, toolInvoker, runPromise),\n catch: (cause) => new QuickJsExecutionError({ message: String(cause) }),\n });\n }).pipe(\n Effect.withSpan(\"executor.code.exec.quickjs\", {\n attributes: { \"executor.runtime\": \"quickjs\" },\n }),\n );\n\nexport const makeQuickJsExecutor = (\n options: QuickJsExecutorOptions = {},\n): CodeExecutor<QuickJsExecutionError> => ({\n execute: (code: string, toolInvoker: SandboxToolInvoker) =>\n runInQuickJs(options, code, toolInvoker),\n});\n"],"mappings":"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","names":["context"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rafads/runtime-quickjs",
|
|
3
|
+
"version": "1.5.38",
|
|
4
|
+
"homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/kernel/runtime-quickjs",
|
|
5
|
+
"bugs": {
|
|
6
|
+
"url": "https://github.com/UsefulSoftwareCo/executor/issues"
|
|
7
|
+
},
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/UsefulSoftwareCo/executor.git",
|
|
12
|
+
"directory": "packages/kernel/runtime-quickjs"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"type": "module",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"import": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"default": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup && tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src",
|
|
31
|
+
"typecheck": "tsgo --noEmit",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:watch": "vitest",
|
|
34
|
+
"typecheck:slow": "bunx tsc --noEmit -p tsconfig.json"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@rafads/codemode-core": "1.5.38",
|
|
38
|
+
"quickjs-emscripten": "^0.31.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@effect/vitest": "4.0.0-beta.59",
|
|
42
|
+
"@types/node": "^24.3.1",
|
|
43
|
+
"bun-types": "^1.2.22",
|
|
44
|
+
"effect": "4.0.0-beta.59",
|
|
45
|
+
"tsup": "^8.5.0",
|
|
46
|
+
"typescript": "^5.9.3",
|
|
47
|
+
"vitest": "^4.1.5"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"effect": "4.0.0-beta.59"
|
|
51
|
+
}
|
|
52
|
+
}
|