@wangjian2254/pi-web 0.8.10
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/.next/BUILD_ID +1 -0
- package/.next/app-path-routes-manifest.json +47 -0
- package/.next/build-manifest.json +20 -0
- package/.next/diagnostics/build-diagnostics.json +6 -0
- package/.next/diagnostics/framework.json +1 -0
- package/.next/export-marker.json +6 -0
- package/.next/images-manifest.json +68 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +161 -0
- package/.next/react-loadable-manifest.json +2358 -0
- package/.next/required-server-files.js +369 -0
- package/.next/required-server-files.json +369 -0
- package/.next/routes-manifest.json +378 -0
- package/.next/server/app/_global-error/page.js +31 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_global-error.html +1 -0
- package/.next/server/app/_global-error.meta +27 -0
- package/.next/server/app/_global-error.rsc +14 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +14 -0
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +20 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/.next/server/app/_not-found/page.js +1 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_not-found.html +1 -0
- package/.next/server/app/_not-found.meta +27 -0
- package/.next/server/app/_not-found.rsc +20 -0
- package/.next/server/app/_not-found.segments/_full.segment.rsc +20 -0
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +24 -0
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +5 -0
- package/.next/server/app/api/agent/[id]/bash-output/route.js +1 -0
- package/.next/server/app/api/agent/[id]/bash-output/route.js.nft.json +1 -0
- package/.next/server/app/api/agent/[id]/bash-output/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/agent/[id]/events/route.js +3 -0
- package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -0
- package/.next/server/app/api/agent/[id]/events/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/agent/[id]/route.js +1 -0
- package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/agent/[id]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/agent/new/route.js +1 -0
- package/.next/server/app/api/agent/new/route.js.nft.json +1 -0
- package/.next/server/app/api/agent/new/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/agent/running/events/route.js +3 -0
- package/.next/server/app/api/agent/running/events/route.js.nft.json +1 -0
- package/.next/server/app/api/agent/running/events/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/agent/running/route.js +1 -0
- package/.next/server/app/api/agent/running/route.js.nft.json +1 -0
- package/.next/server/app/api/agent/running/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/app-update/route.js +1 -0
- package/.next/server/app/api/app-update/route.js.nft.json +1 -0
- package/.next/server/app/api/app-update/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/all-providers/route.js +1 -0
- package/.next/server/app/api/auth/all-providers/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/all-providers/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/api-key/[provider]/route.js +1 -0
- package/.next/server/app/api/auth/api-key/[provider]/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/api-key/[provider]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/login/[provider]/route.js +3 -0
- package/.next/server/app/api/auth/login/[provider]/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/login/[provider]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/logout/[provider]/route.js +1 -0
- package/.next/server/app/api/auth/logout/[provider]/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/logout/[provider]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/providers/route.js +1 -0
- package/.next/server/app/api/auth/providers/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/providers/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/cwd/browse/route.js +1 -0
- package/.next/server/app/api/cwd/browse/route.js.nft.json +1 -0
- package/.next/server/app/api/cwd/browse/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/cwd/validate/route.js +1 -0
- package/.next/server/app/api/cwd/validate/route.js.nft.json +1 -0
- package/.next/server/app/api/cwd/validate/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/default-cwd/route.js +1 -0
- package/.next/server/app/api/default-cwd/route.js.nft.json +1 -0
- package/.next/server/app/api/default-cwd/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/file-index/route.js +1 -0
- package/.next/server/app/api/file-index/route.js.nft.json +1 -0
- package/.next/server/app/api/file-index/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/files/[...path]/route.js +49 -0
- package/.next/server/app/api/files/[...path]/route.js.nft.json +1 -0
- package/.next/server/app/api/files/[...path]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/git/diff/route.js +6 -0
- package/.next/server/app/api/git/diff/route.js.nft.json +1 -0
- package/.next/server/app/api/git/diff/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/git/status/route.js +6 -0
- package/.next/server/app/api/git/status/route.js.nft.json +1 -0
- package/.next/server/app/api/git/status/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/home/route.js +1 -0
- package/.next/server/app/api/home/route.js.nft.json +1 -0
- package/.next/server/app/api/home/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/models/route.js +1 -0
- package/.next/server/app/api/models/route.js.nft.json +1 -0
- package/.next/server/app/api/models/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/models-config/catalog/route.js +1 -0
- package/.next/server/app/api/models-config/catalog/route.js.nft.json +1 -0
- package/.next/server/app/api/models-config/catalog/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/models-config/discover/route.js +1 -0
- package/.next/server/app/api/models-config/discover/route.js.nft.json +1 -0
- package/.next/server/app/api/models-config/discover/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/models-config/route.js +1 -0
- package/.next/server/app/api/models-config/route.js.nft.json +1 -0
- package/.next/server/app/api/models-config/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/models-config/test/route.js +1 -0
- package/.next/server/app/api/models-config/test/route.js.nft.json +1 -0
- package/.next/server/app/api/models-config/test/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/plugins/route.js +1 -0
- package/.next/server/app/api/plugins/route.js.nft.json +1 -0
- package/.next/server/app/api/plugins/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/project-trust/route.js +1 -0
- package/.next/server/app/api/project-trust/route.js.nft.json +1 -0
- package/.next/server/app/api/project-trust/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sessions/[id]/auto-name/route.js +10 -0
- package/.next/server/app/api/sessions/[id]/auto-name/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/[id]/auto-name/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sessions/[id]/context/route.js +1 -0
- package/.next/server/app/api/sessions/[id]/context/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/[id]/context/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sessions/[id]/entries/[entryId]/thinking/route.js +1 -0
- package/.next/server/app/api/sessions/[id]/entries/[entryId]/thinking/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/[id]/entries/[entryId]/thinking/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sessions/[id]/export/route.js +54 -0
- package/.next/server/app/api/sessions/[id]/export/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/[id]/export/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sessions/[id]/route.js +1 -0
- package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/[id]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sessions/[id]/state/route.js +1 -0
- package/.next/server/app/api/sessions/[id]/state/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/[id]/state/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sessions/route.js +1 -0
- package/.next/server/app/api/sessions/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/skills/check/route.js +1 -0
- package/.next/server/app/api/skills/check/route.js.nft.json +1 -0
- package/.next/server/app/api/skills/check/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/skills/install/route.js +1 -0
- package/.next/server/app/api/skills/install/route.js.nft.json +1 -0
- package/.next/server/app/api/skills/install/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/skills/route.js +6 -0
- package/.next/server/app/api/skills/route.js.nft.json +1 -0
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/skills/search/route.js +1 -0
- package/.next/server/app/api/skills/search/route.js.nft.json +1 -0
- package/.next/server/app/api/skills/search/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/skills/update/route.js +1 -0
- package/.next/server/app/api/skills/update/route.js.nft.json +1 -0
- package/.next/server/app/api/skills/update/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/worktrees/route.js +1 -0
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -0
- package/.next/server/app/favicon.ico/route.js +1 -0
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -0
- package/.next/server/app/favicon.ico.body +0 -0
- package/.next/server/app/favicon.ico.meta +1 -0
- package/.next/server/app/index.html +1 -0
- package/.next/server/app/index.meta +21 -0
- package/.next/server/app/index.rsc +21 -0
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +24 -0
- package/.next/server/app/index.segments/_full.segment.rsc +21 -0
- package/.next/server/app/index.segments/_tree.segment.rsc +6 -0
- package/.next/server/app/manifest.webmanifest/route.js +17 -0
- package/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -0
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -0
- package/.next/server/app/manifest.webmanifest.body +1 -0
- package/.next/server/app/manifest.webmanifest.meta +1 -0
- package/.next/server/app/page.js +93 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +1 -0
- package/.next/server/app-paths-manifest.json +47 -0
- package/.next/server/chunks/1286.js +1 -0
- package/.next/server/chunks/1412.js +38 -0
- package/.next/server/chunks/1605.js +1 -0
- package/.next/server/chunks/169.js +1 -0
- package/.next/server/chunks/1776.js +1 -0
- package/.next/server/chunks/18.js +86 -0
- package/.next/server/chunks/1813.js +1 -0
- package/.next/server/chunks/1822.js +90 -0
- package/.next/server/chunks/1881.js +1 -0
- package/.next/server/chunks/2022.js +1 -0
- package/.next/server/chunks/2063.js +148 -0
- package/.next/server/chunks/2156.js +1 -0
- package/.next/server/chunks/2157.js +1 -0
- package/.next/server/chunks/2325.js +82 -0
- package/.next/server/chunks/2349.js +1 -0
- package/.next/server/chunks/2430.js +193 -0
- package/.next/server/chunks/2838.js +1 -0
- package/.next/server/chunks/3016.js +226 -0
- package/.next/server/chunks/3227.js +1 -0
- package/.next/server/chunks/3266.js +1 -0
- package/.next/server/chunks/3379.js +1 -0
- package/.next/server/chunks/3479.js +1 -0
- package/.next/server/chunks/367.js +115 -0
- package/.next/server/chunks/3957.js +8 -0
- package/.next/server/chunks/4107.js +62 -0
- package/.next/server/chunks/4569.js +34 -0
- package/.next/server/chunks/4741.js +165 -0
- package/.next/server/chunks/4755.js +153 -0
- package/.next/server/chunks/5002.js +1 -0
- package/.next/server/chunks/5112.js +1 -0
- package/.next/server/chunks/5235.js +94 -0
- package/.next/server/chunks/5318.js +1 -0
- package/.next/server/chunks/5452.js +23 -0
- package/.next/server/chunks/5453.js +1 -0
- package/.next/server/chunks/5491.js +1 -0
- package/.next/server/chunks/5582.js +3 -0
- package/.next/server/chunks/5709.js +79 -0
- package/.next/server/chunks/573.js +93 -0
- package/.next/server/chunks/5749.js +27 -0
- package/.next/server/chunks/5782.js +36 -0
- package/.next/server/chunks/6163.js +104 -0
- package/.next/server/chunks/6169.js +64 -0
- package/.next/server/chunks/6374.js +1 -0
- package/.next/server/chunks/6399.js +24 -0
- package/.next/server/chunks/6429.js +1 -0
- package/.next/server/chunks/6496.js +1 -0
- package/.next/server/chunks/6521.js +1 -0
- package/.next/server/chunks/703.js +1 -0
- package/.next/server/chunks/7112.js +138 -0
- package/.next/server/chunks/7245.js +77 -0
- package/.next/server/chunks/7307.js +1 -0
- package/.next/server/chunks/7372.js +287 -0
- package/.next/server/chunks/7516.js +1 -0
- package/.next/server/chunks/7531.js +24 -0
- package/.next/server/chunks/7591.js +1 -0
- package/.next/server/chunks/7880.js +32 -0
- package/.next/server/chunks/7916.js +1 -0
- package/.next/server/chunks/8003.js +1 -0
- package/.next/server/chunks/8253.js +41 -0
- package/.next/server/chunks/8272.js +172 -0
- package/.next/server/chunks/8604.js +1 -0
- package/.next/server/chunks/885.js +215 -0
- package/.next/server/chunks/8872.js +1 -0
- package/.next/server/chunks/9006.js +1 -0
- package/.next/server/chunks/9018.js +1 -0
- package/.next/server/chunks/9047.js +1 -0
- package/.next/server/chunks/9108.js +1 -0
- package/.next/server/chunks/9280.js +256 -0
- package/.next/server/chunks/9478.js +1 -0
- package/.next/server/chunks/974.js +1 -0
- package/.next/server/chunks/9775.js +1 -0
- package/.next/server/functions-config-manifest.json +19 -0
- package/.next/server/instrumentation.js +1 -0
- package/.next/server/instrumentation.js.nft.json +1 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +1 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/.next/server/middleware.js +163 -0
- package/.next/server/middleware.js.nft.json +1 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +1 -0
- package/.next/server/pages/404.html +1 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages-manifest.json +4 -0
- package/.next/server/prefetch-hints.json +39 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +1 -0
- package/.next/server/webpack-runtime.js +1 -0
- package/.next/static/J_ZfdqxTZWPTlFJk0cFFy/_buildManifest.js +1 -0
- package/.next/static/J_ZfdqxTZWPTlFJk0cFFy/_ssgManifest.js +1 -0
- package/.next/static/chunks/1169.bdfe59d2bdd2fd7a.js +79 -0
- package/.next/static/chunks/1213.e5c6e70a79b5f7e6.js +24 -0
- package/.next/static/chunks/1519.2f596e5f5af9ef57.js +62 -0
- package/.next/static/chunks/2121.b6920b57bd44dc00.js +8 -0
- package/.next/static/chunks/2521.7f745f50d30076e7.js +77 -0
- package/.next/static/chunks/2585.4d6aa847c780c666.js +1 -0
- package/.next/static/chunks/2600.45ba17a0f756fc31.js +1 -0
- package/.next/static/chunks/2619.9431a3f48da8eef4.js +1 -0
- package/.next/static/chunks/26d302b2.b77b53a34ca944aa.js +122 -0
- package/.next/static/chunks/2768.1a75ba9e2be767cf.js +1 -0
- package/.next/static/chunks/2931.c2acdbf72808b646.js +41 -0
- package/.next/static/chunks/3016.406e568aa95ff867.js +1 -0
- package/.next/static/chunks/3064.3a2a1e7cd4fdca5f.js +1 -0
- package/.next/static/chunks/3098.8355b3073369e6c6.js +1 -0
- package/.next/static/chunks/3174.03fbed7b7d7a8256.js +1 -0
- package/.next/static/chunks/3189.b048866768087750.js +1 -0
- package/.next/static/chunks/3217.1a053843c58b70b5.js +24 -0
- package/.next/static/chunks/3249-d891ccff87c62b6d.js +7 -0
- package/.next/static/chunks/3308.61466f0df05a0277.js +74 -0
- package/.next/static/chunks/331.fc5d78e1e91daf43.js +1 -0
- package/.next/static/chunks/3510.5d4d1c79533e080c.js +1 -0
- package/.next/static/chunks/364.ce5400a9dd70b9dc.js +1 -0
- package/.next/static/chunks/3675.b362b13bde55d05d.js +138 -0
- package/.next/static/chunks/370.8e8f3cf8eb0e29dd.js +1 -0
- package/.next/static/chunks/3794-d29203733ca4633c.js +52 -0
- package/.next/static/chunks/3831.25ae62d10dccc27a.js +1 -0
- package/.next/static/chunks/3a7aa434.280905293fc59b77.js +82 -0
- package/.next/static/chunks/4.0eb5f9326ce27ce3.js +1 -0
- package/.next/static/chunks/4020.3cc19c463c49f969.js +23 -0
- package/.next/static/chunks/4035.0acc428926d5c8dd.js +1 -0
- package/.next/static/chunks/4127.faf29bf971c4c969.js +1 -0
- package/.next/static/chunks/4208.8ea72bb20afa959e.js +287 -0
- package/.next/static/chunks/4263.ffa8d9bd8a0faaae.js +1 -0
- package/.next/static/chunks/4449.8427233f9ccd03de.js +1 -0
- package/.next/static/chunks/4561.d1a3aaca8bae3224.js +34 -0
- package/.next/static/chunks/4799.3c6182ded3f32244.js +1 -0
- package/.next/static/chunks/4bd1b696-8a4ab4fdf0ae305a.js +1 -0
- package/.next/static/chunks/5167.ee4f95d1419b58b7.js +93 -0
- package/.next/static/chunks/5270.28592864d38e881c.js +1 -0
- package/.next/static/chunks/5354.b559c717a607dc5c.js +1 -0
- package/.next/static/chunks/5448.d3972d9fb464b54f.js +38 -0
- package/.next/static/chunks/587.d52737d7288c11b4.js +1 -0
- package/.next/static/chunks/5909.9e37f7b495b11995.js +115 -0
- package/.next/static/chunks/5949.5504b3545fcc3d34.js +104 -0
- package/.next/static/chunks/6310.11650bfd096161c8.js +172 -0
- package/.next/static/chunks/633e7c23.c1fb9d5dc2d4eabe.js +62 -0
- package/.next/static/chunks/6690.ca9ec043dbe8477a.js +226 -0
- package/.next/static/chunks/6774.8cd53427dbf32cac.js +86 -0
- package/.next/static/chunks/6968.b80277c724dbc96e.js +1 -0
- package/.next/static/chunks/7236.55a9728d35f5b8a6.js +1 -0
- package/.next/static/chunks/7477.adc836ca6242f190.js +94 -0
- package/.next/static/chunks/7513.d01d7fcbc6360501.js +1 -0
- package/.next/static/chunks/7806.a903780fcfa3a30e.js +1 -0
- package/.next/static/chunks/8216.64a72d4d35ea7be0.js +1 -0
- package/.next/static/chunks/8255.9df58822ebb2e95f.js +1 -0
- package/.next/static/chunks/8435.10e9cecef654c172.js +148 -0
- package/.next/static/chunks/8663.6ec5792fb4952e45.js +27 -0
- package/.next/static/chunks/872.96937e758ddce860.js +1 -0
- package/.next/static/chunks/8803.75bde095fe3613f5.js +1 -0
- package/.next/static/chunks/8863.72f5dbb820a0e4c3.js +1 -0
- package/.next/static/chunks/90542734.026d4575f63ad955.js +1 -0
- package/.next/static/chunks/911.6117d29223492070.js +90 -0
- package/.next/static/chunks/9354.d3ff9fa6f9cce6a4.js +32 -0
- package/.next/static/chunks/9379.5bc9c9343ec5a16c.js +64 -0
- package/.next/static/chunks/9389.906fe7aa9cd6a170.js +1 -0
- package/.next/static/chunks/9428.47f8f2cfd1b7abed.js +215 -0
- package/.next/static/chunks/9793.4567af813117ad25.js +1 -0
- package/.next/static/chunks/9804.755b81a1e7b890f6.js +1 -0
- package/.next/static/chunks/9884.c6cac4659c50ebfa.js +36 -0
- package/.next/static/chunks/a15fdc23.ca6360563c6c6cb7.js +1 -0
- package/.next/static/chunks/app/_global-error/page-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/_not-found/page-16aa12ab6fbc821c.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/bash-output/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/events/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/agent/new/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/agent/running/events/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/agent/running/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/app-update/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/auth/all-providers/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/auth/api-key/[provider]/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/auth/login/[provider]/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/auth/logout/[provider]/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/auth/providers/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/cwd/browse/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/cwd/validate/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/default-cwd/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/file-index/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/files/[...path]/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/git/diff/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/git/status/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/home/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/models/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/models-config/catalog/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/models-config/discover/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/models-config/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/models-config/test/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/plugins/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/project-trust/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/context/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/export/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/state/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/sessions/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/skills/check/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/skills/install/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/skills/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/skills/search/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/skills/update/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/api/worktrees/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/layout-e5f7bb44574d63fc.js +1 -0
- package/.next/static/chunks/app/manifest.webmanifest/route-169a43802549110e.js +1 -0
- package/.next/static/chunks/app/page-f820ce4b1ac503d7.js +87 -0
- package/.next/static/chunks/d3ac728e-7964f816a1ca64e5.js +1 -0
- package/.next/static/chunks/e413bedd.3a12a8cb02e28fdf.js +153 -0
- package/.next/static/chunks/framework-b33a8f5d57cd8d87.js +1 -0
- package/.next/static/chunks/main-430d592a1108ec6e.js +5 -0
- package/.next/static/chunks/main-app-a5a42985016f7a3f.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-169a43802549110e.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-169a43802549110e.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/global-error-5303c7949f15b13b.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-169a43802549110e.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-169a43802549110e.js +1 -0
- package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/.next/static/chunks/webpack-17a06dc12cf6e786.js +1 -0
- package/.next/static/css/4cbedad236d913cb.css +1 -0
- package/.next/static/css/88714c00e109ce28.css +1 -0
- package/.next/static/css/d0108a26a7a2390c.css +1 -0
- package/.next/static/media/15605e25b523335c-s.woff2 +0 -0
- package/.next/static/media/1a3dce5cfb5f7760-s.woff2 +0 -0
- package/.next/static/media/1cdd02902f937a18-s.woff2 +0 -0
- package/.next/static/media/4c4b3b30b6bcb2be-s.woff2 +0 -0
- package/.next/static/media/641a7b8a5800ee0e-s.woff2 +0 -0
- package/.next/static/media/7deddc85b7ffd1dc-s.p.woff2 +0 -0
- package/.next/static/media/KaTeX_AMS-Regular.1608a09b.woff +0 -0
- package/.next/static/media/KaTeX_AMS-Regular.4aafdb68.ttf +0 -0
- package/.next/static/media/KaTeX_AMS-Regular.a79f1c31.woff2 +0 -0
- package/.next/static/media/KaTeX_Caligraphic-Bold.b6770918.woff +0 -0
- package/.next/static/media/KaTeX_Caligraphic-Bold.cce5b8ec.ttf +0 -0
- package/.next/static/media/KaTeX_Caligraphic-Bold.ec17d132.woff2 +0 -0
- package/.next/static/media/KaTeX_Caligraphic-Regular.07ef19e7.ttf +0 -0
- package/.next/static/media/KaTeX_Caligraphic-Regular.55fac258.woff2 +0 -0
- package/.next/static/media/KaTeX_Caligraphic-Regular.dad44a7f.woff +0 -0
- package/.next/static/media/KaTeX_Fraktur-Bold.9f256b85.woff +0 -0
- package/.next/static/media/KaTeX_Fraktur-Bold.b18f59e1.ttf +0 -0
- package/.next/static/media/KaTeX_Fraktur-Bold.d42a5579.woff2 +0 -0
- package/.next/static/media/KaTeX_Fraktur-Regular.7c187121.woff +0 -0
- package/.next/static/media/KaTeX_Fraktur-Regular.d3c882a6.woff2 +0 -0
- package/.next/static/media/KaTeX_Fraktur-Regular.ed38e79f.ttf +0 -0
- package/.next/static/media/KaTeX_Main-Bold.b74a1a8b.ttf +0 -0
- package/.next/static/media/KaTeX_Main-Bold.c3fb5ac2.woff2 +0 -0
- package/.next/static/media/KaTeX_Main-Bold.d181c465.woff +0 -0
- package/.next/static/media/KaTeX_Main-BoldItalic.6f2bb1df.woff2 +0 -0
- package/.next/static/media/KaTeX_Main-BoldItalic.70d8b0a5.ttf +0 -0
- package/.next/static/media/KaTeX_Main-BoldItalic.e3f82f9d.woff +0 -0
- package/.next/static/media/KaTeX_Main-Italic.47373d1e.ttf +0 -0
- package/.next/static/media/KaTeX_Main-Italic.8916142b.woff2 +0 -0
- package/.next/static/media/KaTeX_Main-Italic.9024d815.woff +0 -0
- package/.next/static/media/KaTeX_Main-Regular.0462f03b.woff2 +0 -0
- package/.next/static/media/KaTeX_Main-Regular.7f51fe03.woff +0 -0
- package/.next/static/media/KaTeX_Main-Regular.b7f8fe9b.ttf +0 -0
- package/.next/static/media/KaTeX_Math-BoldItalic.572d331f.woff2 +0 -0
- package/.next/static/media/KaTeX_Math-BoldItalic.a879cf83.ttf +0 -0
- package/.next/static/media/KaTeX_Math-BoldItalic.f1035d8d.woff +0 -0
- package/.next/static/media/KaTeX_Math-Italic.5295ba48.woff +0 -0
- package/.next/static/media/KaTeX_Math-Italic.939bc644.ttf +0 -0
- package/.next/static/media/KaTeX_Math-Italic.f28c23ac.woff2 +0 -0
- package/.next/static/media/KaTeX_SansSerif-Bold.8c5b5494.woff2 +0 -0
- package/.next/static/media/KaTeX_SansSerif-Bold.94e1e8dc.ttf +0 -0
- package/.next/static/media/KaTeX_SansSerif-Bold.bf59d231.woff +0 -0
- package/.next/static/media/KaTeX_SansSerif-Italic.3b1e59b3.woff2 +0 -0
- package/.next/static/media/KaTeX_SansSerif-Italic.7c9bc82b.woff +0 -0
- package/.next/static/media/KaTeX_SansSerif-Italic.b4c20c84.ttf +0 -0
- package/.next/static/media/KaTeX_SansSerif-Regular.74048478.woff +0 -0
- package/.next/static/media/KaTeX_SansSerif-Regular.ba21ed5f.woff2 +0 -0
- package/.next/static/media/KaTeX_SansSerif-Regular.d4d7ba48.ttf +0 -0
- package/.next/static/media/KaTeX_Script-Regular.03e9641d.woff2 +0 -0
- package/.next/static/media/KaTeX_Script-Regular.07505710.woff +0 -0
- package/.next/static/media/KaTeX_Script-Regular.fe9cbbe1.ttf +0 -0
- package/.next/static/media/KaTeX_Size1-Regular.e1e279cb.woff +0 -0
- package/.next/static/media/KaTeX_Size1-Regular.eae34984.woff2 +0 -0
- package/.next/static/media/KaTeX_Size1-Regular.fabc004a.ttf +0 -0
- package/.next/static/media/KaTeX_Size2-Regular.57727022.woff +0 -0
- package/.next/static/media/KaTeX_Size2-Regular.5916a24f.woff2 +0 -0
- package/.next/static/media/KaTeX_Size2-Regular.d6b476ec.ttf +0 -0
- package/.next/static/media/KaTeX_Size3-Regular.9acaf01c.woff +0 -0
- package/.next/static/media/KaTeX_Size3-Regular.a144ef58.ttf +0 -0
- package/.next/static/media/KaTeX_Size3-Regular.b4230e7e.woff2 +0 -0
- package/.next/static/media/KaTeX_Size4-Regular.10d95fd3.woff2 +0 -0
- package/.next/static/media/KaTeX_Size4-Regular.7a996c9d.woff +0 -0
- package/.next/static/media/KaTeX_Size4-Regular.fbccdabe.ttf +0 -0
- package/.next/static/media/KaTeX_Typewriter-Regular.6258592b.woff +0 -0
- package/.next/static/media/KaTeX_Typewriter-Regular.a8709e36.woff2 +0 -0
- package/.next/static/media/KaTeX_Typewriter-Regular.d97aaf4a.ttf +0 -0
- package/.next/static/media/ec14413c594b3356-s.p.woff2 +0 -0
- package/.next/trace +6 -0
- package/.next/trace-build +1 -0
- package/.next/types/app/api/agent/[id]/bash-output/route.ts +353 -0
- package/.next/types/app/api/agent/[id]/events/route.ts +353 -0
- package/.next/types/app/api/agent/[id]/route.ts +353 -0
- package/.next/types/app/api/agent/new/route.ts +353 -0
- package/.next/types/app/api/agent/running/events/route.ts +353 -0
- package/.next/types/app/api/agent/running/route.ts +353 -0
- package/.next/types/app/api/app-update/route.ts +353 -0
- package/.next/types/app/api/auth/all-providers/route.ts +353 -0
- package/.next/types/app/api/auth/api-key/[provider]/route.ts +353 -0
- package/.next/types/app/api/auth/login/[provider]/route.ts +353 -0
- package/.next/types/app/api/auth/logout/[provider]/route.ts +353 -0
- package/.next/types/app/api/auth/providers/route.ts +353 -0
- package/.next/types/app/api/cwd/browse/route.ts +353 -0
- package/.next/types/app/api/cwd/validate/route.ts +353 -0
- package/.next/types/app/api/default-cwd/route.ts +353 -0
- package/.next/types/app/api/file-index/route.ts +353 -0
- package/.next/types/app/api/files/[...path]/route.ts +353 -0
- package/.next/types/app/api/git/diff/route.ts +353 -0
- package/.next/types/app/api/git/status/route.ts +353 -0
- package/.next/types/app/api/home/route.ts +353 -0
- package/.next/types/app/api/models/route.ts +353 -0
- package/.next/types/app/api/models-config/catalog/route.ts +353 -0
- package/.next/types/app/api/models-config/discover/route.ts +353 -0
- package/.next/types/app/api/models-config/route.ts +353 -0
- package/.next/types/app/api/models-config/test/route.ts +353 -0
- package/.next/types/app/api/plugins/route.ts +353 -0
- package/.next/types/app/api/project-trust/route.ts +353 -0
- package/.next/types/app/api/sessions/[id]/auto-name/route.ts +353 -0
- package/.next/types/app/api/sessions/[id]/context/route.ts +353 -0
- package/.next/types/app/api/sessions/[id]/entries/[entryId]/thinking/route.ts +353 -0
- package/.next/types/app/api/sessions/[id]/export/route.ts +353 -0
- package/.next/types/app/api/sessions/[id]/route.ts +353 -0
- package/.next/types/app/api/sessions/[id]/state/route.ts +353 -0
- package/.next/types/app/api/sessions/route.ts +353 -0
- package/.next/types/app/api/skills/check/route.ts +353 -0
- package/.next/types/app/api/skills/install/route.ts +353 -0
- package/.next/types/app/api/skills/route.ts +353 -0
- package/.next/types/app/api/skills/search/route.ts +353 -0
- package/.next/types/app/api/skills/update/route.ts +353 -0
- package/.next/types/app/api/worktrees/route.ts +353 -0
- package/.next/types/app/layout.ts +89 -0
- package/.next/types/app/page.ts +89 -0
- package/.next/types/cache-life.d.ts +146 -0
- package/.next/types/package.json +1 -0
- package/.next/types/root-params.d.ts +3 -0
- package/.next/types/routes.d.ts +112 -0
- package/.next/types/validator.ts +430 -0
- package/LICENSE +21 -0
- package/README.ja.md +132 -0
- package/README.md +156 -0
- package/README.ru.md +132 -0
- package/README.zh-CN.md +134 -0
- package/bin/node-version.js +35 -0
- package/bin/pi-web-options.js +43 -0
- package/bin/pi-web.js +115 -0
- package/bin/process-lifecycle.js +46 -0
- package/next.config.ts +53 -0
- package/package.json +79 -0
- package/public/icons/apple-touch-icon.png +0 -0
- package/public/icons/catppuccin/LICENSE +22 -0
- package/public/icons/catppuccin/README.md +10 -0
- package/public/icons/catppuccin/latte/_file.svg +3 -0
- package/public/icons/catppuccin/latte/_folder.svg +3 -0
- package/public/icons/catppuccin/latte/_folder_open.svg +3 -0
- package/public/icons/catppuccin/latte/bash.svg +7 -0
- package/public/icons/catppuccin/latte/bun-lock.svg +8 -0
- package/public/icons/catppuccin/latte/config.svg +3 -0
- package/public/icons/catppuccin/latte/css.svg +6 -0
- package/public/icons/catppuccin/latte/database.svg +3 -0
- package/public/icons/catppuccin/latte/docker.svg +3 -0
- package/public/icons/catppuccin/latte/env.svg +3 -0
- package/public/icons/catppuccin/latte/eslint.svg +6 -0
- package/public/icons/catppuccin/latte/git.svg +6 -0
- package/public/icons/catppuccin/latte/go.svg +3 -0
- package/public/icons/catppuccin/latte/graphql.svg +3 -0
- package/public/icons/catppuccin/latte/html.svg +6 -0
- package/public/icons/catppuccin/latte/javascript-react.svg +8 -0
- package/public/icons/catppuccin/latte/javascript.svg +6 -0
- package/public/icons/catppuccin/latte/json.svg +3 -0
- package/public/icons/catppuccin/latte/lock.svg +3 -0
- package/public/icons/catppuccin/latte/markdown.svg +3 -0
- package/public/icons/catppuccin/latte/ms-word.svg +6 -0
- package/public/icons/catppuccin/latte/next.svg +6 -0
- package/public/icons/catppuccin/latte/npm-lock.svg +7 -0
- package/public/icons/catppuccin/latte/pdf.svg +3 -0
- package/public/icons/catppuccin/latte/python.svg +8 -0
- package/public/icons/catppuccin/latte/rust.svg +6 -0
- package/public/icons/catppuccin/latte/sass.svg +3 -0
- package/public/icons/catppuccin/latte/terraform.svg +3 -0
- package/public/icons/catppuccin/latte/toml.svg +3 -0
- package/public/icons/catppuccin/latte/typescript-react.svg +8 -0
- package/public/icons/catppuccin/latte/typescript.svg +6 -0
- package/public/icons/catppuccin/latte/yaml.svg +3 -0
- package/public/icons/catppuccin/mocha/_file.svg +3 -0
- package/public/icons/catppuccin/mocha/_folder.svg +3 -0
- package/public/icons/catppuccin/mocha/_folder_open.svg +3 -0
- package/public/icons/catppuccin/mocha/bash.svg +7 -0
- package/public/icons/catppuccin/mocha/bun-lock.svg +8 -0
- package/public/icons/catppuccin/mocha/config.svg +3 -0
- package/public/icons/catppuccin/mocha/css.svg +6 -0
- package/public/icons/catppuccin/mocha/database.svg +3 -0
- package/public/icons/catppuccin/mocha/docker.svg +3 -0
- package/public/icons/catppuccin/mocha/env.svg +3 -0
- package/public/icons/catppuccin/mocha/eslint.svg +6 -0
- package/public/icons/catppuccin/mocha/git.svg +6 -0
- package/public/icons/catppuccin/mocha/go.svg +3 -0
- package/public/icons/catppuccin/mocha/graphql.svg +3 -0
- package/public/icons/catppuccin/mocha/html.svg +6 -0
- package/public/icons/catppuccin/mocha/javascript-react.svg +8 -0
- package/public/icons/catppuccin/mocha/javascript.svg +6 -0
- package/public/icons/catppuccin/mocha/json.svg +3 -0
- package/public/icons/catppuccin/mocha/lock.svg +3 -0
- package/public/icons/catppuccin/mocha/markdown.svg +3 -0
- package/public/icons/catppuccin/mocha/ms-word.svg +6 -0
- package/public/icons/catppuccin/mocha/next.svg +6 -0
- package/public/icons/catppuccin/mocha/npm-lock.svg +7 -0
- package/public/icons/catppuccin/mocha/pdf.svg +3 -0
- package/public/icons/catppuccin/mocha/python.svg +8 -0
- package/public/icons/catppuccin/mocha/rust.svg +6 -0
- package/public/icons/catppuccin/mocha/sass.svg +3 -0
- package/public/icons/catppuccin/mocha/terraform.svg +3 -0
- package/public/icons/catppuccin/mocha/toml.svg +3 -0
- package/public/icons/catppuccin/mocha/typescript-react.svg +8 -0
- package/public/icons/catppuccin/mocha/typescript.svg +6 -0
- package/public/icons/catppuccin/mocha/yaml.svg +3 -0
- package/public/icons/icon-192.png +0 -0
- package/public/icons/icon-512.png +0 -0
- package/public/offline.html +83 -0
- package/public/sw.js +118 -0
- package/public/sw.test.mjs +86 -0
package/README.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Pi Web
|
|
2
|
+
|
|
3
|
+
[中文文档](./README.zh-CN.md) | [日本語](./README.ja.md) | [Русский](./README.ru.md)
|
|
4
|
+
|
|
5
|
+
Local browser UI for the [pi coding agent](https://github.com/earendil-works/pi). Pi Web uses the same local configuration and session files as pi, so you can browse and resume conversations, run agent turns, configure models and resources, and inspect project files from a browser.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Session workspace**: browse, resume, rename, export, and delete conversations grouped by project, with running state, context usage, cost, and compaction details.
|
|
12
|
+
- **Two ways to branch**: **New session** creates an independent session file from an earlier message; **Edit from here** creates a branch inside the current session.
|
|
13
|
+
- **Project file tools**: browse and upload files, inspect Git diffs, and preview source, Markdown, images, audio, PDFs, and DOCX files with automatic refresh.
|
|
14
|
+
- **Git worktrees**: switch checkouts from the sidebar while keeping sessions from the same repository grouped together.
|
|
15
|
+
- **Web-based configuration**: manage provider login and API keys, models, model tests, plugin packages, and skills without leaving Pi Web.
|
|
16
|
+
- **English and Simplified Chinese UI**: Pi Web follows the browser language initially and provides a language switcher in the top bar.
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
Pi Web requires Node.js 22.19.0 or newer. Check your version with `node --version`, then run:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx @wangjian2254/pi-web@latest
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The CLI opens a browser after the server is ready. If it does not, open [http://127.0.0.1:30141](http://127.0.0.1:30141). Pi Web listens only on `127.0.0.1` by default.
|
|
27
|
+
|
|
28
|
+
If no model provider is configured yet, open the **Models** panel to sign in or add an API key.
|
|
29
|
+
|
|
30
|
+
To install the `pi-web` command globally:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install -g @wangjian2254/pi-web@latest
|
|
34
|
+
pi-web
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
To update, stop the running process with `Ctrl+C` and run the same install command again. To uninstall, run `npm uninstall -g @wangjian2254/pi-web`.
|
|
38
|
+
|
|
39
|
+
## Configuration
|
|
40
|
+
|
|
41
|
+
For port and hostname, command-line options override the corresponding environment variables. Either `--no-open` or `PI_WEB_NO_OPEN=1` disables automatic browser opening.
|
|
42
|
+
|
|
43
|
+
| Option or environment variable | Purpose | Default |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| `--port <port>`, `-p <port>`, or `PORT` | Server port | `30141` |
|
|
46
|
+
| `--hostname <host>`, `-H <host>`, or `PI_WEB_HOSTNAME` | Bind hostname | `127.0.0.1` |
|
|
47
|
+
| `--no-open` or `PI_WEB_NO_OPEN=1` | Do not open a browser automatically | Browser opens |
|
|
48
|
+
| `PI_WEB_ALLOWED_HOSTS` | Additional exact proxy or custom hostnames, comma-separated | Unset |
|
|
49
|
+
| `PI_WEB_PASSWORD` | Enable HTTP Basic Auth; the username is always `pi` | Authentication disabled |
|
|
50
|
+
|
|
51
|
+
For example:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pi-web -p 8080 -H 0.0.0.0 --no-open
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Remote Access
|
|
58
|
+
|
|
59
|
+
Binding to a non-loopback address exposes an agent that can execute high-privilege actions. On a trusted LAN, require a long random password:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
PI_WEB_PASSWORD='a-long-random-password' pi-web --hostname 0.0.0.0
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Basic Auth does not encrypt the password in transit. Do not expose Pi Web over plain HTTP to the internet; use HTTPS through a trusted reverse proxy or a trusted VPN. If a reverse proxy sends an external hostname, add that exact name to `PI_WEB_ALLOWED_HOSTS`. This allow-list does not change the address Pi Web binds to.
|
|
66
|
+
|
|
67
|
+
### HTTP Proxy
|
|
68
|
+
|
|
69
|
+
Server-side model and API requests honor the standard `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` environment variables.
|
|
70
|
+
|
|
71
|
+
On macOS or Linux:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
HTTP_PROXY=http://127.0.0.1:7890 \
|
|
75
|
+
HTTPS_PROXY=http://127.0.0.1:7890 \
|
|
76
|
+
NO_PROXY=localhost,127.0.0.1 \
|
|
77
|
+
npx @wangjian2254/pi-web@latest
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
On Windows PowerShell:
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
$env:HTTP_PROXY = "http://127.0.0.1:7890"
|
|
84
|
+
$env:HTTPS_PROXY = "http://127.0.0.1:7890"
|
|
85
|
+
$env:NO_PROXY = "localhost,127.0.0.1"
|
|
86
|
+
npx @wangjian2254/pi-web@latest
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Notes
|
|
90
|
+
|
|
91
|
+
- **Agent data**: Pi Web reads pi data from `~/.pi/agent` by default, including session files under `sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl`. Set `PI_CODING_AGENT_DIR` to use another pi agent directory.
|
|
92
|
+
- **Filesystem access**: Pi Web must be able to read the agent data directory and the working directories recorded by its sessions. Run Pi Web in the same filesystem environment as pi when sharing existing sessions.
|
|
93
|
+
- **Shared configuration**: the Models panel uses pi's model, settings, and credential storage, so changes are visible to both interfaces.
|
|
94
|
+
- **File access boundary**: the file browser is limited to working directories selected in Pi Web and project or session roots it already knows about; it is not a general filesystem browser.
|
|
95
|
+
- **Git worktrees**: see [Worktrees in Pi Web](./docs/worktrees.md) for switcher visibility, worktree creation, and removal behavior.
|
|
96
|
+
|
|
97
|
+
### Downstream Session Context Menu
|
|
98
|
+
|
|
99
|
+
Electron wrappers and other downstream integrations can provide a session-row
|
|
100
|
+
context menu without patching `SessionSidebar`. Listen for the cancelable
|
|
101
|
+
`pi-web:session-row-contextmenu` browser event and call `preventDefault()`
|
|
102
|
+
synchronously when the integration will handle it:
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
window.addEventListener("pi-web:session-row-contextmenu", (event) => {
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
const { id, path, cwd, name, clientX, clientY, refresh } = event.detail;
|
|
108
|
+
|
|
109
|
+
void openSessionMenu({ id, path, cwd, name, clientX, clientY }).then((changed) => {
|
|
110
|
+
if (changed) refresh();
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The detail object contains `id`, `path`, `cwd`, optional `name`, pointer
|
|
116
|
+
coordinates, and a `refresh()` callback for actions that change the session
|
|
117
|
+
list. If no listener cancels the extension event, Pi Web preserves the
|
|
118
|
+
browser's native context menu. This hook is browser-side and independent of
|
|
119
|
+
Pi agent extensions.
|
|
120
|
+
|
|
121
|
+
## Development
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npm install
|
|
125
|
+
npm run dev
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The development server runs at [http://127.0.0.1:30141](http://127.0.0.1:30141). Run the common checks with:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
npm test
|
|
132
|
+
node_modules/.bin/tsc --noEmit
|
|
133
|
+
npm run lint
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Do not run `next build` or `npm run build` during normal development. It writes to `.next/` and can interfere with the development server; leave builds for release work.
|
|
137
|
+
|
|
138
|
+
Contributor guides: [Internationalization](./docs/i18n.md) and [Release process](./docs/release.md).
|
|
139
|
+
|
|
140
|
+
## Repository Layout
|
|
141
|
+
|
|
142
|
+
```text
|
|
143
|
+
app/ Next.js UI and API routes
|
|
144
|
+
components/ React UI components
|
|
145
|
+
hooks/ Client state and interaction hooks
|
|
146
|
+
lib/ Session, agent, model, file, Git, and security logic
|
|
147
|
+
public/ Static assets and PWA files
|
|
148
|
+
bin/ npm CLI entrypoint and launch option parsing
|
|
149
|
+
docs/ Focused user and contributor guides
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
See [AGENTS.md](./AGENTS.md) for the architecture notes and detailed file map.
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
[MIT](./LICENSE)
|
package/README.ru.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Pi Web
|
|
2
|
+
|
|
3
|
+
[English](./README.md) | [中文文档](./README.zh-CN.md) | [日本語](./README.ja.md)
|
|
4
|
+
|
|
5
|
+
Локальный браузерный интерфейс для [pi coding agent](https://github.com/earendil-works/pi). Pi Web использует те же локальные настройки и файлы сессий, что и pi, поэтому в браузере можно находить и продолжать диалоги, запускать агента, настраивать модели и ресурсы, а также просматривать файлы проекта.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Возможности
|
|
10
|
+
|
|
11
|
+
- **Рабочее пространство сессий**: просмотр, продолжение, переименование, экспорт и удаление диалогов, сгруппированных по проектам, с отображением состояния выполнения, использования контекста, стоимости и сведений о сжатии.
|
|
12
|
+
- **Два способа создать ветку**: **New session** создаёт независимый файл сессии из более раннего сообщения, а **Edit from here** создаёт ветку внутри текущей сессии.
|
|
13
|
+
- **Инструменты для файлов проекта**: просмотр и загрузка файлов, проверка Git Diff, предпросмотр исходного кода, Markdown, изображений, аудио, PDF и DOCX с автоматическим обновлением.
|
|
14
|
+
- **Git worktree**: переключение рабочих деревьев в боковой панели с сохранением общей группы сессий одного репозитория.
|
|
15
|
+
- **Настройка через Web**: управление входом в Provider и API Key, моделями, тестами моделей, пакетами плагинов и навыками без выхода из Pi Web.
|
|
16
|
+
- **Интерфейс на английском и упрощённом китайском**: при первом запуске Pi Web учитывает язык браузера, а затем язык можно переключить в верхней панели.
|
|
17
|
+
|
|
18
|
+
## Быстрый старт
|
|
19
|
+
|
|
20
|
+
Для работы Pi Web требуется Node.js 22.19.0 или новее. Проверьте версию командой `node --version`, затем выполните:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx @wangjian2254/pi-web@latest
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Когда сервер будет готов, CLI попытается открыть браузер автоматически. Если этого не произошло, откройте [http://127.0.0.1:30141](http://127.0.0.1:30141). По умолчанию Pi Web прослушивает только `127.0.0.1`.
|
|
27
|
+
|
|
28
|
+
Если Provider модели ещё не настроен, откройте панель **Models**, войдите в учётную запись или добавьте API Key.
|
|
29
|
+
|
|
30
|
+
Чтобы установить команду `pi-web` глобально:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install -g @wangjian2254/pi-web@latest
|
|
34
|
+
pi-web
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Для обновления остановите запущенный процесс с помощью `Ctrl+C` и повторите ту же команду установки. Для удаления выполните `npm uninstall -g @wangjian2254/pi-web`.
|
|
38
|
+
|
|
39
|
+
## Настройка
|
|
40
|
+
|
|
41
|
+
Для порта и имени хоста параметры командной строки имеют приоритет над соответствующими переменными окружения. И `--no-open`, и `PI_WEB_NO_OPEN=1` отключают автоматическое открытие браузера независимо друг от друга.
|
|
42
|
+
|
|
43
|
+
| Параметр или переменная окружения | Назначение | Значение по умолчанию |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| `--port <port>`, `-p <port>` или `PORT` | Порт сервера | `30141` |
|
|
46
|
+
| `--hostname <host>`, `-H <host>` или `PI_WEB_HOSTNAME` | Имя хоста для привязки | `127.0.0.1` |
|
|
47
|
+
| `--no-open` или `PI_WEB_NO_OPEN=1` | Не открывать браузер автоматически | Браузер открывается |
|
|
48
|
+
| `PI_WEB_ALLOWED_HOSTS` | Дополнительные точные имена прокси или пользовательских хостов через запятую | Не задано |
|
|
49
|
+
| `PI_WEB_PASSWORD` | Включить HTTP Basic Auth; имя пользователя всегда `pi` | Аутентификация отключена |
|
|
50
|
+
|
|
51
|
+
Пример:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pi-web -p 8080 -H 0.0.0.0 --no-open
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Удалённый доступ
|
|
58
|
+
|
|
59
|
+
Привязка к адресу, отличному от loopback, открывает сетевой доступ к агенту, способному выполнять операции с широкими полномочиями. Даже в доверенной локальной сети используйте длинный случайный пароль:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
PI_WEB_PASSWORD='длинный-случайный-пароль' pi-web --hostname 0.0.0.0
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Basic Auth не шифрует пароль при передаче. Не публикуйте Pi Web в интернете по обычному HTTP; используйте HTTPS через доверенный обратный прокси или надёжное VPN-подключение. Если обратный прокси передаёт внешнее имя хоста, добавьте это точное имя в `PI_WEB_ALLOWED_HOSTS`. Этот список разрешённых имён не меняет адрес, к которому привязывается Pi Web.
|
|
66
|
+
|
|
67
|
+
### HTTP-прокси
|
|
68
|
+
|
|
69
|
+
Для серверных запросов к моделям и API используются стандартные переменные окружения `HTTP_PROXY`, `HTTPS_PROXY` и `NO_PROXY`.
|
|
70
|
+
|
|
71
|
+
В macOS и Linux:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
HTTP_PROXY=http://127.0.0.1:7890 \
|
|
75
|
+
HTTPS_PROXY=http://127.0.0.1:7890 \
|
|
76
|
+
NO_PROXY=localhost,127.0.0.1 \
|
|
77
|
+
npx @wangjian2254/pi-web@latest
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
В Windows PowerShell:
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
$env:HTTP_PROXY = "http://127.0.0.1:7890"
|
|
84
|
+
$env:HTTPS_PROXY = "http://127.0.0.1:7890"
|
|
85
|
+
$env:NO_PROXY = "localhost,127.0.0.1"
|
|
86
|
+
npx @wangjian2254/pi-web@latest
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Примечания
|
|
90
|
+
|
|
91
|
+
- **Данные агента**: по умолчанию Pi Web читает данные pi из `~/.pi/agent`, включая файлы сессий в `sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl`. Чтобы использовать другой каталог агента pi, задайте `PI_CODING_AGENT_DIR`.
|
|
92
|
+
- **Доступ к файловой системе**: Pi Web должен иметь доступ для чтения к каталогу данных агента и рабочим каталогам, записанным в сессиях. При совместном использовании существующих сессий запускайте Pi Web в той же файловой среде, что и pi.
|
|
93
|
+
- **Общие настройки**: панель Models использует хранилища моделей, настроек и учётных данных pi, поэтому изменения видны в обоих интерфейсах.
|
|
94
|
+
- **Граница доступа к файлам**: файловый браузер ограничен рабочими каталогами, выбранными в Pi Web, и уже известными корнями проектов или сессий; это не универсальный файловый менеджер.
|
|
95
|
+
- **Git worktree**: условия отображения переключателя, создание рабочих деревьев и их удаление описаны в документе [Worktrees in Pi Web](./docs/worktrees.md).
|
|
96
|
+
|
|
97
|
+
## Разработка
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npm install
|
|
101
|
+
npm run dev
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Сервер разработки доступен по адресу [http://127.0.0.1:30141](http://127.0.0.1:30141). Основные проверки запускаются командами:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm test
|
|
108
|
+
node_modules/.bin/tsc --noEmit
|
|
109
|
+
npm run lint
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Не запускайте `next build` или `npm run build` во время обычной разработки. Эти команды записывают данные в `.next/` и могут помешать работе сервера разработки; выполняйте сборку только при подготовке релиза.
|
|
113
|
+
|
|
114
|
+
Руководства для участников: [Internationalization](./docs/i18n.md) и [Release process](./docs/release.md).
|
|
115
|
+
|
|
116
|
+
## Структура репозитория
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
app/ UI Next.js и маршруты API
|
|
120
|
+
components/ Компоненты интерфейса React
|
|
121
|
+
hooks/ Состояние клиента и обработчики взаимодействий
|
|
122
|
+
lib/ Логика сессий, агента, моделей, файлов, Git и безопасности
|
|
123
|
+
public/ Статические ресурсы и файлы PWA
|
|
124
|
+
bin/ Точка входа npm CLI и разбор параметров запуска
|
|
125
|
+
docs/ Тематические руководства для пользователей и участников
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Описание архитектуры и подробная карта файлов приведены в [AGENTS.md](./AGENTS.md).
|
|
129
|
+
|
|
130
|
+
## Лицензия
|
|
131
|
+
|
|
132
|
+
[MIT](./LICENSE)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Pi Web
|
|
2
|
+
|
|
3
|
+
[English](./README.md) | [日本語](./README.ja.md) | [Русский](./README.ru.md)
|
|
4
|
+
|
|
5
|
+
[pi 编程智能体](https://github.com/earendil-works/pi)的本地浏览器界面。Pi Web 与 pi 共用本机配置和会话文件,可在浏览器中查找和继续对话、运行智能体、配置模型与资源,并查看项目文件。
|
|
6
|
+
|
|
7
|
+
中文微信群:请查看 [GitHub Discussions 帖子](https://github.com/agegr/pi-web/discussions/271)。
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
## 功能
|
|
12
|
+
|
|
13
|
+
- **会话工作区**:按项目查找、继续、重命名、导出和删除对话,并查看运行状态、上下文占用、花费和压缩信息。
|
|
14
|
+
- **两种分支方式**:**新会话**会从较早的消息创建独立会话文件;**从此处编辑**会在当前会话内创建分支。
|
|
15
|
+
- **项目文件工具**:浏览和上传文件、查看 Git Diff,并预览源码、Markdown、图片、音频、PDF 和 DOCX;文件变化后会自动刷新。
|
|
16
|
+
- **Git worktree**:从侧边栏切换 checkout,同时把同一仓库不同 worktree 的会话归在一起。
|
|
17
|
+
- **网页配置**:无需离开 Pi Web,即可管理 Provider 登录和 API Key、模型、模型测试、插件包及技能。
|
|
18
|
+
- **英文和简体中文界面**:Pi Web 首次打开时跟随浏览器语言,也可从顶部栏切换语言。
|
|
19
|
+
|
|
20
|
+
## 快速开始
|
|
21
|
+
|
|
22
|
+
Pi Web 要求 Node.js 22.19.0 或更高版本。先用 `node --version` 检查版本,然后运行:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx @wangjian2254/pi-web@latest
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
服务就绪后,命令行会尝试自动打开浏览器。如果没有打开,请访问 [http://127.0.0.1:30141](http://127.0.0.1:30141)。Pi Web 默认仅监听 `127.0.0.1`。
|
|
29
|
+
|
|
30
|
+
如果尚未配置模型 Provider,请打开**模型(Models)**面板登录或添加 API Key。
|
|
31
|
+
|
|
32
|
+
如需全局安装 `pi-web` 命令:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g @wangjian2254/pi-web@latest
|
|
36
|
+
pi-web
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
更新前先用 `Ctrl+C` 停止正在运行的进程,再次执行同一条安装命令。卸载时运行 `npm uninstall -g @wangjian2254/pi-web`。
|
|
40
|
+
|
|
41
|
+
## 配置
|
|
42
|
+
|
|
43
|
+
端口和主机名以命令行参数为准,优先于对应的环境变量。`--no-open` 与 `PI_WEB_NO_OPEN=1` 中任意一个都会关闭自动打开浏览器。
|
|
44
|
+
|
|
45
|
+
| 参数或环境变量 | 用途 | 默认值 |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| `--port <端口>`、`-p <端口>` 或 `PORT` | 服务端口 | `30141` |
|
|
48
|
+
| `--hostname <主机>`、`-H <主机>` 或 `PI_WEB_HOSTNAME` | 监听主机名 | `127.0.0.1` |
|
|
49
|
+
| `--no-open` 或 `PI_WEB_NO_OPEN=1` | 不自动打开浏览器 | 自动打开 |
|
|
50
|
+
| `PI_WEB_ALLOWED_HOSTS` | 额外允许的代理或自定义主机名,多个值用逗号分隔,必须精确匹配 | 未设置 |
|
|
51
|
+
| `PI_WEB_PASSWORD` | 启用 HTTP Basic Auth,用户名固定为 `pi` | 不启用认证 |
|
|
52
|
+
|
|
53
|
+
例如:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pi-web -p 8080 -H 0.0.0.0 --no-open
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 远程访问
|
|
60
|
+
|
|
61
|
+
监听非回环地址会暴露一个可执行高权限操作的智能体。在可信局域网中使用时,请设置足够长的随机密码:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
PI_WEB_PASSWORD='足够长的随机密码' pi-web --hostname 0.0.0.0
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Basic Auth 不会加密传输中的密码。不要通过明文 HTTP 将 Pi Web 暴露到互联网;远程访问应使用可信反向代理提供 HTTPS,或通过可信 VPN。如果反向代理传递外部主机名,请把该名称精确加入 `PI_WEB_ALLOWED_HOSTS`。这个白名单不会改变 Pi Web 的监听地址。
|
|
68
|
+
|
|
69
|
+
### HTTP 代理
|
|
70
|
+
|
|
71
|
+
服务端的模型和 API 请求会读取标准的 `HTTP_PROXY`、`HTTPS_PROXY` 和 `NO_PROXY` 环境变量。
|
|
72
|
+
|
|
73
|
+
macOS 或 Linux:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
HTTP_PROXY=http://127.0.0.1:7890 \
|
|
77
|
+
HTTPS_PROXY=http://127.0.0.1:7890 \
|
|
78
|
+
NO_PROXY=localhost,127.0.0.1 \
|
|
79
|
+
npx @wangjian2254/pi-web@latest
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Windows PowerShell:
|
|
83
|
+
|
|
84
|
+
```powershell
|
|
85
|
+
$env:HTTP_PROXY = "http://127.0.0.1:7890"
|
|
86
|
+
$env:HTTPS_PROXY = "http://127.0.0.1:7890"
|
|
87
|
+
$env:NO_PROXY = "localhost,127.0.0.1"
|
|
88
|
+
npx @wangjian2254/pi-web@latest
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 注意事项
|
|
92
|
+
|
|
93
|
+
- **智能体数据**:Pi Web 默认读取 `~/.pi/agent` 下的 pi 数据,包括 `sessions/<编码后的工作目录>/<时间戳>_<uuid>.jsonl` 中的会话文件。可通过 `PI_CODING_AGENT_DIR` 指定其他 pi agent 目录。
|
|
94
|
+
- **文件系统访问**:Pi Web 必须能读取智能体数据目录及会话记录中的工作目录。与现有 pi 会话共用数据时,请让 Pi Web 运行在与 pi 相同的文件系统环境中。
|
|
95
|
+
- **共享配置**:模型面板使用 pi 的模型、设置和凭据存储,因此两种界面都能看到相关更改。
|
|
96
|
+
- **文件访问边界**:文件浏览器仅能访问在 Pi Web 中选择过的工作目录,以及它已识别的项目或会话根目录;它不是通用的文件系统浏览器。
|
|
97
|
+
- **Git worktree**:切换器何时显示、如何创建 worktree,以及删除会产生什么影响,见 [Pi Web 里的 Worktree](./docs/worktrees.zh-CN.md)。
|
|
98
|
+
|
|
99
|
+
## 开发
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm install
|
|
103
|
+
npm run dev
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
开发服务器运行在 [http://127.0.0.1:30141](http://127.0.0.1:30141)。常用检查命令:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npm test
|
|
110
|
+
node_modules/.bin/tsc --noEmit
|
|
111
|
+
npm run lint
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
日常开发时不要运行 `next build` 或 `npm run build`。它们会写入 `.next/`,可能干扰开发服务器;仅在发布流程中执行构建。
|
|
115
|
+
|
|
116
|
+
贡献者文档:[国际化](./docs/i18n.md)和[发布流程](./docs/release.md)。
|
|
117
|
+
|
|
118
|
+
## 仓库结构
|
|
119
|
+
|
|
120
|
+
```text
|
|
121
|
+
app/ Next.js 界面和 API 路由
|
|
122
|
+
components/ React 界面组件
|
|
123
|
+
hooks/ 客户端状态和交互 hooks
|
|
124
|
+
lib/ 会话、智能体、模型、文件、Git 和安全逻辑
|
|
125
|
+
public/ 静态资源和 PWA 文件
|
|
126
|
+
bin/ npm CLI 入口及启动参数解析
|
|
127
|
+
docs/ 面向用户和贡献者的专题文档
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
架构说明和详细文件地图见 [AGENTS.md](./AGENTS.md)。
|
|
131
|
+
|
|
132
|
+
## 许可证
|
|
133
|
+
|
|
134
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const MIN_NODE_VERSION = "22.19.0";
|
|
4
|
+
|
|
5
|
+
function parseNodeVersion(version) {
|
|
6
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)/.exec(version);
|
|
7
|
+
if (!match) return null;
|
|
8
|
+
return match.slice(1).map(Number);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function isNodeVersionSupported(version) {
|
|
12
|
+
const current = parseNodeVersion(version);
|
|
13
|
+
const minimum = parseNodeVersion(MIN_NODE_VERSION);
|
|
14
|
+
if (!current || !minimum) return false;
|
|
15
|
+
|
|
16
|
+
for (let index = 0; index < minimum.length; index += 1) {
|
|
17
|
+
if (current[index] > minimum[index]) return true;
|
|
18
|
+
if (current[index] < minimum[index]) return false;
|
|
19
|
+
}
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getUnsupportedNodeVersionMessage(version) {
|
|
24
|
+
return [
|
|
25
|
+
`Pi Web requires Node.js ${MIN_NODE_VERSION} or newer.`,
|
|
26
|
+
`Current Node.js version: ${version}.`,
|
|
27
|
+
"Upgrade Node.js and try again: https://nodejs.org/",
|
|
28
|
+
].join("\n");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = {
|
|
32
|
+
MIN_NODE_VERSION,
|
|
33
|
+
getUnsupportedNodeVersionMessage,
|
|
34
|
+
isNodeVersionSupported,
|
|
35
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
4
|
+
const { parseArgs } = require("util");
|
|
5
|
+
|
|
6
|
+
const TRUE_VALUES = new Set(["1", "true", "yes", "on"]);
|
|
7
|
+
|
|
8
|
+
function isEnabled(value) {
|
|
9
|
+
return typeof value === "string" && TRUE_VALUES.has(value.trim().toLowerCase());
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function normalizePort(value) {
|
|
13
|
+
if (typeof value !== "string" || !/^\d+$/.test(value)) {
|
|
14
|
+
throw new Error("Port must be a non-negative integer.");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const port = Number(value);
|
|
18
|
+
if (!Number.isSafeInteger(port) || port > 65535) {
|
|
19
|
+
throw new Error("Port must be between 0 and 65535.");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return String(port);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function parseLaunchOptions(args = process.argv.slice(2), env = process.env) {
|
|
26
|
+
const { values: cliArgs } = parseArgs({
|
|
27
|
+
args,
|
|
28
|
+
options: {
|
|
29
|
+
port: { type: "string", short: "p" },
|
|
30
|
+
hostname: { type: "string", short: "H" },
|
|
31
|
+
"no-open": { type: "boolean" },
|
|
32
|
+
},
|
|
33
|
+
strict: false,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
port: normalizePort(cliArgs.port ?? env.PORT ?? "30141"),
|
|
38
|
+
hostname: cliArgs.hostname ?? env.PI_WEB_HOSTNAME ?? "127.0.0.1",
|
|
39
|
+
openBrowser: !cliArgs["no-open"] && !isEnabled(env.PI_WEB_NO_OPEN),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = { parseLaunchOptions };
|
package/bin/pi-web.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
5
|
+
const { getUnsupportedNodeVersionMessage, isNodeVersionSupported } = require("./node-version");
|
|
6
|
+
|
|
7
|
+
if (!isNodeVersionSupported(process.versions.node)) {
|
|
8
|
+
console.error(getUnsupportedNodeVersionMessage(process.versions.node));
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
|
+
const { spawn } = require("child_process");
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
15
|
+
const path = require("path");
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
17
|
+
const fs = require("fs");
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
19
|
+
const { parseLaunchOptions } = require("./pi-web-options");
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
21
|
+
const { wireChildProcessLifecycle } = require("./process-lifecycle");
|
|
22
|
+
|
|
23
|
+
const pkgDir = path.join(__dirname, "..");
|
|
24
|
+
const nextDir = path.join(pkgDir, ".next");
|
|
25
|
+
|
|
26
|
+
// Resolve next's CLI entry directly to avoid relying on .bin symlinks (which
|
|
27
|
+
// may not exist when installed via npx).
|
|
28
|
+
let nextBin;
|
|
29
|
+
try {
|
|
30
|
+
nextBin = require.resolve("next/dist/bin/next", { paths: [pkgDir] });
|
|
31
|
+
} catch {
|
|
32
|
+
// Fallback: locate next package root and derive the bin path manually.
|
|
33
|
+
try {
|
|
34
|
+
const nextPkg = require.resolve("next/package.json", { paths: [pkgDir] });
|
|
35
|
+
nextBin = path.join(path.dirname(nextPkg), "dist", "bin", "next");
|
|
36
|
+
} catch {
|
|
37
|
+
nextBin = path.join(pkgDir, "node_modules", "next", "dist", "bin", "next");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const { port, hostname, openBrowser } = parseLaunchOptions();
|
|
42
|
+
const loopbackHostnames = new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
|
|
43
|
+
const passwordEnabled = Boolean(process.env.PI_WEB_PASSWORD);
|
|
44
|
+
|
|
45
|
+
if (!fs.existsSync(nextDir)) {
|
|
46
|
+
console.error("Build artifacts not found. Please report this issue.");
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!loopbackHostnames.has(hostname)) {
|
|
51
|
+
if (passwordEnabled) {
|
|
52
|
+
console.warn(
|
|
53
|
+
`Warning: pi-web is listening on ${hostname} with Basic Auth over HTTP. Use HTTPS or a trusted VPN to protect the password in transit.`,
|
|
54
|
+
);
|
|
55
|
+
} else {
|
|
56
|
+
console.warn(
|
|
57
|
+
`Warning: pi-web is listening on ${hostname} without authentication. Only use this on a trusted network.`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const nextArgs = ["start", "-p", port];
|
|
63
|
+
nextArgs.push("-H", hostname);
|
|
64
|
+
|
|
65
|
+
// Always run next's JS entry with node directly — avoids .bin symlink issues
|
|
66
|
+
// and path-with-spaces problems on Windows when shell: true is used.
|
|
67
|
+
const child = spawn(process.execPath, [nextBin, ...nextArgs], {
|
|
68
|
+
cwd: pkgDir,
|
|
69
|
+
stdio: ["inherit", "pipe", "inherit"],
|
|
70
|
+
env: { ...process.env, PI_WEB_HOSTNAME: hostname },
|
|
71
|
+
});
|
|
72
|
+
wireChildProcessLifecycle(child);
|
|
73
|
+
|
|
74
|
+
let browserOpened = false;
|
|
75
|
+
const url = `http://${hostname}:${port}`;
|
|
76
|
+
|
|
77
|
+
child.stdout.on("data", (chunk) => {
|
|
78
|
+
const text = chunk.toString();
|
|
79
|
+
process.stdout.write(text);
|
|
80
|
+
if (openBrowser && !browserOpened && text.includes("Ready")) {
|
|
81
|
+
browserOpened = true;
|
|
82
|
+
const isWindows = process.platform === "win32";
|
|
83
|
+
const isMac = process.platform === "darwin";
|
|
84
|
+
// Avoid `shell: true` to suppress Node.js DEP0190 deprecation
|
|
85
|
+
// ("Passing args to a child process with shell option true can lead to
|
|
86
|
+
// security vulnerabilities, as the arguments are not escaped").
|
|
87
|
+
// Pass a structured argv so Node.js handles escaping instead of
|
|
88
|
+
// concatenating the args into a shell command string.
|
|
89
|
+
let opener;
|
|
90
|
+
if (isWindows) {
|
|
91
|
+
// `start` is a cmd.exe built-in, so invoke cmd directly. The empty
|
|
92
|
+
// title argument is required by `start` before the target URL.
|
|
93
|
+
opener = spawn(process.env.ComSpec || "cmd.exe", ["/c", "start", "", url], {
|
|
94
|
+
stdio: "ignore",
|
|
95
|
+
detached: true,
|
|
96
|
+
});
|
|
97
|
+
} else if (isMac) {
|
|
98
|
+
opener = spawn("open", [url], {
|
|
99
|
+
stdio: "ignore",
|
|
100
|
+
detached: true,
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
opener = spawn("xdg-open", [url], {
|
|
104
|
+
stdio: "ignore",
|
|
105
|
+
detached: true,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
opener.on("error", (error) => {
|
|
110
|
+
console.warn(`Could not open browser automatically: ${error.message}`);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
opener.unref();
|
|
114
|
+
}
|
|
115
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
4
|
+
const os = require("node:os");
|
|
5
|
+
|
|
6
|
+
const forwardedSignals = ["SIGINT", "SIGTERM"];
|
|
7
|
+
const shutdownTimeoutMs = 5_000;
|
|
8
|
+
|
|
9
|
+
function getSignalExitCode(signal) {
|
|
10
|
+
const signalNumber = signal ? os.constants.signals[signal] : undefined;
|
|
11
|
+
return typeof signalNumber === "number" ? 128 + signalNumber : 1;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function wireChildProcessLifecycle(child, parentProcess = process, timeoutMs = shutdownTimeoutMs) {
|
|
15
|
+
const signalHandlers = new Map();
|
|
16
|
+
let shutdownTimer;
|
|
17
|
+
|
|
18
|
+
const forceKill = () => child.kill("SIGKILL");
|
|
19
|
+
|
|
20
|
+
for (const signal of forwardedSignals) {
|
|
21
|
+
const handler = () => {
|
|
22
|
+
if (shutdownTimer) {
|
|
23
|
+
forceKill();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
shutdownTimer = setTimeout(forceKill, timeoutMs);
|
|
28
|
+
shutdownTimer.unref();
|
|
29
|
+
child.kill(signal);
|
|
30
|
+
};
|
|
31
|
+
signalHandlers.set(signal, handler);
|
|
32
|
+
parentProcess.on(signal, handler);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
child.once("exit", (code, signal) => {
|
|
36
|
+
if (shutdownTimer) clearTimeout(shutdownTimer);
|
|
37
|
+
|
|
38
|
+
for (const [forwardedSignal, handler] of signalHandlers) {
|
|
39
|
+
parentProcess.removeListener(forwardedSignal, handler);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
parentProcess.exit(code ?? getSignalExitCode(signal));
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = { wireChildProcessLifecycle };
|