@trim21/personal-pi-extensions 0.1.655 → 0.1.659
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 +2 -2
- package/package.json +1 -1
- package/src/codemode/protocol.ts +4 -9
- package/src/codemode/sandbox.ts +1 -13
- package/src/codemode/source.ts +3 -13
- package/src/codemode/tool.ts +2 -10
- package/src/codemode/worker.js +80 -88
- package/src/codemode/worker.ts +1 -1
package/README.md
CHANGED
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
- **只有脚本输出进上下文**:`text(value)` / `console.log(...)` 与 `return` 值进入工具结果,
|
|
44
44
|
中间的工具调用与它们的返回内容不会(也不在会话记录里留下工具调用条目)。
|
|
45
45
|
- **脚本接口**:`tools` / `ALL_TOOLS` / `text` / `image` / `exit` / `console.*` /
|
|
46
|
-
`store(key, value)` / `load(key)`;首行可选 `// @options: {"
|
|
47
|
-
|
|
46
|
+
`store(key, value)` / `load(key)`;首行可选 `// @options: {"max_output_tokens": 10000}`。
|
|
47
|
+
脚本没有超时:死循环由调用方中止(Esc)结束,等嵌套调用返回(含用户审批弹窗)多久都不算超时。
|
|
48
48
|
- **store** 写在会话的自定义 entry 上(跟随分支),输出超过 `max_output_tokens` 时头尾
|
|
49
49
|
截断并把全文落到 `$TMPDIR/pi-codemode-*.txt`。
|
|
50
50
|
- **构建**:worker 入口是 esbuild 产物 `src/codemode/worker.js`(随仓库提交,
|
package/package.json
CHANGED
package/src/codemode/protocol.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 每次执行起一个新的 worker:主线程把注册时编好的 wasm 模块连同脚本、可调用工具、
|
|
5
5
|
* 初始 store 一起发过去,worker 里建 QuickJS VM 跑脚本,脚本的嵌套调用与输出回传,
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* 主线程执行工具后把结果发回去。脚本没有超时,只有调用方的中止:中止时主线程直接
|
|
7
|
+
* `worker.terminate()`,因此不需要取消消息。
|
|
8
8
|
*
|
|
9
9
|
* worker 边界两侧都做 typebox 校验:worker 里跑的是模型写的代码,回传的消息同样
|
|
10
10
|
* 当外部输入对待。
|
|
@@ -60,12 +60,7 @@ const outputSchema = Type.Object({
|
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
const scriptErrorSchema = Type.Object({
|
|
63
|
-
kind: Type.Union([
|
|
64
|
-
Type.Literal("script"),
|
|
65
|
-
Type.Literal("timeout"),
|
|
66
|
-
Type.Literal("aborted"),
|
|
67
|
-
Type.Literal("sandbox"),
|
|
68
|
-
]),
|
|
63
|
+
kind: Type.Union([Type.Literal("script"), Type.Literal("aborted"), Type.Literal("sandbox")]),
|
|
69
64
|
name: Type.Optional(Type.String()),
|
|
70
65
|
message: Type.String(),
|
|
71
66
|
stack: Type.Optional(Type.String()),
|
|
@@ -104,7 +99,7 @@ export interface WorkerBootstrap {
|
|
|
104
99
|
export type CodemodeOutputItem =
|
|
105
100
|
{ type: "text"; text: string } | { type: "image"; data: string; mimeType: string };
|
|
106
101
|
|
|
107
|
-
export type ScriptErrorKind = "script" | "
|
|
102
|
+
export type ScriptErrorKind = "script" | "aborted" | "sandbox";
|
|
108
103
|
|
|
109
104
|
export interface ScriptError {
|
|
110
105
|
kind: ScriptErrorKind;
|
package/src/codemode/sandbox.ts
CHANGED
|
@@ -42,7 +42,7 @@ export interface SandboxRunOptions {
|
|
|
42
42
|
code: string;
|
|
43
43
|
tools: readonly ScriptTool[];
|
|
44
44
|
store: Record<string, unknown>;
|
|
45
|
-
|
|
45
|
+
/** 调用方中止本次执行;脚本没有自己的超时,死循环只能靠它结束。 */
|
|
46
46
|
signal?: AbortSignal;
|
|
47
47
|
/** 每次嵌套调用:由调用方执行工具并把结果回给脚本。 */
|
|
48
48
|
onCall(request: { id: number; name: string; args: unknown }): Promise<SandboxCallOutcome>;
|
|
@@ -84,7 +84,6 @@ function runInWorker(wasm: object, options: SandboxRunOptions): Promise<SandboxO
|
|
|
84
84
|
const calls: ScriptCall[] = [];
|
|
85
85
|
const started = new Map<number, { name: string; at: number }>();
|
|
86
86
|
let settled = false;
|
|
87
|
-
let deadline: NodeJS.Timeout | undefined;
|
|
88
87
|
|
|
89
88
|
const finish = (
|
|
90
89
|
body:
|
|
@@ -95,9 +94,6 @@ function runInWorker(wasm: object, options: SandboxRunOptions): Promise<SandboxO
|
|
|
95
94
|
return;
|
|
96
95
|
}
|
|
97
96
|
settled = true;
|
|
98
|
-
if (deadline) {
|
|
99
|
-
clearTimeout(deadline);
|
|
100
|
-
}
|
|
101
97
|
void worker.terminate();
|
|
102
98
|
resolve({ ...body, output, calls });
|
|
103
99
|
};
|
|
@@ -106,14 +102,6 @@ function runInWorker(wasm: object, options: SandboxRunOptions): Promise<SandboxO
|
|
|
106
102
|
finish({ ok: false, error: { kind, message }, writes: NO_WRITES });
|
|
107
103
|
};
|
|
108
104
|
|
|
109
|
-
// 默认没有超时(Infinity):setTimeout 会把 Infinity 当成 1ms,必须显式判断
|
|
110
|
-
if (Number.isFinite(options.timeoutMs)) {
|
|
111
|
-
deadline = setTimeout(() => {
|
|
112
|
-
fail(`the script exceeded its ${options.timeoutMs}ms deadline`, "timeout");
|
|
113
|
-
}, options.timeoutMs);
|
|
114
|
-
deadline.unref();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
105
|
if (options.signal) {
|
|
118
106
|
if (options.signal.aborted) {
|
|
119
107
|
fail("codemode execution was aborted", "aborted");
|
package/src/codemode/source.ts
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* codemode 脚本源码的解析:首行可选的 `// @options: {"max_output_tokens"
|
|
2
|
+
* codemode 脚本源码的解析:首行可选的 `// @options: {"max_output_tokens":…}`。
|
|
3
3
|
*
|
|
4
4
|
* 选项行与脚本首行共用一行,解析后原样保留为空行,脚本里报错的行号因此与用户写的
|
|
5
5
|
* 一致。解析失败(空输入、JSON 非法、未知字段、只有选项行没有代码)直接报错。
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const OPTIONS_PREFIX = "// @options:";
|
|
9
|
-
const SUPPORTED_FIELDS = ["max_output_tokens"
|
|
9
|
+
const SUPPORTED_FIELDS = ["max_output_tokens"] as const;
|
|
10
10
|
|
|
11
11
|
export const DEFAULT_OUTPUT_TOKENS = 10_000;
|
|
12
|
-
/**
|
|
13
|
-
* 脚本默认没有超时:编排一批工具调用本来就可能跑几分钟(例如批量读大文件)。
|
|
14
|
-
* 调用方中止与 `// @options: {"timeout_ms": …}` 都能提前结束。
|
|
15
|
-
*/
|
|
16
|
-
export const DEFAULT_TIMEOUT_MS = Infinity;
|
|
17
12
|
|
|
18
13
|
export class CodemodeSourceError extends Error {
|
|
19
14
|
constructor(message: string) {
|
|
@@ -24,7 +19,6 @@ export class CodemodeSourceError extends Error {
|
|
|
24
19
|
|
|
25
20
|
export interface CodemodeSourceOptions {
|
|
26
21
|
maxOutputTokens: number;
|
|
27
|
-
timeoutMs: number;
|
|
28
22
|
}
|
|
29
23
|
|
|
30
24
|
export interface ParsedCodemodeSource {
|
|
@@ -54,11 +48,7 @@ function parseOptions(json: string): Partial<CodemodeSourceOptions> {
|
|
|
54
48
|
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
55
49
|
throw new CodemodeSourceError(`${OPTIONS_PREFIX} ${key} must be a positive number`);
|
|
56
50
|
}
|
|
57
|
-
|
|
58
|
-
options.maxOutputTokens = value;
|
|
59
|
-
} else {
|
|
60
|
-
options.timeoutMs = value;
|
|
61
|
-
}
|
|
51
|
+
options.maxOutputTokens = value;
|
|
62
52
|
}
|
|
63
53
|
return options;
|
|
64
54
|
}
|
package/src/codemode/tool.ts
CHANGED
|
@@ -22,12 +22,7 @@ import { type ToolBus, toolResultText } from "../lib/tool-bus.js";
|
|
|
22
22
|
import { renderDeclarations, toScriptTools } from "./declarations.js";
|
|
23
23
|
import type { CodemodeOutputItem, ScriptError, StoreWrites } from "./protocol.js";
|
|
24
24
|
import { type CodemodeSandbox, createCodemodeSandbox, type ScriptCall } from "./sandbox.js";
|
|
25
|
-
import {
|
|
26
|
-
CODEMODE_SOURCE_GRAMMAR,
|
|
27
|
-
DEFAULT_OUTPUT_TOKENS,
|
|
28
|
-
DEFAULT_TIMEOUT_MS,
|
|
29
|
-
parseCodemodeSource,
|
|
30
|
-
} from "./source.js";
|
|
25
|
+
import { CODEMODE_SOURCE_GRAMMAR, DEFAULT_OUTPUT_TOKENS, parseCodemodeSource } from "./source.js";
|
|
31
26
|
|
|
32
27
|
export const CODEMODE_TOOL_NAME = "codemode";
|
|
33
28
|
|
|
@@ -230,7 +225,7 @@ export function createCodemodeTools(pi: ExtensionAPI): CodemodeTools {
|
|
|
230
225
|
parameters: Type.Object({
|
|
231
226
|
code: Type.String({
|
|
232
227
|
description:
|
|
233
|
-
'Raw JavaScript source. Top-level await and return work. May start with a `// @options: {"
|
|
228
|
+
'Raw JavaScript source. Top-level await and return work. May start with a `// @options: {"max_output_tokens": 10000}` line.',
|
|
234
229
|
}),
|
|
235
230
|
}),
|
|
236
231
|
constrainedSampling: {
|
|
@@ -241,12 +236,10 @@ export function createCodemodeTools(pi: ExtensionAPI): CodemodeTools {
|
|
|
241
236
|
|
|
242
237
|
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
243
238
|
let code: string;
|
|
244
|
-
let timeoutMs = DEFAULT_TIMEOUT_MS;
|
|
245
239
|
let maxOutputTokens = DEFAULT_OUTPUT_TOKENS;
|
|
246
240
|
try {
|
|
247
241
|
const parsed = parseCodemodeSource(params.code);
|
|
248
242
|
code = parsed.code;
|
|
249
|
-
timeoutMs = parsed.options.timeoutMs ?? timeoutMs;
|
|
250
243
|
maxOutputTokens = parsed.options.maxOutputTokens ?? maxOutputTokens;
|
|
251
244
|
} catch (error) {
|
|
252
245
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -264,7 +257,6 @@ export function createCodemodeTools(pi: ExtensionAPI): CodemodeTools {
|
|
|
264
257
|
code,
|
|
265
258
|
tools: scriptTools,
|
|
266
259
|
store: readStore(ctx),
|
|
267
|
-
timeoutMs,
|
|
268
260
|
signal,
|
|
269
261
|
onOutput: (items) => {
|
|
270
262
|
const text = textOf(items);
|
package/src/codemode/worker.js
CHANGED
|
@@ -5,8 +5,7 @@ import { JSException, MAX_STACK_SIZE, QuickJS } from "quickjs-wasi";
|
|
|
5
5
|
// src/codemode/prelude.ts
|
|
6
6
|
var MAX_STORE_VALUE_CHARS = 256 * 1024;
|
|
7
7
|
var MAX_STORE_TOTAL_CHARS = 1024 * 1024;
|
|
8
|
-
var IMAGE_HELPER_EXPECTS =
|
|
9
|
-
"image expects a non-empty image URL string, an object with image_url, or a raw MCP image block";
|
|
8
|
+
var IMAGE_HELPER_EXPECTS = "image expects a non-empty image URL string, an object with image_url, or a raw MCP image block";
|
|
10
9
|
var PRELUDE_SOURCE = String.raw`(function (bridge, toolsJson, storeJson) {
|
|
11
10
|
"use strict";
|
|
12
11
|
const stringify = JSON.stringify;
|
|
@@ -288,70 +287,65 @@ import { Type } from "typebox";
|
|
|
288
287
|
import { Value } from "typebox/value";
|
|
289
288
|
var outputItemSchema = Type.Union([
|
|
290
289
|
Type.Object({ type: Type.Literal("text"), text: Type.String() }),
|
|
291
|
-
Type.Object({ type: Type.Literal("image"), data: Type.String(), mimeType: Type.String() })
|
|
290
|
+
Type.Object({ type: Type.Literal("image"), data: Type.String(), mimeType: Type.String() })
|
|
292
291
|
]);
|
|
293
292
|
var toolDeclSchema = Type.Object({
|
|
294
293
|
name: Type.String(),
|
|
295
|
-
description: Type.Optional(Type.String())
|
|
294
|
+
description: Type.Optional(Type.String())
|
|
296
295
|
});
|
|
297
296
|
var startSchema = Type.Object({
|
|
298
297
|
t: Type.Literal("start"),
|
|
299
298
|
code: Type.String(),
|
|
300
299
|
tools: Type.Array(toolDeclSchema),
|
|
301
|
-
store: Type.Record(Type.String(), Type.Unknown())
|
|
300
|
+
store: Type.Record(Type.String(), Type.Unknown())
|
|
302
301
|
});
|
|
303
302
|
var resultSchema = Type.Union([
|
|
304
303
|
Type.Object({
|
|
305
304
|
t: Type.Literal("result"),
|
|
306
305
|
id: Type.Number(),
|
|
307
306
|
ok: Type.Literal(true),
|
|
308
|
-
value: Type.Unknown()
|
|
307
|
+
value: Type.Unknown()
|
|
309
308
|
}),
|
|
310
309
|
Type.Object({
|
|
311
310
|
t: Type.Literal("result"),
|
|
312
311
|
id: Type.Number(),
|
|
313
312
|
ok: Type.Literal(false),
|
|
314
|
-
error: Type.String()
|
|
315
|
-
})
|
|
313
|
+
error: Type.String()
|
|
314
|
+
})
|
|
316
315
|
]);
|
|
317
316
|
var callSchema = Type.Object({
|
|
318
317
|
t: Type.Literal("call"),
|
|
319
318
|
id: Type.Number(),
|
|
320
319
|
name: Type.String(),
|
|
321
|
-
args: Type.Unknown()
|
|
320
|
+
args: Type.Unknown()
|
|
322
321
|
});
|
|
323
322
|
var outputSchema = Type.Object({
|
|
324
323
|
t: Type.Literal("output"),
|
|
325
|
-
items: Type.Array(outputItemSchema)
|
|
324
|
+
items: Type.Array(outputItemSchema)
|
|
326
325
|
});
|
|
327
326
|
var scriptErrorSchema = Type.Object({
|
|
328
|
-
kind: Type.Union([
|
|
329
|
-
Type.Literal("script"),
|
|
330
|
-
Type.Literal("timeout"),
|
|
331
|
-
Type.Literal("aborted"),
|
|
332
|
-
Type.Literal("sandbox"),
|
|
333
|
-
]),
|
|
327
|
+
kind: Type.Union([Type.Literal("script"), Type.Literal("aborted"), Type.Literal("sandbox")]),
|
|
334
328
|
name: Type.Optional(Type.String()),
|
|
335
329
|
message: Type.String(),
|
|
336
|
-
stack: Type.Optional(Type.String())
|
|
330
|
+
stack: Type.Optional(Type.String())
|
|
337
331
|
});
|
|
338
332
|
var storeWritesSchema = Type.Object({
|
|
339
333
|
set: Type.Record(Type.String(), Type.Unknown()),
|
|
340
|
-
delete: Type.Array(Type.String())
|
|
334
|
+
delete: Type.Array(Type.String())
|
|
341
335
|
});
|
|
342
336
|
var doneSchema = Type.Union([
|
|
343
337
|
Type.Object({
|
|
344
338
|
t: Type.Literal("done"),
|
|
345
339
|
ok: Type.Literal(true),
|
|
346
340
|
value: Type.Unknown(),
|
|
347
|
-
writes: storeWritesSchema
|
|
341
|
+
writes: storeWritesSchema
|
|
348
342
|
}),
|
|
349
343
|
Type.Object({
|
|
350
344
|
t: Type.Literal("done"),
|
|
351
345
|
ok: Type.Literal(false),
|
|
352
346
|
error: scriptErrorSchema,
|
|
353
|
-
writes: storeWritesSchema
|
|
354
|
-
})
|
|
347
|
+
writes: storeWritesSchema
|
|
348
|
+
})
|
|
355
349
|
]);
|
|
356
350
|
var hostMessageSchema = Type.Union([startSchema, resultSchema]);
|
|
357
351
|
var workerMessageSchema = Type.Union([callSchema, outputSchema, doneSchema]);
|
|
@@ -369,7 +363,7 @@ function decodeHostMessage(value) {
|
|
|
369
363
|
// src/codemode/worker.ts
|
|
370
364
|
var MEMORY_LIMIT_BYTES = 512 * 1024 * 1024;
|
|
371
365
|
function toScriptIdentifier(name) {
|
|
372
|
-
return name.replaceAll(/[^A-Za-z0-9_$]/g, "_").replaceAll(
|
|
366
|
+
return name.replaceAll(/[^A-Za-z0-9_$]/g, "_").replaceAll(/^\d/g, "_");
|
|
373
367
|
}
|
|
374
368
|
function discardOutput(memory) {
|
|
375
369
|
return {
|
|
@@ -381,7 +375,7 @@ function discardOutput(memory) {
|
|
|
381
375
|
}
|
|
382
376
|
view.setUint32(nwrittenPtr, written, true);
|
|
383
377
|
return 0;
|
|
384
|
-
}
|
|
378
|
+
}
|
|
385
379
|
};
|
|
386
380
|
}
|
|
387
381
|
function post(message) {
|
|
@@ -427,61 +421,60 @@ async function runScript(wasm, start) {
|
|
|
427
421
|
memoryLimit: MEMORY_LIMIT_BYTES,
|
|
428
422
|
// 没有这个上限时深递归会打穿 wasm 栈变成 trap,而不是脚本里可捕获的 RangeError
|
|
429
423
|
maxStackSize: MAX_STACK_SIZE,
|
|
430
|
-
wasi: discardOutput
|
|
424
|
+
wasi: discardOutput
|
|
431
425
|
});
|
|
432
|
-
const bridge = vm.newFunction(
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
t: "call",
|
|
439
|
-
id: a.toNumber(),
|
|
440
|
-
name: stringOr(b, ""),
|
|
441
|
-
args: c === void 0 || c.isUndefined ? void 0 : JSON.parse(c.toString()),
|
|
442
|
-
});
|
|
443
|
-
break;
|
|
444
|
-
}
|
|
445
|
-
case "output": {
|
|
446
|
-
post({
|
|
447
|
-
t: "output",
|
|
448
|
-
items:
|
|
449
|
-
a.toString() === "image"
|
|
450
|
-
? [
|
|
451
|
-
{
|
|
452
|
-
type: "image",
|
|
453
|
-
data: stringOr(b, ""),
|
|
454
|
-
mimeType: stringOr(c, "application/octet-stream"),
|
|
455
|
-
},
|
|
456
|
-
]
|
|
457
|
-
: [{ type: "text", text: stringOr(b, "") }],
|
|
458
|
-
});
|
|
459
|
-
break;
|
|
460
|
-
}
|
|
461
|
-
case "done": {
|
|
462
|
-
const writes = c === void 0 || c.isUndefined ? emptyWrites() : parseWrites(c.toString());
|
|
463
|
-
if (a.toBoolean()) {
|
|
426
|
+
const bridge = vm.newFunction(
|
|
427
|
+
"bridge",
|
|
428
|
+
(kind, a, b, c) => {
|
|
429
|
+
const stringOr = (value, fallback) => value === void 0 || value.isUndefined ? fallback : value.toString();
|
|
430
|
+
switch (kind.toString()) {
|
|
431
|
+
case "call": {
|
|
464
432
|
post({
|
|
465
|
-
t: "
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
433
|
+
t: "call",
|
|
434
|
+
id: a.toNumber(),
|
|
435
|
+
name: stringOr(b, ""),
|
|
436
|
+
args: c === void 0 || c.isUndefined ? void 0 : JSON.parse(c.toString())
|
|
469
437
|
});
|
|
470
|
-
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
case "output": {
|
|
471
441
|
post({
|
|
472
|
-
t: "
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
442
|
+
t: "output",
|
|
443
|
+
items: a.toString() === "image" ? [
|
|
444
|
+
{
|
|
445
|
+
type: "image",
|
|
446
|
+
data: stringOr(b, ""),
|
|
447
|
+
mimeType: stringOr(c, "application/octet-stream")
|
|
448
|
+
}
|
|
449
|
+
] : [{ type: "text", text: stringOr(b, "") }]
|
|
476
450
|
});
|
|
451
|
+
break;
|
|
452
|
+
}
|
|
453
|
+
case "done": {
|
|
454
|
+
const writes = c === void 0 || c.isUndefined ? emptyWrites() : parseWrites(c.toString());
|
|
455
|
+
if (a.toBoolean()) {
|
|
456
|
+
post({
|
|
457
|
+
t: "done",
|
|
458
|
+
ok: true,
|
|
459
|
+
value: b === void 0 || b.isUndefined ? void 0 : JSON.parse(b.toString()),
|
|
460
|
+
writes
|
|
461
|
+
});
|
|
462
|
+
} else {
|
|
463
|
+
post({
|
|
464
|
+
t: "done",
|
|
465
|
+
ok: false,
|
|
466
|
+
error: scriptError(b === void 0 ? void 0 : b.toString(), "script"),
|
|
467
|
+
writes
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
break;
|
|
477
471
|
}
|
|
478
|
-
break;
|
|
479
472
|
}
|
|
473
|
+
return vm.undefined;
|
|
480
474
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
scope.escape(
|
|
475
|
+
);
|
|
476
|
+
const api = vm.withScope(
|
|
477
|
+
(scope) => scope.escape(
|
|
485
478
|
vm.callFunction(
|
|
486
479
|
vm.evalCode(PRELUDE_SOURCE, "codemode-prelude.js"),
|
|
487
480
|
vm.undefined,
|
|
@@ -491,13 +484,13 @@ async function runScript(wasm, start) {
|
|
|
491
484
|
start.tools.map((tool) => ({
|
|
492
485
|
name: tool.name,
|
|
493
486
|
jsName: toScriptIdentifier(tool.name),
|
|
494
|
-
description: tool.description
|
|
495
|
-
}))
|
|
496
|
-
)
|
|
487
|
+
description: tool.description
|
|
488
|
+
}))
|
|
489
|
+
)
|
|
497
490
|
),
|
|
498
|
-
vm.newString(JSON.stringify(start.store))
|
|
499
|
-
)
|
|
500
|
-
)
|
|
491
|
+
vm.newString(JSON.stringify(start.store))
|
|
492
|
+
)
|
|
493
|
+
)
|
|
501
494
|
);
|
|
502
495
|
const settle = api.getProp("settle");
|
|
503
496
|
const run = api.getProp("run");
|
|
@@ -519,21 +512,18 @@ async function runScript(wasm, start) {
|
|
|
519
512
|
api,
|
|
520
513
|
vm.newNumber(result.id),
|
|
521
514
|
result.ok ? vm.true : vm.false,
|
|
522
|
-
result.ok
|
|
523
|
-
? result.value === void 0
|
|
524
|
-
? vm.undefined
|
|
525
|
-
: vm.newString(JSON.stringify(result.value))
|
|
526
|
-
: vm.newString(result.error),
|
|
515
|
+
result.ok ? result.value === void 0 ? vm.undefined : vm.newString(JSON.stringify(result.value)) : vm.newString(result.error)
|
|
527
516
|
);
|
|
528
517
|
});
|
|
529
|
-
} catch {
|
|
518
|
+
} catch {
|
|
519
|
+
}
|
|
530
520
|
drain();
|
|
531
521
|
});
|
|
532
522
|
try {
|
|
533
523
|
const fn = vm.evalCode(
|
|
534
524
|
`(async (tools, console) => {${start.code}
|
|
535
525
|
})`,
|
|
536
|
-
"codemode.js"
|
|
526
|
+
"codemode.js"
|
|
537
527
|
);
|
|
538
528
|
vm.callFunction(run, api, fn).dispose();
|
|
539
529
|
fn.dispose();
|
|
@@ -545,16 +535,16 @@ async function runScript(wasm, start) {
|
|
|
545
535
|
ok: false,
|
|
546
536
|
error: scriptError(
|
|
547
537
|
JSON.stringify({ name: error.name, message: error.message, stack: error.stack }),
|
|
548
|
-
"script"
|
|
538
|
+
"script"
|
|
549
539
|
),
|
|
550
|
-
writes: emptyWrites()
|
|
540
|
+
writes: emptyWrites()
|
|
551
541
|
});
|
|
552
542
|
} else {
|
|
553
543
|
post({
|
|
554
544
|
t: "done",
|
|
555
545
|
ok: false,
|
|
556
546
|
error: { kind: "sandbox", message: error instanceof Error ? error.message : String(error) },
|
|
557
|
-
writes: emptyWrites()
|
|
547
|
+
writes: emptyWrites()
|
|
558
548
|
});
|
|
559
549
|
}
|
|
560
550
|
}
|
|
@@ -572,7 +562,7 @@ function main() {
|
|
|
572
562
|
t: "done",
|
|
573
563
|
ok: false,
|
|
574
564
|
error: { kind: "sandbox", message: "codemode worker: expected a start message first" },
|
|
575
|
-
writes: emptyWrites()
|
|
565
|
+
writes: emptyWrites()
|
|
576
566
|
});
|
|
577
567
|
return;
|
|
578
568
|
}
|
|
@@ -580,4 +570,6 @@ function main() {
|
|
|
580
570
|
});
|
|
581
571
|
}
|
|
582
572
|
main();
|
|
583
|
-
export {
|
|
573
|
+
export {
|
|
574
|
+
toScriptIdentifier
|
|
575
|
+
};
|
package/src/codemode/worker.ts
CHANGED
|
@@ -28,7 +28,7 @@ const MEMORY_LIMIT_BYTES = 512 * 1024 * 1024;
|
|
|
28
28
|
|
|
29
29
|
/** 工具名到脚本标识符的归一化:非法字符换成 `_`,数字开头补 `_`。 */
|
|
30
30
|
export function toScriptIdentifier(name: string): string {
|
|
31
|
-
return name.replaceAll(/[^A-Za-z0-9_$]/g, "_").replaceAll(
|
|
31
|
+
return name.replaceAll(/[^A-Za-z0-9_$]/g, "_").replaceAll(/^\d/g, "_");
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|