pi-web-ui 0.19.1 → 0.19.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.
@@ -202,6 +202,26 @@ function looksLikeText(buf) {
202
202
  }
203
203
  return control / Math.max(text.length, 1) < 0.02;
204
204
  }
205
+ /** Decode bytes: strict UTF-8 first, falling back to GBK (Windows legacy
206
+ * Chinese files), then latin1 as a last resort — so previews and inline
207
+ * attachments never show mojibake for GBK/GB2312 encoded files. */
208
+ function decodeText(buf) {
209
+ try {
210
+ return new TextDecoder("utf-8", { fatal: true }).decode(buf);
211
+ }
212
+ catch {
213
+ try {
214
+ return new TextDecoder("gbk").decode(buf);
215
+ }
216
+ catch {
217
+ return buf.toString("latin1");
218
+ }
219
+ }
220
+ }
221
+ /** Windows persona appendix: legacy Chinese files are often GBK/GB2312 — read
222
+ * them via the terminal with the right encoding, never paste mojibake into
223
+ * reasoning/answers. Appended to the SDK system prompt on win32 only. */
224
+ const WINDOWS_GBK_PERSONA = `You are a coding agent running on Windows. 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.`;
205
225
  /**
206
226
  * Cheap per-message discriminator for the serialization cache key. Persisted
207
227
  * message content never changes, so this is stable across snapshots, while
@@ -882,6 +902,16 @@ export class ClientSession {
882
902
  const services = await createAgentSessionServices({
883
903
  cwd: effectiveCwd,
884
904
  modelRuntime: this.sharedModelRuntime,
905
+ ...(process.platform === "win32"
906
+ ? {
907
+ // Windows 上很多老中文文件(.html/.txt/.md/.log、导出文档)是
908
+ // GBK/GB2312 编码,read 工具按 UTF-8 读会乱码——注入 persona 让模型
909
+ // 改用终端按 GBK 读,且绝不把乱码贴进推理/回答。
910
+ resourceLoaderOptions: {
911
+ systemPromptOverride: (base) => base ? `${base}\n\n${WINDOWS_GBK_PERSONA}` : WINDOWS_GBK_PERSONA,
912
+ },
913
+ }
914
+ : {}),
885
915
  });
886
916
  return {
887
917
  ...(await createAgentSessionFromServices({ services, sessionManager })),
@@ -2211,7 +2241,7 @@ export class ClientSession {
2211
2241
  content: [
2212
2242
  {
2213
2243
  type: "text",
2214
- text: `\n<file path="${wirePath}">\n\`\`\`\n${buf.toString("utf8")}\n\`\`\`\n</file>`,
2244
+ text: `\n<file path="${wirePath}">\n\`\`\`\n${decodeText(buf)}\n\`\`\`\n</file>`,
2215
2245
  },
2216
2246
  ],
2217
2247
  display: true,
@@ -2344,7 +2374,7 @@ export class ClientSession {
2344
2374
  content: [
2345
2375
  {
2346
2376
  type: "text",
2347
- text: `\n<file path="${rel}">\n\`\`\`\n${buf.toString("utf8")}\n\`\`\`\n</file>`,
2377
+ text: `\n<file path="${rel}">\n\`\`\`\n${decodeText(buf)}\n\`\`\`\n</file>`,
2348
2378
  },
2349
2379
  ],
2350
2380
  display: true,
@@ -2396,7 +2426,7 @@ export class ClientSession {
2396
2426
  out.push(makeReference());
2397
2427
  continue;
2398
2428
  }
2399
- const parts = buf.toString("utf8").split("\n");
2429
+ const parts = decodeText(buf).split("\n");
2400
2430
  // A trailing newline yields an empty phantom line — drop it so line
2401
2431
  // numbers match the preview panel.
2402
2432
  if (parts.length > 0 && parts[parts.length - 1] === "")
@@ -2971,7 +3001,7 @@ export class ClientSession {
2971
3001
  type: "file_content",
2972
3002
  path: rel,
2973
3003
  name,
2974
- text: data.toString("utf8"),
3004
+ text: decodeText(data),
2975
3005
  truncated: bytesRead < stat.size,
2976
3006
  binary: false,
2977
3007
  kind: "text",
package/package.json CHANGED
@@ -1,87 +1,87 @@
1
- {
2
- "name": "pi-web-ui",
3
- "version": "0.19.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
- "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
- "typebox": "^1.3.14",
69
- "ws": "^8.18.0"
70
- },
71
- "devDependencies": {
72
- "@types/express": "^4.17.21",
73
- "@types/node": "^22.10.0",
74
- "@types/react": "^18.3.12",
75
- "@types/react-dom": "^18.3.1",
76
- "@types/ws": "^8.5.13",
77
- "@vitejs/plugin-react": "^4.3.4",
78
- "concurrently": "^9.1.0",
79
- "playwright-core": "^1.62.1",
80
- "tsx": "^4.19.2",
81
- "typescript": "^5.7.2",
82
- "vite": "^6.0.3"
83
- },
84
- "allowScripts": {
85
- "node-pty@1.1.0": true
86
- }
87
- }
1
+ {
2
+ "name": "pi-web-ui",
3
+ "version": "0.19.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
+ "typebox": "^1.3.14",
69
+ "ws": "^8.18.0"
70
+ },
71
+ "devDependencies": {
72
+ "@types/express": "^4.17.21",
73
+ "@types/node": "^22.10.0",
74
+ "@types/react": "^18.3.12",
75
+ "@types/react-dom": "^18.3.1",
76
+ "@types/ws": "^8.5.13",
77
+ "@vitejs/plugin-react": "^4.3.4",
78
+ "concurrently": "^9.1.0",
79
+ "playwright-core": "^1.62.1",
80
+ "tsx": "^4.19.2",
81
+ "typescript": "^5.7.2",
82
+ "vite": "^6.0.3"
83
+ },
84
+ "allowScripts": {
85
+ "node-pty@1.1.0": true
86
+ }
87
+ }