pi-ptc-subagents 7.0.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +143 -65
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pi-ptc-subagents
|
|
2
2
|
|
|
3
|
-
Programmable tool calling and subagent dispatch for [pi](https://pi.dev).
|
|
3
|
+
Programmable tool calling and subagent dispatch for [pi](https://pi.dev) — and a [Kimi Code](https://www.kimi.com/code) plugin (`ptc-tools`, MCP) that brings the same "write one program, batch-call your tools" to Kimi sessions. The npm package name is the pi-face distribution; the Kimi face ships from this repo's releases.
|
|
4
4
|
|
|
5
5
|
pi calls tools one at a time. This package lets the model write a program that calls them
|
|
6
6
|
in one go — and lets that program spawn pi subagents. Two capabilities. One package.
|
package/dist/index.js
CHANGED
|
@@ -3986,69 +3986,43 @@ function createSearchMemory() {
|
|
|
3986
3986
|
};
|
|
3987
3987
|
}
|
|
3988
3988
|
// ../tui/src/bounds.ts
|
|
3989
|
-
const RENDER_BOUNDS = {
|
|
3989
|
+
const RENDER_BOUNDS$1 = {
|
|
3990
3990
|
MAX_LOG_LINES_EXPANDED: 12,
|
|
3991
3991
|
VALUE_TREE_MAX_DEPTH: 4,
|
|
3992
3992
|
VALUE_TREE_MAX_CHILDREN: 6,
|
|
3993
3993
|
VALUE_TREE_MAX_LINE_CHARS: 120
|
|
3994
3994
|
};
|
|
3995
3995
|
// ../tui/src/text.ts
|
|
3996
|
-
const ANSI_PATTERN = /\x1B\[[0-9:;<=>?]*[ -/]*[@-~]|\x1B\][^\x07\x1B]*(?:\x07|\x1B\\)|[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g;
|
|
3997
|
-
function stripAnsi(text) {
|
|
3998
|
-
return text.replace(ANSI_PATTERN, "");
|
|
3996
|
+
const ANSI_PATTERN$1 = /\x1B\[[0-9:;<=>?]*[ -/]*[@-~]|\x1B\][^\x07\x1B]*(?:\x07|\x1B\\)|[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g;
|
|
3997
|
+
function stripAnsi$1(text) {
|
|
3998
|
+
return text.replace(ANSI_PATTERN$1, "");
|
|
3999
3999
|
}
|
|
4000
|
-
function sanitizeText(text) {
|
|
4001
|
-
return stripAnsi(text.replace(/\r/g, ""));
|
|
4000
|
+
function sanitizeText$1(text) {
|
|
4001
|
+
return stripAnsi$1(text.replace(/\r/g, ""));
|
|
4002
4002
|
}
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
if (value !== null && typeof value === "object") {
|
|
4017
|
-
if (seen.has(value)) return "[Circular]";
|
|
4018
|
-
seen.add(value);
|
|
4019
|
-
}
|
|
4020
|
-
if (Array.isArray(value)) {
|
|
4021
|
-
const shown = value.slice(0, RENDER_BOUNDS.VALUE_TREE_MAX_CHILDREN);
|
|
4022
|
-
const rest = value.length - shown.length;
|
|
4023
|
-
const oneLine = `[${shown.map((v) => JSON.stringify(v)).join(", ")}]`;
|
|
4024
|
-
const rendered = value.length === 0 ? "[]" : rest === 0 && shown.every((v) => primitive(v)) && oneLine.length <= MAX_LINE_CHARS ? oneLine : `[\n${shown.map((v) => truncateLine(`${pad} ${renderModelValue(v, depth + 1, seen)}`)).join(",\n")}${rest > 0 ? `,\n${pad} …(余 ${rest} 项)` : ""}\n${pad}]`;
|
|
4025
|
-
seen.delete(value);
|
|
4026
|
-
return rendered;
|
|
4003
|
+
RENDER_BOUNDS$1.VALUE_TREE_MAX_LINE_CHARS;
|
|
4004
|
+
// ../tui/src/truncate.ts
|
|
4005
|
+
const TRUNCATION_MAX_BYTES$1 = 51200;
|
|
4006
|
+
const TMP_FILE_TTL_MS$1 = 864e5;
|
|
4007
|
+
const TMP_FILE_PREFIX$1 = "pi-ptc-output-";
|
|
4008
|
+
let sweptTmp$1 = false;
|
|
4009
|
+
function sweepExpiredTmp$1() {
|
|
4010
|
+
sweptTmp$1 = true;
|
|
4011
|
+
let names;
|
|
4012
|
+
try {
|
|
4013
|
+
names = readdirSync(tmpdir());
|
|
4014
|
+
} catch {
|
|
4015
|
+
return;
|
|
4027
4016
|
}
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
seen.delete(value);
|
|
4035
|
-
return rendered;
|
|
4017
|
+
for (const name of names) {
|
|
4018
|
+
if (!name.startsWith(TMP_FILE_PREFIX$1)) continue;
|
|
4019
|
+
try {
|
|
4020
|
+
const file = join(tmpdir(), name);
|
|
4021
|
+
if (Date.now() - statSync(file).mtimeMs > TMP_FILE_TTL_MS$1) rmSync(file, { force: true });
|
|
4022
|
+
} catch {}
|
|
4036
4023
|
}
|
|
4037
|
-
return String(value);
|
|
4038
4024
|
}
|
|
4039
|
-
function
|
|
4040
|
-
return v === null || [
|
|
4041
|
-
"string",
|
|
4042
|
-
"number",
|
|
4043
|
-
"boolean"
|
|
4044
|
-
].includes(typeof v);
|
|
4045
|
-
}
|
|
4046
|
-
function undefinedValue(value) {
|
|
4047
|
-
return typeof value === "object" && value !== null && value.$void === true;
|
|
4048
|
-
}
|
|
4049
|
-
// ../tui/src/truncate.ts
|
|
4050
|
-
const TRUNCATION_MAX_BYTES = 51200;
|
|
4051
|
-
function applyAdr0015Truncation(text) {
|
|
4025
|
+
function applyAdr0015Truncation$1(text) {
|
|
4052
4026
|
const lines = text.split("\n");
|
|
4053
4027
|
const bytes = Buffer.byteLength(text, "utf8");
|
|
4054
4028
|
if (bytes <= 51200 && lines.length <= 2e3) return {
|
|
@@ -4062,10 +4036,11 @@ function applyAdr0015Truncation(text) {
|
|
|
4062
4036
|
kept = keptLines.join("\n");
|
|
4063
4037
|
}
|
|
4064
4038
|
const keptBuffer = Buffer.from(kept, "utf8");
|
|
4065
|
-
if (keptBuffer.length > 51200) kept = keptBuffer.subarray(keptBuffer.length - TRUNCATION_MAX_BYTES).toString("utf8");
|
|
4066
|
-
const fullOutputPath = join(tmpdir(),
|
|
4039
|
+
if (keptBuffer.length > 51200) kept = keptBuffer.subarray(keptBuffer.length - TRUNCATION_MAX_BYTES$1).toString("utf8");
|
|
4040
|
+
const fullOutputPath = join(tmpdir(), `${TMP_FILE_PREFIX$1}${randomUUID()}.txt`);
|
|
4067
4041
|
mkdirSync(tmpdir(), { recursive: true });
|
|
4068
4042
|
writeFileSync(fullOutputPath, text, "utf8");
|
|
4043
|
+
if (!sweptTmp$1) sweepExpiredTmp$1();
|
|
4069
4044
|
return {
|
|
4070
4045
|
text: [`…(已截断:省略前 ${lines.length - keptLines.length} 行 / ${bytes - Buffer.byteLength(kept, "utf8")} 字节,全文在 ${fullOutputPath})`, kept].join("\n"),
|
|
4071
4046
|
truncated: true,
|
|
@@ -4132,14 +4107,14 @@ async function runWebSearch(action, context) {
|
|
|
4132
4107
|
};
|
|
4133
4108
|
return {
|
|
4134
4109
|
ok: true,
|
|
4135
|
-
text: sanitizeText(renderSearchOverview(outcome.value, budget))
|
|
4110
|
+
text: sanitizeText$1(renderSearchOverview(outcome.value, budget))
|
|
4136
4111
|
};
|
|
4137
4112
|
}
|
|
4138
4113
|
if (action.kind === "open") {
|
|
4139
4114
|
const cached = context.memory.lookup(action.url);
|
|
4140
4115
|
if (cached !== void 0) return {
|
|
4141
4116
|
ok: true,
|
|
4142
|
-
text: sanitizeText(`(记忆命中,未发请求)\n${cached.slice(0, budget)}`)
|
|
4117
|
+
text: sanitizeText$1(`(记忆命中,未发请求)\n${cached.slice(0, budget)}`)
|
|
4143
4118
|
};
|
|
4144
4119
|
if (!context.quota.tryAcquire()) return {
|
|
4145
4120
|
ok: false,
|
|
@@ -4158,7 +4133,7 @@ async function runWebSearch(action, context) {
|
|
|
4158
4133
|
context.memory.storeText(action.url, outcome.value);
|
|
4159
4134
|
return {
|
|
4160
4135
|
ok: true,
|
|
4161
|
-
text: sanitizeText(outcome.value.slice(0, budget))
|
|
4136
|
+
text: sanitizeText$1(outcome.value.slice(0, budget))
|
|
4162
4137
|
};
|
|
4163
4138
|
}
|
|
4164
4139
|
let regex;
|
|
@@ -4178,7 +4153,7 @@ async function runWebSearch(action, context) {
|
|
|
4178
4153
|
})).filter(({ line }) => regex.test(line));
|
|
4179
4154
|
return {
|
|
4180
4155
|
ok: true,
|
|
4181
|
-
text: sanitizeText(lines.length > 0 ? lines.slice(0, 50).map(({ line, index }) => `${index + 1}: ${line}`).join("\n") : "(页内无匹配行)").slice(0, budget)
|
|
4156
|
+
text: sanitizeText$1(lines.length > 0 ? lines.slice(0, 50).map(({ line, index }) => `${index + 1}: ${line}`).join("\n") : "(页内无匹配行)").slice(0, budget)
|
|
4182
4157
|
};
|
|
4183
4158
|
}
|
|
4184
4159
|
/** 页文获取:记忆命中免费;否则占额抓取并回存记忆 */
|
|
@@ -4208,7 +4183,7 @@ async function ensurePageText(url, context) {
|
|
|
4208
4183
|
text: outcome.value
|
|
4209
4184
|
};
|
|
4210
4185
|
}
|
|
4211
|
-
//
|
|
4186
|
+
// src/web-ds-search-tool.ts
|
|
4212
4187
|
const WEB_DS_SEARCH_PARAMETERS = _Object_({
|
|
4213
4188
|
action: Union([
|
|
4214
4189
|
Literal("search"),
|
|
@@ -4371,14 +4346,13 @@ const WORKER_ENV_ALLOW_LIST = [
|
|
|
4371
4346
|
"TEMP",
|
|
4372
4347
|
"TMP"
|
|
4373
4348
|
];
|
|
4374
|
-
const WORKER_EXEC_ARGV_DENY = /^(-e|--eval|-p|--print|--input-type|-)(=|$)/;
|
|
4375
4349
|
function workerEnv() {
|
|
4376
4350
|
return Object.fromEntries(WORKER_ENV_ALLOW_LIST.filter((key) => key in process.env).map((key) => [key, process.env[key]]));
|
|
4377
4351
|
}
|
|
4378
4352
|
function spawnPtcWorker() {
|
|
4379
4353
|
return new Worker(buildWorkerUrl(import.meta.url), {
|
|
4380
4354
|
env: workerEnv(),
|
|
4381
|
-
execArgv:
|
|
4355
|
+
execArgv: [],
|
|
4382
4356
|
resourceLimits: {
|
|
4383
4357
|
maxOldGenerationSizeMb: 512,
|
|
4384
4358
|
maxYoungGenerationSizeMb: 64
|
|
@@ -4655,7 +4629,111 @@ function resolveBindingNames(activeToolNames, optIns = []) {
|
|
|
4655
4629
|
const allowed = /* @__PURE__ */ new Set([...DEFAULT_BINDING_NAMES, ...optIns]);
|
|
4656
4630
|
return KNOWN_BINDING_NAMES.filter((name) => activeToolNames.includes(name) && allowed.has(name));
|
|
4657
4631
|
}
|
|
4658
|
-
// ../
|
|
4632
|
+
// ../output/dist/index.js
|
|
4633
|
+
const RENDER_BOUNDS = {
|
|
4634
|
+
MAX_LOG_LINES_EXPANDED: 12,
|
|
4635
|
+
VALUE_TREE_MAX_DEPTH: 4,
|
|
4636
|
+
VALUE_TREE_MAX_CHILDREN: 6,
|
|
4637
|
+
VALUE_TREE_MAX_LINE_CHARS: 120
|
|
4638
|
+
};
|
|
4639
|
+
const ANSI_PATTERN = /\x1B\[[0-9:;<=>?]*[ -/]*[@-~]|\x1B\][^\x07\x1B]*(?:\x07|\x1B\\)|[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g;
|
|
4640
|
+
function stripAnsi(text) {
|
|
4641
|
+
return text.replace(ANSI_PATTERN, "");
|
|
4642
|
+
}
|
|
4643
|
+
function sanitizeText(text) {
|
|
4644
|
+
return stripAnsi(text.replace(/\r/g, ""));
|
|
4645
|
+
}
|
|
4646
|
+
const MAX_LINE_CHARS = RENDER_BOUNDS.VALUE_TREE_MAX_LINE_CHARS;
|
|
4647
|
+
function truncateLine(line, maxChars = MAX_LINE_CHARS) {
|
|
4648
|
+
if (line.length <= maxChars) return line;
|
|
4649
|
+
let cut = maxChars;
|
|
4650
|
+
while (cut > 0 && (line.charCodeAt(cut) & 64512) === 56320) cut--;
|
|
4651
|
+
return `${line.slice(0, cut)}…`;
|
|
4652
|
+
}
|
|
4653
|
+
function renderModelValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
|
|
4654
|
+
const pad = " ".repeat(depth);
|
|
4655
|
+
if (depth >= RENDER_BOUNDS.VALUE_TREE_MAX_DEPTH) return "…";
|
|
4656
|
+
if (typeof value === "string") return depth === 0 ? value : JSON.stringify(value);
|
|
4657
|
+
if (value === null || typeof value === "number" || typeof value === "boolean") return String(value);
|
|
4658
|
+
if (undefinedValue(value)) return "(无完成值)";
|
|
4659
|
+
if (value !== null && typeof value === "object") {
|
|
4660
|
+
if (seen.has(value)) return "[Circular]";
|
|
4661
|
+
seen.add(value);
|
|
4662
|
+
}
|
|
4663
|
+
if (Array.isArray(value)) {
|
|
4664
|
+
const shown = value.slice(0, RENDER_BOUNDS.VALUE_TREE_MAX_CHILDREN);
|
|
4665
|
+
const rest = value.length - shown.length;
|
|
4666
|
+
const oneLine = `[${shown.map((v) => JSON.stringify(v)).join(", ")}]`;
|
|
4667
|
+
const rendered = value.length === 0 ? "[]" : rest === 0 && shown.every((v) => primitive(v)) && oneLine.length <= MAX_LINE_CHARS ? oneLine : `[\n${shown.map((v) => truncateLine(`${pad} ${renderModelValue(v, depth + 1, seen)}`)).join(",\n")}${rest > 0 ? `,\n${pad} …(余 ${rest} 项)` : ""}\n${pad}]`;
|
|
4668
|
+
seen.delete(value);
|
|
4669
|
+
return rendered;
|
|
4670
|
+
}
|
|
4671
|
+
if (value !== null && typeof value === "object") {
|
|
4672
|
+
const entries = Object.entries(value);
|
|
4673
|
+
const shown = entries.slice(0, RENDER_BOUNDS.VALUE_TREE_MAX_CHILDREN);
|
|
4674
|
+
const rest = entries.length - shown.length;
|
|
4675
|
+
const oneLine = `{ ${shown.map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join(", ")} }`;
|
|
4676
|
+
const rendered = entries.length === 0 ? "{}" : rest === 0 && shown.every(([, v]) => primitive(v)) && oneLine.length <= MAX_LINE_CHARS ? oneLine : `{\n${shown.map(([k, v]) => truncateLine(`${pad} ${k}: ${renderModelValue(v, depth + 1, seen)}`)).join(",\n")}${rest > 0 ? `,\n${pad} …(余 ${rest} 项)` : ""}\n${pad}}`;
|
|
4677
|
+
seen.delete(value);
|
|
4678
|
+
return rendered;
|
|
4679
|
+
}
|
|
4680
|
+
return String(value);
|
|
4681
|
+
}
|
|
4682
|
+
function primitive(v) {
|
|
4683
|
+
return v === null || [
|
|
4684
|
+
"string",
|
|
4685
|
+
"number",
|
|
4686
|
+
"boolean"
|
|
4687
|
+
].includes(typeof v);
|
|
4688
|
+
}
|
|
4689
|
+
function undefinedValue(value) {
|
|
4690
|
+
return typeof value === "object" && value !== null && value.$void === true;
|
|
4691
|
+
}
|
|
4692
|
+
const TRUNCATION_MAX_BYTES = 51200;
|
|
4693
|
+
const TMP_FILE_TTL_MS = 864e5;
|
|
4694
|
+
const TMP_FILE_PREFIX = "pi-ptc-output-";
|
|
4695
|
+
let sweptTmp = false;
|
|
4696
|
+
function sweepExpiredTmp() {
|
|
4697
|
+
sweptTmp = true;
|
|
4698
|
+
let names;
|
|
4699
|
+
try {
|
|
4700
|
+
names = readdirSync(tmpdir());
|
|
4701
|
+
} catch {
|
|
4702
|
+
return;
|
|
4703
|
+
}
|
|
4704
|
+
for (const name of names) {
|
|
4705
|
+
if (!name.startsWith(TMP_FILE_PREFIX)) continue;
|
|
4706
|
+
try {
|
|
4707
|
+
const file = join(tmpdir(), name);
|
|
4708
|
+
if (Date.now() - statSync(file).mtimeMs > TMP_FILE_TTL_MS) rmSync(file, { force: true });
|
|
4709
|
+
} catch {}
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
4712
|
+
function applyAdr0015Truncation(text) {
|
|
4713
|
+
const lines = text.split("\n");
|
|
4714
|
+
const bytes = Buffer.byteLength(text, "utf8");
|
|
4715
|
+
if (bytes <= 51200 && lines.length <= 2e3) return {
|
|
4716
|
+
text,
|
|
4717
|
+
truncated: false
|
|
4718
|
+
};
|
|
4719
|
+
let keptLines = lines.slice(-2e3);
|
|
4720
|
+
let kept = keptLines.join("\n");
|
|
4721
|
+
while (Buffer.byteLength(kept, "utf8") > 51200 && keptLines.length > 1) {
|
|
4722
|
+
keptLines = keptLines.slice(Math.max(1, Math.floor(keptLines.length / 2)));
|
|
4723
|
+
kept = keptLines.join("\n");
|
|
4724
|
+
}
|
|
4725
|
+
const keptBuffer = Buffer.from(kept, "utf8");
|
|
4726
|
+
if (keptBuffer.length > 51200) kept = keptBuffer.subarray(keptBuffer.length - TRUNCATION_MAX_BYTES).toString("utf8");
|
|
4727
|
+
const fullOutputPath = join(tmpdir(), `${TMP_FILE_PREFIX}${randomUUID()}.txt`);
|
|
4728
|
+
mkdirSync(tmpdir(), { recursive: true });
|
|
4729
|
+
writeFileSync(fullOutputPath, text, "utf8");
|
|
4730
|
+
if (!sweptTmp) sweepExpiredTmp();
|
|
4731
|
+
return {
|
|
4732
|
+
text: [`…(已截断:省略前 ${lines.length - keptLines.length} 行 / ${bytes - Buffer.byteLength(kept, "utf8")} 字节,全文在 ${fullOutputPath})`, kept].join("\n"),
|
|
4733
|
+
truncated: true,
|
|
4734
|
+
fullOutputPath
|
|
4735
|
+
};
|
|
4736
|
+
}
|
|
4659
4737
|
function renderToolResult(outcome) {
|
|
4660
4738
|
let body;
|
|
4661
4739
|
if (outcome.status === "fulfilled") body = (outcome.logs.length > 0 ? [...outcome.logs, renderModelValue(outcome.value)] : [renderModelValue(outcome.value)]).join("\n");
|
|
@@ -4832,7 +4910,7 @@ function renderPtcResult(surface) {
|
|
|
4832
4910
|
if (options.expanded && !options.isPartial) for (const block of result.content) {
|
|
4833
4911
|
if (block.type !== "text") continue;
|
|
4834
4912
|
const lines = block.text.split("\n");
|
|
4835
|
-
const kept = lines.slice(0, RENDER_BOUNDS.MAX_LOG_LINES_EXPANDED);
|
|
4913
|
+
const kept = lines.slice(0, RENDER_BOUNDS$1.MAX_LOG_LINES_EXPANDED);
|
|
4836
4914
|
for (const line of kept) box.addChild(new Text(line));
|
|
4837
4915
|
if (lines.length > kept.length) box.addChild(new Text(`…(共 ${lines.length} 行,省略 ${lines.length - kept.length} 行)`));
|
|
4838
4916
|
}
|
|
@@ -5344,7 +5422,7 @@ function registerTaskFace(registerTool, session, surface) {
|
|
|
5344
5422
|
const outputBytes = await session.outputSize(args.task_id);
|
|
5345
5423
|
if (outputBytes === void 0) return textResult(record);
|
|
5346
5424
|
if (outputBytes > 51200) {
|
|
5347
|
-
const { text } = applyAdr0015Truncation(await session.readOutputTail(args.task_id, 51200) ?? "");
|
|
5425
|
+
const { text } = applyAdr0015Truncation$1(await session.readOutputTail(args.task_id, 51200) ?? "");
|
|
5348
5426
|
return textResult({
|
|
5349
5427
|
...record,
|
|
5350
5428
|
output: text,
|
|
@@ -5355,7 +5433,7 @@ function registerTaskFace(registerTool, session, surface) {
|
|
|
5355
5433
|
})
|
|
5356
5434
|
});
|
|
5357
5435
|
}
|
|
5358
|
-
const { text } = applyAdr0015Truncation(await session.readOutputTail(args.task_id, 51200) ?? "");
|
|
5436
|
+
const { text } = applyAdr0015Truncation$1(await session.readOutputTail(args.task_id, 51200) ?? "");
|
|
5359
5437
|
return textResult({
|
|
5360
5438
|
...record,
|
|
5361
5439
|
output: text
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-ptc-subagents",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.0",
|
|
4
4
|
"description": "Programmable tool calling (PTC) and subagent fan-out for pi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi",
|
|
@@ -31,10 +31,14 @@
|
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "pnpm -r --filter=!@pi-ptc/website run build",
|
|
34
|
+
"build:kimi": "pnpm --filter @pi-ptc/kimi-mcp run build && node scripts/assemble-kimi.mjs",
|
|
34
35
|
"prepack": "pnpm run build && rm -rf dist docs/routes && cp -R packages/entry/dist dist && cp -R packages/routes/docs/routes docs/routes",
|
|
35
36
|
"check": "pnpm -r --filter=!@pi-ptc/website run check",
|
|
36
37
|
"lint": "oxlint",
|
|
37
|
-
"test": "
|
|
38
|
+
"test": "pnpm run test:pi && pnpm run test:output && pnpm run test:kimi",
|
|
39
|
+
"test:pi": "node --test tests/pi/*.test.mjs",
|
|
40
|
+
"test:output": "node --test tests/output/*.test.mjs",
|
|
41
|
+
"test:kimi": "node --test tests/kimi/*.test.mjs",
|
|
38
42
|
"pretest": "pnpm run build",
|
|
39
43
|
"fmt": "oxfmt",
|
|
40
44
|
"fmt:check": "oxfmt --check"
|