@trim21/personal-pi-extensions 0.1.695 → 0.1.697
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/package.json +1 -1
- package/src/codemode/tool.ts +32 -21
- package/src/lib/github.ts +3 -4
package/package.json
CHANGED
package/src/codemode/tool.ts
CHANGED
|
@@ -235,17 +235,27 @@ async function truncateOutput(
|
|
|
235
235
|
};
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
+
/** 代码块围栏比内容里最长的反引号串更长,免得内容里的 ``` 把面板截断。 */
|
|
239
|
+
function codeBlock(content: string, language: string): string {
|
|
240
|
+
const longest = (content.match(/`+/g) ?? []).reduce((max, run) => Math.max(max, run.length), 0);
|
|
241
|
+
const fence = "`".repeat(Math.max(3, longest + 1));
|
|
242
|
+
return `${fence}${language}\n${content.trimEnd()}\n${fence}`;
|
|
243
|
+
}
|
|
244
|
+
|
|
238
245
|
/**
|
|
239
|
-
* TUI
|
|
240
|
-
*
|
|
246
|
+
* TUI 面板:`## Input` 是脚本原文,`## Output` 是脚本经 `text()` / `console.log`
|
|
247
|
+
* 产生的文本(没有输出就没有这一段;返回值与图片只进工具结果正文)。
|
|
248
|
+
* 副标题在 `detail` 后带上输出字符数,不展开面板也能看出这次产出了多少文本。
|
|
241
249
|
*/
|
|
242
|
-
function scriptPendant(code: string,
|
|
243
|
-
const
|
|
244
|
-
|
|
250
|
+
function scriptPendant(code: string, detail: string, output: string): ToolPendant {
|
|
251
|
+
const sections = [`## Input\n${codeBlock(code, "js")}`];
|
|
252
|
+
if (output.trim() !== "") {
|
|
253
|
+
sections.push(`## Output\n${codeBlock(output, "")}`);
|
|
254
|
+
}
|
|
245
255
|
return {
|
|
246
256
|
title: CODEMODE_TOOL_NAME,
|
|
247
|
-
subtitle
|
|
248
|
-
markdown:
|
|
257
|
+
subtitle: `${detail} · ${output.length} chars output`,
|
|
258
|
+
markdown: sections.join("\n\n"),
|
|
249
259
|
};
|
|
250
260
|
}
|
|
251
261
|
|
|
@@ -302,13 +312,15 @@ export function createCodemodeTools(pi: ExtensionAPI): CodemodeTools {
|
|
|
302
312
|
content: [{ type: "text", text: message }],
|
|
303
313
|
details: {
|
|
304
314
|
error: message,
|
|
305
|
-
pendant: scriptPendant(params.code, "invalid @options"),
|
|
315
|
+
pendant: scriptPendant(params.code, "invalid @options", ""),
|
|
306
316
|
},
|
|
307
317
|
};
|
|
308
318
|
}
|
|
309
319
|
|
|
310
320
|
// 脚本的 fs 原语读到的文件也进同一份记账,随结果持久化(与 details.store 同一处)
|
|
311
321
|
const recordedReads: Record<string, FileSnapshot> = {};
|
|
322
|
+
// 脚本流式输出的文本累计:进度面板与结果面板的 Output 段是同一段文本
|
|
323
|
+
let streamedText = "";
|
|
312
324
|
|
|
313
325
|
const outcome = await sandbox.run({
|
|
314
326
|
code,
|
|
@@ -317,12 +329,14 @@ export function createCodemodeTools(pi: ExtensionAPI): CodemodeTools {
|
|
|
317
329
|
signal,
|
|
318
330
|
onOutput: (items) => {
|
|
319
331
|
const text = textOf(items);
|
|
320
|
-
if (text) {
|
|
321
|
-
|
|
322
|
-
content: [{ type: "text", text }],
|
|
323
|
-
details: { pendant: scriptPendant(code, text.slice(0, 80)) },
|
|
324
|
-
});
|
|
332
|
+
if (text === "") {
|
|
333
|
+
return;
|
|
325
334
|
}
|
|
335
|
+
streamedText = streamedText === "" ? text : `${streamedText}\n${text}`;
|
|
336
|
+
onUpdate?.({
|
|
337
|
+
content: [{ type: "text", text }],
|
|
338
|
+
details: { pendant: scriptPendant(code, text.slice(0, 80), streamedText) },
|
|
339
|
+
});
|
|
326
340
|
},
|
|
327
341
|
onCallProgress: ({ phase, name, args }) => {
|
|
328
342
|
const detail =
|
|
@@ -332,7 +346,7 @@ export function createCodemodeTools(pi: ExtensionAPI): CodemodeTools {
|
|
|
332
346
|
const line = `${phase === "start" ? "→" : "←"} ${name}${detail}`;
|
|
333
347
|
onUpdate?.({
|
|
334
348
|
content: [{ type: "text", text: line }],
|
|
335
|
-
details: { pendant: scriptPendant(code, line.slice(0, 120)) },
|
|
349
|
+
details: { pendant: scriptPendant(code, line.slice(0, 120), streamedText) },
|
|
336
350
|
});
|
|
337
351
|
},
|
|
338
352
|
onCall: async ({ name, args }) => {
|
|
@@ -371,13 +385,10 @@ export function createCodemodeTools(pi: ExtensionAPI): CodemodeTools {
|
|
|
371
385
|
if (outcome.ok) {
|
|
372
386
|
const writes = outcome.writes;
|
|
373
387
|
const hasWrites = Object.keys(writes.set).length > 0 || writes.delete.length > 0;
|
|
388
|
+
const outputText = textOf(outcome.output);
|
|
374
389
|
const value =
|
|
375
390
|
outcome.value === undefined ? "" : `\n\n${JSON.stringify(outcome.value, null, 2)}`;
|
|
376
|
-
const truncated = await truncateOutput(
|
|
377
|
-
textOf(outcome.output) + value,
|
|
378
|
-
images,
|
|
379
|
-
maxOutputTokens,
|
|
380
|
-
);
|
|
391
|
+
const truncated = await truncateOutput(outputText + value, images, maxOutputTokens);
|
|
381
392
|
return {
|
|
382
393
|
content: [
|
|
383
394
|
{ type: "text" as const, text: truncated.text },
|
|
@@ -392,7 +403,7 @@ export function createCodemodeTools(pi: ExtensionAPI): CodemodeTools {
|
|
|
392
403
|
// store 的写入随工具结果持久化,下一次调用从这里重放恢复
|
|
393
404
|
...(hasWrites && { store: writes }),
|
|
394
405
|
...(hasReads(recordedReads) && { reads: recordedReads }),
|
|
395
|
-
pendant: scriptPendant(code, `${outcome.calls.length} tool call(s)
|
|
406
|
+
pendant: scriptPendant(code, `${outcome.calls.length} tool call(s)`, outputText),
|
|
396
407
|
...(truncated.fullOutputPath && { fullOutputPath: truncated.fullOutputPath }),
|
|
397
408
|
},
|
|
398
409
|
};
|
|
@@ -413,7 +424,7 @@ export function createCodemodeTools(pi: ExtensionAPI): CodemodeTools {
|
|
|
413
424
|
calls: outcome.calls,
|
|
414
425
|
error: outcome.error.kind,
|
|
415
426
|
...(hasReads(recordedReads) && { reads: recordedReads }),
|
|
416
|
-
pendant: scriptPendant(code, `failed (${outcome.error.kind})
|
|
427
|
+
pendant: scriptPendant(code, `failed (${outcome.error.kind})`, body),
|
|
417
428
|
},
|
|
418
429
|
};
|
|
419
430
|
},
|
package/src/lib/github.ts
CHANGED
|
@@ -50,10 +50,9 @@ const searchItemSchema = Type.Object({
|
|
|
50
50
|
created_at: Type.String(),
|
|
51
51
|
updated_at: Type.String(),
|
|
52
52
|
closed_at: Type.Union([Type.String(), Type.Null()]),
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
]),
|
|
53
|
+
// 搜索 API 只在条目是 PR 时才带这个键(纯 issue 条目压根没有它);PR 条目一定带
|
|
54
|
+
// `merged_at`,未合并为 null、已合并为时间戳
|
|
55
|
+
pull_request: Type.Optional(Type.Object({ merged_at: Type.Union([Type.String(), Type.Null()]) })),
|
|
57
56
|
});
|
|
58
57
|
|
|
59
58
|
type SearchItem = Static<typeof searchItemSchema>;
|