@qt4798/pi-web 0.10.5 → 0.10.6

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 (66) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +11 -11
  3. package/.next/build-manifest.json +2 -2
  4. package/.next/required-server-files.js +1 -1
  5. package/.next/required-server-files.json +1 -1
  6. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  7. package/.next/server/app/_global-error.html +1 -1
  8. package/.next/server/app/_global-error.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/server/app/_not-found.html +1 -1
  17. package/.next/server/app/_not-found.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  21. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  22. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  23. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  24. package/.next/server/app/api/agent/[id]/events/route.js +1 -1
  25. package/.next/server/app/api/agent/running/events/route.js +1 -1
  26. package/.next/server/app/api/files/[...path]/route.js +1 -1
  27. package/.next/server/app/api/sessions/[id]/context/route.js +1 -1
  28. package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
  29. package/.next/server/app/api/sessions/[id]/route.js +1 -1
  30. package/.next/server/app/api/subagents/transcript/route.js +1 -1
  31. package/.next/server/app/api/tasks/settings/route.js +1 -1
  32. package/.next/server/app/api/usage/route.js +1 -1
  33. package/.next/server/app/api/worktrees/route.js +1 -1
  34. package/.next/server/app/index.html +1 -1
  35. package/.next/server/app/index.rsc +3 -3
  36. package/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
  37. package/.next/server/app/index.segments/_full.segment.rsc +3 -3
  38. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  39. package/.next/server/app/index.segments/_index.segment.rsc +1 -1
  40. package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  41. package/.next/server/app/page.js +13 -13
  42. package/.next/server/app/page_client-reference-manifest.js +1 -1
  43. package/.next/server/app-paths-manifest.json +11 -11
  44. package/.next/server/chunks/1499.js +7 -7
  45. package/.next/server/chunks/4253.js +7 -7
  46. package/.next/server/chunks/5582.js +2 -2
  47. package/.next/server/chunks/6429.js +1 -1
  48. package/.next/server/chunks/7915.js +1 -1
  49. package/.next/server/functions-config-manifest.json +2 -10
  50. package/.next/server/middleware-build-manifest.js +1 -1
  51. package/.next/server/middleware.js +2 -2
  52. package/.next/server/pages/404.html +1 -1
  53. package/.next/server/pages/500.html +1 -1
  54. package/.next/static/chunks/6049-f3857747b04cfc1d.js +1 -0
  55. package/.next/static/chunks/app/page-ad0ed57b98b86121.js +47 -0
  56. package/.next/static/chunks/{main-e9857f44fcf8c636.js → main-425c48afc83a1949.js} +1 -1
  57. package/.next/trace +9 -9
  58. package/.next/trace-build +1 -1
  59. package/README.md +3 -0
  60. package/bin/pi-web-options.js +24 -1
  61. package/bin/pi-web.js +15 -9
  62. package/package.json +1 -1
  63. package/.next/static/chunks/266-afbb4abec8f065f2.js +0 -1
  64. package/.next/static/chunks/app/page-1f553bf2c117387b.js +0 -47
  65. /package/.next/static/{kWqylj4DXUQD6uvs2QXWr → nawYHsRT9tos_eI6-jhCH}/_buildManifest.js +0 -0
  66. /package/.next/static/{kWqylj4DXUQD6uvs2QXWr → nawYHsRT9tos_eI6-jhCH}/_ssgManifest.js +0 -0
