pi-web-ui 0.91.0 → 0.93.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 +90 -1
- package/README.md +69 -14
- package/README.zh-CN.md +36 -10
- package/bin/pi-web-ui.mjs +39 -8
- package/dist/server/agent-service.js +938 -163
- package/dist/server/auth-cookie.js +26 -0
- package/dist/server/claim-files-tool.js +115 -0
- package/dist/server/claim-store.js +301 -0
- package/dist/server/client-state.js +114 -6
- package/dist/server/conversation-read-tool.js +371 -28
- package/dist/server/conversation-touches.js +357 -0
- package/dist/server/delegate-task.js +10 -3
- package/dist/server/dsh/dsh-agent-service.js +50 -1
- package/dist/server/files-service.js +78 -26
- package/dist/server/http-proxy.js +72 -0
- package/dist/server/index.js +94 -11
- package/dist/server/model-admin.js +124 -2
- package/dist/server/model-enrich.js +478 -0
- package/dist/server/patch-node-pty.js +11 -0
- package/dist/server/plugin-schedule.js +27 -2
- package/dist/server/plugins.js +66 -10
- package/dist/server/present-files-tool.js +303 -0
- package/dist/server/protocol-version.js +1 -1
- package/dist/server/read-tool.js +125 -0
- package/dist/server/resolve-global-sdk.js +72 -0
- package/dist/server/sdk-origin.js +64 -0
- package/dist/server/serialize.js +80 -22
- package/dist/server/settings-service.js +19 -1
- package/dist/server/skill-tool.js +2 -1
- package/dist/server/subagents.js +30 -13
- package/dist/server/terminals.js +38 -18
- package/dist/server/text-sniff.js +15 -0
- package/dist/server/themes.js +32 -2
- package/dist/server/tool-info.js +89 -0
- package/dist/server/tool-manager.js +110 -11
- package/package.json +2 -2
- package/plugin-sdk/README.md +1 -0
- package/plugins/catalog.json +20 -0
- package/themes/ayu-light.css +136 -0
- package/themes/catppuccin-latte.css +140 -0
- package/themes/catppuccin.css +144 -0
- package/themes/codex.css +136 -0
- package/themes/cyberpunk.css +4 -0
- package/themes/dazzle.css +4 -0
- package/themes/everforest-light.css +136 -0
- package/themes/geist.css +136 -0
- package/themes/gruvbox-light.css +136 -0
- package/themes/kanagawa-lotus.css +136 -0
- package/themes/md-preview.css +4 -0
- package/themes/mist.css +4 -0
- package/themes/nord.css +134 -0
- package/themes/one-dark.css +135 -0
- package/themes/paper.css +16 -12
- package/themes/rose-pine-dawn.css +136 -0
- package/themes/sakura.css +4 -0
- package/themes/solarized-light.css +135 -0
- package/themes/tokyo-night.css +144 -0
- package/themes/white.css +4 -0
- package/web/dist/assets/{TerminalPanel-GtDQ1h85.js → TerminalPanel-C1A23aI-.js} +1 -1
- package/web/dist/assets/index-B48QWf0I.js +364 -0
- package/web/dist/assets/index-DGL5OInG.css +1 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-CdsKltOS.css +0 -1
- package/web/dist/assets/index-OoULNF70.js +0 -363
package/bin/pi-web-ui.mjs
CHANGED
|
@@ -55,6 +55,13 @@ import { fileURLToPath } from "node:url";
|
|
|
55
55
|
const BIN_DIR = dirname(fileURLToPath(import.meta.url));
|
|
56
56
|
/** <pkg>/dist/server/index.js — the actual server entry. */
|
|
57
57
|
const SERVER_ENTRY = join(BIN_DIR, "..", "dist", "server", "index.js");
|
|
58
|
+
/** 可选的「优先用全局/祖先那份 pi SDK」解析钩子(issue #260,`PI_WEB_SDK=global` 才生效)。
|
|
59
|
+
* 必须早于任何 SDK 静态 import 加载 —— 所以每条启动路径都把它当 `--import` 传进去;
|
|
60
|
+
* 默认不启用时它自己什么都不做(见 server/resolve-global-sdk.ts)。 */
|
|
61
|
+
const SDK_HOOK = join(BIN_DIR, "..", "dist", "server", "resolve-global-sdk.js");
|
|
62
|
+
/** dist 可能是旧构建(没有这个钩子文件)—— 只有文件在才注入:`--import <missing>` 会让
|
|
63
|
+
* CLI/服务直接起不来,那比少个开关严重得多。 */
|
|
64
|
+
const HAS_SDK_HOOK = existsSync(SDK_HOOK);
|
|
58
65
|
const NODE = process.execPath;
|
|
59
66
|
let pkg = { version: "0.0.0" };
|
|
60
67
|
try {
|
|
@@ -390,6 +397,7 @@ async function startForeground(opts) {
|
|
|
390
397
|
if (opts.host) process.env.PI_WEB_HOST = opts.host;
|
|
391
398
|
if (opts.agentDir) process.env.PI_CODING_AGENT_DIR = resolve(opts.agentDir);
|
|
392
399
|
const url = `http://localhost:${effectivePort(opts)}`;
|
|
400
|
+
if (HAS_SDK_HOOK) await import(pathToFileURL(SDK_HOOK).href);
|
|
393
401
|
await import(pathToFileURL(SERVER_ENTRY).href);
|
|
394
402
|
if (!opts.noBrowser) openBrowserWhenUp(url);
|
|
395
403
|
}
|
|
@@ -623,7 +631,7 @@ function buildWinShortcutPs1(env, cwd, taskName, url, logPath, pidPath) {
|
|
|
623
631
|
" try { if ((Invoke-WebRequest -Uri $h -UseBasicParsing -TimeoutSec 2).StatusCode -eq 200) { Start-Process $u | Out-Null; break } } catch {}",
|
|
624
632
|
" }",
|
|
625
633
|
"} -ArgumentList $url",
|
|
626
|
-
`& ${psQuote(node)} ${psQuote(SERVER_ENTRY)} *>> $log`,
|
|
634
|
+
`& ${psQuote(node)} ${HAS_SDK_HOOK ? `--import ${psQuote(SDK_HOOK)} ` : ""}${psQuote(SERVER_ENTRY)} *>> $log`,
|
|
627
635
|
"Remove-Item $pidFile -ErrorAction SilentlyContinue",
|
|
628
636
|
"",
|
|
629
637
|
].join("\r\n");
|
|
@@ -726,6 +734,7 @@ URL=${shQuote(url)}
|
|
|
726
734
|
LOG=/tmp/pi-web-ui-shortcut.log
|
|
727
735
|
NODE=${shQuote(node)}
|
|
728
736
|
ENTRY=${shQuote(SERVER_ENTRY)}
|
|
737
|
+
SDK_HOOK_ARG=${HAS_SDK_HOOK ? `${shQuote("--import")} ${shQuote(SDK_HOOK)} ` : ""}
|
|
729
738
|
${exports}
|
|
730
739
|
|
|
731
740
|
if launchctl print "gui/$(id -u)/$LABEL" >/dev/null 2>&1; then
|
|
@@ -734,7 +743,7 @@ elif [ -f "$PLIST" ]; then
|
|
|
734
743
|
launchctl bootstrap "gui/$(id -u)" "$PLIST"
|
|
735
744
|
else
|
|
736
745
|
# 未安装服务:在本终端前台运行服务器(关闭窗口即停止)
|
|
737
|
-
"$NODE" "$ENTRY" >>"$LOG" 2>&1 &
|
|
746
|
+
"$NODE" $SDK_HOOK_ARG"$ENTRY" >>"$LOG" 2>&1 &
|
|
738
747
|
SERVER_PID=$!
|
|
739
748
|
trap 'kill "$SERVER_PID" 2>/dev/null' EXIT
|
|
740
749
|
fi
|
|
@@ -786,13 +795,14 @@ LOG=${shQuote(log)}
|
|
|
786
795
|
URL=${shQuote(url)}
|
|
787
796
|
NODE=${shQuote(node)}
|
|
788
797
|
ENTRY=${shQuote(SERVER_ENTRY)}
|
|
798
|
+
SDK_HOOK_ARG=${HAS_SDK_HOOK ? `${shQuote("--import")} ${shQuote(SDK_HOOK)} ` : ""}
|
|
789
799
|
UNIT=${shQuote(unitName)}.service
|
|
790
800
|
|
|
791
801
|
if ! curl -sf "$URL/api/health" >/dev/null 2>&1; then
|
|
792
802
|
systemctl start "$UNIT" 2>/dev/null || true
|
|
793
803
|
if ! curl -sf "$URL/api/health" >/dev/null 2>&1; then
|
|
794
804
|
mkdir -p "$(dirname "$LOG")"
|
|
795
|
-
"$NODE" "$ENTRY" >>"$LOG" 2>&1 &
|
|
805
|
+
"$NODE" $SDK_HOOK_ARG"$ENTRY" >>"$LOG" 2>&1 &
|
|
796
806
|
SERVER_PID=$!
|
|
797
807
|
trap 'kill "$SERVER_PID" 2>/dev/null' EXIT
|
|
798
808
|
fi
|
|
@@ -909,7 +919,7 @@ function buildWinStartPs1(env, cwd, logPath, pidPath) {
|
|
|
909
919
|
`$PID | Out-File -Encoding ascii ${psQuote(pidPath)}`,
|
|
910
920
|
"try {",
|
|
911
921
|
" while ($true) {",
|
|
912
|
-
` & ${psQuote(realNode())} ${psQuote(SERVER_ENTRY)} *>> ${psQuote(logPath)}`,
|
|
922
|
+
` & ${psQuote(realNode())} ${HAS_SDK_HOOK ? `--import ${psQuote(SDK_HOOK)} ` : ""}${psQuote(SERVER_ENTRY)} *>> ${psQuote(logPath)}`,
|
|
913
923
|
" Start-Sleep 10",
|
|
914
924
|
" }",
|
|
915
925
|
"} finally {",
|
|
@@ -968,7 +978,9 @@ function buildPlist(label, cwd, env) {
|
|
|
968
978
|
<key>ProgramArguments</key>
|
|
969
979
|
<array>
|
|
970
980
|
<string>${esc(NODE)}</string>
|
|
971
|
-
|
|
981
|
+
${
|
|
982
|
+
HAS_SDK_HOOK ? ` <string>--import</string>\n <string>${esc(SDK_HOOK)}</string>\n` : ""
|
|
983
|
+
} <string>${esc(SERVER_ENTRY)}</string>
|
|
972
984
|
</array>
|
|
973
985
|
|
|
974
986
|
<key>RunAtLoad</key>
|
|
@@ -1000,6 +1012,17 @@ function systemdQuote(value) {
|
|
|
1000
1012
|
return JSON.stringify(String(value)).replace(/%/g, "%%");
|
|
1001
1013
|
}
|
|
1002
1014
|
|
|
1015
|
+
/**
|
|
1016
|
+
* systemd paths (WorkingDirectory=) must NOT be quoted: unlike Environment= and
|
|
1017
|
+
* ExecStart=, the path directives do not strip surrounding double quotes, so
|
|
1018
|
+
* WorkingDirectory="/home/me/work" makes systemd fail with "path is not absolute".
|
|
1019
|
+
* The whole (trimmed) value is the path, so inner spaces need no escaping —
|
|
1020
|
+
* only % has to be doubled to survive specifier expansion.
|
|
1021
|
+
*/
|
|
1022
|
+
function systemdPath(value) {
|
|
1023
|
+
return String(value).replace(/%/g, "%%");
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1003
1026
|
/** Build the systemd unit file. */
|
|
1004
1027
|
function buildUnit(cwd, env) {
|
|
1005
1028
|
const envLines = Object.entries(env)
|
|
@@ -1017,9 +1040,9 @@ After=network.target
|
|
|
1017
1040
|
[Service]
|
|
1018
1041
|
Type=simple
|
|
1019
1042
|
User=${process.env.SUDO_USER ?? userInfo().username}
|
|
1020
|
-
WorkingDirectory=${
|
|
1043
|
+
WorkingDirectory=${systemdPath(cwd)}
|
|
1021
1044
|
${envLines}
|
|
1022
|
-
${capabilities}ExecStart=${JSON.stringify(NODE)} ${JSON.stringify(SERVER_ENTRY)}
|
|
1045
|
+
${capabilities}ExecStart=${JSON.stringify(NODE)}${HAS_SDK_HOOK ? ` --import ${JSON.stringify(SDK_HOOK)}` : ""} ${JSON.stringify(SERVER_ENTRY)}
|
|
1023
1046
|
Restart=always
|
|
1024
1047
|
RestartSec=5
|
|
1025
1048
|
|
|
@@ -1147,7 +1170,15 @@ function installSystemd(opts) {
|
|
|
1147
1170
|
return;
|
|
1148
1171
|
}
|
|
1149
1172
|
// Generated units can contain credentials. install also corrects an existing unit's mode.
|
|
1150
|
-
|
|
1173
|
+
// Stage through a temp file: `install /dev/stdin` fails on some hosts (WSL) with
|
|
1174
|
+
// ENXIO when stdin is a pipe rather than a tty.
|
|
1175
|
+
const staged = join(tmpdir(), `pi-web-ui-${name}-${process.pid}.service`);
|
|
1176
|
+
writeFileSync(staged, content, { mode: 0o600 });
|
|
1177
|
+
try {
|
|
1178
|
+
runSystemdRoot("install", ["-m", "600", staged, unitPath]);
|
|
1179
|
+
} finally {
|
|
1180
|
+
rmSync(staged, { force: true });
|
|
1181
|
+
}
|
|
1151
1182
|
runSystemdRoot("systemctl", ["daemon-reload"]);
|
|
1152
1183
|
runSystemdRoot("systemctl", ["enable", `${name}.service`]);
|
|
1153
1184
|
// enable --now does not restart an already-active unit after configuration changes.
|