pi-web-ui 0.64.4 → 0.64.6
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/dist/server/agent-service.js +95 -5
- package/dist/server/bg-servers.js +111 -26
- package/dist/server/client-state.js +2 -0
- package/dist/server/dsh/dsh-agent-service.js +31 -21
- package/dist/server/dsh/dsh-sessions.js +12 -2
- package/dist/server/files-service.js +51 -28
- package/dist/server/index.js +1 -0
- package/dist/server/process-utils.js +41 -0
- package/dist/server/protocol-version.js +1 -1
- package/dist/server/settings-service.js +33 -0
- package/dist/server/subagent-templates.js +14 -1
- package/dist/server/subagents.js +107 -11
- package/package.json +110 -110
- package/web/dist/assets/{TerminalPanel-D6-kd9NX.js → TerminalPanel-CoPFNu1d.js} +1 -1
- package/web/dist/assets/{abnfDiagram-VCTEODGH-Ciapjs2h.js → abnfDiagram-VCTEODGH-Dltz1N0G.js} +1 -1
- package/web/dist/assets/{arc-DeXTszP5.js → arc-QOm2xRll.js} +1 -1
- package/web/dist/assets/{architectureDiagram-5GKGNRK7-CT2YpHJP.js → architectureDiagram-5GKGNRK7-L3XUBFbb.js} +1 -1
- package/web/dist/assets/{blockDiagram-I7D4REHJ-CUbGhz2G.js → blockDiagram-I7D4REHJ-CJmza4yx.js} +1 -1
- package/web/dist/assets/{c4Diagram-7LVT6UL2-B3tmW0uO.js → c4Diagram-7LVT6UL2-CwgA5WEW.js} +1 -1
- package/web/dist/assets/channel-VncP7yyT.js +1 -0
- package/web/dist/assets/{chunk-2Q5K7J3B-B5eVe3ZU.js → chunk-2Q5K7J3B-DoqSiCVF.js} +1 -1
- package/web/dist/assets/{chunk-5VM5RSS4-zHW5GxYE.js → chunk-5VM5RSS4-CO14GhQ1.js} +1 -1
- package/web/dist/assets/{chunk-F27PBJKO-D9YBCGH8.js → chunk-F27PBJKO-kRFf9SDx.js} +1 -1
- package/web/dist/assets/{chunk-IMKFNOWR-DFERzrJy.js → chunk-IMKFNOWR-Cm6JOqm0.js} +1 -1
- package/web/dist/assets/{chunk-JWPE2WC7-VCholTr0.js → chunk-JWPE2WC7-DTpnGTdB.js} +1 -1
- package/web/dist/assets/{chunk-POPQ4Y6H-DgLTPLwv.js → chunk-POPQ4Y6H-CdSt_7xq.js} +1 -1
- package/web/dist/assets/{chunk-SVP7TREG-B_43mnQv.js → chunk-SVP7TREG-IQRTD_4U.js} +1 -1
- package/web/dist/assets/{chunk-TICWLB2K-DexHBk9f.js → chunk-TICWLB2K-Duj1rt_5.js} +1 -1
- package/web/dist/assets/{chunk-XXDRQBXY-B4NDVbVt.js → chunk-XXDRQBXY-BFf3gcbL.js} +1 -1
- package/web/dist/assets/classDiagram-ZZMXUADV-BWCNDr-F.js +1 -0
- package/web/dist/assets/classDiagram-v2-VYDZK3BY-BWCNDr-F.js +1 -0
- package/web/dist/assets/{cose-bilkent-JH36ORCC-D4MfizXL.js → cose-bilkent-JH36ORCC-D5k0Z1dx.js} +1 -1
- package/web/dist/assets/{cynefin-OW5HDTMX-BoCpr6Nu.js → cynefin-OW5HDTMX-OsV-x0h-.js} +1 -1
- package/web/dist/assets/{cynefinDiagram-5FMLGOSQ-wCccvWLd.js → cynefinDiagram-5FMLGOSQ-DM7XHm4s.js} +1 -1
- package/web/dist/assets/{dagre-GXQ25YYZ-hZXj_BO7.js → dagre-GXQ25YYZ-B0bIbgMh.js} +1 -1
- package/web/dist/assets/{diagram-S7CK7UJ4-DgqjaR7A.js → diagram-S7CK7UJ4-lMVsMjfI.js} +1 -1
- package/web/dist/assets/{diagram-UQ7AKVKN-D2yHlsqg.js → diagram-UQ7AKVKN-BJDbkaYf.js} +1 -1
- package/web/dist/assets/{diagram-VSXAHHWV-B2ppn0d7.js → diagram-VSXAHHWV-1zUfVr-L.js} +1 -1
- package/web/dist/assets/{diagram-VX7I27RA-DGl4RYFm.js → diagram-VX7I27RA-B-Qy3dth.js} +1 -1
- package/web/dist/assets/{diagram-Z3DM3KII-Bu_MuKt2.js → diagram-Z3DM3KII-DbKcoZFP.js} +1 -1
- package/web/dist/assets/{ebnfDiagram-PWID7BFC-B462IWhy.js → ebnfDiagram-PWID7BFC-CuMZBzDi.js} +1 -1
- package/web/dist/assets/{erDiagram-RLTQ6QDP-4N5KTVz0.js → erDiagram-RLTQ6QDP-Dkw_Uhg2.js} +1 -1
- package/web/dist/assets/{flowDiagram-HODETNUW-D5YGm0jY.js → flowDiagram-HODETNUW-CwDYMy38.js} +1 -1
- package/web/dist/assets/{ganttDiagram-EL5Y4UJY-DtPjqo-N.js → ganttDiagram-EL5Y4UJY-B2s3myqg.js} +1 -1
- package/web/dist/assets/{gitGraphDiagram-WWUBYQGX-DDi56hwo.js → gitGraphDiagram-WWUBYQGX-CJ3rUTG5.js} +1 -1
- package/web/dist/assets/{index-Bfi5_bc1.js → index-30RM921r.js} +25 -25
- package/web/dist/assets/index-B_lYcsGw.css +10 -0
- package/web/dist/assets/{infoDiagram-27XIBGKW-FRX_QzzT.js → infoDiagram-27XIBGKW-DuIoOHyL.js} +1 -1
- package/web/dist/assets/{ishikawaDiagram-5VMMS53U-BYvNCcn0.js → ishikawaDiagram-5VMMS53U-Fm14e_CH.js} +1 -1
- package/web/dist/assets/{journeyDiagram-3NMN7TZE-HbYFhz4W.js → journeyDiagram-3NMN7TZE-BuokOq_3.js} +1 -1
- package/web/dist/assets/{kanban-definition-UXKFOSKX-BJFVJp0b.js → kanban-definition-UXKFOSKX-D2FQMRnh.js} +1 -1
- package/web/dist/assets/{layout-DJnxm5X9.js → layout-CZUvkkNF.js} +1 -1
- package/web/dist/assets/{linear-M6L-f6ON.js → linear-tIFeS1QT.js} +1 -1
- package/web/dist/assets/{mermaid.core-BPgLSPyb.js → mermaid.core-BI5_3AOv.js} +5 -5
- package/web/dist/assets/{mindmap-definition-YA3MSWOX-CT34wBkW.js → mindmap-definition-YA3MSWOX-D5RmpgpB.js} +1 -1
- package/web/dist/assets/{pegDiagram-XKGWAZYB-y7gUs6p-.js → pegDiagram-XKGWAZYB-DpZxaRI3.js} +1 -1
- package/web/dist/assets/{pieDiagram-E7YTZNPT-8Ksrkk_P.js → pieDiagram-E7YTZNPT-Co7MADQz.js} +1 -1
- package/web/dist/assets/{quadrantDiagram-AXDQQJYC-B1JgOvVm.js → quadrantDiagram-AXDQQJYC-BsRraVQ-.js} +1 -1
- package/web/dist/assets/{railroadDiagram-O6MQD6OU-kYgyfD-Z.js → railroadDiagram-O6MQD6OU-DW2pw5p_.js} +1 -1
- package/web/dist/assets/{requirementDiagram-BXWQKSXE-DsU0dCxH.js → requirementDiagram-BXWQKSXE-DeaEY9Dk.js} +1 -1
- package/web/dist/assets/{sankeyDiagram-P5KCCOFB-Bn3K22Ux.js → sankeyDiagram-P5KCCOFB-BlKg1xhH.js} +1 -1
- package/web/dist/assets/{sequenceDiagram-WJ2MYXX4-Ovxqv6CH.js → sequenceDiagram-WJ2MYXX4-C0ffpRmx.js} +1 -1
- package/web/dist/assets/{sizeCapture-INFHLROL-DIkQtrVp.js → sizeCapture-INFHLROL-DHFDdkAo.js} +1 -1
- package/web/dist/assets/{stateDiagram-D77RDMKH-C4ql6zER.js → stateDiagram-D77RDMKH-CwKStGSS.js} +1 -1
- package/web/dist/assets/stateDiagram-v2-MP3YSRHH-B0qJoPpx.js +1 -0
- package/web/dist/assets/{swimlanes-42K2YHIH-2hpivmJO.js → swimlanes-42K2YHIH-MB6Uskqk.js} +1 -1
- package/web/dist/assets/swimlanesDiagram-VR7AAH4N-IYPIFoU6.js +8 -0
- package/web/dist/assets/{timeline-definition-24CTP7MA-BuH_ON1U.js → timeline-definition-24CTP7MA-CkcuHQ1A.js} +1 -1
- package/web/dist/assets/{vennDiagram-4TSXK5OY-D9E14XfU.js → vennDiagram-4TSXK5OY-DRiGv5ga.js} +1 -1
- package/web/dist/assets/{wardleyDiagram-VM6X3IG4-D6h0zd6l.js → wardleyDiagram-VM6X3IG4-Cwldlf89.js} +1 -1
- package/web/dist/assets/{xychartDiagram-S5SC5T6Z-C7uuvJqC.js → xychartDiagram-S5SC5T6Z-Biqu8RpV.js} +1 -1
- package/web/dist/index.html +2 -2
- package/web/dist/assets/channel-C-ah19CA.js +0 -1
- package/web/dist/assets/classDiagram-ZZMXUADV-BjgHzd13.js +0 -1
- package/web/dist/assets/classDiagram-v2-VYDZK3BY-BjgHzd13.js +0 -1
- package/web/dist/assets/index-BVwF4g4j.css +0 -10
- package/web/dist/assets/stateDiagram-v2-MP3YSRHH-CM0zTC3x.js +0 -1
- package/web/dist/assets/swimlanesDiagram-VR7AAH4N-BqO7jiba.js +0 -8
|
@@ -219,6 +219,8 @@ export class SettingsService {
|
|
|
219
219
|
}),
|
|
220
220
|
subagentTemplates: this.templates.list(),
|
|
221
221
|
subagentDefaultTemplates: DEFAULT_TEMPLATES.map((t) => t.name),
|
|
222
|
+
subagentDefaultModel: this.settings.subagentDefaultModel ?? null,
|
|
223
|
+
subagentModels: this.collectSubagentModels(),
|
|
222
224
|
},
|
|
223
225
|
});
|
|
224
226
|
}
|
|
@@ -236,6 +238,30 @@ export class SettingsService {
|
|
|
236
238
|
return [];
|
|
237
239
|
}
|
|
238
240
|
}
|
|
241
|
+
/** 已配置鉴权的全部模型(子代理模型选择器用;跟随视觉桥的收集方式但不限视觉)。 */
|
|
242
|
+
collectSubagentModels() {
|
|
243
|
+
try {
|
|
244
|
+
const runtime = this.host.getSession().modelRuntime;
|
|
245
|
+
const out = [];
|
|
246
|
+
for (const p of runtime.getProviders()) {
|
|
247
|
+
if (!runtime.hasConfiguredAuth(p.id))
|
|
248
|
+
continue;
|
|
249
|
+
for (const m of runtime.getModels(p.id)) {
|
|
250
|
+
out.push({
|
|
251
|
+
provider: p.id,
|
|
252
|
+
id: m.id,
|
|
253
|
+
label: `${m.name ?? m.id} (${p.id})`,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// 稳定排序:provider 名 → 模型名。
|
|
258
|
+
return out.sort((a, b) => (a.provider === b.provider ? a.label.localeCompare(b.label) : a.provider.localeCompare(b.provider)));
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
// Session not ready yet — the picker stays empty until next push.
|
|
262
|
+
return [];
|
|
263
|
+
}
|
|
264
|
+
}
|
|
239
265
|
/** Persist + apply a partial settings update (prompt text/mode, toggles). */
|
|
240
266
|
async set(partial) {
|
|
241
267
|
const needsReload = partial.promptMode !== undefined ||
|
|
@@ -291,6 +317,11 @@ export class SettingsService {
|
|
|
291
317
|
if (partial.reviewDisabledSkills !== undefined) {
|
|
292
318
|
this.settings.reviewDisabledSkills = partial.reviewDisabledSkills;
|
|
293
319
|
}
|
|
320
|
+
if (partial.subagentDefaultModel !== undefined) {
|
|
321
|
+
// 空串归一为 null(跟随主对话);其余剥空白后存格式 provider/id。
|
|
322
|
+
const m = partial.subagentDefaultModel?.trim() ?? "";
|
|
323
|
+
this.settings.subagentDefaultModel = m ? m : null;
|
|
324
|
+
}
|
|
294
325
|
this.host.stateStore.saveSettings(this.host.clientId, this.settings);
|
|
295
326
|
this.push();
|
|
296
327
|
if (needsReload)
|
|
@@ -360,6 +391,8 @@ export class SettingsService {
|
|
|
360
391
|
visionBridgeModel: this.settings.visionBridgeModel,
|
|
361
392
|
visionBridgePromptMode: this.settings.visionBridgePromptMode,
|
|
362
393
|
visionBridgePrompt: this.settings.visionBridgePrompt,
|
|
394
|
+
// 子代理默认模型也不进预设——保留当前值。
|
|
395
|
+
subagentDefaultModel: this.settings.subagentDefaultModel,
|
|
363
396
|
};
|
|
364
397
|
this.host.stateStore.saveSettings(this.host.clientId, this.settings);
|
|
365
398
|
this.push();
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* subagent-templates.ts — 子代理模板库(全局共享,<dataDir>/subagent-templates.json)。
|
|
3
3
|
*
|
|
4
4
|
* 模板 = 派生子代理时套用的预设:角色系统提示词(replace/append 同主设置语义)+
|
|
5
|
-
* 技能白名单 +
|
|
5
|
+
* 技能白名单 + 扩展白名单 + 可选模型。白名单空数组 = 该维度不限定,子代理跟随主会话设置。
|
|
6
|
+
* `model` 为 "provider/id"(与 subagent_spawn 的 model 参数、设置面板子代理默认模型
|
|
7
|
+
* 同格式);空字符串 = 跟随主对话当前模型。
|
|
6
8
|
* 带 `enabled: false` 的模板停用:设置面板仍可见、可重新启用,但 AI 工具
|
|
7
9
|
* (subagent_templates / subagent_spawn)查询不到它、也不能选择它——「关闭 =
|
|
8
10
|
* 对 AI 不可见」。
|
|
@@ -14,6 +16,8 @@ import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
|
14
16
|
import { dirname } from "node:path";
|
|
15
17
|
/** 名字去空白折叠后非空且 ≤ 60 字符(工具参数可读,允许中文)。 */
|
|
16
18
|
const NAME_MAX = 60;
|
|
19
|
+
/** 模型 id 上限("provider/id",含斜杠与自定义模型目录 id)。 */
|
|
20
|
+
const MODEL_MAX = 200;
|
|
17
21
|
/**
|
|
18
22
|
* 内置默认模板(第一次运行时种子进列表;用户改动后以 <dataDir> 文件为准)。
|
|
19
23
|
* 文案改编自 pi-subagents 社区项目(tintinweb / nicobailon)的角色提示词,
|
|
@@ -21,6 +25,7 @@ const NAME_MAX = 60;
|
|
|
21
25
|
* 白名单留空 = 技能/扩展跟随主会话设置,开箱即用。
|
|
22
26
|
*/
|
|
23
27
|
export const DEFAULT_TEMPLATES = [
|
|
28
|
+
// 全部内置模板默认 model 为空字符串 = 跟随主对话模型(面板改模板时可指定专属模型)。
|
|
24
29
|
{
|
|
25
30
|
name: "review",
|
|
26
31
|
description: "代码 / 计划 / 方案 / PR 审查:有证据的 P0-P2 发现与合并结论",
|
|
@@ -46,6 +51,7 @@ export const DEFAULT_TEMPLATES = [
|
|
|
46
51
|
"\n只报告由目标改动引起或可达的具体当前问题,并为每条提供源码证明、测试/复现或契约冲突。P0 = 阻止合并;P1 = 发布前应修;P2 = 仅报告。没有符合条件的问题时,明确写「No issues found.」。",
|
|
47
52
|
enabledSkills: [],
|
|
48
53
|
enabledExtensions: [],
|
|
54
|
+
model: "",
|
|
49
55
|
enabled: true,
|
|
50
56
|
},
|
|
51
57
|
{
|
|
@@ -71,6 +77,7 @@ export const DEFAULT_TEMPLATES = [
|
|
|
71
77
|
"实现内容:X。\n改动文件:Y。\n验证:Z。\n未决风险/问题:R。\n建议下一步:N。",
|
|
72
78
|
enabledSkills: [],
|
|
73
79
|
enabledExtensions: [],
|
|
80
|
+
model: "",
|
|
74
81
|
enabled: true,
|
|
75
82
|
},
|
|
76
83
|
{
|
|
@@ -94,6 +101,7 @@ export const DEFAULT_TEMPLATES = [
|
|
|
94
101
|
"## Gaps\n未能自信回答的部分与建议下一步。",
|
|
95
102
|
enabledSkills: [],
|
|
96
103
|
enabledExtensions: [],
|
|
104
|
+
model: "",
|
|
97
105
|
enabled: true,
|
|
98
106
|
},
|
|
99
107
|
{
|
|
@@ -119,6 +127,7 @@ export const DEFAULT_TEMPLATES = [
|
|
|
119
127
|
"## Start Here\n另一个 agent 应最先打开的文件及原因。",
|
|
120
128
|
enabledSkills: [],
|
|
121
129
|
enabledExtensions: [],
|
|
130
|
+
model: "",
|
|
122
131
|
enabled: true,
|
|
123
132
|
},
|
|
124
133
|
{
|
|
@@ -135,6 +144,7 @@ export const DEFAULT_TEMPLATES = [
|
|
|
135
144
|
"只报告能由证据支持的发现,不要臆测。没有发现问题时明确说「未发现安全问题」。保持简洁。",
|
|
136
145
|
enabledSkills: [],
|
|
137
146
|
enabledExtensions: [],
|
|
147
|
+
model: "",
|
|
138
148
|
enabled: true,
|
|
139
149
|
},
|
|
140
150
|
{
|
|
@@ -148,6 +158,7 @@ export const DEFAULT_TEMPLATES = [
|
|
|
148
158
|
"- 简洁、具体,引用证据(路径、命令输出、行号)。",
|
|
149
159
|
enabledSkills: [],
|
|
150
160
|
enabledExtensions: [],
|
|
161
|
+
model: "",
|
|
151
162
|
enabled: true,
|
|
152
163
|
},
|
|
153
164
|
];
|
|
@@ -170,6 +181,8 @@ function normalize(raw) {
|
|
|
170
181
|
enabledExtensions: Array.isArray(o.enabledExtensions)
|
|
171
182
|
? o.enabledExtensions.filter((x) => typeof x === "string")
|
|
172
183
|
: [],
|
|
184
|
+
// 空字符串 = 跟随主对话;其余剥掉首尾空白,超长当脏数据丢弃。
|
|
185
|
+
model: typeof o.model === "string" ? o.model.trim() : "",
|
|
173
186
|
enabled: o.enabled !== false,
|
|
174
187
|
};
|
|
175
188
|
}
|
package/dist/server/subagents.js
CHANGED
|
@@ -25,6 +25,21 @@
|
|
|
25
25
|
// ---------------------------------------------------------------------------
|
|
26
26
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
27
27
|
import { Type } from "typebox";
|
|
28
|
+
/**
|
|
29
|
+
* subagent_wait_all 的最长阻塞时间:必须短暂低于工具看门狗(默认 20 分钟,
|
|
30
|
+
* PI_WEB_TOOL_TIMEOUT_MS 可调),否则看门狗会先中止整个会话而不是让 wait
|
|
31
|
+
* 干净地超时返回。留 20% 余量。
|
|
32
|
+
*/
|
|
33
|
+
const WAIT_CAP_MS = (() => {
|
|
34
|
+
const v = Number(process.env.PI_WEB_TOOL_TIMEOUT_MS);
|
|
35
|
+
const watchdog = Number.isFinite(v) && v > 0 ? v : 20 * 60_000;
|
|
36
|
+
return Math.max(60_000, Math.floor(watchdog * 0.8));
|
|
37
|
+
})();
|
|
38
|
+
/** 子代理是否已到终态(运行结束、被中止或出错)。wait 工具据此判断
|
|
39
|
+
* 是否可以取结果;streaming=false 即可(error/canceled 都在快照里带标记)。 */
|
|
40
|
+
export function isSubagentTerminal(r) {
|
|
41
|
+
return !!r && !r.streaming;
|
|
42
|
+
}
|
|
28
43
|
/** 从 prompt 取首行作为标题(截断 40 字符)。 */
|
|
29
44
|
export function subagentTitle(prompt) {
|
|
30
45
|
const line = prompt.split("\n")[0]?.trim() ?? "";
|
|
@@ -46,16 +61,22 @@ export function makeSubagentTools(host) {
|
|
|
46
61
|
label: "Spawn subagent",
|
|
47
62
|
description: "在后台启动一个独立的子代理对话,用一个明确的指令去完成一项可独立交付的工作(调研/实现/审查等)。" +
|
|
48
63
|
"子代理会出现在左栏「运行的对话」列表(带子代理标识),用户可点开查看、补充、中止。主 agent 可并行派发多个:" +
|
|
49
|
-
"用 subagent_list 查看运行态、subagent_get_result 取结果、
|
|
64
|
+
"用 subagent_wait_all 一次性等全部完成(不用轮询)、subagent_list 查看运行态、subagent_get_result 取结果、" +
|
|
65
|
+
"subagent_steer 中途改向、subagent_stop 停止。" +
|
|
50
66
|
"适合:长耗时探索、并行调研、独立子任务委派。可选 template 参数:使用设置面板配置的子代理模板" +
|
|
51
|
-
"(角色系统提示词 +
|
|
67
|
+
"(角色系统提示词 + 技能/扩展白名单 + 可选模型);可选 model 参数:显式指定子代理模型(provider/id 格式," +
|
|
68
|
+
"如 \"anthropic/claude-opus-4-5\"),优先级高于模板与设置面板的默认模型;都不传 = 跟随主对话当前模型。",
|
|
52
69
|
promptSnippet: "spawn an independent background subagent for a deliverable task (parallel work)",
|
|
53
70
|
parameters: Type.Object({
|
|
54
71
|
prompt: Type.String({ description: "交给子代理的完整指令(要达成的目标 + 约束 + 期望产出)。" }),
|
|
55
72
|
type: Type.Optional(Type.String({ description: "子代理类型/角色名(如 explore/implement/review),用于展示。默认 general。" })),
|
|
56
73
|
template: Type.Optional(Type.String({
|
|
57
74
|
description: "可选:子代理模板名(设置面板「子代理模板」配置的预设,见 subagent_templates 工具)。" +
|
|
58
|
-
"模板 = 角色系统提示词 +
|
|
75
|
+
"模板 = 角色系统提示词 + 技能/扩展白名单 + 可选模型;不传 = 不使用模板,按主会话默认配置运行。",
|
|
76
|
+
})),
|
|
77
|
+
model: Type.Optional(Type.String({
|
|
78
|
+
description: "可选:子代理模型 \"provider/id\"(如 \"anthropic/claude-opus-4-5\"),显式指定本次子代理的模型," +
|
|
79
|
+
"优先级高于模板自带模型与设置面板默认模型;不传 = 模板模型 → 设置面板默认模型 → 跟随主对话当前模型。",
|
|
59
80
|
})),
|
|
60
81
|
cwd: Type.Optional(Type.String({ description: "子代理工作目录(相对/绝对)。默认继承主会话工作目录。" })),
|
|
61
82
|
}),
|
|
@@ -63,16 +84,17 @@ export function makeSubagentTools(host) {
|
|
|
63
84
|
if (p.template && !host.isTemplateUsable(p.template)) {
|
|
64
85
|
return text(`子代理模板不可用:${p.template}(不存在或已停用)。用 subagent_templates 查看当前可用模板清单;不传 template 则按默认配置运行。`);
|
|
65
86
|
}
|
|
66
|
-
const convId = await host.spawnSubagent(p.prompt, p.type ?? "general", p.cwd ?? ctx.cwd, p.template);
|
|
87
|
+
const convId = await host.spawnSubagent(p.prompt, p.type ?? "general", p.cwd ?? ctx.cwd, p.template, p.model);
|
|
67
88
|
return text(`子代理已启动(运行列表可见):${convId}\n类型:${p.type ?? "general"} · 标题:${subagentTitle(p.prompt)}` +
|
|
68
89
|
(p.template ? `\n模板:${p.template}` : "") +
|
|
69
|
-
`\n
|
|
90
|
+
(p.model ? `\n模型:${p.model}` : "") +
|
|
91
|
+
`\n用 subagent_wait_all 一次等全部完成(不用轮询),subagent_get_result 取单个结果,subagent_list 看运行态,subagent_steer 改向,subagent_stop 停止。`, { convId, template: p.template, model: p.model });
|
|
70
92
|
},
|
|
71
93
|
}),
|
|
72
94
|
defineTool({
|
|
73
95
|
name: "subagent_get_result",
|
|
74
96
|
label: "Get subagent result",
|
|
75
|
-
description: "
|
|
97
|
+
description: "取一个子代理的结果或当前运行态。若尚未完成,返回当前状态与已产出的文本;运行报错(如 provider 400)会在这里明确标出错误。",
|
|
76
98
|
promptSnippet: "fetch a subagent's result / current progress",
|
|
77
99
|
parameters: Type.Object({
|
|
78
100
|
runId: Type.String({ description: "subagent_spawn 返回的 convId。左栏点击同名对话可直接查看。" }),
|
|
@@ -81,10 +103,11 @@ export function makeSubagentTools(host) {
|
|
|
81
103
|
const r = host.getSubagent(p.runId);
|
|
82
104
|
if (!r)
|
|
83
105
|
return text(`未找到子代理 ${shortId(p.runId)}(可能已移出)。`, undefined);
|
|
106
|
+
const verdict = subagentVerdict(r);
|
|
84
107
|
if (r.streaming || r.state === "running") {
|
|
85
108
|
return text(`子代理 ${shortId(r.convId)}(${r.type})仍在运行(状态 ${r.state})。\n当前输出:\n${r.output || "(暂无输出)"}`, r);
|
|
86
109
|
}
|
|
87
|
-
return text(`子代理 ${shortId(r.convId)}(${r.type})状态:${r
|
|
110
|
+
return text(`子代理 ${shortId(r.convId)}(${r.type})状态:${verdict}\n${verdictText(r)}\n${r.output || "(无结果)"}`, r);
|
|
88
111
|
},
|
|
89
112
|
}),
|
|
90
113
|
defineTool({
|
|
@@ -104,14 +127,14 @@ export function makeSubagentTools(host) {
|
|
|
104
127
|
defineTool({
|
|
105
128
|
name: "subagent_list",
|
|
106
129
|
label: "List subagents",
|
|
107
|
-
description: "列出全部子代理的运行态:convId
|
|
130
|
+
description: "列出全部子代理的运行态:convId、类型、状态、标题、消息数(报错/中止的会在状态里标出)。",
|
|
108
131
|
promptSnippet: "list all subagents and their live status",
|
|
109
132
|
parameters: Type.Object({}),
|
|
110
133
|
execute: async () => {
|
|
111
134
|
const list = host.listSubagents();
|
|
112
135
|
if (list.length === 0)
|
|
113
136
|
return text("当前没有子代理。");
|
|
114
|
-
const lines = list.map((r) => `- ${r.convId} · ${r.type} · ${r
|
|
137
|
+
const lines = list.map((r) => `- ${r.convId} · ${r.type} · ${subagentVerdict(r)} · ${r.title}(msg: ${r.messageCount})`);
|
|
115
138
|
return text(lines.join("\n"));
|
|
116
139
|
},
|
|
117
140
|
}),
|
|
@@ -126,10 +149,60 @@ export function makeSubagentTools(host) {
|
|
|
126
149
|
return text(`已请求停止子代理 ${shortId(p.runId)}。`);
|
|
127
150
|
},
|
|
128
151
|
}),
|
|
152
|
+
defineTool({
|
|
153
|
+
name: "subagent_wait_all",
|
|
154
|
+
label: "Wait for subagents",
|
|
155
|
+
description: "一次性等待多个子代理全部完成(阻塞本回合直到它们都到达终态或超时),然后汇总返回每个的结果/错误——" +
|
|
156
|
+
"不用反复调 subagent_get_result 轮询。传 runIds 指定要等的子代理(subagent_spawn 返回的 convId);" +
|
|
157
|
+
"不传 = 等当前全部运行中的子代理。超时或本轮被中止时返回剩余未完成名单,可再次调用继续等。" +
|
|
158
|
+
"适合:并行派发多个子代理后收口。",
|
|
159
|
+
promptSnippet: "wait for multiple subagents to finish (no polling) and get all results",
|
|
160
|
+
parameters: Type.Object({
|
|
161
|
+
runIds: Type.Optional(Type.Array(Type.String({ description: "要等待的子代理 convId(subagent_spawn 返回值)。缺省 = 等当前全部运行中的。" }))),
|
|
162
|
+
timeoutSeconds: Type.Optional(Type.Integer({
|
|
163
|
+
description: `最多等待秒数(默认 600,上限约 ${Math.floor(WAIT_CAP_MS / 1000)}——必须低于工具看门狗,超时返回未完成名单可再调)。`,
|
|
164
|
+
minimum: 1,
|
|
165
|
+
maximum: Math.floor(WAIT_CAP_MS / 1000),
|
|
166
|
+
})),
|
|
167
|
+
}),
|
|
168
|
+
execute: async (_id, p, signal) => {
|
|
169
|
+
const wanted = new Set(p.runIds && p.runIds.length > 0 ? p.runIds : host.listSubagents().map((r) => r.convId));
|
|
170
|
+
const timeoutMs = Math.min(Math.max(p.timeoutSeconds ?? 600, 1), Math.floor(WAIT_CAP_MS / 1000)) * 1000;
|
|
171
|
+
const waitStart = Date.now();
|
|
172
|
+
const deadline = waitStart + timeoutMs;
|
|
173
|
+
// 已到终态的、(或已被移出找不到的)直接归位;剩下的阻塞轮询到
|
|
174
|
+
// 全部完成/超时/中止(移出 = 无法再等,立即按收口处理)。
|
|
175
|
+
const pending = () => [...wanted].filter((id) => {
|
|
176
|
+
const r = host.getSubagent(id);
|
|
177
|
+
return r !== undefined && !isSubagentTerminal(r);
|
|
178
|
+
});
|
|
179
|
+
while (pending().length > 0 && Date.now() < deadline && !(signal?.aborted ?? false)) {
|
|
180
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
181
|
+
}
|
|
182
|
+
const remaining = pending();
|
|
183
|
+
const lines = [...wanted]
|
|
184
|
+
.map((id) => {
|
|
185
|
+
const r = host.getSubagent(id);
|
|
186
|
+
if (!r)
|
|
187
|
+
return `- ${shortId(id)}:未找到(可能已移出)`;
|
|
188
|
+
const body = verdictText(r);
|
|
189
|
+
return (`- ${shortId(r.convId)}(${r.type})· ${r.title} · ${subagentVerdict(r)}` +
|
|
190
|
+
(body ? `\n ${body}` : "") +
|
|
191
|
+
(r.output ? `\n ${r.output.split("\n").slice(0, 30).join("\n ")}` : ""));
|
|
192
|
+
})
|
|
193
|
+
.join("\n");
|
|
194
|
+
const head = remaining.length === 0
|
|
195
|
+
? `全部 ${wanted.size} 个子代理已收口:`
|
|
196
|
+
: signal?.aborted
|
|
197
|
+
? `本轮被中止,${remaining.length} 个仍在运行:`
|
|
198
|
+
: `等待超过 ${Math.round(timeoutMs / 1000)}s 超时(实际等待 ${Math.round((Date.now() - waitStart) / 1000)}s),${remaining.length} 个仍在运行:`;
|
|
199
|
+
return text(`${head}\n${lines}\n` + promptRemaining(remaining));
|
|
200
|
+
},
|
|
201
|
+
}),
|
|
129
202
|
defineTool({
|
|
130
203
|
name: "subagent_templates",
|
|
131
204
|
label: "List subagent templates",
|
|
132
|
-
description: "列出设置面板「子代理模板」配置的可用模板(角色系统提示词 +
|
|
205
|
+
description: "列出设置面板「子代理模板」配置的可用模板(角色系统提示词 + 技能/扩展白名单 + 可选模型 的组合预设)," +
|
|
133
206
|
"供 subagent_spawn 的 template 参数选用。已停用的模板不会出现在这里。list 为空 = 未配置模板,子代理按默认配置运行。",
|
|
134
207
|
promptSnippet: "list configurable subagent templates (role prompt + skills/extensions whitelist presets)",
|
|
135
208
|
parameters: Type.Object({}),
|
|
@@ -138,7 +211,8 @@ export function makeSubagentTools(host) {
|
|
|
138
211
|
if (list.length === 0) {
|
|
139
212
|
return text("当前没有可用的子代理模板(设置面板 → 子代理模板 添加后可用)。子代理默认按主会话配置运行。");
|
|
140
213
|
}
|
|
141
|
-
const lines = list.map((t) => `- ${t.name}${t.description ? `:${t.description}` : ""}`
|
|
214
|
+
const lines = list.map((t) => `- ${t.name}${t.description ? `:${t.description}` : ""}` +
|
|
215
|
+
(t.model ? `(模型:${t.model})` : "(跟随主对话模型)"));
|
|
142
216
|
return text(`可用的子代理模板(subagent_spawn 的 template 参数传名字,如 subagent_spawn(template="${list[0]?.name}")):\n${lines.join("\n")}`);
|
|
143
217
|
},
|
|
144
218
|
}),
|
|
@@ -148,3 +222,25 @@ export function makeSubagentTools(host) {
|
|
|
148
222
|
function shortId(id) {
|
|
149
223
|
return id.slice(0, 8);
|
|
150
224
|
}
|
|
225
|
+
/** 人类可读的终态判定:报错 > 中止 > done > running。 */
|
|
226
|
+
function subagentVerdict(r) {
|
|
227
|
+
if (r.error)
|
|
228
|
+
return "error(报错)";
|
|
229
|
+
if (r.canceled)
|
|
230
|
+
return "canceled(已中止)";
|
|
231
|
+
return r.state;
|
|
232
|
+
}
|
|
233
|
+
/** 终态的可读说明(错误文本 / 中止说明 / 空)。运行中返回空。 */
|
|
234
|
+
function verdictText(r) {
|
|
235
|
+
if (r.error)
|
|
236
|
+
return `错误:${r.error}`;
|
|
237
|
+
if (r.canceled)
|
|
238
|
+
return "(被中止,未产出结论)";
|
|
239
|
+
return "";
|
|
240
|
+
}
|
|
241
|
+
/** 未完成部分的引导文案。 */
|
|
242
|
+
function promptRemaining(remaining) {
|
|
243
|
+
if (remaining.length === 0)
|
|
244
|
+
return "";
|
|
245
|
+
return `\n未完成:${remaining.map(shortId).join(", ")}。可再次调用 subagent_wait_all(或 subagent_steer 补充指令 / subagent_stop 中止)。`;
|
|
246
|
+
}
|
package/package.json
CHANGED
|
@@ -1,110 +1,110 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pi-web-ui",
|
|
3
|
-
"version": "0.64.
|
|
4
|
-
"description": "Web chat interface for the pi coding agent, powered by the pi SDK (@earendil-works/pi-coding-agent) — one-command run, Docker/systemd/launchd deployable",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": {
|
|
7
|
-
"name": "xingshuyin",
|
|
8
|
-
"email": "xingshuyin@users.noreply.github.com"
|
|
9
|
-
},
|
|
10
|
-
"type": "module",
|
|
11
|
-
"bin": {
|
|
12
|
-
"pi-web-ui": "bin/pi-web-ui.mjs"
|
|
13
|
-
},
|
|
14
|
-
"main": "bin/pi-web-ui.mjs",
|
|
15
|
-
"files": [
|
|
16
|
-
"bin/",
|
|
17
|
-
"dist/",
|
|
18
|
-
"web/dist/",
|
|
19
|
-
"web/public/",
|
|
20
|
-
"themes/",
|
|
21
|
-
"deploy/",
|
|
22
|
-
"extensions/",
|
|
23
|
-
"README.md",
|
|
24
|
-
"LICENSE"
|
|
25
|
-
],
|
|
26
|
-
"keywords": [
|
|
27
|
-
"pi",
|
|
28
|
-
"pi-package",
|
|
29
|
-
"coding-agent",
|
|
30
|
-
"ai",
|
|
31
|
-
"chat",
|
|
32
|
-
"web-ui",
|
|
33
|
-
"terminal",
|
|
34
|
-
"llm"
|
|
35
|
-
],
|
|
36
|
-
"repository": {
|
|
37
|
-
"type": "git",
|
|
38
|
-
"url": "git+https://github.com/xing-shuyin/pi-web-ui.git"
|
|
39
|
-
},
|
|
40
|
-
"pi": {
|
|
41
|
-
"extensions": [
|
|
42
|
-
"./extensions"
|
|
43
|
-
]
|
|
44
|
-
},
|
|
45
|
-
"engines": {
|
|
46
|
-
"node": ">=22.19.0"
|
|
47
|
-
},
|
|
48
|
-
"scripts": {
|
|
49
|
-
"prepublishOnly": "npm run build",
|
|
50
|
-
"dev": "concurrently -k -n server,web -c blue,green \"npm:dev:server\" \"npm:dev:web\"",
|
|
51
|
-
"dev:server": "cross-env PI_WEB_PORT=8788 PI_WEB_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173 node --watch --import tsx server/index.ts",
|
|
52
|
-
"dev:web": "vite --config web/vite.config.ts",
|
|
53
|
-
"build": "npm run build:web && npm run build:server && npm run build:dsh-runtime",
|
|
54
|
-
"build:web": "vite build --config web/vite.config.ts",
|
|
55
|
-
"build:server": "tsc -p tsconfig.server.json",
|
|
56
|
-
"build:dsh-runtime": "node scripts/copy-dsh-runtime.mjs",
|
|
57
|
-
"typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
|
|
58
|
-
"test": "vitest run",
|
|
59
|
-
"test:unit": "vitest run",
|
|
60
|
-
"test:smoke": "node tests/run-smoke.mjs",
|
|
61
|
-
"check:protocol": "node scripts/check-protocol-sync.mjs",
|
|
62
|
-
"test:freeze": "node tests/freeze-test.mjs",
|
|
63
|
-
"start": "node dist/server/index.js",
|
|
64
|
-
"format": "prettier --write server/ web/src/ extensions/ scripts/ bin/ tests/*.mjs tests/unit/ *.mjs",
|
|
65
|
-
"format:check": "prettier --check server/ web/src/ extensions/ scripts/ bin/ tests/*.mjs tests/unit/ *.mjs",
|
|
66
|
-
"lint": "oxlint server/ web/src/ extensions/ scripts/",
|
|
67
|
-
"lint:fix": "oxlint --fix server/ web/src/ extensions/ scripts/"
|
|
68
|
-
},
|
|
69
|
-
"dependencies": {
|
|
70
|
-
"@deepseek-ai/dsh-sdk-jsonrpc-server": "^0.1.1-rc.2",
|
|
71
|
-
"@deepseek-ai/dsh-sdk-protocol": "^0.1.1-rc.2",
|
|
72
|
-
"@earendil-works/pi-coding-agent": "^0.84.4",
|
|
73
|
-
"@xterm/addon-fit": "^0.11.0",
|
|
74
|
-
"@xterm/xterm": "^6.0.0",
|
|
75
|
-
"compression": "^1.8.1",
|
|
76
|
-
"express": "^4.21.2",
|
|
77
|
-
"highlight.js": "^11.10.0",
|
|
78
|
-
"mermaid": "^11.17.2",
|
|
79
|
-
"node-pty": "^1.1.0",
|
|
80
|
-
"react": "^18.3.1",
|
|
81
|
-
"react-dom": "^18.3.1",
|
|
82
|
-
"react-icons": "^5.7.0",
|
|
83
|
-
"react-markdown": "^9.0.1",
|
|
84
|
-
"rehype-highlight": "^7.0.1",
|
|
85
|
-
"remark-gfm": "^4.0.0",
|
|
86
|
-
"typebox": "^1.3.14",
|
|
87
|
-
"ws": "^8.18.0"
|
|
88
|
-
},
|
|
89
|
-
"devDependencies": {
|
|
90
|
-
"@types/compression": "^1.8.1",
|
|
91
|
-
"@types/express": "^4.17.21",
|
|
92
|
-
"@types/node": "^22.10.0",
|
|
93
|
-
"@types/react": "^18.3.12",
|
|
94
|
-
"@types/react-dom": "^18.3.1",
|
|
95
|
-
"@types/ws": "^8.5.13",
|
|
96
|
-
"@vitejs/plugin-react": "^4.3.4",
|
|
97
|
-
"concurrently": "^9.1.0",
|
|
98
|
-
"cross-env": "^10.1.0",
|
|
99
|
-
"oxlint": "^1.81.0",
|
|
100
|
-
"playwright-core": "^1.62.1",
|
|
101
|
-
"prettier": "^3.9.6",
|
|
102
|
-
"tsx": "^4.19.2",
|
|
103
|
-
"typescript": "^5.7.2",
|
|
104
|
-
"vite": "^6.0.3",
|
|
105
|
-
"vitest": "^4.1.11"
|
|
106
|
-
},
|
|
107
|
-
"allowScripts": {
|
|
108
|
-
"node-pty@1.1.0": true
|
|
109
|
-
}
|
|
110
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-web-ui",
|
|
3
|
+
"version": "0.64.6",
|
|
4
|
+
"description": "Web chat interface for the pi coding agent, powered by the pi SDK (@earendil-works/pi-coding-agent) — one-command run, Docker/systemd/launchd deployable",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "xingshuyin",
|
|
8
|
+
"email": "xingshuyin@users.noreply.github.com"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"bin": {
|
|
12
|
+
"pi-web-ui": "bin/pi-web-ui.mjs"
|
|
13
|
+
},
|
|
14
|
+
"main": "bin/pi-web-ui.mjs",
|
|
15
|
+
"files": [
|
|
16
|
+
"bin/",
|
|
17
|
+
"dist/",
|
|
18
|
+
"web/dist/",
|
|
19
|
+
"web/public/",
|
|
20
|
+
"themes/",
|
|
21
|
+
"deploy/",
|
|
22
|
+
"extensions/",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"keywords": [
|
|
27
|
+
"pi",
|
|
28
|
+
"pi-package",
|
|
29
|
+
"coding-agent",
|
|
30
|
+
"ai",
|
|
31
|
+
"chat",
|
|
32
|
+
"web-ui",
|
|
33
|
+
"terminal",
|
|
34
|
+
"llm"
|
|
35
|
+
],
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/xing-shuyin/pi-web-ui.git"
|
|
39
|
+
},
|
|
40
|
+
"pi": {
|
|
41
|
+
"extensions": [
|
|
42
|
+
"./extensions"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=22.19.0"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"prepublishOnly": "npm run build",
|
|
50
|
+
"dev": "concurrently -k -n server,web -c blue,green \"npm:dev:server\" \"npm:dev:web\"",
|
|
51
|
+
"dev:server": "cross-env PI_WEB_PORT=8788 PI_WEB_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173 node --watch --import tsx server/index.ts",
|
|
52
|
+
"dev:web": "vite --config web/vite.config.ts",
|
|
53
|
+
"build": "npm run build:web && npm run build:server && npm run build:dsh-runtime",
|
|
54
|
+
"build:web": "vite build --config web/vite.config.ts",
|
|
55
|
+
"build:server": "tsc -p tsconfig.server.json",
|
|
56
|
+
"build:dsh-runtime": "node scripts/copy-dsh-runtime.mjs",
|
|
57
|
+
"typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
|
|
58
|
+
"test": "vitest run",
|
|
59
|
+
"test:unit": "vitest run",
|
|
60
|
+
"test:smoke": "node tests/run-smoke.mjs",
|
|
61
|
+
"check:protocol": "node scripts/check-protocol-sync.mjs",
|
|
62
|
+
"test:freeze": "node tests/freeze-test.mjs",
|
|
63
|
+
"start": "node dist/server/index.js",
|
|
64
|
+
"format": "prettier --write server/ web/src/ extensions/ scripts/ bin/ tests/*.mjs tests/unit/ *.mjs",
|
|
65
|
+
"format:check": "prettier --check server/ web/src/ extensions/ scripts/ bin/ tests/*.mjs tests/unit/ *.mjs",
|
|
66
|
+
"lint": "oxlint server/ web/src/ extensions/ scripts/",
|
|
67
|
+
"lint:fix": "oxlint --fix server/ web/src/ extensions/ scripts/"
|
|
68
|
+
},
|
|
69
|
+
"dependencies": {
|
|
70
|
+
"@deepseek-ai/dsh-sdk-jsonrpc-server": "^0.1.1-rc.2",
|
|
71
|
+
"@deepseek-ai/dsh-sdk-protocol": "^0.1.1-rc.2",
|
|
72
|
+
"@earendil-works/pi-coding-agent": "^0.84.4",
|
|
73
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
74
|
+
"@xterm/xterm": "^6.0.0",
|
|
75
|
+
"compression": "^1.8.1",
|
|
76
|
+
"express": "^4.21.2",
|
|
77
|
+
"highlight.js": "^11.10.0",
|
|
78
|
+
"mermaid": "^11.17.2",
|
|
79
|
+
"node-pty": "^1.1.0",
|
|
80
|
+
"react": "^18.3.1",
|
|
81
|
+
"react-dom": "^18.3.1",
|
|
82
|
+
"react-icons": "^5.7.0",
|
|
83
|
+
"react-markdown": "^9.0.1",
|
|
84
|
+
"rehype-highlight": "^7.0.1",
|
|
85
|
+
"remark-gfm": "^4.0.0",
|
|
86
|
+
"typebox": "^1.3.14",
|
|
87
|
+
"ws": "^8.18.0"
|
|
88
|
+
},
|
|
89
|
+
"devDependencies": {
|
|
90
|
+
"@types/compression": "^1.8.1",
|
|
91
|
+
"@types/express": "^4.17.21",
|
|
92
|
+
"@types/node": "^22.10.0",
|
|
93
|
+
"@types/react": "^18.3.12",
|
|
94
|
+
"@types/react-dom": "^18.3.1",
|
|
95
|
+
"@types/ws": "^8.5.13",
|
|
96
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
97
|
+
"concurrently": "^9.1.0",
|
|
98
|
+
"cross-env": "^10.1.0",
|
|
99
|
+
"oxlint": "^1.81.0",
|
|
100
|
+
"playwright-core": "^1.62.1",
|
|
101
|
+
"prettier": "^3.9.6",
|
|
102
|
+
"tsx": "^4.19.2",
|
|
103
|
+
"typescript": "^5.7.2",
|
|
104
|
+
"vite": "^6.0.3",
|
|
105
|
+
"vitest": "^4.1.11"
|
|
106
|
+
},
|
|
107
|
+
"allowScripts": {
|
|
108
|
+
"node-pty@1.1.0": true
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as l,j as n}from"./markdown-BJJLXG-8.js";import{u as O,b as M,T as z,a as W,F as Y,c as H,d as Z,e as q,f as ee,g as ne,h as te,i as se,r as ae}from"./index-
|
|
1
|
+
import{a as l,j as n}from"./markdown-BJJLXG-8.js";import{u as O,b as M,T as z,a as W,F as Y,c as H,d as Z,e as q,f as ee,g as ne,h as te,i as se,r as ae}from"./index-30RM921r.js";import{D as re,o as ie}from"./xterm-D1D2FVe3.js";import"./react-ezqUM1Or.js";function le(t){let c=null;return{clean:t.replace(/\r?\n?\[pi-term-exit:(-?\d+)\]\r?\n?/g,(a,h)=>(c=Number(h),`\r
|
|
2
2
|
`)).replace(/\r?\n?\x1b\[90m\[(?:进程已退出,退出码 |Process exited with code )-?\d+\]\x1b\[0m\r?\n?/g,`\r
|
|
3
3
|
`),exitCode:c}}function ce({conversationId:t,terminalId:c,command:f,cwd:a,title:h,active:u,running:b,exitCode:y,send:j,register:T}){const k=l.useRef(null),N=l.useRef(null),{locale:o}=O(),w=l.useRef(o);w.current=o;const F=f?JSON.stringify(f):"";l.useEffect(()=>{const m=k.current;if(!m)return;const r=new re({theme:M(),fontFamily:'"SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace',fontSize:13,cursorBlink:!0,scrollback:8e3}),g=new ie;r.loadAddon(g),r.open(m),N.current={term:r,fit:g},u&&r.focus();const C=()=>{r.options.theme=M()};window.addEventListener(z,C),r.attachCustomKeyEventHandler(d=>{var A;if(d.type!=="keydown")return!0;const D=(A=d.key)==null?void 0:A.toLowerCase();if((d.ctrlKey||d.metaKey)&&D==="v")return!1;if(d.ctrlKey&&!d.shiftKey&&!d.altKey&&D==="c"&&r.hasSelection()){const E=r.textarea;return E&&(E.value=r.getSelection(),E.select()),!1}return!0});const _=T(t,c,{write:d=>r.write(le(d).clean),dispose:()=>r.dispose()}),$=()=>{try{g.fit(),j({type:"terminal_resize",terminalId:c,conversationId:t,cols:r.cols,rows:r.rows})}catch{}},B=requestAnimationFrame(()=>{try{g.fit()}catch{}j(f?{type:"run_command",terminalId:c,conversationId:t,command:f,cols:r.cols,rows:r.rows}:{type:"terminal_create",terminalId:c,title:h,locale:w.current,conversationId:t,cwd:a,cols:r.cols,rows:r.rows})}),S=r.onData(d=>{j({type:"terminal_input",terminalId:c,conversationId:t,data:d})});let v=null;return typeof ResizeObserver<"u"&&(v=new ResizeObserver(()=>{m.offsetWidth>0&&m.offsetHeight>0&&$()}),v.observe(m)),()=>{cancelAnimationFrame(B),S.dispose(),window.removeEventListener(z,C),v==null||v.disconnect(),_(),r.dispose(),N.current=null}},[t,c,F,j,T]),l.useEffect(()=>{if(!u)return;const m=requestAnimationFrame(()=>{const r=N.current;if(r){try{r.fit.fit(),j({type:"terminal_resize",terminalId:c,conversationId:t,cols:r.term.cols,rows:r.term.rows})}catch{}r.term.focus()}});return()=>cancelAnimationFrame(m)},[u]);const{t:R}=O(),x=l.useRef(void 0);return l.useEffect(()=>{if(b===x.current||(x.current=b,b!==!1))return;const m=N.current;m&&m.term.write(`\r
|
|
4
4
|
\x1B[90m${R("exitBanner",{code:y??""})}\x1B[0m\r
|
package/web/dist/assets/{abnfDiagram-VCTEODGH-Ciapjs2h.js → abnfDiagram-VCTEODGH-Dltz1N0G.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-SVP7TREG-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-SVP7TREG-IQRTD_4U.js";import{p as f}from"./chunk-JWPE2WC7-DTpnGTdB.js";import{_ as n,l as o}from"./mermaid.core-BI5_3AOv.js";import{M as c,b as d}from"./cynefin-OW5HDTMX-OsV-x0h-.js";import"./index-30RM921r.js";import"./markdown-BJJLXG-8.js";import"./react-ezqUM1Or.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},I={parser:R,db:a,renderer:u,styles:p};export{I as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a0 as ln,a1 as an,a2 as y,a3 as tn,a4 as H,a5 as q,a6 as _,a7 as un,a8 as rn,a9 as L,aa as o,ab as B,ac as sn,ad as on,ae as fn}from"./mermaid.core-
|
|
1
|
+
import{a0 as ln,a1 as an,a2 as y,a3 as tn,a4 as H,a5 as q,a6 as _,a7 as un,a8 as rn,a9 as L,aa as o,ab as B,ac as sn,ad as on,ae as fn}from"./mermaid.core-BI5_3AOv.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,C,a){var O=I-l,i=D-h,n=C-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function W(l,h,I,D,v,A,C){var a=l-I,O=h-D,i=(C?A:-A)/L(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,F=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*L(fn(0,T*T*R-P*P)),j=(P*g-m*S)/R,z=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=j-F,e=z-t,r=w-F,G=p-t;return x*x+e*e>r*r+G*G&&(j=w,z=p),{cx:j,cy:z,x01:-n,y01:-d,x11:j*(v/T-1),y11:z*(v/T-1)}}function hn(){var l=cn,h=yn,I=B(0),D=null,v=gn,A=dn,C=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-an,c=A.apply(this,arguments)-an,F=un(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(F>tn-y)a.moveTo(s*H(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*H(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=F,S=F,j=C.apply(this,arguments)/2,z=j>y&&(D?+D.apply(this,arguments):L(u*u+s*s)),w=_(un(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if(z>y){var G=sn(z/u*q(j)),M=sn(z/s*q(j));(P-=G*2)>y?(G*=t?1:-1,R+=G,T-=G):(P=0,R=T=(f+c)/2),(S-=M*2)>y?(M*=t?1:-1,m+=M,g-=M):(S=0,m=g=(f+c)/2)}var J=s*H(m),K=s*q(m),N=u*H(T),Q=u*q(T);if(w>y){var U=s*H(g),V=s*q(g),X=u*H(R),Y=u*q(R),E;if(F<rn)if(E=pn(J,K,X,Y,U,V,N,Q)){var Z=J-E[0],$=K-E[1],b=U-E[0],k=V-E[1],nn=1/q(on((Z*b+$*k)/(L(Z*Z+$*$)*L(b*b+k*k)))/2),en=L(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=W(X,Y,J,K,s,x,t),r=W(U,V,N,Q,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(J,K),a.arc(0,0,s,m,g,!t)):a.moveTo(J,K),!(u>y)||!(P>y)?a.lineTo(N,Q):p>y?(e=W(N,Q,U,V,u,-p,t),r=W(J,K,X,Y,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-rn/2;return[H(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:B(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:B(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:B(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:B(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:B(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:B(+n),i):A},i.padAngle=function(n){return arguments.length?(C=typeof n=="function"?n:B(+n),i):C},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
|