package/.next/trace-build CHANGED
@@ -1 +1 @@
1
- [{"name":"run-webpack","duration":57803718,"timestamp":601173715570,"id":14,"parentId":1,"tags":{},"startTime":1787227488514,"traceId":"c4e8cdc81c758c63"},{"name":"run-typescript","duration":6646529,"timestamp":601231520535,"id":996,"parentId":1,"tags":{},"startTime":1787227546317,"traceId":"c4e8cdc81c758c63"},{"name":"static-check","duration":1254069,"timestamp":601238187460,"id":999,"parentId":1,"tags":{},"startTime":1787227552983,"traceId":"c4e8cdc81c758c63"},{"name":"static-generation","duration":1941657,"timestamp":601239800716,"id":1177,"parentId":1,"tags":{},"startTime":1787227554597,"traceId":"c4e8cdc81c758c63"},{"name":"collect-build-traces","duration":17784999,"timestamp":601239443458,"id":1174,"parentId":1,"tags":{},"startTime":1787227554239,"traceId":"c4e8cdc81c758c63"},{"name":"output-standalone","duration":2229931,"timestamp":601257234824,"id":1185,"parentId":1,"tags":{},"startTime":1787227572030,"traceId":"c4e8cdc81c758c63"},{"name":"telemetry-flush","duration":14,"timestamp":601259466326,"id":1188,"parentId":1,"tags":{},"startTime":1787227574262,"traceId":"c4e8cdc81c758c63"},{"name":"next-build","duration":86277123,"timestamp":601173189221,"id":1,"tags":{"buildMode":"default","version":"16.2.12","bundler":"webpack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1787227487987,"traceId":"c4e8cdc81c758c63"}]
1
+ [{"name":"run-webpack","duration":68112934,"timestamp":31817147685,"id":14,"parentId":1,"tags":{},"startTime":1787274921560,"traceId":"f10178ae678b2107"},{"name":"run-typescript","duration":13756892,"timestamp":31885263208,"id":1053,"parentId":1,"tags":{},"startTime":1787274989677,"traceId":"f10178ae678b2107"},{"name":"static-check","duration":3590039,"timestamp":31899050341,"id":1056,"parentId":1,"tags":{},"startTime":1787275003464,"traceId":"f10178ae678b2107"},{"name":"static-generation","duration":3514443,"timestamp":31903486412,"id":1234,"parentId":1,"tags":{},"startTime":1787275007900,"traceId":"f10178ae678b2107"},{"name":"collect-build-traces","duration":31283709,"timestamp":31902646163,"id":1231,"parentId":1,"tags":{},"startTime":1787275007060,"traceId":"f10178ae678b2107"},{"name":"output-standalone","duration":4038921,"timestamp":31933935674,"id":1242,"parentId":1,"tags":{},"startTime":1787275038350,"traceId":"f10178ae678b2107"},{"name":"telemetry-flush","duration":35,"timestamp":31937976617,"id":1245,"parentId":1,"tags":{},"startTime":1787275042391,"traceId":"f10178ae678b2107"},{"name":"next-build","duration":122263352,"timestamp":31815713305,"id":1,"tags":{"buildMode":"default","version":"16.2.12","bundler":"webpack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1787274920125,"traceId":"f10178ae678b2107"}]
package/README.md CHANGED
@@ -98,6 +98,8 @@ PI_WEB_NO_OPEN=1 pi-web # 后台服务不自动打开浏览器
98
98
 
99
99
  设置 `PI_WEB_PASSWORD` 后,所有网页接口和 API 端点都需要 HTTP Basic Auth 认证,用户名为 `pi`。不设或留空则禁用认证。
100
100
 
101
+ > 当监听地址超出本机(如默认的 `0.0.0.0`)而未设置 `PI_WEB_PASSWORD` 时,`pi-web` 会**拒绝启动**——裸奔在局域网意味着网内任何设备都能读取会话并执行 agent 命令。可信内网确需免密时,设置 `PI_WEB_ALLOW_INSECURE_LAN=1` 显式豁免(风险自负)。
102
+
101
103
  > Basic Auth 不加密传输中的密码。请勿将纯 HTTP 直接暴露到公网,通过可信反向代理启用 HTTPS 或使用可信 VPN 进行远程访问。
102
104
 
103
105
  ### 从源码运行
@@ -215,6 +217,7 @@ node bin/pi-web.js -H 127.0.0.1 -p 30141 --no-open
215
217
  | 变量 | 用途 |
216
218
  | --- | --- |
217
219
  | `PI_WEB_PASSWORD` | 启用 Basic Auth;用户名固定为 `pi`。 |
220
+ | `PI_WEB_ALLOW_INSECURE_LAN=1` | 非环回监听且未设密码时,豁免启动拒绝(仅限可信内网)。 |
218
221
  | `PI_WEB_ALLOWED_HOSTS` | 以逗号分隔的外部允许域名,例如 `piweb.example.com`。 |
219
222
  | `PI_CODING_AGENT_DIR` | 指向另一套 Pi 数据目录;默认使用 `~/.pi/agent`。 |
220
223
  | `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` | 为服务端模型/API 请求设置代理。 |
@@ -9,6 +9,29 @@ function isEnabled(value) {
9
9
  return typeof value === "string" && TRUE_VALUES.has(value.trim().toLowerCase());
10
10
  }
11
11
 
12
+ function isLoopbackHost(hostname) {
13
+ return hostname === "127.0.0.1" || hostname === "localhost" || hostname === "::1";
14
+ }
15
+
16
+ /**
17
+ * Decide how to handle a listener bound beyond loopback.
18
+ * Returns one of:
19
+ * - "loopback" : local-only, nothing to warn about
20
+ * - "warn-plaintext" : password set, but Basic Auth over HTTP is plaintext
21
+ * - "warn-insecure-lan" : explicit PI_WEB_ALLOW_INSECURE_LAN=1 override
22
+ * - "refuse" : no password and no override — must not start
23
+ *
24
+ * An unauthenticated LAN listener hands every device on the network full read
25
+ * access to sessions/files plus same-origin write access (agent prompts, task
26
+ * shell commands), so "refuse" is the safe default.
27
+ */
28
+ function assessLanExposure(hostname, env = process.env) {
29
+ if (isLoopbackHost(hostname)) return "loopback";
30
+ if (env.PI_WEB_PASSWORD) return "warn-plaintext";
31
+ if (isEnabled(env.PI_WEB_ALLOW_INSECURE_LAN)) return "warn-insecure-lan";
32
+ return "refuse";
33
+ }
34
+
12
35
  function parseLaunchOptions(args = process.argv.slice(2), env = process.env) {
13
36
  const { values: cliArgs } = parseArgs({
14
37
  args,
@@ -33,4 +56,4 @@ function parseLaunchOptions(args = process.argv.slice(2), env = process.env) {
33
56
  };
34
57
  }
35
58
 
36
- module.exports = { parseLaunchOptions };
59
+ module.exports = { parseLaunchOptions, assessLanExposure };
package/bin/pi-web.js CHANGED
@@ -8,7 +8,7 @@ const path = require("path");
8
8
  // eslint-disable-next-line @typescript-eslint/no-require-imports
9
9
  const fs = require("fs");
10
10
  // eslint-disable-next-line @typescript-eslint/no-require-imports
11
- const { parseLaunchOptions } = require("./pi-web-options");
11
+ const { parseLaunchOptions, assessLanExposure } = require("./pi-web-options");
12
12
 
13
13
  // Apply the undici CVE fix (formerly a postinstall hook). Running it here —
14
14
  // before the pi agent's undici can be loaded — keeps installs quiet under
@@ -51,6 +51,20 @@ if (!fs.existsSync(nextDir)) {
51
51
  process.exit(1);
52
52
  }
53
53
 
54
+ const lanExposure = assessLanExposure(hostname);
55
+ if (lanExposure === "warn-plaintext") {
56
+ console.warn("Pi Web is exposed beyond loopback. HTTP Basic Auth does not encrypt credentials; use HTTPS or a trusted VPN.");
57
+ } else if (lanExposure === "warn-insecure-lan") {
58
+ console.warn("Pi Web is exposed beyond loopback WITHOUT authentication (PI_WEB_ALLOW_INSECURE_LAN=1). Anyone on the network can run agent commands on this machine.");
59
+ } else if (lanExposure === "refuse") {
60
+ // Hard fail: an unauthenticated listener on a LAN address hands every
61
+ // device on the network full read access to sessions/files plus
62
+ // same-origin write access (agent prompts, task shell commands).
63
+ console.error("Refusing to start: Pi Web is bound to " + hostname + " (beyond loopback) but PI_WEB_PASSWORD is not set.");
64
+ console.error("Set PI_WEB_PASSWORD to require HTTP Basic Auth, bind to 127.0.0.1 instead, or set PI_WEB_ALLOW_INSECURE_LAN=1 to override.");
65
+ process.exit(1);
66
+ }
67
+
54
68
  const nextArgs = ["start", "-p", port, "-H", hostname];
55
69
 
56
70
  // Always run next's JS entry with node directly — avoids .bin symlink issues
@@ -61,14 +75,6 @@ const child = spawn(process.execPath, [nextBin, ...nextArgs], {
61
75
  env: { ...process.env, PI_WEB_HOSTNAME: hostname },
62
76
  });
63
77
 
64
- if (hostname !== "127.0.0.1" && hostname !== "localhost" && hostname !== "::1") {
65
- if (process.env.PI_WEB_PASSWORD) {
66
- console.warn("Pi Web is exposed beyond loopback. HTTP Basic Auth does not encrypt credentials; use HTTPS or a trusted VPN.");
67
- } else {
68
- console.warn("Pi Web is exposed beyond loopback without authentication. Use only on a trusted network.");
69
- }
70
- }
71
-
72
78
  let browserOpened = false;
73
79
  const url = `http://${hostname}:${port}`;
74
80
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qt4798/pi-web",
3
- "version": "0.10.5",
3
+ "version": "0.10.6",
4
4
  "description": "Web workspace for the pi coding agent",
5
5
  "homepage": "https://github.com/t479842598/pi-web-QT#readme",
6
6
  "repository": {