pi-web-ui 0.8.4 → 0.8.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/LICENSE +21 -21
- package/README.md +414 -398
- package/README.zh-CN.md +359 -359
- package/bin/pi-web-ui.mjs +50 -2
- package/deploy/com.xingshuyin.pi-web-ui.plist +48 -48
- package/deploy/pi-web-ui-task.xml +71 -71
- package/deploy/pi-web-ui.service +31 -31
- package/dist/server/agent-service.js +13 -3
- package/package.json +1 -1
- package/web/dist/assets/{index-CqRE1kpZ.js → index-BPM4qIYE.js} +50 -50
- package/web/dist/assets/index-DicNqNt1.css +41 -0
- package/web/dist/favicon.svg +8 -8
- package/web/dist/index.html +15 -15
- package/web/dist/assets/index-Ton8iALZ.css +0 -41
package/bin/pi-web-ui.mjs
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* pi-web-ui CLI.
|
|
4
4
|
*
|
|
5
|
-
* pi-web-ui 启动生产服务器(前台,Ctrl+C
|
|
5
|
+
* pi-web-ui 启动生产服务器(前台,Ctrl+C 停止,自动打开浏览器)
|
|
6
6
|
* pi-web-ui --port 9000 --cwd /path 同上,覆盖端口 / 工作目录 / 数据目录
|
|
7
|
+
* pi-web-ui --no-browser 启动但不自动打开浏览器
|
|
7
8
|
* pi-web-ui --version | --help
|
|
8
9
|
* pi-web-ui server install [选项] 安装系统服务(开机自启)并启动
|
|
9
10
|
* pi-web-ui server uninstall [选项] 卸载系统服务
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
* PI_CODING_AGENT_DIR。
|
|
22
23
|
*/
|
|
23
24
|
import { spawnSync } from "node:child_process";
|
|
25
|
+
import { get as httpGet } from "node:http";
|
|
24
26
|
import {
|
|
25
27
|
existsSync,
|
|
26
28
|
mkdirSync,
|
|
@@ -47,8 +49,9 @@ try {
|
|
|
47
49
|
const HELP = `pi-web-ui v${pkg.version} — web chat for the pi coding agent
|
|
48
50
|
|
|
49
51
|
用法:
|
|
50
|
-
pi-web-ui 启动服务器(前台,Ctrl+C
|
|
52
|
+
pi-web-ui 启动服务器(前台,Ctrl+C 停止,自动打开浏览器)
|
|
51
53
|
pi-web-ui --port 9000 --cwd /path 启动并指定端口 / 工作目录 / 数据目录
|
|
54
|
+
pi-web-ui --no-browser 启动但不自动打开浏览器
|
|
52
55
|
pi-web-ui server install [选项] 安装系统服务(开机自启)并启动
|
|
53
56
|
pi-web-ui server uninstall [选项] 卸载系统服务
|
|
54
57
|
pi-web-ui server start|stop|restart|status [选项]
|
|
@@ -109,6 +112,7 @@ function parseFlags(argv) {
|
|
|
109
112
|
dataDir: undefined,
|
|
110
113
|
name: undefined,
|
|
111
114
|
print: false,
|
|
115
|
+
noBrowser: false,
|
|
112
116
|
help: false,
|
|
113
117
|
};
|
|
114
118
|
const positionals = [];
|
|
@@ -141,6 +145,9 @@ function parseFlags(argv) {
|
|
|
141
145
|
case "--print":
|
|
142
146
|
opts.print = true;
|
|
143
147
|
break;
|
|
148
|
+
case "--no-browser":
|
|
149
|
+
opts.noBrowser = true;
|
|
150
|
+
break;
|
|
144
151
|
case "--help":
|
|
145
152
|
case "-h":
|
|
146
153
|
opts.help = true;
|
|
@@ -157,11 +164,52 @@ function parseFlags(argv) {
|
|
|
157
164
|
// 前台启动
|
|
158
165
|
// ---------------------------------------------------------------------------
|
|
159
166
|
|
|
167
|
+
/** Open a URL in the OS default browser; failures are ignored (best-effort). */
|
|
168
|
+
function openBrowser(url) {
|
|
169
|
+
if (isMac) {
|
|
170
|
+
spawnSync("open", [url], { stdio: "ignore" });
|
|
171
|
+
} else if (isWin) {
|
|
172
|
+
spawnSync("cmd", ["/c", "start", "", url], { stdio: "ignore" });
|
|
173
|
+
} else {
|
|
174
|
+
spawnSync("xdg-open", [url], { stdio: "ignore" });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Poll `url` until the server answers (or ~15s pass), then open it in the
|
|
180
|
+
* default browser. The foreground server runs in this process, so the first
|
|
181
|
+
* HTTP response is the "listening" signal; if the server crashes meanwhile
|
|
182
|
+
* (e.g. port already taken), the pending timers die with the process and
|
|
183
|
+
* nothing is opened.
|
|
184
|
+
*/
|
|
185
|
+
function openBrowserWhenUp(url) {
|
|
186
|
+
const deadline = Date.now() + 15_000;
|
|
187
|
+
const attempt = () => {
|
|
188
|
+
const req = httpGet(url, (res) => {
|
|
189
|
+
res.resume();
|
|
190
|
+
console.log(` 🌐 已自动打开浏览器:${url}(--no-browser 可关闭)`);
|
|
191
|
+
openBrowser(url);
|
|
192
|
+
});
|
|
193
|
+
req.setTimeout(1000, () => {
|
|
194
|
+
req.destroy();
|
|
195
|
+
if (Date.now() < deadline) setTimeout(attempt, 150);
|
|
196
|
+
});
|
|
197
|
+
req.on("error", () => {
|
|
198
|
+
if (Date.now() < deadline) setTimeout(attempt, 150);
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
attempt();
|
|
202
|
+
}
|
|
203
|
+
|
|
160
204
|
async function startForeground(opts) {
|
|
161
205
|
if (opts.port) process.env.PORT = opts.port;
|
|
162
206
|
if (opts.cwd) process.env.PI_WEB_CWD = resolve(opts.cwd);
|
|
163
207
|
if (opts.dataDir) process.env.PI_WEB_DATA_DIR = resolve(opts.dataDir);
|
|
208
|
+
const url = `http://localhost:${String(
|
|
209
|
+
opts.port ?? process.env.PORT ?? "8787",
|
|
210
|
+
)}`;
|
|
164
211
|
await import(pathToFileURL(SERVER_ENTRY).href);
|
|
212
|
+
if (!opts.noBrowser) openBrowserWhenUp(url);
|
|
165
213
|
}
|
|
166
214
|
|
|
167
215
|
// ---------------------------------------------------------------------------
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
-
<!--
|
|
4
|
-
pi-web-ui launchd agent — macOS auto-start at login.
|
|
5
|
-
|
|
6
|
-
Install:
|
|
7
|
-
npm i -g pi-web-ui
|
|
8
|
-
cp deploy/com.xingshuyin.pi-web-ui.plist ~/Library/LaunchAgents/
|
|
9
|
-
# edit ProgramArguments / WorkingDirectory / PI_WEB_CWD for your setup
|
|
10
|
-
launchctl load ~/Library/LaunchAgents/com.xingshuyin.pi-web-ui.plist
|
|
11
|
-
# (or: launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.xingshuyin.pi-web-ui.plist)
|
|
12
|
-
|
|
13
|
-
Find the pi-web-ui binary path with: which pi-web-ui
|
|
14
|
-
-->
|
|
15
|
-
<plist version="1.0">
|
|
16
|
-
<dict>
|
|
17
|
-
<key>Label</key>
|
|
18
|
-
<string>com.xingshuyin.pi-web-ui</string>
|
|
19
|
-
|
|
20
|
-
<key>ProgramArguments</key>
|
|
21
|
-
<array>
|
|
22
|
-
<string>/usr/local/bin/pi-web-ui</string>
|
|
23
|
-
</array>
|
|
24
|
-
|
|
25
|
-
<key>RunAtLoad</key>
|
|
26
|
-
<true/>
|
|
27
|
-
|
|
28
|
-
<!-- Restart if it crashes -->
|
|
29
|
-
<key>KeepAlive</key>
|
|
30
|
-
<true/>
|
|
31
|
-
|
|
32
|
-
<key>WorkingDirectory</key>
|
|
33
|
-
<string>/Users/YOUR_USER</string>
|
|
34
|
-
|
|
35
|
-
<key>EnvironmentVariables</key>
|
|
36
|
-
<dict>
|
|
37
|
-
<key>PORT</key>
|
|
38
|
-
<string>8787</string>
|
|
39
|
-
<key>PI_WEB_CWD</key>
|
|
40
|
-
<string>/Users/YOUR_USER</string>
|
|
41
|
-
</dict>
|
|
42
|
-
|
|
43
|
-
<key>StandardOutPath</key>
|
|
44
|
-
<string>/tmp/pi-web-ui.log</string>
|
|
45
|
-
<key>StandardErrorPath</key>
|
|
46
|
-
<string>/tmp/pi-web-ui.err</string>
|
|
47
|
-
</dict>
|
|
48
|
-
</plist>
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<!--
|
|
4
|
+
pi-web-ui launchd agent — macOS auto-start at login.
|
|
5
|
+
|
|
6
|
+
Install:
|
|
7
|
+
npm i -g pi-web-ui
|
|
8
|
+
cp deploy/com.xingshuyin.pi-web-ui.plist ~/Library/LaunchAgents/
|
|
9
|
+
# edit ProgramArguments / WorkingDirectory / PI_WEB_CWD for your setup
|
|
10
|
+
launchctl load ~/Library/LaunchAgents/com.xingshuyin.pi-web-ui.plist
|
|
11
|
+
# (or: launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.xingshuyin.pi-web-ui.plist)
|
|
12
|
+
|
|
13
|
+
Find the pi-web-ui binary path with: which pi-web-ui
|
|
14
|
+
-->
|
|
15
|
+
<plist version="1.0">
|
|
16
|
+
<dict>
|
|
17
|
+
<key>Label</key>
|
|
18
|
+
<string>com.xingshuyin.pi-web-ui</string>
|
|
19
|
+
|
|
20
|
+
<key>ProgramArguments</key>
|
|
21
|
+
<array>
|
|
22
|
+
<string>/usr/local/bin/pi-web-ui</string>
|
|
23
|
+
</array>
|
|
24
|
+
|
|
25
|
+
<key>RunAtLoad</key>
|
|
26
|
+
<true/>
|
|
27
|
+
|
|
28
|
+
<!-- Restart if it crashes -->
|
|
29
|
+
<key>KeepAlive</key>
|
|
30
|
+
<true/>
|
|
31
|
+
|
|
32
|
+
<key>WorkingDirectory</key>
|
|
33
|
+
<string>/Users/YOUR_USER</string>
|
|
34
|
+
|
|
35
|
+
<key>EnvironmentVariables</key>
|
|
36
|
+
<dict>
|
|
37
|
+
<key>PORT</key>
|
|
38
|
+
<string>8787</string>
|
|
39
|
+
<key>PI_WEB_CWD</key>
|
|
40
|
+
<string>/Users/YOUR_USER</string>
|
|
41
|
+
</dict>
|
|
42
|
+
|
|
43
|
+
<key>StandardOutPath</key>
|
|
44
|
+
<string>/tmp/pi-web-ui.log</string>
|
|
45
|
+
<key>StandardErrorPath</key>
|
|
46
|
+
<string>/tmp/pi-web-ui.err</string>
|
|
47
|
+
</dict>
|
|
48
|
+
</plist>
|
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-16"?>
|
|
2
|
-
<!--
|
|
3
|
-
pi-web-ui Task Scheduler task — Windows auto-start at logon.
|
|
4
|
-
|
|
5
|
-
The easy way (no admin needed, generates everything for you):
|
|
6
|
-
npm i -g pi-web-ui
|
|
7
|
-
pi-web-ui server install --port 8787 --cwd C:\path\to\project
|
|
8
|
-
pi-web-ui server status | restart | stop | uninstall
|
|
9
|
-
|
|
10
|
-
Manual install with this template (edit the paths below first):
|
|
11
|
-
schtasks /Create /TN "pi-web-ui" /XML pi-web-ui-task.xml /F
|
|
12
|
-
schtasks /Run /TN "pi-web-ui"
|
|
13
|
-
|
|
14
|
-
Notes:
|
|
15
|
-
- The task runs the PowerShell launcher the CLI generates at
|
|
16
|
-
%APPDATA%\pi-web-ui\pi-web-ui.ps1 with -WindowStyle Hidden, so the
|
|
17
|
-
server runs with no black console window (nothing to accidentally
|
|
18
|
-
close/kill). The ps1 sets PORT/PI_WEB_CWD, cd's to the workspace,
|
|
19
|
-
launches node, and appends output to %USERPROFILE%\pi-web-ui.log.
|
|
20
|
-
Preview both generated files with: pi-web-ui server install --print
|
|
21
|
-
- Save this file as UTF-16 LE (schtasks requires it; the CLI does this
|
|
22
|
-
automatically when it writes the task XML).
|
|
23
|
-
- LogonTrigger = starts when you log in, same as a launchd user agent.
|
|
24
|
-
For boot-start without login, use Docker instead (see README).
|
|
25
|
-
-->
|
|
26
|
-
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
|
27
|
-
<RegistrationInfo>
|
|
28
|
-
<Description>pi-web-ui — web chat for the pi coding agent (auto-start at logon)</Description>
|
|
29
|
-
</RegistrationInfo>
|
|
30
|
-
<Triggers>
|
|
31
|
-
<LogonTrigger>
|
|
32
|
-
<Enabled>true</Enabled>
|
|
33
|
-
</LogonTrigger>
|
|
34
|
-
</Triggers>
|
|
35
|
-
<Principals>
|
|
36
|
-
<Principal id="Author">
|
|
37
|
-
<LogonType>InteractiveToken</LogonType>
|
|
38
|
-
<RunLevel>LeastPrivilege</RunLevel>
|
|
39
|
-
</Principal>
|
|
40
|
-
</Principals>
|
|
41
|
-
<Settings>
|
|
42
|
-
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
|
|
43
|
-
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
|
|
44
|
-
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
|
|
45
|
-
<AllowHardTerminate>true</AllowHardTerminate>
|
|
46
|
-
<StartWhenAvailable>false</StartWhenAvailable>
|
|
47
|
-
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
|
|
48
|
-
<IdleSettings>
|
|
49
|
-
<StopOnIdleEnd>false</StopOnIdleEnd>
|
|
50
|
-
<RestartOnIdle>false</RestartOnIdle>
|
|
51
|
-
</IdleSettings>
|
|
52
|
-
<AllowStartOnDemand>true</AllowStartOnDemand>
|
|
53
|
-
<Enabled>true</Enabled>
|
|
54
|
-
<Hidden>false</Hidden>
|
|
55
|
-
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
|
56
|
-
<WakeToRun>false</WakeToRun>
|
|
57
|
-
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
|
|
58
|
-
<Priority>7</Priority>
|
|
59
|
-
<RestartOnFailure>
|
|
60
|
-
<Interval>PT1M</Interval>
|
|
61
|
-
<Count>3</Count>
|
|
62
|
-
</RestartOnFailure>
|
|
63
|
-
</Settings>
|
|
64
|
-
<Actions Context="Author">
|
|
65
|
-
<Exec>
|
|
66
|
-
<Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
|
|
67
|
-
<Arguments>-NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File "%APPDATA%\pi-web-ui\pi-web-ui.ps1"</Arguments>
|
|
68
|
-
<WorkingDirectory>%USERPROFILE%</WorkingDirectory>
|
|
69
|
-
</Exec>
|
|
70
|
-
</Actions>
|
|
71
|
-
</Task>
|
|
1
|
+
<?xml version="1.0" encoding="UTF-16"?>
|
|
2
|
+
<!--
|
|
3
|
+
pi-web-ui Task Scheduler task — Windows auto-start at logon.
|
|
4
|
+
|
|
5
|
+
The easy way (no admin needed, generates everything for you):
|
|
6
|
+
npm i -g pi-web-ui
|
|
7
|
+
pi-web-ui server install --port 8787 --cwd C:\path\to\project
|
|
8
|
+
pi-web-ui server status | restart | stop | uninstall
|
|
9
|
+
|
|
10
|
+
Manual install with this template (edit the paths below first):
|
|
11
|
+
schtasks /Create /TN "pi-web-ui" /XML pi-web-ui-task.xml /F
|
|
12
|
+
schtasks /Run /TN "pi-web-ui"
|
|
13
|
+
|
|
14
|
+
Notes:
|
|
15
|
+
- The task runs the PowerShell launcher the CLI generates at
|
|
16
|
+
%APPDATA%\pi-web-ui\pi-web-ui.ps1 with -WindowStyle Hidden, so the
|
|
17
|
+
server runs with no black console window (nothing to accidentally
|
|
18
|
+
close/kill). The ps1 sets PORT/PI_WEB_CWD, cd's to the workspace,
|
|
19
|
+
launches node, and appends output to %USERPROFILE%\pi-web-ui.log.
|
|
20
|
+
Preview both generated files with: pi-web-ui server install --print
|
|
21
|
+
- Save this file as UTF-16 LE (schtasks requires it; the CLI does this
|
|
22
|
+
automatically when it writes the task XML).
|
|
23
|
+
- LogonTrigger = starts when you log in, same as a launchd user agent.
|
|
24
|
+
For boot-start without login, use Docker instead (see README).
|
|
25
|
+
-->
|
|
26
|
+
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
|
27
|
+
<RegistrationInfo>
|
|
28
|
+
<Description>pi-web-ui — web chat for the pi coding agent (auto-start at logon)</Description>
|
|
29
|
+
</RegistrationInfo>
|
|
30
|
+
<Triggers>
|
|
31
|
+
<LogonTrigger>
|
|
32
|
+
<Enabled>true</Enabled>
|
|
33
|
+
</LogonTrigger>
|
|
34
|
+
</Triggers>
|
|
35
|
+
<Principals>
|
|
36
|
+
<Principal id="Author">
|
|
37
|
+
<LogonType>InteractiveToken</LogonType>
|
|
38
|
+
<RunLevel>LeastPrivilege</RunLevel>
|
|
39
|
+
</Principal>
|
|
40
|
+
</Principals>
|
|
41
|
+
<Settings>
|
|
42
|
+
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
|
|
43
|
+
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
|
|
44
|
+
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
|
|
45
|
+
<AllowHardTerminate>true</AllowHardTerminate>
|
|
46
|
+
<StartWhenAvailable>false</StartWhenAvailable>
|
|
47
|
+
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
|
|
48
|
+
<IdleSettings>
|
|
49
|
+
<StopOnIdleEnd>false</StopOnIdleEnd>
|
|
50
|
+
<RestartOnIdle>false</RestartOnIdle>
|
|
51
|
+
</IdleSettings>
|
|
52
|
+
<AllowStartOnDemand>true</AllowStartOnDemand>
|
|
53
|
+
<Enabled>true</Enabled>
|
|
54
|
+
<Hidden>false</Hidden>
|
|
55
|
+
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
|
56
|
+
<WakeToRun>false</WakeToRun>
|
|
57
|
+
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
|
|
58
|
+
<Priority>7</Priority>
|
|
59
|
+
<RestartOnFailure>
|
|
60
|
+
<Interval>PT1M</Interval>
|
|
61
|
+
<Count>3</Count>
|
|
62
|
+
</RestartOnFailure>
|
|
63
|
+
</Settings>
|
|
64
|
+
<Actions Context="Author">
|
|
65
|
+
<Exec>
|
|
66
|
+
<Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
|
|
67
|
+
<Arguments>-NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File "%APPDATA%\pi-web-ui\pi-web-ui.ps1"</Arguments>
|
|
68
|
+
<WorkingDirectory>%USERPROFILE%</WorkingDirectory>
|
|
69
|
+
</Exec>
|
|
70
|
+
</Actions>
|
|
71
|
+
</Task>
|
package/deploy/pi-web-ui.service
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
# pi-web-ui systemd unit — Linux auto-start on boot.
|
|
2
|
-
#
|
|
3
|
-
# Install (adjust User/WorkingDirectory/Environment to taste):
|
|
4
|
-
# sudo npm i -g pi-web-ui
|
|
5
|
-
# sudo cp deploy/pi-web-ui.service /etc/systemd/system/
|
|
6
|
-
# sudo systemctl daemon-reload
|
|
7
|
-
# sudo systemctl enable --now pi-web-ui
|
|
8
|
-
# sudo systemctl status pi-web-ui
|
|
9
|
-
#
|
|
10
|
-
# Logs: journalctl -u pi-web-ui -f
|
|
11
|
-
|
|
12
|
-
[Unit]
|
|
13
|
-
Description=pi-web-ui — web chat for the pi coding agent
|
|
14
|
-
After=network.target
|
|
15
|
-
|
|
16
|
-
[Service]
|
|
17
|
-
Type=simple
|
|
18
|
-
# Run as an unprivileged user (change to your user, e.g. yourname)
|
|
19
|
-
User=YOUR_USER
|
|
20
|
-
# The workspace the agent operates in (read/edit/bash/write)
|
|
21
|
-
WorkingDirectory=/home/YOUR_USER
|
|
22
|
-
Environment=PORT=8787
|
|
23
|
-
# Point at your pi config dir if it's not the default ~/.pi/agent
|
|
24
|
-
#Environment=PI_CODING_AGENT_DIR=/home/YOUR_USER/.pi/agent
|
|
25
|
-
ExecStart=/usr/bin/pi-web-ui
|
|
26
|
-
Restart=on-failure
|
|
27
|
-
RestartSec=5
|
|
28
|
-
# npm global bin may live elsewhere (nvm, etc.) — find with: which pi-web-ui
|
|
29
|
-
|
|
30
|
-
[Install]
|
|
31
|
-
WantedBy=multi-user.target
|
|
1
|
+
# pi-web-ui systemd unit — Linux auto-start on boot.
|
|
2
|
+
#
|
|
3
|
+
# Install (adjust User/WorkingDirectory/Environment to taste):
|
|
4
|
+
# sudo npm i -g pi-web-ui
|
|
5
|
+
# sudo cp deploy/pi-web-ui.service /etc/systemd/system/
|
|
6
|
+
# sudo systemctl daemon-reload
|
|
7
|
+
# sudo systemctl enable --now pi-web-ui
|
|
8
|
+
# sudo systemctl status pi-web-ui
|
|
9
|
+
#
|
|
10
|
+
# Logs: journalctl -u pi-web-ui -f
|
|
11
|
+
|
|
12
|
+
[Unit]
|
|
13
|
+
Description=pi-web-ui — web chat for the pi coding agent
|
|
14
|
+
After=network.target
|
|
15
|
+
|
|
16
|
+
[Service]
|
|
17
|
+
Type=simple
|
|
18
|
+
# Run as an unprivileged user (change to your user, e.g. yourname)
|
|
19
|
+
User=YOUR_USER
|
|
20
|
+
# The workspace the agent operates in (read/edit/bash/write)
|
|
21
|
+
WorkingDirectory=/home/YOUR_USER
|
|
22
|
+
Environment=PORT=8787
|
|
23
|
+
# Point at your pi config dir if it's not the default ~/.pi/agent
|
|
24
|
+
#Environment=PI_CODING_AGENT_DIR=/home/YOUR_USER/.pi/agent
|
|
25
|
+
ExecStart=/usr/bin/pi-web-ui
|
|
26
|
+
Restart=on-failure
|
|
27
|
+
RestartSec=5
|
|
28
|
+
# npm global bin may live elsewhere (nvm, etc.) — find with: which pi-web-ui
|
|
29
|
+
|
|
30
|
+
[Install]
|
|
31
|
+
WantedBy=multi-user.target
|
|
@@ -955,18 +955,23 @@ export class ClientSession {
|
|
|
955
955
|
async checkUpdate() {
|
|
956
956
|
const current = ClientSession.currentAppVersion();
|
|
957
957
|
try {
|
|
958
|
-
|
|
958
|
+
// Fetch the full package doc (not /latest): it carries the per-version
|
|
959
|
+
// publish timestamps so the UI can hint when a version was JUST
|
|
960
|
+
// published and the registry/CDN caches may not have caught up yet.
|
|
961
|
+
const res = await fetch("https://registry.npmjs.org/pi-web-ui", {
|
|
959
962
|
signal: AbortSignal.timeout(8_000),
|
|
960
963
|
});
|
|
961
964
|
if (!res.ok)
|
|
962
965
|
throw new Error(`HTTP ${res.status}`);
|
|
963
966
|
const data = (await res.json());
|
|
964
|
-
const latest = data
|
|
967
|
+
const latest = data["dist-tags"]?.latest ?? null;
|
|
968
|
+
const latestPublishedAt = latest && data.time ? (data.time[latest] ?? null) : null;
|
|
965
969
|
const upToDate = latest === null || ClientSession.compareVersions(current, latest) >= 0;
|
|
966
970
|
this.emit({
|
|
967
971
|
type: "update_status",
|
|
968
972
|
current,
|
|
969
973
|
latest,
|
|
974
|
+
latestPublishedAt,
|
|
970
975
|
upToDate,
|
|
971
976
|
pendingRestart: this.pendingRestart,
|
|
972
977
|
});
|
|
@@ -976,6 +981,7 @@ export class ClientSession {
|
|
|
976
981
|
type: "update_status",
|
|
977
982
|
current,
|
|
978
983
|
latest: null,
|
|
984
|
+
latestPublishedAt: null,
|
|
979
985
|
upToDate: false,
|
|
980
986
|
pendingRestart: this.pendingRestart,
|
|
981
987
|
error: `检查更新失败:${err.message}`,
|
|
@@ -1751,7 +1757,11 @@ export class ClientSession {
|
|
|
1751
1757
|
isStreaming,
|
|
1752
1758
|
});
|
|
1753
1759
|
}
|
|
1754
|
-
this.emit({
|
|
1760
|
+
this.emit({
|
|
1761
|
+
type: "conversations",
|
|
1762
|
+
conversations,
|
|
1763
|
+
activeId: this.activeId,
|
|
1764
|
+
});
|
|
1755
1765
|
}
|
|
1756
1766
|
/** List persisted sessions for this client, newest first. */
|
|
1757
1767
|
/** Push the persisted session list to the client (client-requested). */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-web-ui",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
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
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|