pi-ptc-subagents 7.7.1 → 7.9.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/CHANGELOG.md +42 -0
- package/dist/index.js +40 -6060
- package/dist/ptc/cli.js +3 -58
- package/dist/ptc/index.js +1 -77
- package/dist/ptc-engine.js +3 -0
- package/dist/worker.js +3 -145
- package/package.json +6 -6
- package/dist/ptc/fs-bindings-DCGErhvt.js +0 -423
- package/dist/ptc/worker.js +0 -197
package/dist/ptc/cli.js
CHANGED
|
@@ -1,61 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { resolve } from "node:path";
|
|
5
|
-
// src/cli.ts
|
|
6
|
-
const USAGE = `用法:ptc <program.ts> [--workdir <dir>] [--timeout <ms>] [--json]
|
|
2
|
+
import{r as e,t}from"../ptc-engine.js";import{readFileSync as n}from"node:fs";import{resolve as r}from"node:path";const i=`用法:ptc <program.ts> [--workdir <dir>] [--timeout <ms>] [--json]
|
|
7
3
|
|
|
8
4
|
程序在运行格里跑(看不见 process / fetch / 动态 import),能调的只有文件四件套
|
|
9
|
-
(read / write / grep / glob / edit),且只在 workdir 内活动。`;
|
|
10
|
-
|
|
11
|
-
let program = "";
|
|
12
|
-
let workdir = process.cwd();
|
|
13
|
-
let timeoutMs;
|
|
14
|
-
let json = false;
|
|
15
|
-
for (let i = 0; i < argv.length; i++) {
|
|
16
|
-
const arg = argv[i];
|
|
17
|
-
if (arg === "--json") json = true;
|
|
18
|
-
else if (arg === "--workdir" || arg === "-w") workdir = argv[++i] ?? workdir;
|
|
19
|
-
else if (arg === "--timeout") timeoutMs = Number(argv[++i]);
|
|
20
|
-
else if (arg.startsWith("-")) throw new Error(`未知参数 ${arg}`);
|
|
21
|
-
else if (program) throw new Error(`只能跑一个程序(多给了 ${arg})`);
|
|
22
|
-
else program = arg;
|
|
23
|
-
}
|
|
24
|
-
if (!program) throw new Error(USAGE);
|
|
25
|
-
if (timeoutMs !== void 0 && !Number.isFinite(timeoutMs)) throw new Error("--timeout 要一个毫秒数");
|
|
26
|
-
return {
|
|
27
|
-
program,
|
|
28
|
-
workdir: resolve(workdir),
|
|
29
|
-
timeoutMs,
|
|
30
|
-
json
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
function isVoid(value) {
|
|
34
|
-
return typeof value === "object" && value !== null && "$void" in value;
|
|
35
|
-
}
|
|
36
|
-
async function main() {
|
|
37
|
-
const argv = process.argv.slice(2);
|
|
38
|
-
if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) {
|
|
39
|
-
console.log(USAGE);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
const options = parseArgs(argv);
|
|
43
|
-
const outcome = await runPtcProgram({
|
|
44
|
-
code: readFileSync(options.program, "utf8"),
|
|
45
|
-
cwd: options.workdir,
|
|
46
|
-
timeoutMs: options.timeoutMs,
|
|
47
|
-
bindings: createFsBindings(options.workdir)
|
|
48
|
-
});
|
|
49
|
-
for (const line of outcome.logs) console.error(line);
|
|
50
|
-
if (options.json) console.log(JSON.stringify(outcome, null, 2));
|
|
51
|
-
else if (outcome.status === "fulfilled") console.log(isVoid(outcome.value) ? "(程序无返回值)" : JSON.stringify(outcome.value, null, 2));
|
|
52
|
-
if (outcome.status !== "fulfilled") {
|
|
53
|
-
console.error(outcome.status === "canceled" ? outcome.reason : outcome.error);
|
|
54
|
-
process.exitCode = 1;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
main().catch((error) => {
|
|
58
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
59
|
-
process.exitCode = 1;
|
|
60
|
-
});
|
|
61
|
-
export {};
|
|
5
|
+
(read / write / grep / glob / edit),且只在 workdir 内活动。`;function a(e){let t=``,n=process.cwd(),a,o=!1;for(let r=0;r<e.length;r++){let i=e[r];if(i===`--json`)o=!0;else if(i===`--workdir`||i===`-w`)n=e[++r]??n;else if(i===`--timeout`)a=Number(e[++r]);else if(i.startsWith(`-`))throw Error(`未知参数 ${i}`);else if(t)throw Error(`只能跑一个程序(多给了 ${i})`);else t=i}if(!t)throw Error(i);if(a!==void 0&&!Number.isFinite(a))throw Error(`--timeout 要一个毫秒数`);return{program:t,workdir:r(n),timeoutMs:a,json:o}}function o(e){return typeof e==`object`&&!!e&&`$void`in e}async function s(){let r=process.argv.slice(2);if(r.length===0||r.includes(`--help`)||r.includes(`-h`)){console.log(i);return}let s=a(r),c=await e({code:n(s.program,`utf8`),cwd:s.workdir,timeoutMs:s.timeoutMs,bindings:t(s.workdir)});for(let e of c.logs)console.error(e);s.json?console.log(JSON.stringify(c,null,2)):c.status===`fulfilled`&&console.log(o(c.value)?`(程序无返回值)`:JSON.stringify(c.value,null,2)),c.status!==`fulfilled`&&(console.error(c.status===`canceled`?c.reason:c.error),process.exitCode=1)}s().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});export{};
|
|
6
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/ptc/index.js
CHANGED
|
@@ -1,77 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// src/pool.ts
|
|
3
|
-
var WorkerPool = class {
|
|
4
|
-
#spawn;
|
|
5
|
-
#capacity;
|
|
6
|
-
#idle = [];
|
|
7
|
-
#waiters = [];
|
|
8
|
-
#retired = /* @__PURE__ */ new WeakSet();
|
|
9
|
-
#spawned = 0;
|
|
10
|
-
#draining = false;
|
|
11
|
-
constructor(spawn, capacity = DEFAULT_LIMITS.poolSize) {
|
|
12
|
-
this.#spawn = spawn;
|
|
13
|
-
this.#capacity = capacity;
|
|
14
|
-
}
|
|
15
|
-
acquire(timeoutMs = DEFAULT_LIMITS.poolAcquireTimeoutMs) {
|
|
16
|
-
const idle = this.#idle.pop();
|
|
17
|
-
if (idle) return Promise.resolve(idle);
|
|
18
|
-
if (this.#spawned < this.#capacity) {
|
|
19
|
-
this.#draining = false;
|
|
20
|
-
this.#spawned++;
|
|
21
|
-
return Promise.resolve(this.#track(this.#spawn()));
|
|
22
|
-
}
|
|
23
|
-
return new Promise((resolve, reject) => {
|
|
24
|
-
const timer = setTimeout(() => {
|
|
25
|
-
const index = this.#waiters.findIndex((w) => w.timer === timer);
|
|
26
|
-
if (index >= 0) this.#waiters.splice(index, 1);
|
|
27
|
-
reject(/* @__PURE__ */ new Error(`worker acquire timed out after ${timeoutMs}ms`));
|
|
28
|
-
}, timeoutMs);
|
|
29
|
-
this.#waiters.push({
|
|
30
|
-
resolve,
|
|
31
|
-
timer
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
release(worker) {
|
|
36
|
-
if (this.#draining) {
|
|
37
|
-
this.#retire(worker);
|
|
38
|
-
worker.terminate();
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
const waiter = this.#waiters.shift();
|
|
42
|
-
if (waiter) {
|
|
43
|
-
clearTimeout(waiter.timer);
|
|
44
|
-
waiter.resolve(worker);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
this.#idle.push(worker);
|
|
48
|
-
}
|
|
49
|
-
/** 被杀/卡死/崩溃的 worker:收回名额并摘出空闲表(terminate 幂等) */
|
|
50
|
-
discard(worker) {
|
|
51
|
-
this.#retire(worker);
|
|
52
|
-
const index = this.#idle.indexOf(worker);
|
|
53
|
-
if (index >= 0) this.#idle.splice(index, 1);
|
|
54
|
-
worker.terminate();
|
|
55
|
-
}
|
|
56
|
-
drain() {
|
|
57
|
-
this.#draining = true;
|
|
58
|
-
for (const worker of this.#idle.splice(0)) {
|
|
59
|
-
this.#retire(worker);
|
|
60
|
-
worker.terminate();
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
#track(worker) {
|
|
64
|
-
worker.once("exit", () => {
|
|
65
|
-
this.#retire(worker);
|
|
66
|
-
const index = this.#idle.indexOf(worker);
|
|
67
|
-
if (index >= 0) this.#idle.splice(index, 1);
|
|
68
|
-
});
|
|
69
|
-
return worker;
|
|
70
|
-
}
|
|
71
|
-
#retire(worker) {
|
|
72
|
-
if (this.#retired.has(worker)) return;
|
|
73
|
-
this.#retired.add(worker);
|
|
74
|
-
this.#spawned = Math.max(0, this.#spawned - 1);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
export { DEFAULT_LIMITS, WorkerPool, createFsBindings, runPtcProgram, spawnPtcWorker };
|
|
1
|
+
export{a as DEFAULT_LIMITS,n as WorkerPool,t as createFsBindings,r as runPtcProgram,i as spawnPtcWorker}from"../ptc-engine.js";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{existsSync as e,globSync as t,readFileSync as n,readdirSync as r,realpathSync as i,renameSync as a,statSync as o,writeFileSync as s}from"node:fs";import{basename as c,dirname as l,resolve as u,sep as d}from"node:path";import{randomUUID as f}from"node:crypto";import{Worker as p}from"node:worker_threads";const m={timeoutMs:12e4,maxTimeoutMs:6e5,graceMs:3e3,maxOutputBytes:67108864,maxPendingCalls:128,maxParallelSubCalls:10,poolSize:4,poolAcquireTimeoutMs:3e4};function h(e){return e===void 0?m.timeoutMs:Math.min(Math.max(e,1e3),m.maxTimeoutMs)}var g=class{#e=/* @__PURE__ */ new Map;#t=[];start(e,t,n){let r=``;try{r=JSON.stringify(n)??``}catch{r=String(n)}this.#e.set(e,{callId:e,name:t,argsPreview:r.slice(0,60),status:`running`,startedAt:performance.now()}),this.#t.push(e)}end(e,t){let n=this.#e.get(e);n&&(n.status=t,n.durationMs=Math.round(performance.now()-n.startedAt))}snapshot(){return this.#t.map(e=>this.#e.get(e))}};function _(t){let n=new URL(`./worker.js`,t);if(e(n))return n;let r=new URL(`../src/worker-entry.ts`,t);if(e(r))return r;throw Error(`PTC worker 缺失:期望 ${n.pathname}`)}const v=[`PATH`,`PATHEXT`,`SYSTEMROOT`,`WINDIR`,`TEMP`,`TMP`];function y(){return Object.fromEntries(v.filter(e=>e in process.env).map(e=>[e,process.env[e]]))}function b(){return new p(_(import.meta.url),{env:y(),execArgv:[],resourceLimits:{maxOldGenerationSizeMb:512,maxYoungGenerationSizeMb:64}})}async function x(e){let t=h(e.timeoutMs),n=e.cwd??process.cwd(),r=e.pool?await e.pool.acquire():b();return new Promise(i=>{let a=crypto.randomUUID(),o=[],s=[],c=new g,l=0,u=0,d=[],f=/* @__PURE__ */ new Set,p=!1,h=!1,_,v=e=>r.postMessage(e),y=t=>{if(p)return;p=!0,clearTimeout(b),d.length=0;for(let e of f)e.abort();let n={...t,subCalls:c.snapshot()};n.status===`fulfilled`&&s.length>0&&(n.images=s),i(n),e.pool?(h=!0,_=setTimeout(()=>{h&&(h=!1,e.pool.discard(r))},m.graceMs),_.unref(),v({kind:`reset`})):r.terminate()},b=setTimeout(()=>{v({kind:`cancel`,id:a,reason:`timeout`}),y({status:`canceled`,reason:`timeout after ${t}ms`,logs:o})},t),x=t=>{if(!(p&&t.kind!==`ready`)){if(t.kind===`ready`)h&&(h=!1,_&&clearTimeout(_),r.off(`message`,x),r.off(`error`,S),r.off(`exit`,C),e.pool.release(r));else if(t.runId===a){if(t.kind===`log`)o.push(t.text);else if(t.kind===`call`){if(l>=m.maxPendingCalls){v({kind:`result`,callId:t.callId,ok:!1,error:`maxPendingCalls ${m.maxPendingCalls} reached`});return}l++,c.start(t.callId,t.name,t.args);let r=async()=>{if(p)return;let r=new AbortController;f.add(r);try{let i=e.bindings[t.name];if(!i){c.end(t.callId,`rejected`),v({kind:`result`,callId:t.callId,ok:!1,error:`unknown binding ${t.name}`});return}let a=await i(t.args,{cwd:n,emitImage:e=>s.push(e),signal:r.signal});c.end(t.callId,`ok`),v({kind:`result`,callId:t.callId,ok:!0,value:a===void 0?null:a})}catch(e){c.end(t.callId,`error`),v({kind:`result`,callId:t.callId,ok:!1,error:e instanceof Error?e.message:String(e)})}finally{f.delete(r),l--,u--;let e=d.shift();e&&(u++,e())}};u<m.maxParallelSubCalls?(u++,r()):d.push(r)}else if(t.kind===`settled`){let e=t.outcome;if(JSON.stringify({logs:e.logs,value:e.status===`fulfilled`?e.value:void 0}).length>m.maxOutputBytes){y({status:`rejected`,error:`output exceeds ${m.maxOutputBytes} bytes budget`,logs:o});return}y(e)}}}};r.on(`message`,x);let S=e=>void y({status:`rejected`,error:`worker error: ${e instanceof Error?e.message:String(e)}`,logs:o}),C=e=>{p||y({status:`rejected`,error:`worker exited early with code ${e}`,logs:o})};r.on(`error`,S),r.on(`exit`,C),v({kind:`init`,surface:e.surface??`run_code`,bindingNames:Object.keys(e.bindings)}),v({kind:`run`,id:a,code:e.code,args:e.args??{}})})}var S=class{#e;#t;#n=[];#r=[];#i=/* @__PURE__ */ new WeakSet;#a=0;#o=!1;constructor(e,t=m.poolSize){this.#e=e,this.#t=t}acquire(e=m.poolAcquireTimeoutMs){let t=this.#n.pop();if(t)return Promise.resolve(t);if(this.#a<this.#t){this.#o=!1;let e=this.#e();return this.#a++,Promise.resolve(this.#s(e))}return new Promise((t,n)=>{let r=setTimeout(()=>{let t=this.#r.findIndex(e=>e.timer===r);t>=0&&this.#r.splice(t,1),n(/* @__PURE__ */ Error(`worker acquire timed out after ${e}ms`))},e);this.#r.push({resolve:t,timer:r})})}release(e){if(this.#o){this.#c(e),e.terminate();return}let t=this.#r.shift();t?(clearTimeout(t.timer),t.resolve(e)):this.#n.push(e)}discard(e){this.#c(e);let t=this.#n.indexOf(e);t>=0&&this.#n.splice(t,1),e.terminate()}drain(){this.#o=!0;for(let e of this.#n.splice(0))this.#c(e),e.terminate()}#s(e){return e.once(`exit`,()=>{this.#c(e);let t=this.#n.indexOf(e);t>=0&&this.#n.splice(t,1)}),e}#c(e){this.#i.has(e)||(this.#i.add(e),this.#a=Math.max(0,this.#a-1))}};const C=/* @__PURE__ */ new Set([`node_modules`,`.git`]),w=/* @__PURE__ */ new Set([`.png`,`.jpg`,`.jpeg`,`.gif`,`.webp`,`.ico`,`.zip`,`.gz`,`.tgz`,`.pdf`,`.woff`,`.woff2`,`.map`]),T=2097152,E=2097152;function D(e,t){let n=e?.[t];if(typeof n!=`string`||n.length===0)throw Error(`${t} 必须是非空字符串`);return n}function O(e,t){let n=u(e,t),r;try{r=i(n)}catch{r=u(i(l(n)),c(n))}if(r!==e&&!r.startsWith(e+d))throw Error(`path escapes workdir: ${t}`);return r}function*k(e){let t;try{t=r(e,{withFileTypes:!0})}catch{return}for(let n of t)if(n.isDirectory()){if(C.has(n.name))continue;yield*k(u(e,n.name))}else n.isFile()&&(yield u(e,n.name))}function A(e){let t=o(e),r=e.lastIndexOf(`.`),i=r===-1?``:e.slice(r).toLowerCase();if(t.size>T||w.has(i))return;let a=n(e,`utf8`);return a.includes(`�`)?void 0:a}function j(r,d){let p;try{p=i(u(r))}catch{throw Error(`workdir 不存在或不可达: ${r}(workdir 传用户工作区绝对路径)`)}let m={read:async e=>{let t=O(p,D(e,`path`)),r=o(t);if(!r.isFile())throw Error(`not a file: ${D(e,`path`)}`);if(r.size>T)throw Error(`file too large (${r.size} bytes > ${T})`);return n(t,`utf8`)},write:async t=>{let n=D(t,`path`),r=D(t,`content`),i=Buffer.byteLength(r,`utf8`);if(i>E)throw Error(`content too large (${i} bytes > ${E} bytes)`);let o=u(p,n),d=l(o);if(!e(d))throw Error(`parent dir does not exist: ${l(n)}(write 不隐式建目录)`);let m=O(p,d),h=u(m,c(o)),g=`${h}.ptc-${f()}`;return s(g,r,`utf8`),a(g,h),{written:h.slice(p.length+1)}},grep:async e=>{let t=D(e,`pattern`),n=typeof e?.path==`string`?O(p,D(e,`path`)):p,r;try{r=new RegExp(t)}catch{throw Error(`invalid pattern: ${t}`)}let i=[],a=o(n).isFile()?[n]:k(n);outer:for(let e of a){let t;try{t=A(e)}catch{continue}if(t===void 0)continue;let n=t.split(`
|
|
2
|
+
`);for(let t=0;t<n.length;t++)if(r.test(n[t])&&(i.push(`${e.slice(p.length+1)}:${t+1}: ${n[t]}`),i.length>=500)){i.push(`…(已截断:达到 500 条上限)`);break outer}}return i},glob:async e=>{let n=D(e,`pattern`),r;try{r=t(n,{cwd:p})}catch{throw Error(`invalid glob: ${n}`)}return r.slice(0,1e3)},edit:async e=>{let t=O(p,D(e,`path`)),r=D(e,`old_string`),i=D(e,`new_string`),o=n(t,`utf8`),c=o.split(r).length-1;if(c===0)throw Error(`old_string not found`);if(c>1)throw Error(`old_string matches ${c} places — must be unique`);let l=`${t}.ptc-${f()}`;return s(l,o.replace(r,i),`utf8`),a(l,t),{edited:t.slice(p.length+1)}}};return d?{read:e=>(d(),m.read(e)),write:e=>(d(),m.write(e)),grep:e=>(d(),m.grep(e)),glob:e=>(d(),m.glob(e)),edit:e=>(d(),m.edit(e))}:m}export{m as a,b as i,S as n,x as r,j as t};
|
|
3
|
+
//# sourceMappingURL=ptc-engine.js.map
|
package/dist/worker.js
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { parentPort, workerData } from "node:worker_threads";
|
|
3
|
-
import vm from "node:vm";
|
|
4
|
-
// ../ptc/src/compile.ts
|
|
5
|
-
function compileProgram(source) {
|
|
6
|
-
return `"use strict";\n${stripTypeScriptTypes(`async function __ptcProgram() {\n${source}\n}`, { mode: "strip" })}\n;globalThis.__ptcProgram = __ptcProgram;`;
|
|
7
|
-
}
|
|
8
|
-
// ../ptc/src/worker-main.ts
|
|
9
|
-
const CELL_PREAMBLE = `"use strict";
|
|
1
|
+
import{stripTypeScriptTypes as e}from"node:module";import{parentPort as t,workerData as n}from"node:worker_threads";import r from"node:vm";function i(t){return`"use strict";\n${e(`async function __ptcProgram() {\n${t}\n}`,{mode:`strip`})}\n;globalThis.__ptcProgram = __ptcProgram;`}function a(e){let t=[],n=`run_code`,a=/* @__PURE__ */ new Map,o=1,s=null,c=[];e.onFrame(r=>{if(r.kind===`init`)t=r.bindingNames,n=r.surface,e.post({kind:`ready`});else if(r.kind===`reset`){s=null;for(let{reject:e}of a.values())e(/* @__PURE__ */ Error(`run reset:worker 被复用`));a=/* @__PURE__ */ new Map,e.post({kind:`ready`})}else if(r.kind===`result`){let e=a.get(r.callId);if(!e)return;if(a.delete(r.callId),r.ok){let t;try{t=JSON.stringify(r.value??null)}catch{t=void 0}t===void 0?e.reject(/* @__PURE__ */ Error(`binding 返回值不可 JSON 序列化(如循环引用)`)):e.resolve(t)}else e.reject(Error(r.error))}else r.kind!==`cancel`&&u(r.code,r.id,r.args)});function l(){return`"use strict";
|
|
10
2
|
(function () {
|
|
11
3
|
var __bridge = globalThis.__ptcCall;
|
|
12
4
|
var __emit = globalThis.__ptcConsole;
|
|
@@ -59,139 +51,5 @@ if (__PTC_WORKFLOW__) {
|
|
|
59
51
|
});
|
|
60
52
|
}
|
|
61
53
|
})();
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
let bindingNames = [];
|
|
65
|
-
let surface = "run_code";
|
|
66
|
-
let pending = /* @__PURE__ */ new Map();
|
|
67
|
-
let nextCallId = 1;
|
|
68
|
-
let currentRunId = null;
|
|
69
|
-
let logs = [];
|
|
70
|
-
deps.onFrame((frame) => {
|
|
71
|
-
if (frame.kind === "init") {
|
|
72
|
-
bindingNames = frame.bindingNames;
|
|
73
|
-
surface = frame.surface;
|
|
74
|
-
deps.post({ kind: "ready" });
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
if (frame.kind === "reset") {
|
|
78
|
-
currentRunId = null;
|
|
79
|
-
for (const { reject } of pending.values()) reject(/* @__PURE__ */ new Error("run reset:worker 被复用"));
|
|
80
|
-
pending = /* @__PURE__ */ new Map();
|
|
81
|
-
deps.post({ kind: "ready" });
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
if (frame.kind === "result") {
|
|
85
|
-
const entry = pending.get(frame.callId);
|
|
86
|
-
if (!entry) return;
|
|
87
|
-
pending.delete(frame.callId);
|
|
88
|
-
if (frame.ok) {
|
|
89
|
-
let json;
|
|
90
|
-
try {
|
|
91
|
-
json = JSON.stringify(frame.value ?? null);
|
|
92
|
-
} catch {
|
|
93
|
-
json = void 0;
|
|
94
|
-
}
|
|
95
|
-
if (json === void 0) entry.reject(/* @__PURE__ */ new Error("binding 返回值不可 JSON 序列化(如循环引用)"));
|
|
96
|
-
else entry.resolve(json);
|
|
97
|
-
} else entry.reject(new Error(frame.error));
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
if (frame.kind === "cancel") return;
|
|
101
|
-
run(frame.code, frame.id, frame.args);
|
|
102
|
-
});
|
|
103
|
-
function preamble() {
|
|
104
|
-
return CELL_PREAMBLE.replace(/__PTC_NAMES__/g, () => JSON.stringify(bindingNames)).replace(/__PTC_WORKFLOW__/g, () => surface === "workflow" ? "true" : "false");
|
|
105
|
-
}
|
|
106
|
-
async function run(code, runId, args) {
|
|
107
|
-
currentRunId = runId;
|
|
108
|
-
logs = [];
|
|
109
|
-
const postLog = (level, text) => {
|
|
110
|
-
logs.push(text);
|
|
111
|
-
deps.post({
|
|
112
|
-
kind: "log",
|
|
113
|
-
runId,
|
|
114
|
-
level,
|
|
115
|
-
text
|
|
116
|
-
});
|
|
117
|
-
};
|
|
118
|
-
const outcome = await execute(code, vm.createContext({
|
|
119
|
-
__ptcArgsJson: JSON.stringify(args ?? {}),
|
|
120
|
-
__ptcCall(name, argsJson) {
|
|
121
|
-
if (currentRunId === null) return Promise.reject(/* @__PURE__ */ new Error("run 已结束:reset 后不再接受工具调用"));
|
|
122
|
-
let parsed = null;
|
|
123
|
-
try {
|
|
124
|
-
parsed = JSON.parse(argsJson);
|
|
125
|
-
} catch {
|
|
126
|
-
return Promise.reject(/* @__PURE__ */ new Error("工具参数不是合法 JSON"));
|
|
127
|
-
}
|
|
128
|
-
const call = new Promise((resolve, reject) => {
|
|
129
|
-
const callId = nextCallId++;
|
|
130
|
-
pending.set(callId, {
|
|
131
|
-
resolve,
|
|
132
|
-
reject
|
|
133
|
-
});
|
|
134
|
-
deps.post({
|
|
135
|
-
kind: "call",
|
|
136
|
-
runId: currentRunId ?? "",
|
|
137
|
-
callId,
|
|
138
|
-
name,
|
|
139
|
-
args: parsed
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
call.catch(() => {});
|
|
143
|
-
return call;
|
|
144
|
-
},
|
|
145
|
-
__ptcConsole(level, text) {
|
|
146
|
-
postLog(level, String(text));
|
|
147
|
-
}
|
|
148
|
-
}));
|
|
149
|
-
deps.post({
|
|
150
|
-
kind: "settled",
|
|
151
|
-
runId,
|
|
152
|
-
outcome
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
function errorMessage(error) {
|
|
156
|
-
if (error instanceof Error) return error.message;
|
|
157
|
-
if (error && typeof error === "object" && typeof error.message === "string") return error.message;
|
|
158
|
-
return String(error);
|
|
159
|
-
}
|
|
160
|
-
async function execute(code, context) {
|
|
161
|
-
try {
|
|
162
|
-
vm.runInContext(preamble(), context, { filename: "ptc_preamble.js" });
|
|
163
|
-
vm.runInContext(compileProgram(code), context, { filename: "run_code.js" });
|
|
164
|
-
const value = await context.__ptcProgram.call(context);
|
|
165
|
-
if (value === void 0) return {
|
|
166
|
-
status: "fulfilled",
|
|
167
|
-
value: { $void: true },
|
|
168
|
-
logs
|
|
169
|
-
};
|
|
170
|
-
const json = JSON.stringify(value);
|
|
171
|
-
if (json === void 0) return {
|
|
172
|
-
status: "rejected",
|
|
173
|
-
error: "程序返回值不可序列化",
|
|
174
|
-
logs
|
|
175
|
-
};
|
|
176
|
-
return {
|
|
177
|
-
status: "fulfilled",
|
|
178
|
-
value: JSON.parse(json),
|
|
179
|
-
logs
|
|
180
|
-
};
|
|
181
|
-
} catch (error) {
|
|
182
|
-
return {
|
|
183
|
-
status: "rejected",
|
|
184
|
-
error: errorMessage(error),
|
|
185
|
-
logs
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
// ../ptc/src/worker-entry.ts
|
|
191
|
-
if (!parentPort) throw new Error("worker-entry 只能在 worker 线程里加载");
|
|
192
|
-
Object.freeze(workerData);
|
|
193
|
-
workerMain({
|
|
194
|
-
post: (frame) => parentPort.postMessage(frame),
|
|
195
|
-
onFrame: (handler) => parentPort.on("message", (frame) => handler(frame))
|
|
196
|
-
});
|
|
197
|
-
export {};
|
|
54
|
+
`.replace(/__PTC_NAMES__/g,()=>JSON.stringify(t)).replace(/__PTC_WORKFLOW__/g,()=>n===`workflow`?`true`:`false`)}async function u(t,n,i){s=n,c=[];let l=(t,r)=>{c.push(r),e.post({kind:`log`,runId:n,level:t,text:r})},u=await f(t,r.createContext({__ptcArgsJson:JSON.stringify(i??{}),__ptcCall(t,n){if(s===null)return Promise.reject(/* @__PURE__ */ Error(`run 已结束:reset 后不再接受工具调用`));let r=null;try{r=JSON.parse(n)}catch{return Promise.reject(/* @__PURE__ */ Error(`工具参数不是合法 JSON`))}let i=new Promise((n,i)=>{let c=o++;a.set(c,{resolve:n,reject:i}),e.post({kind:`call`,runId:s??``,callId:c,name:t,args:r})});return i.catch(()=>{}),i},__ptcConsole(e,t){l(e,String(t))}}));e.post({kind:`settled`,runId:n,outcome:u})}function d(e){return e instanceof Error||e&&typeof e==`object`&&typeof e.message==`string`?e.message:String(e)}async function f(e,t){try{r.runInContext(l(),t,{filename:`ptc_preamble.js`}),r.runInContext(i(e),t,{filename:`run_code.js`});let n=await t.__ptcProgram.call(t);if(n===void 0)return{status:`fulfilled`,value:{$void:!0},logs:c};let a=JSON.stringify(n);return a===void 0?{status:`rejected`,error:`程序返回值不可序列化`,logs:c}:{status:`fulfilled`,value:JSON.parse(a),logs:c}}catch(e){return{status:`rejected`,error:d(e),logs:c}}}}if(!t)throw Error(`worker-entry 只能在 worker 线程里加载`);Object.freeze(n),a({post:e=>t.postMessage(e),onFrame:e=>t.on(`message`,t=>e(t))});export{};
|
|
55
|
+
//# sourceMappingURL=worker.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-ptc-subagents",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.9.0",
|
|
4
4
|
"description": "Programmable tool calling (PTC) and subagent fan-out for pi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi",
|
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "pnpm -r --filter=!@pi-ptc/website run build",
|
|
39
39
|
"build:kimi": "pnpm --filter @pi-ptc/kimi-mcp run build && node scripts/assemble-kimi.mjs",
|
|
40
|
-
"prepack": "pnpm run build && rm -rf dist docs/routes && cp -R packages/entry/dist dist && cp -R packages/
|
|
40
|
+
"prepack": "pnpm run build && rm -rf dist docs/routes && cp -R packages/entry/dist dist && cp -R packages/routes/docs/routes docs/routes",
|
|
41
41
|
"check": "pnpm -r --filter=!@pi-ptc/website run check",
|
|
42
42
|
"check:imports": "node scripts/check-artifact-imports.mjs",
|
|
43
43
|
"lint": "oxlint",
|
|
44
44
|
"test": "pnpm run check:imports && pnpm run test:pi && pnpm run test:output && pnpm run test:kimi && pnpm run test:standalone",
|
|
45
|
-
"test:pi": "node --test tests/pi/*.test.mjs",
|
|
46
|
-
"test:output": "node --test tests/output/*.test.mjs",
|
|
47
|
-
"test:kimi": "node --test tests/kimi/*.test.mjs",
|
|
48
|
-
"test:standalone": "node --test tests/standalone/*.test.mjs",
|
|
45
|
+
"test:pi": "node --enable-source-maps --test tests/pi/*.test.mjs",
|
|
46
|
+
"test:output": "node --enable-source-maps --test tests/output/*.test.mjs",
|
|
47
|
+
"test:kimi": "node --enable-source-maps --test tests/kimi/*.test.mjs",
|
|
48
|
+
"test:standalone": "node --enable-source-maps --test tests/standalone/*.test.mjs",
|
|
49
49
|
"pretest": "pnpm run build",
|
|
50
50
|
"fmt": "oxfmt",
|
|
51
51
|
"fmt:check": "oxfmt --check"
|