pi-web-ui 0.62.1 → 0.63.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.
Files changed (56) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +504 -497
  3. package/README.zh-CN.md +427 -422
  4. package/bin/pi-web-ui.mjs +1809 -1881
  5. package/deploy/com.xingshuyin.pi-web-ui.plist +48 -48
  6. package/deploy/nginx-subpath.conf +88 -88
  7. package/deploy/pi-web-ui-task.xml +54 -54
  8. package/deploy/pi-web-ui.service +31 -31
  9. package/dist/server/agent-service.js +318 -88
  10. package/dist/server/attachments.js +37 -28
  11. package/dist/server/bg-servers.js +6 -1
  12. package/dist/server/client-state.js +15 -7
  13. package/dist/server/control-socket.js +1 -5
  14. package/dist/server/dsh/dsh-agent-service.js +454 -118
  15. package/dist/server/dsh/dsh-client.js +1 -3
  16. package/dist/server/dsh/dsh-sessions.js +4 -14
  17. package/dist/server/dsh/runtime/cordis.yml +1 -1
  18. package/dist/server/dsh/runtime/goal-rpc.mjs +645 -662
  19. package/dist/server/dsh/runtime/launcher.mjs +8 -18
  20. package/dist/server/dsh/runtime/override.patch.yml +9 -9
  21. package/dist/server/dsh/runtime/runtime-root.mjs +7 -11
  22. package/dist/server/ensure-bash.js +2 -5
  23. package/dist/server/files-service.js +42 -36
  24. package/dist/server/goal-service.js +59 -30
  25. package/dist/server/index.js +17 -10
  26. package/dist/server/mcp-bridge.js +11 -5
  27. package/dist/server/model-admin.js +78 -72
  28. package/dist/server/plugin-facilities.js +2 -4
  29. package/dist/server/plugin-updater.js +1 -1
  30. package/dist/server/plugins.js +26 -8
  31. package/dist/server/process-utils.js +4 -4
  32. package/dist/server/protocol-version.js +1 -1
  33. package/dist/server/scm.js +27 -21
  34. package/dist/server/serialize.js +1 -3
  35. package/dist/server/settings-service.js +63 -21
  36. package/dist/server/slash-commands.js +29 -3
  37. package/dist/server/subagent-templates.js +249 -0
  38. package/dist/server/subagents.js +150 -0
  39. package/dist/server/terminals.js +101 -40
  40. package/dist/server/text-sniff.js +4 -24
  41. package/dist/server/update-check.js +2 -4
  42. package/dist/server/uploads.js +1 -3
  43. package/dist/server/vision-bridge.js +2 -7
  44. package/dist/server/wait-subscription-scan.js +102 -21
  45. package/dist/server/webui-context.js +1 -1
  46. package/extensions/webui.ts +190 -192
  47. package/package.json +109 -103
  48. package/web/dist/assets/TerminalPanel-DwutHqgi.js +2 -0
  49. package/web/dist/assets/index-CJoS1bmZ.js +323 -0
  50. package/web/dist/assets/index-CrDJOsa5.css +10 -0
  51. package/web/dist/favicon.svg +8 -8
  52. package/web/dist/index.html +15 -15
  53. package/web/public/favicon.svg +8 -8
  54. package/web/dist/assets/TerminalPanel-CrduzEDu.js +0 -2
  55. package/web/dist/assets/index-ORTpR6ZQ.css +0 -10
  56. package/web/dist/assets/index-eRkSgiu6.js +0 -321
