pi-web-ui 0.64.0 → 0.64.2
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/LICENSE +21 -21
- package/README.md +504 -504
- package/README.zh-CN.md +427 -427
- package/bin/pi-web-ui.mjs +1809 -1809
- package/deploy/com.xingshuyin.pi-web-ui.plist +48 -48
- package/deploy/nginx-subpath.conf +88 -88
- package/deploy/pi-web-ui-task.xml +54 -54
- package/deploy/pi-web-ui.service +31 -31
- package/dist/server/agent-service.js +45 -22
- package/dist/server/attachments.js +16 -11
- package/dist/server/dsh/dsh-agent-service.js +27 -7
- package/dist/server/dsh/runtime/cordis.yml +1 -1
- package/dist/server/dsh/runtime/goal-rpc.mjs +645 -645
- package/dist/server/dsh/runtime/launcher.mjs +164 -164
- package/dist/server/dsh/runtime/override.patch.yml +71 -71
- package/dist/server/dsh/runtime/runtime-root.mjs +86 -86
- package/dist/server/files-service.js +235 -43
- package/dist/server/goal-service.js +4 -1
- package/dist/server/index.js +48 -13
- package/dist/server/marker-service.js +8 -3
- package/dist/server/markers/builtins/rename.js +3 -3
- package/dist/server/model-admin.js +12 -6
- package/dist/server/plugins.js +4 -4
- package/dist/server/slash-commands.js +3 -0
- package/dist/server/terminals.js +25 -15
- package/dist/server/vision-bridge.js +9 -9
- package/dist/server/webui-context.js +2 -2
- package/extensions/webui.ts +190 -190
- package/package.json +109 -109
- package/themes/cyberpunk.css +81 -81
- package/themes/dazzle.css +81 -81
- package/themes/md-preview.css +98 -98
- package/themes/white.css +160 -160
- package/web/dist/assets/TerminalPanel-BXISCcrQ.js +6 -0
- package/web/dist/assets/index-BxuvIAJQ.js +326 -0
- package/web/dist/assets/{index-CMgDryBL.css → index-DVnuQrK5.css} +1 -1
- package/web/dist/favicon.svg +8 -8
- package/web/dist/index.html +21 -21
- package/web/dist/manifest.webmanifest +50 -50
- package/web/dist/sw.js +126 -126
- package/web/public/favicon.svg +8 -8
- package/web/public/manifest.webmanifest +50 -50
- package/web/public/sw.js +126 -126
- package/web/dist/assets/TerminalPanel-DNkAT34Z.js +0 -2
- package/web/dist/assets/index-_1vyEugI.js +0 -326
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { countLines, decodeText, looksLikeText, sniffImageMime } from "./text-sniff.js";
|
|
2
2
|
import { saveUpload, uploadsRoot } from "./uploads.js";
|
|
3
|
+
import { isAbsoluteWirePath, wireToAbs } from "./files-service.js";
|
|
3
4
|
import { buildVisionBridgePrompt, findVisionModels, transcribeImages } from "./vision-bridge.js";
|
|
4
5
|
/** 跨快照的视觉转写缓存:批次 hash(名称 + base64 头 + 提示词)→ 转写文本。
|
|
5
6
|
* 编辑重问重发相同图片不再重复耗视觉 token。进程级共享即可。 */
|
|
@@ -120,9 +121,11 @@ export async function buildAttachmentMessages(ctx, attachments) {
|
|
|
120
121
|
const ext = extname(att.path).toLowerCase();
|
|
121
122
|
if (!IMAGE_EXT.has(ext) || ext === ".svg")
|
|
122
123
|
continue;
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
124
|
+
// 机器浏览的绝对路径(盘符 / posix "/")允许在工作区之外。
|
|
125
|
+
const absPath = isAbsoluteWirePath(att.path);
|
|
126
|
+
const abs = absPath ? wireToAbs(att.path) : resolve(root, att.path);
|
|
127
|
+
const rawRel = absPath ? null : relative(root, abs);
|
|
128
|
+
if (!absPath && (rawRel.startsWith("..") || rawRel.includes(`${sep}..`)))
|
|
126
129
|
continue;
|
|
127
130
|
let st;
|
|
128
131
|
try {
|
|
@@ -381,9 +384,10 @@ export async function buildAttachmentMessages(ctx, attachments) {
|
|
|
381
384
|
pushUploadAside(att.name ?? basename(abs), abs.split(sep).join("/"), buf);
|
|
382
385
|
continue;
|
|
383
386
|
}
|
|
384
|
-
const
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
+
const absPath = isAbsoluteWirePath(att.path);
|
|
388
|
+
const abs = absPath ? wireToAbs(att.path) : resolve(root, att.path);
|
|
389
|
+
const rawRel = absPath ? null : relative(root, abs);
|
|
390
|
+
if (!absPath && (rawRel.startsWith("..") || rawRel.includes(`${sep}..`))) {
|
|
387
391
|
ctx.emit({
|
|
388
392
|
type: "notice",
|
|
389
393
|
level: "warning",
|
|
@@ -393,8 +397,9 @@ export async function buildAttachmentMessages(ctx, attachments) {
|
|
|
393
397
|
continue;
|
|
394
398
|
}
|
|
395
399
|
// Normalize to forward slashes (relative() returns "\\" on Windows);
|
|
396
|
-
// <file path> and details.path must use the wire format.
|
|
397
|
-
|
|
400
|
+
// <file path> and details.path must use the wire format. 机器浏览的绝对
|
|
401
|
+
// 路径直接按绝对路径引用(SDK 读文件工具接受绝对路径,与上传文件一致)。
|
|
402
|
+
const rel = absPath ? abs.split(sep).join("/") : rawRel.split(sep).join("/");
|
|
398
403
|
let stat;
|
|
399
404
|
try {
|
|
400
405
|
stat = await fs.stat(abs);
|
|
@@ -449,9 +454,9 @@ export async function buildAttachmentMessages(ctx, attachments) {
|
|
|
449
454
|
content: [
|
|
450
455
|
{
|
|
451
456
|
type: "text",
|
|
452
|
-
text: `
|
|
453
|
-
<vision-bridge>
|
|
454
|
-
${transcript}
|
|
457
|
+
text: `
|
|
458
|
+
<vision-bridge>
|
|
459
|
+
${transcript}
|
|
455
460
|
</vision-bridge>`,
|
|
456
461
|
},
|
|
457
462
|
...(pathImg
|
|
@@ -1029,8 +1029,8 @@ export class DshClientSession {
|
|
|
1029
1029
|
for (const sink of [...this.sinks])
|
|
1030
1030
|
sink(msg);
|
|
1031
1031
|
}
|
|
1032
|
-
emitNotice(level, text) {
|
|
1033
|
-
this.emit({ type: "notice", level, text });
|
|
1032
|
+
emitNotice(level, text, textEn) {
|
|
1033
|
+
this.emit({ type: "notice", level, text, textEn });
|
|
1034
1034
|
}
|
|
1035
1035
|
pushTerminals() {
|
|
1036
1036
|
for (const conv of this.convs.values()) {
|
|
@@ -1308,6 +1308,9 @@ export class DshClientSession {
|
|
|
1308
1308
|
text: hadGoal
|
|
1309
1309
|
? "已新建分支继续对话(DSH 引擎不支持原地续聊旧会话);原目标已随旧会话存档,如需继续请重新设置目标"
|
|
1310
1310
|
: "已新建分支继续对话(DSH 引擎不支持原地续聊旧会话)",
|
|
1311
|
+
textEn: hadGoal
|
|
1312
|
+
? "Started a branch to continue (DSH engine cannot resume an old session in place); the old goal was archived with it — set a new goal to continue"
|
|
1313
|
+
: "Started a branch to continue (DSH engine cannot resume an old session in place)",
|
|
1311
1314
|
});
|
|
1312
1315
|
return fork;
|
|
1313
1316
|
}
|
|
@@ -1622,11 +1625,21 @@ export class DshClientSession {
|
|
|
1622
1625
|
async dismissConversation(id) {
|
|
1623
1626
|
const conv = this.convs.get(id);
|
|
1624
1627
|
if (!conv) {
|
|
1625
|
-
this.emit({
|
|
1628
|
+
this.emit({
|
|
1629
|
+
type: "notice",
|
|
1630
|
+
level: "warning",
|
|
1631
|
+
text: "该对话不存在或已关闭",
|
|
1632
|
+
textEn: "This conversation does not exist or is already closed",
|
|
1633
|
+
});
|
|
1626
1634
|
return;
|
|
1627
1635
|
}
|
|
1628
1636
|
if (id === this.activeId) {
|
|
1629
|
-
this.emit({
|
|
1637
|
+
this.emit({
|
|
1638
|
+
type: "notice",
|
|
1639
|
+
level: "warning",
|
|
1640
|
+
text: "当前对话不能直接移出,请先切换到其他对话",
|
|
1641
|
+
textEn: "The active conversation cannot be removed directly — switch to another conversation first",
|
|
1642
|
+
});
|
|
1630
1643
|
return;
|
|
1631
1644
|
}
|
|
1632
1645
|
if (!conv.listed) {
|
|
@@ -1638,11 +1651,17 @@ export class DshClientSession {
|
|
|
1638
1651
|
type: "notice",
|
|
1639
1652
|
level: "warning",
|
|
1640
1653
|
text: `对话「${conv.title}」仍在运行中,请先等待结束或停止后再移出`,
|
|
1654
|
+
textEn: `Conversation "${conv.title}" is still running — wait for it to finish or press Stop before removing`,
|
|
1641
1655
|
});
|
|
1642
1656
|
return;
|
|
1643
1657
|
}
|
|
1644
1658
|
if (conv.terminals.list().length > 0) {
|
|
1645
|
-
this.emit({
|
|
1659
|
+
this.emit({
|
|
1660
|
+
type: "notice",
|
|
1661
|
+
level: "warning",
|
|
1662
|
+
text: `对话「${conv.title}」还有未关闭的终端,请先关闭终端后再移出`,
|
|
1663
|
+
textEn: `Conversation "${conv.title}" still has open terminals — close them before removing`,
|
|
1664
|
+
});
|
|
1646
1665
|
return;
|
|
1647
1666
|
}
|
|
1648
1667
|
this.removeConversation(id);
|
|
@@ -2668,7 +2687,7 @@ export class DshClientSession {
|
|
|
2668
2687
|
try {
|
|
2669
2688
|
const result = await def.run(args, { clientId: this.clientId });
|
|
2670
2689
|
if (typeof result === "string" && result.trim()) {
|
|
2671
|
-
this.emit({ type: "notice", level: "info", text: result });
|
|
2690
|
+
this.emit({ type: "notice", level: "info", text: result, textEn: result });
|
|
2672
2691
|
}
|
|
2673
2692
|
}
|
|
2674
2693
|
catch (err) {
|
|
@@ -2887,7 +2906,8 @@ export class DshClientSession {
|
|
|
2887
2906
|
}
|
|
2888
2907
|
async cloneProvider(_provider, reqId) {
|
|
2889
2908
|
const error = "DSH 引擎不支持自定义 provider";
|
|
2890
|
-
|
|
2909
|
+
const errorEn = "DSH engine does not support custom providers";
|
|
2910
|
+
this.emit({ type: "notice", level: "error", text: error, textEn: errorEn });
|
|
2891
2911
|
this.emit({ type: "clone_provider_result", reqId, ok: false, error });
|
|
2892
2912
|
}
|
|
2893
2913
|
// -----------------------------------------------------------------------
|
|
@@ -1 +1 @@
|
|
|
1
|
-
[]
|
|
1
|
+
[]
|