pi-web-ui 0.10.1 → 0.11.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/LICENSE +21 -21
- package/README.md +428 -428
- package/README.zh-CN.md +359 -359
- package/bin/pi-web-ui.mjs +1248 -844
- 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 +17 -2
- package/extensions/webui.ts +184 -184
- package/package.json +85 -85
- package/web/dist/favicon.svg +8 -8
- package/web/dist/index.html +13 -13
|
@@ -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
|
|
@@ -777,6 +777,7 @@ export class ClientSession {
|
|
|
777
777
|
lastActiveAt: Date.now(),
|
|
778
778
|
msgIds: new Map(),
|
|
779
779
|
nextMsgId: 1,
|
|
780
|
+
userSeqByTs: new Map(),
|
|
780
781
|
uiMessageCache: new Map(),
|
|
781
782
|
lastMessagesSig: "",
|
|
782
783
|
lastMessagesArray: [],
|
|
@@ -910,7 +911,18 @@ export class ClientSession {
|
|
|
910
911
|
const cached = conv.uiMessageCache.get(cacheKey);
|
|
911
912
|
if (cached)
|
|
912
913
|
return cached;
|
|
913
|
-
|
|
914
|
+
// User-message id suffix is a 1-based count of user messages sharing
|
|
915
|
+
// this timestamp (that's what resolveUserMessageEntryId() expects). n is
|
|
916
|
+
// a global per-conversation counter across ALL roles, so it can't be
|
|
917
|
+
// reused as the seq — otherwise editing anything but the first question
|
|
918
|
+
// fails to resolve ("找不到要编辑的消息").
|
|
919
|
+
let seq = n;
|
|
920
|
+
if (m.role === "user") {
|
|
921
|
+
const ts = m.timestamp ?? 0;
|
|
922
|
+
seq = (conv.userSeqByTs.get(ts) ?? 0) + 1;
|
|
923
|
+
conv.userSeqByTs.set(ts, seq);
|
|
924
|
+
}
|
|
925
|
+
const msg = serializeMessage(m, seq);
|
|
914
926
|
if (msg)
|
|
915
927
|
conv.uiMessageCache.set(cacheKey, msg);
|
|
916
928
|
return msg;
|
|
@@ -2110,7 +2122,10 @@ export class ClientSession {
|
|
|
2110
2122
|
const ts = Number(m[1]);
|
|
2111
2123
|
const seq = m[2] ? Number(m[2]) : 1;
|
|
2112
2124
|
let count = 0;
|
|
2113
|
-
|
|
2125
|
+
// Resolve against the compaction-aware current leaf path — the same list
|
|
2126
|
+
// the UI renders (state.messages). Scanning the whole file (getEntries)
|
|
2127
|
+
// could match a summarized entry or one on a different branch.
|
|
2128
|
+
for (const entry of this.session.sessionManager.buildContextEntries()) {
|
|
2114
2129
|
if (entry.type !== "message")
|
|
2115
2130
|
continue;
|
|
2116
2131
|
const msg = entry.message;
|