pi-web-ui 0.11.0 → 0.11.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/bin/pi-web-ui.mjs CHANGED
@@ -26,6 +26,7 @@ import { spawnSync } from "node:child_process";
26
26
  import { get as httpGet } from "node:http";
27
27
  import {
28
28
  chmodSync,
29
+ copyFileSync,
29
30
  existsSync,
30
31
  mkdirSync,
31
32
  realpathSync,
@@ -292,10 +293,21 @@ function winTaskExists(name) {
292
293
  // 桌面快捷方式(server shortcut)
293
294
  // ---------------------------------------------------------------------------
294
295
 
295
- const SHORTCUT_LNK_NAME = "pi-web-ui 启动.lnk"; // Windows 桌面快捷方式
296
- const SHORTCUT_MAC_NAME = "pi-web-ui 启动.command"; // macOS 双击启动器
296
+ const SHORTCUT_LNK_NAME = "pi-web-ui.lnk"; // Windows 桌面快捷方式
297
+ const SHORTCUT_MAC_NAME = "pi-web-ui.command"; // macOS 双击启动器
297
298
  const SHORTCUT_LINUX_NAME = "pi-web-ui.desktop"; // Linux 桌面图标
298
299
 
300
+ /** 快捷方式图标(品牌 .ico,随包发布;.lnk / .desktop 指向它)。 */
301
+ const APP_ICO_NAME = "pi-web-ui.ico"; // 复制到用户目录后的稳定文件名
302
+ const APP_ICO_SOURCE = join(BIN_DIR, "..", "web", "public", "icon.ico"); // 包内品牌图标源文件
303
+ /** Branded SVG logo (source of truth: web/public/favicon.svg) — used on Linux. */
304
+ const APP_SVG_PACKAGE = join(BIN_DIR, "..", "web", "public", "favicon.svg");
305
+
306
+ /** Windows: per-user copy of the branded .ico (stable path for the .lnk icon). */
307
+ function winIcoPath() {
308
+ return join(winServiceDir(), APP_ICO_NAME);
309
+ }
310
+
299
311
  /** Full path to Windows PowerShell 5.1. */
300
312
  function winPowershell() {
301
313
  return join(
@@ -442,7 +454,12 @@ function installWinShortcut(opts) {
442
454
  }
443
455
  mkdirSync(dirname(ps1Path), { recursive: true });
444
456
  writeFileSync(ps1Path, "\uFEFF" + ps1, "utf8"); // PS 5.1 需要 BOM
445
- const node = realNode();
457
+ // 把品牌图标准备好:复制到用户目录(.lnk 图标指向稳定路径)
458
+ if (existsSync(APP_ICO_SOURCE)) {
459
+ copyFileSync(APP_ICO_SOURCE, winIcoPath());
460
+ } else {
461
+ console.log(`⚠ 未找到品牌图标 ${APP_ICO_SOURCE},快捷方式将使用默认图标`);
462
+ }
446
463
  const powershell = winPowershell();
447
464
  const ps = [
448
465
  "$ErrorActionPreference = 'Stop'",
@@ -453,7 +470,7 @@ function installWinShortcut(opts) {
453
470
  `$lnk.Arguments = '-NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File ' + ${psQuote('"' + ps1Path + '"')}`,
454
471
  `$lnk.WorkingDirectory = ${psQuote(cwd)}`,
455
472
  "$lnk.Description = 'pi-web-ui — 双击启动服务并打开浏览器'",
456
- `$lnk.IconLocation = ${psQuote(node)} + ',0'`,
473
+ `$lnk.IconLocation = ${psQuote(winIcoPath())} + ',0'`,
457
474
  "$lnk.Save()",
458
475
  `Write-Output (Join-Path $desktop ${psQuote(SHORTCUT_LNK_NAME)})`,
459
476
  ].join("\r\n");
@@ -584,13 +601,17 @@ function installLinuxShortcut(opts) {
584
601
  const scriptDir = join(homedir(), ".local", "share", "pi-web-ui");
585
602
  const scriptPath = join(scriptDir, `${name}-start.sh`);
586
603
  const desktopPath = join(homedir(), "Desktop", SHORTCUT_LINUX_NAME);
604
+ const icoPath = join(scriptDir, APP_ICO_NAME); // 备用;优先 SVG
605
+ const svgPath = join(scriptDir, "pi-web-ui.svg");
587
606
  const script = buildLinuxStartScript(name, url);
607
+ const desktopIcon = existsSync(APP_SVG_PACKAGE) ? svgPath : APP_ICO_NAME;
588
608
  const desktop = `[Desktop Entry]
589
609
  Version=1.0
590
610
  Type=Application
591
611
  Name=pi-web-ui
592
612
  Comment=启动 pi-web-ui 服务并打开浏览器
593
613
  Exec=${shQuote(scriptPath)}
614
+ Icon=${shQuote(desktopIcon)}
594
615
  Terminal=false
595
616
  Categories=Network;WebBrowser;
596
617
  `;
@@ -600,6 +621,9 @@ Categories=Network;WebBrowser;
600
621
  return;
601
622
  }
602
623
  mkdirSync(scriptDir, { recursive: true });
624
+ // 品牌图标(缺失时跳过,桌面自动回退默认图标)
625
+ if (existsSync(APP_SVG_PACKAGE)) copyFileSync(APP_SVG_PACKAGE, svgPath);
626
+ else if (existsSync(APP_ICO_SOURCE)) copyFileSync(APP_ICO_SOURCE, icoPath);
603
627
  writeFileSync(scriptPath, script);
604
628
  chmodSync(scriptPath, 0o755);
605
629
  writeFileSync(desktopPath, desktop);
@@ -618,7 +642,7 @@ Categories=Network;WebBrowser;
618
642
  /** Remove desktop shortcut artifacts created by `server shortcut`. */
619
643
  function removeShortcut(name) {
620
644
  if (isWin) {
621
- for (const f of [winShortcutPs1Path(name), winPidFilePath(name)]) {
645
+ for (const f of [winShortcutPs1Path(name), winPidFilePath(name), winIcoPath()]) {
622
646
  if (existsSync(f)) rmSync(f);
623
647
  }
624
648
  spawnSync(
package/package.json CHANGED
@@ -1,85 +1,86 @@
1
- {
2
- "name": "pi-web-ui",
3
- "version": "0.11.0",
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
- "license": "MIT",
6
- "type": "module",
7
- "bin": {
8
- "pi-web-ui": "bin/pi-web-ui.mjs"
9
- },
10
- "main": "dist/server/index.js",
11
- "files": [
12
- "bin/",
13
- "dist/",
14
- "web/dist/",
15
- "deploy/",
16
- "extensions/",
17
- "README.md",
18
- "LICENSE"
19
- ],
20
- "keywords": [
21
- "pi",
22
- "pi-package",
23
- "coding-agent",
24
- "ai",
25
- "chat",
26
- "web-ui",
27
- "terminal",
28
- "llm"
29
- ],
30
- "repository": {
31
- "type": "git",
32
- "url": "git+https://github.com/xing-shuyin/pi-web-ui.git"
33
- },
34
- "pi": {
35
- "extensions": [
36
- "./extensions"
37
- ]
38
- },
39
- "engines": {
40
- "node": ">=22.19.0"
41
- },
42
- "scripts": {
43
- "prepublishOnly": "npm run build",
44
- "dev": "concurrently -k -n server,web -c blue,green \"npm:dev:server\" \"npm:dev:web\"",
45
- "dev:server": "node --watch --import tsx server/index.ts",
46
- "dev:web": "vite --config web/vite.config.ts",
47
- "build": "npm run build:web && npm run build:server",
48
- "build:web": "vite build --config web/vite.config.ts",
49
- "build:server": "tsc -p tsconfig.server.json",
50
- "typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit",
51
- "test:freeze": "node freeze-test.mjs",
52
- "start": "node dist/server/index.js"
53
- },
54
- "dependencies": {
55
- "@earendil-works/pi-coding-agent": "^0.83.0",
56
- "@xterm/addon-fit": "^0.11.0",
57
- "@xterm/xterm": "^6.0.0",
58
- "express": "^4.21.2",
59
- "highlight.js": "^11.10.0",
60
- "node-pty": "^1.1.0",
61
- "react": "^18.3.1",
62
- "react-dom": "^18.3.1",
63
- "react-icons": "^5.7.0",
64
- "react-markdown": "^9.0.1",
65
- "rehype-highlight": "^7.0.1",
66
- "remark-gfm": "^4.0.0",
67
- "ws": "^8.18.0"
68
- },
69
- "devDependencies": {
70
- "@types/express": "^4.17.21",
71
- "@types/node": "^22.10.0",
72
- "@types/react": "^18.3.12",
73
- "@types/react-dom": "^18.3.1",
74
- "@types/ws": "^8.5.13",
75
- "@vitejs/plugin-react": "^4.3.4",
76
- "concurrently": "^9.1.0",
77
- "playwright-core": "^1.62.1",
78
- "tsx": "^4.19.2",
79
- "typescript": "^5.7.2",
80
- "vite": "^6.0.3"
81
- },
82
- "allowScripts": {
83
- "node-pty@1.1.0": true
84
- }
85
- }
1
+ {
2
+ "name": "pi-web-ui",
3
+ "version": "0.11.2",
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
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "pi-web-ui": "bin/pi-web-ui.mjs"
9
+ },
10
+ "main": "dist/server/index.js",
11
+ "files": [
12
+ "bin/",
13
+ "dist/",
14
+ "web/dist/",
15
+ "web/public/",
16
+ "deploy/",
17
+ "extensions/",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "keywords": [
22
+ "pi",
23
+ "pi-package",
24
+ "coding-agent",
25
+ "ai",
26
+ "chat",
27
+ "web-ui",
28
+ "terminal",
29
+ "llm"
30
+ ],
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/xing-shuyin/pi-web-ui.git"
34
+ },
35
+ "pi": {
36
+ "extensions": [
37
+ "./extensions"
38
+ ]
39
+ },
40
+ "engines": {
41
+ "node": ">=22.19.0"
42
+ },
43
+ "scripts": {
44
+ "prepublishOnly": "npm run build",
45
+ "dev": "concurrently -k -n server,web -c blue,green \"npm:dev:server\" \"npm:dev:web\"",
46
+ "dev:server": "node --watch --import tsx server/index.ts",
47
+ "dev:web": "vite --config web/vite.config.ts",
48
+ "build": "npm run build:web && npm run build:server",
49
+ "build:web": "vite build --config web/vite.config.ts",
50
+ "build:server": "tsc -p tsconfig.server.json",
51
+ "typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit",
52
+ "test:freeze": "node freeze-test.mjs",
53
+ "start": "node dist/server/index.js"
54
+ },
55
+ "dependencies": {
56
+ "@earendil-works/pi-coding-agent": "^0.83.0",
57
+ "@xterm/addon-fit": "^0.11.0",
58
+ "@xterm/xterm": "^6.0.0",
59
+ "express": "^4.21.2",
60
+ "highlight.js": "^11.10.0",
61
+ "node-pty": "^1.1.0",
62
+ "react": "^18.3.1",
63
+ "react-dom": "^18.3.1",
64
+ "react-icons": "^5.7.0",
65
+ "react-markdown": "^9.0.1",
66
+ "rehype-highlight": "^7.0.1",
67
+ "remark-gfm": "^4.0.0",
68
+ "ws": "^8.18.0"
69
+ },
70
+ "devDependencies": {
71
+ "@types/express": "^4.17.21",
72
+ "@types/node": "^22.10.0",
73
+ "@types/react": "^18.3.12",
74
+ "@types/react-dom": "^18.3.1",
75
+ "@types/ws": "^8.5.13",
76
+ "@vitejs/plugin-react": "^4.3.4",
77
+ "concurrently": "^9.1.0",
78
+ "playwright-core": "^1.62.1",
79
+ "tsx": "^4.19.2",
80
+ "typescript": "^5.7.2",
81
+ "vite": "^6.0.3"
82
+ },
83
+ "allowScripts": {
84
+ "node-pty@1.1.0": true
85
+ }
86
+ }
Binary file
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
2
+ <!-- pi symbol favicon: violet rounded square + white π (drawn as paths,
3
+ no font dependency) -->
4
+ <rect width="64" height="64" rx="14" fill="#8b5cf6"/>
5
+ <rect x="14" y="17" width="36" height="6.5" rx="3.25" fill="#ffffff"/>
6
+ <rect x="17.5" y="23.5" width="6.5" height="25" rx="3.25" fill="#ffffff"/>
7
+ <rect x="40" y="23.5" width="6.5" height="25" rx="3.25" fill="#ffffff"/>
8
+ </svg>
Binary file