package/package.json CHANGED
@@ -1,103 +1,109 @@
1
- {
2
- "name": "pi-web-ui",
3
- "version": "0.62.1",
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
- "author": {
7
- "name": "xingshuyin",
8
- "email": "xingshuyin@users.noreply.github.com"
9
- },
10
- "type": "module",
11
- "bin": {
12
- "pi-web-ui": "bin/pi-web-ui.mjs"
13
- },
14
- "main": "bin/pi-web-ui.mjs",
15
- "files": [
16
- "bin/",
17
- "dist/",
18
- "web/dist/",
19
- "web/public/",
20
- "themes/",
21
- "deploy/",
22
- "extensions/",
23
- "README.md",
24
- "LICENSE"
25
- ],
26
- "keywords": [
27
- "pi",
28
- "pi-package",
29
- "coding-agent",
30
- "ai",
31
- "chat",
32
- "web-ui",
33
- "terminal",
34
- "llm"
35
- ],
36
- "repository": {
37
- "type": "git",
38
- "url": "git+https://github.com/xing-shuyin/pi-web-ui.git"
39
- },
40
- "pi": {
41
- "extensions": [
42
- "./extensions"
43
- ]
44
- },
45
- "engines": {
46
- "node": ">=22.19.0"
47
- },
48
- "scripts": {
49
- "prepublishOnly": "npm run build",
50
- "dev": "concurrently -k -n server,web -c blue,green \"npm:dev:server\" \"npm:dev:web\"",
51
- "dev:server": "cross-env PI_WEB_PORT=8788 PI_WEB_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173 node --watch --import tsx server/index.ts",
52
- "dev:web": "vite --config web/vite.config.ts",
53
- "build": "npm run build:web && npm run build:server && npm run build:dsh-runtime",
54
- "build:web": "vite build --config web/vite.config.ts",
55
- "build:server": "tsc -p tsconfig.server.json",
56
- "build:dsh-runtime": "node scripts/copy-dsh-runtime.mjs",
57
- "typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
58
- "test": "vitest run",
59
- "test:unit": "vitest run",
60
- "test:smoke": "node tests/run-smoke.mjs",
61
- "check:protocol": "node scripts/check-protocol-sync.mjs",
62
- "test:freeze": "node tests/freeze-test.mjs",
63
- "start": "node dist/server/index.js"
64
- },
65
- "dependencies": {
66
- "@deepseek-ai/dsh-sdk-jsonrpc-server": "^0.1.1-rc.2",
67
- "@deepseek-ai/dsh-sdk-protocol": "^0.1.1-rc.2",
68
- "@earendil-works/pi-coding-agent": "^0.84.4",
69
- "@xterm/addon-fit": "^0.11.0",
70
- "@xterm/xterm": "^6.0.0",
71
- "compression": "^1.8.1",
72
- "express": "^4.21.2",
73
- "highlight.js": "^11.10.0",
74
- "node-pty": "^1.1.0",
75
- "react": "^18.3.1",
76
- "react-dom": "^18.3.1",
77
- "react-icons": "^5.7.0",
78
- "react-markdown": "^9.0.1",
79
- "rehype-highlight": "^7.0.1",
80
- "remark-gfm": "^4.0.0",
81
- "typebox": "^1.3.14",
82
- "ws": "^8.18.0"
83
- },
84
- "devDependencies": {
85
- "@types/compression": "^1.8.1",
86
- "@types/express": "^4.17.21",
87
- "@types/node": "^22.10.0",
88
- "@types/react": "^18.3.12",
89
- "@types/react-dom": "^18.3.1",
90
- "@types/ws": "^8.5.13",
91
- "@vitejs/plugin-react": "^4.3.4",
92
- "concurrently": "^9.1.0",
93
- "cross-env": "^10.1.0",
94
- "playwright-core": "^1.62.1",
95
- "tsx": "^4.19.2",
96
- "typescript": "^5.7.2",
97
- "vite": "^6.0.3",
98
- "vitest": "^4.1.11"
99
- },
100
- "allowScripts": {
101
- "node-pty@1.1.0": true
102
- }
103
- }
1
+ {
2
+ "name": "pi-web-ui",
3
+ "version": "0.63.1",
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
+ "author": {
7
+ "name": "xingshuyin",
8
+ "email": "xingshuyin@users.noreply.github.com"
9
+ },
10
+ "type": "module",
11
+ "bin": {
12
+ "pi-web-ui": "bin/pi-web-ui.mjs"
13
+ },
14
+ "main": "bin/pi-web-ui.mjs",
15
+ "files": [
16
+ "bin/",
17
+ "dist/",
18
+ "web/dist/",
19
+ "web/public/",
20
+ "themes/",
21
+ "deploy/",
22
+ "extensions/",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "keywords": [
27
+ "pi",
28
+ "pi-package",
29
+ "coding-agent",
30
+ "ai",
31
+ "chat",
32
+ "web-ui",
33
+ "terminal",
34
+ "llm"
35
+ ],
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/xing-shuyin/pi-web-ui.git"
39
+ },
40
+ "pi": {
41
+ "extensions": [
42
+ "./extensions"
43
+ ]
44
+ },
45
+ "engines": {
46
+ "node": ">=22.19.0"
47
+ },
48
+ "scripts": {
49
+ "prepublishOnly": "npm run build",
50
+ "dev": "concurrently -k -n server,web -c blue,green \"npm:dev:server\" \"npm:dev:web\"",
51
+ "dev:server": "cross-env PI_WEB_PORT=8788 PI_WEB_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173 node --watch --import tsx server/index.ts",
52
+ "dev:web": "vite --config web/vite.config.ts",
53
+ "build": "npm run build:web && npm run build:server && npm run build:dsh-runtime",
54
+ "build:web": "vite build --config web/vite.config.ts",
55
+ "build:server": "tsc -p tsconfig.server.json",
56
+ "build:dsh-runtime": "node scripts/copy-dsh-runtime.mjs",
57
+ "typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
58
+ "test": "vitest run",
59
+ "test:unit": "vitest run",
60
+ "test:smoke": "node tests/run-smoke.mjs",
61
+ "check:protocol": "node scripts/check-protocol-sync.mjs",
62
+ "test:freeze": "node tests/freeze-test.mjs",
63
+ "start": "node dist/server/index.js",
64
+ "format": "prettier --write server/ web/src/ extensions/ scripts/ bin/ tests/*.mjs tests/unit/ *.mjs",
65
+ "format:check": "prettier --check server/ web/src/ extensions/ scripts/ bin/ tests/*.mjs tests/unit/ *.mjs",
66
+ "lint": "oxlint server/ web/src/ extensions/ scripts/",
67
+ "lint:fix": "oxlint --fix server/ web/src/ extensions/ scripts/"
68
+ },
69
+ "dependencies": {
70
+ "@deepseek-ai/dsh-sdk-jsonrpc-server": "^0.1.1-rc.2",
71
+ "@deepseek-ai/dsh-sdk-protocol": "^0.1.1-rc.2",
72
+ "@earendil-works/pi-coding-agent": "^0.84.4",
73
+ "@xterm/addon-fit": "^0.11.0",
74
+ "@xterm/xterm": "^6.0.0",
75
+ "compression": "^1.8.1",
76
+ "express": "^4.21.2",
77
+ "highlight.js": "^11.10.0",
78
+ "node-pty": "^1.1.0",
79
+ "react": "^18.3.1",
80
+ "react-dom": "^18.3.1",
81
+ "react-icons": "^5.7.0",
82
+ "react-markdown": "^9.0.1",
83
+ "rehype-highlight": "^7.0.1",
84
+ "remark-gfm": "^4.0.0",
85
+ "typebox": "^1.3.14",
86
+ "ws": "^8.18.0"
87
+ },
88
+ "devDependencies": {
89
+ "@types/compression": "^1.8.1",
90
+ "@types/express": "^4.17.21",
91
+ "@types/node": "^22.10.0",
92
+ "@types/react": "^18.3.12",
93
+ "@types/react-dom": "^18.3.1",
94
+ "@types/ws": "^8.5.13",
95
+ "@vitejs/plugin-react": "^4.3.4",
96
+ "concurrently": "^9.1.0",
97
+ "cross-env": "^10.1.0",
98
+ "oxlint": "^1.81.0",
99
+ "playwright-core": "^1.62.1",
100
+ "prettier": "^3.9.6",
101
+ "tsx": "^4.19.2",
102
+ "typescript": "^5.7.2",
103
+ "vite": "^6.0.3",
104
+ "vitest": "^4.1.11"
105
+ },
106
+ "allowScripts": {
107
+ "node-pty@1.1.0": true
108
+ }
109
+ }
@@ -0,0 +1,2 @@
1
+ import{a as c,j as s}from"./markdown-DRBrS2Nf.js";import{u as L,b as I,T as K,a as J,F as X,c as B,d as Q,e as U,f as V,g as W,h as Y,i as Z,r as ee}from"./index-CJoS1bmZ.js";import{D as se,o as ne}from"./xterm-D1D2FVe3.js";import"./react-C9ovnpIm.js";function te({conversationId:n,terminalId:r,command:x,cwd:t,title:w,active:u,send:h,register:j}){const T=c.useRef(null),v=c.useRef(null),{locale:b}=L(),g=c.useRef(b);g.current=b;const o=x?JSON.stringify(x):"";return c.useEffect(()=>{const m=T.current;if(!m)return;const a=new se({theme:I(),fontFamily:'"SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace',fontSize:13,cursorBlink:!0,scrollback:8e3}),y=new ne;a.loadAddon(y),a.open(m),v.current={term:a,fit:y},u&&a.focus();const p=()=>{a.options.theme=I()};window.addEventListener(K,p),a.attachCustomKeyEventHandler(d=>{var R;if(d.type!=="keydown")return!0;const F=(R=d.key)==null?void 0:R.toLowerCase();if((d.ctrlKey||d.metaKey)&&F==="v")return!1;if(d.ctrlKey&&!d.shiftKey&&!d.altKey&&F==="c"&&a.hasSelection()){const C=a.textarea;return C&&(C.value=a.getSelection(),C.select()),!1}return!0});const k=j(n,r,{write:d=>a.write(d),dispose:()=>a.dispose()}),_=()=>{try{y.fit(),h({type:"terminal_resize",terminalId:r,conversationId:n,cols:a.cols,rows:a.rows})}catch{}},S=requestAnimationFrame(()=>{try{y.fit()}catch{}h(x?{type:"run_command",terminalId:r,conversationId:n,command:x,cols:a.cols,rows:a.rows}:{type:"terminal_create",terminalId:r,title:w,locale:g.current,conversationId:n,cwd:t,cols:a.cols,rows:a.rows})}),E=a.onData(d=>{h({type:"terminal_input",terminalId:r,conversationId:n,data:d})});let N=null;return typeof ResizeObserver<"u"&&(N=new ResizeObserver(()=>{m.offsetWidth>0&&m.offsetHeight>0&&_()}),N.observe(m)),()=>{cancelAnimationFrame(S),E.dispose(),window.removeEventListener(K,p),N==null||N.disconnect(),k(),a.dispose(),v.current=null}},[n,r,o,h,j]),c.useEffect(()=>{if(!u)return;const m=requestAnimationFrame(()=>{const a=v.current;if(a){try{a.fit.fit(),h({type:"terminal_resize",terminalId:r,conversationId:n,cols:a.term.cols,rows:a.term.rows})}catch{}a.term.focus()}});return()=>cancelAnimationFrame(m)},[u]),s.jsx("div",{ref:T,className:`term-xterm ${u?"":"hidden"}`})}const O={name:"",command:"",cwd:"${pwd}"};function re({chat:n,send:r,terminal:x}){const t=J(),[w,u]=c.useState(null),[h,j]=c.useState(!1),[T,v]=c.useState(!1),[b,g]=c.useState(null),[o,m]=c.useState(O),[a,y]=c.useState(null),p=c.useRef(null),[k,_]=c.useState(!0);c.useEffect(()=>{n.terminals.length===0?u(null):n.terminals.some(e=>e.id===w)||u(n.terminals[n.terminals.length-1].id)},[n.terminals,w]),c.useEffect(()=>{n.terminalActiveId&&(u(n.terminalActiveId),j(!1))},[n.terminalActiveId]),c.useEffect(()=>()=>{p.current&&clearTimeout(p.current)},[]);const S=n.terminals.filter(e=>!e.agentBash),E=n.terminals.filter(e=>e.agentBash),N=e=>{var f;if(!n.ready)return;const l=ee(),i=n.activeConversationId||((f=n.state)==null?void 0:f.conversationId)||"";x.create({...e,id:l,conversationId:i,cols:e.cols??80,rows:e.rows??24,running:!0,exitCode:null}),u(l),j(!1)},d=()=>{var e;return N({title:t("terminalTitle",{n:S.length+1}),cwd:((e=n.state)==null?void 0:e.cwd)??""})},F=e=>{var f;const l=e.name||e.command,i=n.terminals.find(D=>D.title===l);if(i){x.restart(i.id),u(i.id),r({type:"run_command",terminalId:i.id,conversationId:i.conversationId,command:e,cols:80,rows:24});return}N({title:l,cwd:((f=n.state)==null?void 0:f.cwd)??"",command:e})},R=e=>{const l=n.terminals.find(i=>i.id===e);if(l&&r({type:"terminal_kill",terminalId:e,conversationId:l.conversationId}),x.close(e),w===e){const i=n.terminals.filter(f=>f.id!==e);u(i.length>0?i[i.length-1].id:null)}},C=e=>s.jsxs("div",{className:`term-tab ${e.id===w?"active":""}`,children:[s.jsxs("button",{type:"button",className:"term-tab-main",title:`${e.cwd}${e.command?`
2
+ > ${e.command.command}`:""}`,onClick:()=>{u(e.id),j(!1)},children:[s.jsx("span",{className:`term-tab-dot ${e.running?"run":"exit"}`}),s.jsxs("span",{className:"term-tab-title",children:[e.title,!e.running&&s.jsx("span",{className:"term-tab-exit",children:t("exited",{code:e.exitCode===null?"":` ${e.exitCode}`})})]})]}),s.jsx("button",{type:"button",className:"term-tab-close",title:t("closeTerminal"),onClick:()=>R(e.id),children:s.jsx(Z,{})})]},e.id),M=()=>{v(!0),g(null),m(O)},z=e=>{const l=n.commands[e];l&&(v(!1),g(e),m({name:l.name,command:l.command,cwd:l.cwd??""}))},A=()=>{v(!1),g(null)},$=()=>{const e=o.name.trim(),l=o.command.trim();if(!e||!l)return;const i=o.cwd.trim(),f={name:e,command:l,cwd:i||void 0},D=T?[...n.commands,f]:b!==null?n.commands.map((q,G)=>G===b?f:q):n.commands;r({type:"save_commands",commands:D}),A()},H=e=>{if(a===e){const l=n.commands.filter((i,f)=>f!==e);r({type:"save_commands",commands:l}),y(null),p.current&&clearTimeout(p.current)}else y(e),p.current&&clearTimeout(p.current),p.current=setTimeout(()=>y(null),2500)},P=T||b!==null;return s.jsxs("div",{className:"terminal-view",children:[s.jsxs("aside",{className:`term-side term-commands ${h?"open":""}`,children:[s.jsxs("div",{className:"panel-header",children:[s.jsx("span",{className:"panel-title",children:t("commands")}),s.jsxs("div",{className:"panel-header-actions",children:[s.jsx("button",{type:"button",className:"panel-refresh",title:t("rerun"),onClick:()=>r({type:"list_commands"}),children:s.jsx(X,{})}),s.jsx("button",{type:"button",className:"panel-new",title:t("newCommand"),onClick:M,children:s.jsx(B,{})})]})]}),s.jsx("div",{className:"panel-body",children:P?s.jsxs("div",{className:"cmd-form",children:[s.jsx("label",{htmlFor:"cmd-name",children:t("name")}),s.jsx("input",{id:"cmd-name",className:"cmd-input",value:o.name,placeholder:t("exampleName"),autoFocus:!0,onChange:e=>m({...o,name:e.target.value})}),s.jsx("label",{htmlFor:"cmd-command",children:t("command")}),s.jsx("input",{id:"cmd-command",className:"cmd-input",value:o.command,placeholder:t("exampleCommand"),onChange:e=>m({...o,command:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&$()}}),s.jsxs("label",{htmlFor:"cmd-cwd",children:[t("directory")," ",s.jsx("span",{className:"cmd-hint",children:t("cwdHint")})]}),s.jsx("input",{id:"cmd-cwd",className:"cmd-input",value:o.cwd,placeholder:"${pwd}",onChange:e=>m({...o,cwd:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&$()}}),s.jsxs("div",{className:"cmd-form-actions",children:[s.jsx("button",{type:"button",className:"btn",onClick:A,children:t("cancel")}),s.jsx("button",{type:"button",className:"btn primary",disabled:!o.name.trim()||!o.command.trim(),onClick:$,children:t("save")})]})]}):s.jsxs(s.Fragment,{children:[n.commands.length===0&&s.jsx("div",{className:"panel-empty",children:t("noCommands")}),n.commands.map((e,l)=>s.jsxs("div",{className:"cmd-item",children:[s.jsx("button",{type:"button",className:"cmd-run",title:t("clickToRun"),onClick:()=>F(e),children:s.jsx(Q,{})}),s.jsxs("button",{type:"button",className:"cmd-main",title:t("clickToRun"),onClick:()=>F(e),children:[s.jsx("span",{className:"cmd-name",children:e.name}),s.jsx("span",{className:"cmd-command",children:e.command}),e.cwd&&s.jsx("span",{className:"cmd-cwd",children:e.cwd})]}),s.jsx("button",{type:"button",className:"cmd-act",title:t("edit"),onClick:()=>z(l),children:s.jsx(U,{})}),s.jsx("button",{type:"button",className:`cmd-act del ${a===l?"confirm":""}`,title:t("delete"),onClick:()=>H(l),children:a===l?t("confirmQ"):s.jsx(V,{})})]},l))]})}),s.jsxs("div",{className:"term-tabs-block",children:[s.jsxs("div",{className:"panel-header",children:[s.jsx("span",{className:"panel-title",children:t("terminal")}),s.jsx("button",{type:"button",className:"panel-new",title:t("newTerminal"),onClick:d,children:s.jsx(B,{})})]}),s.jsxs("div",{className:"panel-body",children:[n.terminals.length===0&&s.jsx("div",{className:"panel-empty",children:t("noTerminal")}),S.map(C),E.length>0&&s.jsxs("div",{className:"term-folder",children:[s.jsxs("button",{type:"button",className:`term-folder-header ${k?"open":""}`,title:t("aiBashGroup"),onClick:()=>_(e=>!e),children:[s.jsx("span",{className:"term-folder-caret",children:k?"▾":"▸"}),s.jsx("span",{className:"term-folder-title",children:t("aiBashGroup")}),s.jsx("span",{className:"term-folder-count",children:E.length})]}),k&&s.jsx("div",{className:"term-folder-body",children:E.map(C)})]})]})]})]}),s.jsxs("div",{className:"term-main",children:[h&&s.jsx("div",{className:"drawer-backdrop",onClick:()=>j(!1)}),s.jsx("button",{type:"button",className:"term-side-toggle",title:t("commands"),onClick:()=>j(e=>!e),children:s.jsx(W,{})}),n.terminals.length===0?s.jsxs("div",{className:"term-empty",children:[s.jsx(Y,{className:"term-empty-icon"}),s.jsx("div",{className:"term-empty-title",children:t("builtinTerminal")}),s.jsx("div",{className:"term-empty-sub",children:t("termEmptySub")})]}):n.terminals.map(e=>s.jsx(te,{conversationId:e.conversationId,terminalId:e.id,command:e.command,cwd:e.cwd,title:e.title,active:e.id===w,send:r,register:x.register},`${e.conversationId}:${e.id}`))]})]})}export{re as TerminalPanel};