pi-web-ui 0.20.0 → 0.20.1

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.
@@ -225,14 +225,14 @@ function decodeText(buf) {
225
225
  * programs wait for input that never comes. Legacy Chinese files are often
226
226
  * GBK/GB2312 — read them with the right encoding, never paste mojibake into
227
227
  * reasoning/answers. */
228
- const WINDOWS_PERSONA = `You are a coding agent running on Windows. The bash tool runs Git Bash (bash.exe), not PowerShell. Follow these rules to avoid hanging the session:
229
-
230
-
231
-
232
- - ALWAYS pass a timeout parameter to the bash tool (in seconds). There is NO default timeout — a command that never finishes (servers, watchers, infinite loops, slow downloads/installs) will hang the entire conversation indefinitely. Pick a generous timeout for long-running work, but never omit it.
233
- - NEVER run interactive or foreground long-running commands through the bash tool (vi, less, top, python -, node -, npm run dev, sleep 10000). For servers/daemons use background execution with output redirected to a log file, then poll the log; stop them when done.
234
- - In the interactive terminal (TTY) — which is Git Bash too, not PowerShell — NEVER use heredocs (<<'EOF' ... EOF) or here-strings, and NEVER start interactive programs (vi, less, python -, node -, npm init): they wait for keyboard input that never arrives and hang the terminal forever. Prefer writing a temp script file (e.g. .pi-tmp.sh) and running it non-interactively. ALWAYS pass a timeout to long-running commands (e.g. \`timeout 120 npm run dev\`).
235
-
228
+ const WINDOWS_PERSONA = `You are a coding agent running on Windows. The bash tool runs Git Bash (bash.exe), not PowerShell. Follow these rules to avoid hanging the session:
229
+
230
+
231
+
232
+ - ALWAYS pass a timeout parameter to the bash tool (in seconds). There is NO default timeout — a command that never finishes (servers, watchers, infinite loops, slow downloads/installs) will hang the entire conversation indefinitely. Pick a generous timeout for long-running work, but never omit it.
233
+ - NEVER run interactive or foreground long-running commands through the bash tool (vi, less, top, python -, node -, npm run dev, sleep 10000). For servers/daemons use background execution with output redirected to a log file, then poll the log; stop them when done.
234
+ - In the interactive terminal (TTY) — which is Git Bash too, not PowerShell — NEVER use heredocs (<<'EOF' ... EOF) or here-strings, and NEVER start interactive programs (vi, less, python -, node -, npm init): they wait for keyboard input that never arrives and hang the terminal forever. Prefer writing a temp script file (e.g. .pi-tmp.sh) and running it non-interactively. ALWAYS pass a timeout to long-running commands (e.g. \`timeout 120 npm run dev\`).
235
+
236
236
  Many legacy Chinese text files (.html/.txt/.md/.log, exported documents) are GBK/GB2312 encoded: the read tool decodes UTF-8 only and will show mojibake (乱码) for them. If a file's content looks garbled, read it through the terminal instead: in Git Bash use \`cat file | iconv -f GBK -t UTF-8\` (or \`iconv -f GBK -t UTF-8 file\`); in cmd use \`chcp 65001 && type file\`; in PowerShell use \`Get-Content -Encoding Default file\`. Never paste mojibake into your reasoning or answer — describe the decoded content instead.`;
237
237
  /**
238
238
  * Killable bash tool: wraps the SDK bash tool with operations that register
@@ -1565,6 +1565,8 @@ export class ClientSession {
1565
1565
  * the process is going to restart itself (so the notice can say so).
1566
1566
  */
1567
1567
  onUpdateReady = undefined;
1568
+ /** Set by index.ts: called when /pi-web-ui:quit is invoked. */
1569
+ onQuit = undefined;
1568
1570
  /** Ask the npm registry for the latest pi-web-ui version and report it. */
1569
1571
  async checkUpdate() {
1570
1572
  const current = ClientSession.currentAppVersion();
@@ -2038,19 +2040,22 @@ export class ClientSession {
2038
2040
  * (they never reach the server) but stay listed so the picker shows them.
2039
2041
  */
2040
2042
  static NATIVE_COMMANDS = [
2041
- { name: "new", description: "新建对话" },
2042
- { name: "model", description: "切换模型", argumentHint: "[名称]" },
2043
- { name: "compact", description: "压缩上下文", argumentHint: "[说明]" },
2044
- { name: "cwd", description: "切换工作目录", argumentHint: "<路径>" },
2043
+ { name: "new", description: "新建对话", descriptionEn: "New chat" },
2044
+ { name: "model", description: "切换模型", descriptionEn: "Switch model", argumentHint: "[名称]", argumentHintEn: "[name]" },
2045
+ { name: "compact", description: "压缩上下文", descriptionEn: "Compact context", argumentHint: "[说明]", argumentHintEn: "[instructions]" },
2046
+ { name: "cwd", description: "切换工作目录", descriptionEn: "Switch workspace", argumentHint: "<路径>", argumentHintEn: "<path>" },
2045
2047
  {
2046
2048
  name: "thinking",
2047
2049
  description: "设置思考强度",
2048
- argumentHint: "<off|low|medium|high>",
2050
+ descriptionEn: "Set thinking level",
2051
+ argumentHint: "<off|low|medium|high|xhigh|max>",
2052
+ argumentHintEn: "<off|low|medium|high|xhigh|max>",
2049
2053
  },
2050
- { name: "resume", description: "刷新会话列表" },
2051
- { name: "reload", description: "重新加载扩展、技能与模板" },
2052
- { name: "help", description: "显示全部命令" },
2053
- { name: "copy", description: "复制上一条助手回复" },
2054
+ { name: "resume", description: "刷新会话列表", descriptionEn: "Refresh session list" },
2055
+ { name: "reload", description: "重新加载扩展、技能与模板", descriptionEn: "Reload extensions, skills & templates" },
2056
+ { name: "help", description: "显示全部命令", descriptionEn: "Show all commands" },
2057
+ { name: "copy", description: "复制上一条助手回复", descriptionEn: "Copy last assistant reply" },
2058
+ { name: "pi-web-ui:quit", description: "退出服务", descriptionEn: "Quit server (supervisor will restart)" },
2054
2059
  ];
2055
2060
  /** Parse a prompt into "/command args" — returns null when it isn't one. */
2056
2061
  parseSlash(text) {
@@ -2190,6 +2195,20 @@ export class ClientSession {
2190
2195
  });
2191
2196
  }
2192
2197
  return true;
2198
+ case "pi-web-ui:quit": {
2199
+ this.emit({
2200
+ type: "notice",
2201
+ level: "info",
2202
+ text: "正在退出 pi-web-ui… supervisor 将自动重启服务",
2203
+ });
2204
+ setTimeout(() => {
2205
+ const didSchedule = this.onQuit?.() ?? false;
2206
+ if (!didSchedule) {
2207
+ setTimeout(() => process.exit(0), 100);
2208
+ }
2209
+ }, 300);
2210
+ return true;
2211
+ }
2193
2212
  case "help":
2194
2213
  case "copy":
2195
2214
  // Client-side UI actions — the client handles them before sending;
@@ -4349,6 +4368,8 @@ export class AgentService {
4349
4368
  * self-update; returns whether the process will restart itself.
4350
4369
  */
4351
4370
  onUpdateReady = undefined;
4371
+ /** Set by index.ts: called when /pi-web-ui:quit is invoked. */
4372
+ onQuit = undefined;
4352
4373
  constructor(cwd, stateFile) {
4353
4374
  this.cwd = cwd;
4354
4375
  this.stateStore = new ClientStateStore(stateFile);
@@ -4394,8 +4415,9 @@ export class AgentService {
4394
4415
  }
4395
4416
  }
4396
4417
  cs.attachSink(send);
4397
- // Forward the update hook (set once by index.ts) to every session.
4418
+ // Forward hooks (set once by index.ts) to every session.
4398
4419
  cs.onUpdateReady = this.onUpdateReady;
4420
+ cs.onQuit = this.onQuit;
4399
4421
  return cs;
4400
4422
  }
4401
4423
  /** Remove a socket from a client's broadcast set (called on socket close). */
@@ -189,6 +189,26 @@ function scheduleUpdateRestart() {
189
189
  return true;
190
190
  }
191
191
  service.onUpdateReady = scheduleUpdateRestart;
192
+ function scheduleQuit() {
193
+ const isLaunchd = process.platform === "darwin" && process.ppid === 1;
194
+ const isSystemd = process.platform === "linux" && !!process.env.INVOCATION_ID;
195
+ const inDocker = existsSync("/.dockerenv");
196
+ if (isLaunchd || isSystemd || inDocker) {
197
+ setTimeout(() => {
198
+ console.log("pi-web-ui:quit — shutting down (supervisor will restart)…");
199
+ if (isSystemd)
200
+ process.exit(3);
201
+ void shutdown();
202
+ }, 300);
203
+ return true;
204
+ }
205
+ setTimeout(() => {
206
+ console.log("pi-web-ui:quit — shutting down (restart to reload)…");
207
+ void shutdown();
208
+ }, 300);
209
+ return true;
210
+ }
211
+ service.onQuit = scheduleQuit;
192
212
  wss.on("connection", (ws) => {
193
213
  let clientId = null;
194
214
  let closed = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-web-ui",
3
- "version": "0.20.0",
3
+ "version": "0.20.1",
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",