@rexvane/piweb 0.3.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 (535) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +128 -0
  3. package/assets/showcase.png +0 -0
  4. package/bin/pi.js +50 -0
  5. package/bin/piweb.js +12 -0
  6. package/next.config.ts +21 -0
  7. package/package.json +88 -0
  8. package/postcss.config.mjs +7 -0
  9. package/public/file-icons/3d.svg +1 -0
  10. package/public/file-icons/LICENSE +8 -0
  11. package/public/file-icons/adobe-illustrator.svg +1 -0
  12. package/public/file-icons/adobe-photoshop.svg +1 -0
  13. package/public/file-icons/agent.svg +1 -0
  14. package/public/file-icons/asciidoc.svg +1 -0
  15. package/public/file-icons/assembly.svg +1 -0
  16. package/public/file-icons/astro.svg +1 -0
  17. package/public/file-icons/audio.svg +1 -0
  18. package/public/file-icons/authors.svg +1 -0
  19. package/public/file-icons/babel.svg +1 -0
  20. package/public/file-icons/bibliography.svg +1 -0
  21. package/public/file-icons/bicep.svg +1 -0
  22. package/public/file-icons/blender.svg +1 -0
  23. package/public/file-icons/bun.svg +1 -0
  24. package/public/file-icons/c.svg +1 -0
  25. package/public/file-icons/certificate.svg +1 -0
  26. package/public/file-icons/changelog.svg +1 -0
  27. package/public/file-icons/clojure.svg +1 -0
  28. package/public/file-icons/cmake.svg +1 -0
  29. package/public/file-icons/codeowners.svg +1 -0
  30. package/public/file-icons/commitlint.svg +1 -0
  31. package/public/file-icons/conduct.svg +1 -0
  32. package/public/file-icons/console.svg +1 -0
  33. package/public/file-icons/contributing.svg +1 -0
  34. package/public/file-icons/cpp.svg +1 -0
  35. package/public/file-icons/csharp.svg +1 -0
  36. package/public/file-icons/css.svg +1 -0
  37. package/public/file-icons/cursor.svg +1 -0
  38. package/public/file-icons/dart.svg +1 -0
  39. package/public/file-icons/database.svg +1 -0
  40. package/public/file-icons/deno.svg +1 -0
  41. package/public/file-icons/diff.svg +1 -0
  42. package/public/file-icons/docker.svg +1 -0
  43. package/public/file-icons/document.svg +1 -0
  44. package/public/file-icons/editorconfig.svg +1 -0
  45. package/public/file-icons/ejs.svg +1 -0
  46. package/public/file-icons/elixir.svg +1 -0
  47. package/public/file-icons/elm.svg +1 -0
  48. package/public/file-icons/email.svg +1 -0
  49. package/public/file-icons/erlang.svg +1 -0
  50. package/public/file-icons/eslint.svg +1 -0
  51. package/public/file-icons/favicon.svg +1 -0
  52. package/public/file-icons/file.svg +1 -0
  53. package/public/file-icons/folder-admin-open.svg +1 -0
  54. package/public/file-icons/folder-admin.svg +1 -0
  55. package/public/file-icons/folder-android-open.svg +1 -0
  56. package/public/file-icons/folder-android.svg +1 -0
  57. package/public/file-icons/folder-api-open.svg +1 -0
  58. package/public/file-icons/folder-api.svg +1 -0
  59. package/public/file-icons/folder-app-open.svg +1 -0
  60. package/public/file-icons/folder-app.svg +1 -0
  61. package/public/file-icons/folder-archive-open.svg +1 -0
  62. package/public/file-icons/folder-archive.svg +1 -0
  63. package/public/file-icons/folder-atom-open.svg +1 -0
  64. package/public/file-icons/folder-atom.svg +1 -0
  65. package/public/file-icons/folder-audio-open.svg +1 -0
  66. package/public/file-icons/folder-audio.svg +1 -0
  67. package/public/file-icons/folder-aws-open.svg +1 -0
  68. package/public/file-icons/folder-aws.svg +1 -0
  69. package/public/file-icons/folder-backup-open.svg +1 -0
  70. package/public/file-icons/folder-backup.svg +1 -0
  71. package/public/file-icons/folder-benchmark-open.svg +1 -0
  72. package/public/file-icons/folder-benchmark.svg +1 -0
  73. package/public/file-icons/folder-cart-open.svg +1 -0
  74. package/public/file-icons/folder-cart.svg +1 -0
  75. package/public/file-icons/folder-ci-open.svg +1 -0
  76. package/public/file-icons/folder-ci.svg +1 -0
  77. package/public/file-icons/folder-circleci-open.svg +1 -0
  78. package/public/file-icons/folder-circleci.svg +1 -0
  79. package/public/file-icons/folder-class-open.svg +1 -0
  80. package/public/file-icons/folder-class.svg +1 -0
  81. package/public/file-icons/folder-client-open.svg +1 -0
  82. package/public/file-icons/folder-client.svg +1 -0
  83. package/public/file-icons/folder-command-open.svg +1 -0
  84. package/public/file-icons/folder-command.svg +1 -0
  85. package/public/file-icons/folder-components-open.svg +1 -0
  86. package/public/file-icons/folder-components.svg +1 -0
  87. package/public/file-icons/folder-config-open.svg +1 -0
  88. package/public/file-icons/folder-config.svg +1 -0
  89. package/public/file-icons/folder-console-open.svg +1 -0
  90. package/public/file-icons/folder-console.svg +1 -0
  91. package/public/file-icons/folder-content-open.svg +1 -0
  92. package/public/file-icons/folder-content.svg +1 -0
  93. package/public/file-icons/folder-context-open.svg +1 -0
  94. package/public/file-icons/folder-context.svg +1 -0
  95. package/public/file-icons/folder-contract-open.svg +1 -0
  96. package/public/file-icons/folder-contract.svg +1 -0
  97. package/public/file-icons/folder-controller-open.svg +1 -0
  98. package/public/file-icons/folder-controller.svg +1 -0
  99. package/public/file-icons/folder-core-open.svg +1 -0
  100. package/public/file-icons/folder-core.svg +1 -0
  101. package/public/file-icons/folder-coverage-open.svg +1 -0
  102. package/public/file-icons/folder-coverage.svg +1 -0
  103. package/public/file-icons/folder-css-open.svg +1 -0
  104. package/public/file-icons/folder-css.svg +1 -0
  105. package/public/file-icons/folder-database-open.svg +1 -0
  106. package/public/file-icons/folder-database.svg +1 -0
  107. package/public/file-icons/folder-debug-open.svg +1 -0
  108. package/public/file-icons/folder-debug.svg +1 -0
  109. package/public/file-icons/folder-deprecated-open.svg +1 -0
  110. package/public/file-icons/folder-deprecated.svg +1 -0
  111. package/public/file-icons/folder-desktop-open.svg +1 -0
  112. package/public/file-icons/folder-desktop.svg +1 -0
  113. package/public/file-icons/folder-dist-open.svg +1 -0
  114. package/public/file-icons/folder-dist.svg +1 -0
  115. package/public/file-icons/folder-docker-open.svg +1 -0
  116. package/public/file-icons/folder-docker.svg +1 -0
  117. package/public/file-icons/folder-docs-open.svg +1 -0
  118. package/public/file-icons/folder-docs.svg +1 -0
  119. package/public/file-icons/folder-element-open.svg +1 -0
  120. package/public/file-icons/folder-element.svg +1 -0
  121. package/public/file-icons/folder-environment-open.svg +1 -0
  122. package/public/file-icons/folder-environment.svg +1 -0
  123. package/public/file-icons/folder-event-open.svg +1 -0
  124. package/public/file-icons/folder-event.svg +1 -0
  125. package/public/file-icons/folder-examples-open.svg +1 -0
  126. package/public/file-icons/folder-examples.svg +1 -0
  127. package/public/file-icons/folder-features-open.svg +1 -0
  128. package/public/file-icons/folder-features.svg +1 -0
  129. package/public/file-icons/folder-font-open.svg +1 -0
  130. package/public/file-icons/folder-font.svg +1 -0
  131. package/public/file-icons/folder-functions-open.svg +1 -0
  132. package/public/file-icons/folder-functions.svg +1 -0
  133. package/public/file-icons/folder-generator-open.svg +1 -0
  134. package/public/file-icons/folder-generator.svg +1 -0
  135. package/public/file-icons/folder-git-open.svg +1 -0
  136. package/public/file-icons/folder-git.svg +1 -0
  137. package/public/file-icons/folder-github-open.svg +1 -0
  138. package/public/file-icons/folder-github.svg +1 -0
  139. package/public/file-icons/folder-gitlab-open.svg +1 -0
  140. package/public/file-icons/folder-gitlab.svg +1 -0
  141. package/public/file-icons/folder-graphql-open.svg +1 -0
  142. package/public/file-icons/folder-graphql.svg +1 -0
  143. package/public/file-icons/folder-helper-open.svg +1 -0
  144. package/public/file-icons/folder-helper.svg +1 -0
  145. package/public/file-icons/folder-hook-open.svg +1 -0
  146. package/public/file-icons/folder-hook.svg +1 -0
  147. package/public/file-icons/folder-husky-open.svg +1 -0
  148. package/public/file-icons/folder-husky.svg +1 -0
  149. package/public/file-icons/folder-i18n-open.svg +1 -0
  150. package/public/file-icons/folder-i18n.svg +1 -0
  151. package/public/file-icons/folder-images-open.svg +1 -0
  152. package/public/file-icons/folder-images.svg +1 -0
  153. package/public/file-icons/folder-include-open.svg +1 -0
  154. package/public/file-icons/folder-include.svg +1 -0
  155. package/public/file-icons/folder-intellij-open.svg +1 -0
  156. package/public/file-icons/folder-intellij.svg +1 -0
  157. package/public/file-icons/folder-interface-open.svg +1 -0
  158. package/public/file-icons/folder-interface.svg +1 -0
  159. package/public/file-icons/folder-ios-open.svg +1 -0
  160. package/public/file-icons/folder-ios.svg +1 -0
  161. package/public/file-icons/folder-java-open.svg +1 -0
  162. package/public/file-icons/folder-java.svg +1 -0
  163. package/public/file-icons/folder-job-open.svg +1 -0
  164. package/public/file-icons/folder-job.svg +1 -0
  165. package/public/file-icons/folder-jupyter-open.svg +1 -0
  166. package/public/file-icons/folder-jupyter.svg +1 -0
  167. package/public/file-icons/folder-keys-open.svg +1 -0
  168. package/public/file-icons/folder-keys.svg +1 -0
  169. package/public/file-icons/folder-kubernetes-open.svg +1 -0
  170. package/public/file-icons/folder-kubernetes.svg +1 -0
  171. package/public/file-icons/folder-layout-open.svg +1 -0
  172. package/public/file-icons/folder-layout.svg +1 -0
  173. package/public/file-icons/folder-less-open.svg +1 -0
  174. package/public/file-icons/folder-less.svg +1 -0
  175. package/public/file-icons/folder-lib-open.svg +1 -0
  176. package/public/file-icons/folder-lib.svg +1 -0
  177. package/public/file-icons/folder-log-open.svg +1 -0
  178. package/public/file-icons/folder-log.svg +1 -0
  179. package/public/file-icons/folder-messages-open.svg +1 -0
  180. package/public/file-icons/folder-messages.svg +1 -0
  181. package/public/file-icons/folder-meta-open.svg +1 -0
  182. package/public/file-icons/folder-meta.svg +1 -0
  183. package/public/file-icons/folder-middleware-open.svg +1 -0
  184. package/public/file-icons/folder-middleware.svg +1 -0
  185. package/public/file-icons/folder-migrations-open.svg +1 -0
  186. package/public/file-icons/folder-migrations.svg +1 -0
  187. package/public/file-icons/folder-mobile-open.svg +1 -0
  188. package/public/file-icons/folder-mobile.svg +1 -0
  189. package/public/file-icons/folder-mock-open.svg +1 -0
  190. package/public/file-icons/folder-mock.svg +1 -0
  191. package/public/file-icons/folder-molecule-open.svg +1 -0
  192. package/public/file-icons/folder-molecule.svg +1 -0
  193. package/public/file-icons/folder-next-open.svg +1 -0
  194. package/public/file-icons/folder-next.svg +1 -0
  195. package/public/file-icons/folder-node-open.svg +1 -0
  196. package/public/file-icons/folder-node.svg +1 -0
  197. package/public/file-icons/folder-nuxt-open.svg +1 -0
  198. package/public/file-icons/folder-nuxt.svg +1 -0
  199. package/public/file-icons/folder-open.svg +1 -0
  200. package/public/file-icons/folder-organism-open.svg +1 -0
  201. package/public/file-icons/folder-organism.svg +1 -0
  202. package/public/file-icons/folder-packages-open.svg +1 -0
  203. package/public/file-icons/folder-packages.svg +1 -0
  204. package/public/file-icons/folder-plugin-open.svg +1 -0
  205. package/public/file-icons/folder-plugin.svg +1 -0
  206. package/public/file-icons/folder-prisma-open.svg +1 -0
  207. package/public/file-icons/folder-prisma.svg +1 -0
  208. package/public/file-icons/folder-prompts-open.svg +1 -0
  209. package/public/file-icons/folder-prompts.svg +1 -0
  210. package/public/file-icons/folder-proto-open.svg +1 -0
  211. package/public/file-icons/folder-proto.svg +1 -0
  212. package/public/file-icons/folder-public-open.svg +1 -0
  213. package/public/file-icons/folder-public.svg +1 -0
  214. package/public/file-icons/folder-python-open.svg +1 -0
  215. package/public/file-icons/folder-python.svg +1 -0
  216. package/public/file-icons/folder-queue-open.svg +1 -0
  217. package/public/file-icons/folder-queue.svg +1 -0
  218. package/public/file-icons/folder-resource-open.svg +1 -0
  219. package/public/file-icons/folder-resource.svg +1 -0
  220. package/public/file-icons/folder-review-open.svg +1 -0
  221. package/public/file-icons/folder-review.svg +1 -0
  222. package/public/file-icons/folder-robot-open.svg +1 -0
  223. package/public/file-icons/folder-robot.svg +1 -0
  224. package/public/file-icons/folder-routes-open.svg +1 -0
  225. package/public/file-icons/folder-routes.svg +1 -0
  226. package/public/file-icons/folder-rust-open.svg +1 -0
  227. package/public/file-icons/folder-rust.svg +1 -0
  228. package/public/file-icons/folder-sass-open.svg +1 -0
  229. package/public/file-icons/folder-sass.svg +1 -0
  230. package/public/file-icons/folder-scripts-open.svg +1 -0
  231. package/public/file-icons/folder-scripts.svg +1 -0
  232. package/public/file-icons/folder-secure-open.svg +1 -0
  233. package/public/file-icons/folder-secure.svg +1 -0
  234. package/public/file-icons/folder-seeders-open.svg +1 -0
  235. package/public/file-icons/folder-seeders.svg +1 -0
  236. package/public/file-icons/folder-server-open.svg +1 -0
  237. package/public/file-icons/folder-server.svg +1 -0
  238. package/public/file-icons/folder-shared-open.svg +1 -0
  239. package/public/file-icons/folder-shared.svg +1 -0
  240. package/public/file-icons/folder-skills-open.svg +1 -0
  241. package/public/file-icons/folder-skills.svg +1 -0
  242. package/public/file-icons/folder-src-open.svg +1 -0
  243. package/public/file-icons/folder-src.svg +1 -0
  244. package/public/file-icons/folder-store-open.svg +1 -0
  245. package/public/file-icons/folder-store.svg +1 -0
  246. package/public/file-icons/folder-storybook-open.svg +1 -0
  247. package/public/file-icons/folder-storybook.svg +1 -0
  248. package/public/file-icons/folder-supabase-open.svg +1 -0
  249. package/public/file-icons/folder-supabase.svg +1 -0
  250. package/public/file-icons/folder-svelte-open.svg +1 -0
  251. package/public/file-icons/folder-svelte.svg +1 -0
  252. package/public/file-icons/folder-target-open.svg +1 -0
  253. package/public/file-icons/folder-target.svg +1 -0
  254. package/public/file-icons/folder-tasks-open.svg +1 -0
  255. package/public/file-icons/folder-tasks.svg +1 -0
  256. package/public/file-icons/folder-temp-open.svg +1 -0
  257. package/public/file-icons/folder-temp.svg +1 -0
  258. package/public/file-icons/folder-template-open.svg +1 -0
  259. package/public/file-icons/folder-template.svg +1 -0
  260. package/public/file-icons/folder-terraform-open.svg +1 -0
  261. package/public/file-icons/folder-terraform.svg +1 -0
  262. package/public/file-icons/folder-test-open.svg +1 -0
  263. package/public/file-icons/folder-test.svg +1 -0
  264. package/public/file-icons/folder-theme-open.svg +1 -0
  265. package/public/file-icons/folder-theme.svg +1 -0
  266. package/public/file-icons/folder-tools-open.svg +1 -0
  267. package/public/file-icons/folder-tools.svg +1 -0
  268. package/public/file-icons/folder-turborepo-open.svg +1 -0
  269. package/public/file-icons/folder-turborepo.svg +1 -0
  270. package/public/file-icons/folder-typescript-open.svg +1 -0
  271. package/public/file-icons/folder-typescript.svg +1 -0
  272. package/public/file-icons/folder-ui-open.svg +1 -0
  273. package/public/file-icons/folder-ui.svg +1 -0
  274. package/public/file-icons/folder-utils-open.svg +1 -0
  275. package/public/file-icons/folder-utils.svg +1 -0
  276. package/public/file-icons/folder-video-open.svg +1 -0
  277. package/public/file-icons/folder-video.svg +1 -0
  278. package/public/file-icons/folder-views-open.svg +1 -0
  279. package/public/file-icons/folder-views.svg +1 -0
  280. package/public/file-icons/folder-vscode-open.svg +1 -0
  281. package/public/file-icons/folder-vscode.svg +1 -0
  282. package/public/file-icons/folder.svg +1 -0
  283. package/public/file-icons/font.svg +1 -0
  284. package/public/file-icons/fsharp.svg +1 -0
  285. package/public/file-icons/gemfile.svg +1 -0
  286. package/public/file-icons/git.svg +1 -0
  287. package/public/file-icons/go-mod.svg +1 -0
  288. package/public/file-icons/go.svg +1 -0
  289. package/public/file-icons/gradle.svg +1 -0
  290. package/public/file-icons/graphql.svg +1 -0
  291. package/public/file-icons/groovy.svg +1 -0
  292. package/public/file-icons/h.svg +1 -0
  293. package/public/file-icons/handlebars.svg +1 -0
  294. package/public/file-icons/haskell.svg +1 -0
  295. package/public/file-icons/hcl.svg +1 -0
  296. package/public/file-icons/heroku.svg +1 -0
  297. package/public/file-icons/hpp.svg +1 -0
  298. package/public/file-icons/html.svg +1 -0
  299. package/public/file-icons/husky.svg +1 -0
  300. package/public/file-icons/i18n.svg +1 -0
  301. package/public/file-icons/image.svg +1 -0
  302. package/public/file-icons/java.svg +1 -0
  303. package/public/file-icons/javascript.svg +1 -0
  304. package/public/file-icons/jenkins.svg +1 -0
  305. package/public/file-icons/jest.svg +1 -0
  306. package/public/file-icons/jsconfig.svg +1 -0
  307. package/public/file-icons/json.svg +1 -0
  308. package/public/file-icons/julia.svg +1 -0
  309. package/public/file-icons/jupyter.svg +1 -0
  310. package/public/file-icons/just.svg +1 -0
  311. package/public/file-icons/key.svg +1 -0
  312. package/public/file-icons/kotlin.svg +1 -0
  313. package/public/file-icons/lerna.svg +1 -0
  314. package/public/file-icons/less.svg +1 -0
  315. package/public/file-icons/license.svg +1 -0
  316. package/public/file-icons/lintstaged.svg +1 -0
  317. package/public/file-icons/liquid.svg +1 -0
  318. package/public/file-icons/lock.svg +1 -0
  319. package/public/file-icons/log.svg +1 -0
  320. package/public/file-icons/lua.svg +1 -0
  321. package/public/file-icons/makefile.svg +1 -0
  322. package/public/file-icons/markdown.svg +1 -0
  323. package/public/file-icons/maven.svg +1 -0
  324. package/public/file-icons/mdx.svg +1 -0
  325. package/public/file-icons/netlify.svg +1 -0
  326. package/public/file-icons/next.svg +1 -0
  327. package/public/file-icons/nim.svg +1 -0
  328. package/public/file-icons/nix.svg +1 -0
  329. package/public/file-icons/nodejs.svg +1 -0
  330. package/public/file-icons/nodemon.svg +1 -0
  331. package/public/file-icons/npm.svg +1 -0
  332. package/public/file-icons/nx.svg +1 -0
  333. package/public/file-icons/objective-c.svg +1 -0
  334. package/public/file-icons/objective-cpp.svg +1 -0
  335. package/public/file-icons/ocaml.svg +1 -0
  336. package/public/file-icons/pdf.svg +1 -0
  337. package/public/file-icons/php.svg +1 -0
  338. package/public/file-icons/pm2-ecosystem.svg +1 -0
  339. package/public/file-icons/pnpm.svg +1 -0
  340. package/public/file-icons/poetry.svg +1 -0
  341. package/public/file-icons/postcss.svg +1 -0
  342. package/public/file-icons/powerpoint.svg +1 -0
  343. package/public/file-icons/powershell.svg +1 -0
  344. package/public/file-icons/prettier.svg +1 -0
  345. package/public/file-icons/prisma.svg +1 -0
  346. package/public/file-icons/prolog.svg +1 -0
  347. package/public/file-icons/proto.svg +1 -0
  348. package/public/file-icons/pug.svg +1 -0
  349. package/public/file-icons/python-misc.svg +1 -0
  350. package/public/file-icons/python.svg +1 -0
  351. package/public/file-icons/r.svg +1 -0
  352. package/public/file-icons/razor.svg +1 -0
  353. package/public/file-icons/react.svg +1 -0
  354. package/public/file-icons/react_ts.svg +1 -0
  355. package/public/file-icons/readme.svg +1 -0
  356. package/public/file-icons/renovate.svg +1 -0
  357. package/public/file-icons/robots.svg +1 -0
  358. package/public/file-icons/rollup.svg +1 -0
  359. package/public/file-icons/ruby.svg +1 -0
  360. package/public/file-icons/rust.svg +1 -0
  361. package/public/file-icons/sass.svg +1 -0
  362. package/public/file-icons/scala.svg +1 -0
  363. package/public/file-icons/semantic-release.svg +1 -0
  364. package/public/file-icons/settings.svg +1 -0
  365. package/public/file-icons/shader.svg +1 -0
  366. package/public/file-icons/sml.svg +1 -0
  367. package/public/file-icons/solidity.svg +1 -0
  368. package/public/file-icons/stylus.svg +1 -0
  369. package/public/file-icons/svelte.svg +1 -0
  370. package/public/file-icons/svg.svg +1 -0
  371. package/public/file-icons/swift.svg +1 -0
  372. package/public/file-icons/table.svg +1 -0
  373. package/public/file-icons/tailwindcss.svg +1 -0
  374. package/public/file-icons/taskfile.svg +1 -0
  375. package/public/file-icons/terraform.svg +1 -0
  376. package/public/file-icons/test-js.svg +1 -0
  377. package/public/file-icons/test-jsx.svg +1 -0
  378. package/public/file-icons/test-ts.svg +1 -0
  379. package/public/file-icons/tex.svg +1 -0
  380. package/public/file-icons/toml.svg +1 -0
  381. package/public/file-icons/travis.svg +1 -0
  382. package/public/file-icons/tsconfig.svg +1 -0
  383. package/public/file-icons/tune.svg +1 -0
  384. package/public/file-icons/turborepo.svg +1 -0
  385. package/public/file-icons/typescript-def.svg +1 -0
  386. package/public/file-icons/typescript.svg +1 -0
  387. package/public/file-icons/unity.svg +1 -0
  388. package/public/file-icons/uv.svg +1 -0
  389. package/public/file-icons/vala.svg +1 -0
  390. package/public/file-icons/vercel.svg +1 -0
  391. package/public/file-icons/video.svg +1 -0
  392. package/public/file-icons/vim.svg +1 -0
  393. package/public/file-icons/vite.svg +1 -0
  394. package/public/file-icons/vitest.svg +1 -0
  395. package/public/file-icons/vlang.svg +1 -0
  396. package/public/file-icons/vue.svg +1 -0
  397. package/public/file-icons/webassembly.svg +1 -0
  398. package/public/file-icons/webpack.svg +1 -0
  399. package/public/file-icons/word.svg +1 -0
  400. package/public/file-icons/xml.svg +1 -0
  401. package/public/file-icons/yaml.svg +1 -0
  402. package/public/file-icons/yarn.svg +1 -0
  403. package/public/file-icons/zig.svg +1 -0
  404. package/public/file-icons/zip.svg +1 -0
  405. package/public/provider-icons/antgroup-color.svg +1 -0
  406. package/public/provider-icons/anthropic.svg +1 -0
  407. package/public/provider-icons/azure-color.svg +1 -0
  408. package/public/provider-icons/baseten.svg +1 -0
  409. package/public/provider-icons/bedrock-color.svg +1 -0
  410. package/public/provider-icons/cerebras-color.svg +1 -0
  411. package/public/provider-icons/cloudflare-color.svg +1 -0
  412. package/public/provider-icons/deepseek-color.svg +1 -0
  413. package/public/provider-icons/fireworks-color.svg +1 -0
  414. package/public/provider-icons/githubcopilot.svg +1 -0
  415. package/public/provider-icons/google-color.svg +1 -0
  416. package/public/provider-icons/googlecloud-color.svg +1 -0
  417. package/public/provider-icons/groq.svg +1 -0
  418. package/public/provider-icons/huggingface-color.svg +1 -0
  419. package/public/provider-icons/kimi-color.svg +1 -0
  420. package/public/provider-icons/minimax-color.svg +1 -0
  421. package/public/provider-icons/mistral-color.svg +1 -0
  422. package/public/provider-icons/moonshot.svg +1 -0
  423. package/public/provider-icons/nvidia-color.svg +1 -0
  424. package/public/provider-icons/openai.svg +1 -0
  425. package/public/provider-icons/opencode.svg +1 -0
  426. package/public/provider-icons/openrouter-color.svg +1 -0
  427. package/public/provider-icons/qwen-color.svg +1 -0
  428. package/public/provider-icons/together-color.svg +1 -0
  429. package/public/provider-icons/vercel.svg +1 -0
  430. package/public/provider-icons/xai.svg +1 -0
  431. package/public/provider-icons/xiaomimimo.svg +1 -0
  432. package/public/provider-icons/zai.svg +1 -0
  433. package/scripts/build-output.mjs +131 -0
  434. package/scripts/dev.mjs +18 -0
  435. package/scripts/entrypoint.mjs +8 -0
  436. package/scripts/install-build.mjs +134 -0
  437. package/scripts/launcher.mjs +249 -0
  438. package/scripts/pick-folder.ps1 +110 -0
  439. package/scripts/postinstall.mjs +12 -0
  440. package/scripts/process-runner.mjs +60 -0
  441. package/scripts/release.mjs +172 -0
  442. package/scripts/sync-file-icons.mjs +118 -0
  443. package/scripts/sync-provider-icons.mjs +41 -0
  444. package/src/app/api/agent/[id]/events/route.ts +81 -0
  445. package/src/app/api/agent/[id]/route.ts +24 -0
  446. package/src/app/api/agent/[id]/tree/route.ts +49 -0
  447. package/src/app/api/agent/new/route.ts +19 -0
  448. package/src/app/api/config/route.ts +22 -0
  449. package/src/app/api/files/route.ts +63 -0
  450. package/src/app/api/git/route.ts +32 -0
  451. package/src/app/api/growth/route.ts +50 -0
  452. package/src/app/api/health/route.ts +7 -0
  453. package/src/app/api/models/route.ts +129 -0
  454. package/src/app/api/pi-settings/route.ts +22 -0
  455. package/src/app/api/plugins/route.ts +79 -0
  456. package/src/app/api/security/route.ts +41 -0
  457. package/src/app/api/sessions/[id]/export/route.ts +25 -0
  458. package/src/app/api/sessions/[id]/route.ts +37 -0
  459. package/src/app/api/sessions/route.ts +23 -0
  460. package/src/app/api/skills/route.ts +39 -0
  461. package/src/app/api/update/route.ts +33 -0
  462. package/src/app/api/version/route.ts +8 -0
  463. package/src/app/api/web-auth/route.ts +80 -0
  464. package/src/app/api/workspaces/route.ts +78 -0
  465. package/src/app/globals.css +2039 -0
  466. package/src/app/icon.svg +21 -0
  467. package/src/app/layout.tsx +29 -0
  468. package/src/app/login/page.tsx +111 -0
  469. package/src/app/page.tsx +10 -0
  470. package/src/components/AppShell.tsx +1171 -0
  471. package/src/components/ChatInput.tsx +729 -0
  472. package/src/components/ChatWindow.tsx +1320 -0
  473. package/src/components/ContextMeter.tsx +131 -0
  474. package/src/components/DiffView.tsx +139 -0
  475. package/src/components/ExtensionUI.tsx +181 -0
  476. package/src/components/FileViewer.tsx +555 -0
  477. package/src/components/FullDiff.tsx +220 -0
  478. package/src/components/GitPanel.tsx +357 -0
  479. package/src/components/GrowthTree.tsx +317 -0
  480. package/src/components/ModelSelector.tsx +286 -0
  481. package/src/components/OutlineRail.tsx +166 -0
  482. package/src/components/PiMark.tsx +79 -0
  483. package/src/components/ProjectPanel.tsx +309 -0
  484. package/src/components/ProviderBrand.tsx +28 -0
  485. package/src/components/ProviderSetupModal.module.css +560 -0
  486. package/src/components/ProviderSetupModal.tsx +559 -0
  487. package/src/components/SessionSidebar.tsx +1066 -0
  488. package/src/components/SettingsPanel.tsx +2216 -0
  489. package/src/components/TrajectoryAnalyzer.module.css +225 -0
  490. package/src/components/TrajectoryView.tsx +289 -0
  491. package/src/components/icons.tsx +443 -0
  492. package/src/hooks/useFileViewer.ts +58 -0
  493. package/src/hooks/useGrowth.ts +635 -0
  494. package/src/hooks/usePiWeb.ts +900 -0
  495. package/src/i18n.tsx +1043 -0
  496. package/src/lib/agent-manager.ts +1348 -0
  497. package/src/lib/app-root.ts +4 -0
  498. package/src/lib/auth.ts +51 -0
  499. package/src/lib/command-validation.ts +116 -0
  500. package/src/lib/enter-behavior.ts +40 -0
  501. package/src/lib/extension-ui.ts +134 -0
  502. package/src/lib/file-icons.json +557 -0
  503. package/src/lib/file-icons.ts +39 -0
  504. package/src/lib/files-service.ts +280 -0
  505. package/src/lib/git-service.ts +255 -0
  506. package/src/lib/growth-rounds.ts +84 -0
  507. package/src/lib/growth-service.ts +586 -0
  508. package/src/lib/growth-tracker.ts +328 -0
  509. package/src/lib/growth-tree.ts +245 -0
  510. package/src/lib/growth-turns.ts +23 -0
  511. package/src/lib/highlight.ts +59 -0
  512. package/src/lib/model-draft.ts +103 -0
  513. package/src/lib/models-service.ts +852 -0
  514. package/src/lib/path-security.ts +101 -0
  515. package/src/lib/pi-settings.ts +115 -0
  516. package/src/lib/pi.ts +367 -0
  517. package/src/lib/plugins-service.ts +312 -0
  518. package/src/lib/process-format.ts +261 -0
  519. package/src/lib/provider-display.ts +57 -0
  520. package/src/lib/security-service.ts +52 -0
  521. package/src/lib/semver.ts +39 -0
  522. package/src/lib/session-reader.ts +204 -0
  523. package/src/lib/settings-write-lock.ts +45 -0
  524. package/src/lib/skills-service.ts +97 -0
  525. package/src/lib/text-sanitize.ts +20 -0
  526. package/src/lib/theme.ts +137 -0
  527. package/src/lib/trajectory.ts +294 -0
  528. package/src/lib/types.ts +300 -0
  529. package/src/lib/update-service.ts +129 -0
  530. package/src/lib/version.ts +6 -0
  531. package/src/lib/web-auth-shared.ts +35 -0
  532. package/src/lib/web-auth.ts +53 -0
  533. package/src/lib/workspace-store.ts +261 -0
  534. package/src/proxy.ts +53 -0
  535. package/tsconfig.json +49 -0
package/src/i18n.tsx ADDED
@@ -0,0 +1,1043 @@
1
+ "use client";
2
+
3
+ /**
4
+ * 界面语言:简体中文 / English。偏好存 localStorage。
5
+ */
6
+ import { createContext, useCallback, useContext, useEffect, useState } from "react";
7
+
8
+ const zh = {
9
+ // 通用
10
+ confirm: "确认",
11
+ cancel: "取消",
12
+ delete: "删除",
13
+ rename: "重命名",
14
+ renameSession: "重命名会话",
15
+ renameWorkspace: "重命名工作区",
16
+ search: "搜索",
17
+ save: "保存",
18
+ close: "关闭",
19
+ error: "出错",
20
+ copy: "复制",
21
+ copyFailed: "复制失败",
22
+ export: "导出",
23
+ settings: "设置",
24
+ // 侧栏
25
+ newChat: "新会话",
26
+ reconnecting: "连接中断,正在重连…",
27
+ sessionListLoadFailed: "会话列表加载失败",
28
+ retry: "重试",
29
+ compacting: "正在压缩上下文…",
30
+ compactionComplete: "上下文压缩完成",
31
+ compactionFailed: "上下文压缩失败",
32
+ pickWorkspaceFirst: "请先选择工作区",
33
+ capacityFields: "容量",
34
+ contextWindowLabel: "上下文窗口",
35
+ maxTokensLabel: "最大输出",
36
+ capacityHint: "留空用默认 · 支持 256K / 2M 写法",
37
+ capacityInvalid: "第 {n} 行:容量需为数字(可用 K/M)",
38
+ discoverEmpty: "远端没有返回可识别的模型",
39
+ candidateTitle: "发现 {count} 个模型,勾选要添加的",
40
+ candidateAll: "全选",
41
+ candidatePicked: "已选 {n} 个",
42
+ candidateAdopt: "添加 {n} 个",
43
+ runningTool: "Running {name}…",
44
+ thinkingLive: "Thinking",
45
+ stepRunning: "Running",
46
+ stepRan: "已运行",
47
+ stepRead: "读取",
48
+ stepSearched: "搜索",
49
+ stepEdited: "编辑了",
50
+ stepWrote: "写入了",
51
+ resultRead: "读取了 {n} 行",
52
+ resultFound: "找到 {n} 处",
53
+ resultWrote: "{n} 行",
54
+ sumThought: "思考了 {d}",
55
+ sumRan: "运行了 {n} 条命令",
56
+ sumRan1: "运行了 {n} 条命令",
57
+ sumRead: "读了 {n} 个文件",
58
+ sumRead1: "读了 {n} 个文件",
59
+ sumSearched: "搜索了 {n} 次",
60
+ sumSearched1: "搜索了 {n} 次",
61
+ sumJoin: ",",
62
+ toolLines: "{n} 行",
63
+ toolMatches: "{n} 个匹配",
64
+ toolExit: "退出码 {code}",
65
+ toolWritten: "已写入",
66
+ diffSummary: "+{add} −{del} 行",
67
+ backToBottom: "回到底部",
68
+ modeSteer: "插话",
69
+ modeQueue: "排队",
70
+ sendSteer: "插话:当前工具跑完就送达",
71
+ sendQueue: "排队:本轮结束后发送",
72
+ queueEdit: "↑ 取回编辑",
73
+ queueDrop: "丢弃",
74
+ viewInTrajectory: "在轨迹中查看",
75
+ turnRanFor: "耗时 {duration}",
76
+ durationSeconds: "{seconds} 秒",
77
+ durationMinutes: "{minutes} 分 {seconds} 秒",
78
+ clockMd: "{m}月{d}日",
79
+ clockYmd: "{y}年{m}月{d}日",
80
+ turnUsageTitle: "本回合用量",
81
+ filesPanel: "文件",
82
+ outline: "大纲",
83
+ moreActions: "更多",
84
+ filesFilter: "筛选文件…",
85
+ filesShowAll: "显示 node_modules 等",
86
+ filesHideNoise: "隐藏 node_modules 等",
87
+ fileReference: "引用到输入框",
88
+ fileOpenEditor: "在编辑器中打开",
89
+ fileChangedByPi: "本会话中被 pi 修改",
90
+ fileRenderMarkdown: "渲染",
91
+ fileRawSource: "源码",
92
+ gitUnavailable: "未找到 git 命令,请确认已安装并加入 PATH。",
93
+ gitUpstream: "上游 {name}",
94
+ gitNoUpstream: "无上游分支",
95
+ gitConflict: "冲突",
96
+ gitAskCommit: "让 pi 提交",
97
+ gitDetails: "Git 详情",
98
+ gitAskCommitPrompt: "请检查当前工作区的变更,把相关改动分组提交,写清晰的 commit message。",
99
+ gitDiffEmpty: "没有差异",
100
+ gitDiffTruncated: "差异过长,已截断",
101
+ gitBinary: "二进制文件,不显示差异",
102
+ gitStagedDiff: "暂存区差异",
103
+ gitWorktreeDiff: "工作区差异",
104
+ gitNoCommits: "尚无提交",
105
+ gitBack: "返回",
106
+ gitPanel: "Git",
107
+ panelRefresh: "刷新",
108
+ panelLoading: "加载中…",
109
+ filesEmpty: "空目录",
110
+ filesBack: "返回",
111
+ fileBinary: "二进制文件,不提供预览",
112
+ filePreviewTruncated: "文件较大,仅显示前 256 KB",
113
+ entriesTruncated: "目录条目过多,仅显示前 2000 项",
114
+ gitNotRepo: "此工作区不是 Git 仓库。",
115
+ gitDetached: "分离头指针",
116
+ gitAhead: "领先 {n}",
117
+ gitBehind: "落后 {n}",
118
+ gitStaged: "已暂存",
119
+ gitUnstaged: "未暂存",
120
+ gitUntracked: "未跟踪",
121
+ gitNoChanges: "工作区干净,没有变更",
122
+ gitStatusUnknown: "Git 状态读取失败,无法确认是否有变更",
123
+ gitRecentCommits: "最近提交",
124
+ toolNoOutput: "无输出",
125
+ toolFailed: "失败",
126
+ thinkingClamped: "当前模型不支持「{requested}」,已改为「{level}」",
127
+ modelError: "模型返回错误",
128
+ modelErrorTimes: "连续 {n} 次",
129
+ modelErrorRateLimit: "限流:请求过于频繁,稍等片刻再试",
130
+ modelErrorBilling: "余额或配额不足",
131
+ modelErrorAuth: "鉴权失败:检查该供应商的 API Key",
132
+ modelErrorNotFound: "模型不存在或当前 Key 无权访问",
133
+ modelErrorContext: "上下文超出模型窗口,可用 /compact 压缩后重试",
134
+ modelErrorTimeout: "请求超时",
135
+ modelErrorServer: "供应商服务端出错或过载",
136
+ modelErrorNetwork: "网络连接失败",
137
+ turnAborted: "已中止",
138
+ moreLines: "还有 {n} 行",
139
+ commandLines: "{n} 行脚本",
140
+ thinkLabel: "思考",
141
+ expandOutput: "展开全部输出",
142
+ collapseOutput: "收起",
143
+ workspaces: "工作区",
144
+ searchSessions: "搜索会话...",
145
+ addWorkspace: "添加工作区",
146
+ groupBy: "分组方式",
147
+ sortBy: "排序方式",
148
+ byWorkspace: "按工作区",
149
+ flatList: "单列表",
150
+ manualOrder: "按创建时间",
151
+ recentUpdated: "最近更新",
152
+ newSessionHere: "在此工作区新会话",
153
+ removeWorkspace: "从列表移除",
154
+ deleteWorkspace: "删除工作区",
155
+ deleteWorkspaceConfirm: "将把“{name}”从工作区列表中移除。文件夹与会话记录会保留,其会话将显示在“未分组”下。",
156
+ deleteWorkspacePending: "正在删除工作区…",
157
+ workspaceNameConflict: "已存在名为“{name}”的工作区。",
158
+ ungrouped: "未分组",
159
+ forkSession: "在新对话中分支",
160
+ archiveSession: "归档会话",
161
+ unarchiveSession: "取消归档",
162
+ archivedSessions: "已归档",
163
+ deleteAllSessions: "删除全部会话",
164
+ deleteAllConfirm: "删除此工作区的全部会话?不可恢复。",
165
+ contextInject: "上下文注入",
166
+ autoCompact: "自动压缩",
167
+ settingsLoading: "正在读取设置…",
168
+ settingsLoadFailed: "设置读取失败;未显示默认值。请重试。",
169
+ settingsSaveFailed: "设置未保存,请检查输入或网络后重试。",
170
+ settingsRetry: "重试",
171
+ autoCompactDesc: "上下文超出阈值时自动压缩历史",
172
+ reserveTokens: "保留 Token",
173
+ keepRecentTokens: "近期保留",
174
+ autoRetry: "自动重试",
175
+ autoRetryDesc: "请求失败后的自动重试",
176
+ maxRetries: "最大重试次数",
177
+ baseDelayMs: "初始延迟 (ms)",
178
+ reloadExtensions: "重载全部扩展",
179
+ cycleModel: "循环切换模型",
180
+ cycleModelHint: "循环模型(Shift 点击切换到前一个)",
181
+ branches: "分支",
182
+ noBranches: "暂无可跳转的分支节点",
183
+ oauthLogin: "OAuth 登录",
184
+ authMethod: "认证方式",
185
+ loginTitle: "登录 PiWeb",
186
+ loginDesc: "输入 PI_WEB_PASSWORD 设置的密码以继续",
187
+ loginPassword: "密码",
188
+ loginSubmit: "登录",
189
+ loginSubmitting: "登录中…",
190
+ loginFailed: "密码错误",
191
+ webAuth: "密码认证",
192
+ webAuthOn: "已启用(PI_WEB_PASSWORD)",
193
+ webAuthOff: "未启用(仅本机可访问)",
194
+ logout: "退出登录",
195
+ authMethodApiKey: "API 密钥",
196
+ oauthDevicePrompt: "请在浏览器中完成授权",
197
+ oauthOpenAuth: "打开授权页面",
198
+ oauthDeviceCode: "设备码",
199
+ oauthCodeCopied: "已复制",
200
+ usageQuotaLabel: "API 配额",
201
+ usageRequests: "请求",
202
+ usageRefresh: "刷新配额",
203
+ usageProbe: "检测配额",
204
+ usageProbing: "检测中…",
205
+ usageProbeDisclosure: "检测会向 xAI 发送一次可能计费的最小请求。",
206
+ usageProbeFailed: "配额检测失败,未获得用量信息。",
207
+ oauthWait: "等待授权…",
208
+ oauthCancel: "取消登录",
209
+ noSessions: "暂无会话",
210
+ // Hero
211
+ startWith: "新建工作区",
212
+ // 输入卡
213
+ inputPlaceholder: "给 pi 发消息…",
214
+ thinking: "思考",
215
+ thinkingOff: "关闭",
216
+ model: "模型",
217
+ selectModel: "选择模型",
218
+ triggerLoading: "正在加载模型…",
219
+ blockedComposer: "当前模型不可用,请先选择模型",
220
+ emptyModels: "没有可用的模型。",
221
+ emptyEfforts: "当前模型未提供推理等级。",
222
+ thinkingUnsupported: "此模型不支持",
223
+ thinkingUnsupportedHint: "模型没有声明推理能力。自定义模型请在 ~/.pi/agent/models.json 里给该模型加 \"reasoning\": true(可选 thinkingLevelMap 指定档位)",
224
+ toolReadonly: "Read Only",
225
+ toolStandard: "Workspace Write",
226
+ toolFull: "Full access",
227
+ stop: "停止",
228
+ send: "发送",
229
+ imageAttachment: "图片附件",
230
+ imageTooLarge: "单张图片不能超过 20 MB",
231
+ imageCountLimit: "一次最多添加 20 张图片",
232
+ imageTypeUnsupported: "仅支持 JPEG、PNG、WebP 和 GIF 图片",
233
+ dropToAttach: "松开添加附件",
234
+ dropToAttachHint: "图片直接附到消息;其他文件(压缩包/文档等)保存后以路径引用,模型可用工具读取",
235
+ dropLimits: "图片 ≤ 20MB · 最多 20 张 · 其他文件 ≤ 100MB · 最多 16 个",
236
+ uploading: "正在上传…",
237
+ uploadFailed: "上传失败",
238
+ uploadTooLarge: "单个文件不能超过 100 MB",
239
+ uploadCountLimit: "一次最多添加 16 个文件",
240
+ attachmentLine: "附件:{path}({size})",
241
+
242
+ cmdMenu: "命令",
243
+ slashCatalog: "命令与技能",
244
+ skillType: "技能",
245
+ cmdCompact: "压缩更早的对话历史",
246
+ cmdExport: "下载本会话日志",
247
+ cmdModel: "选择本会话使用的模型",
248
+ cmdNew: "新建会话",
249
+ cmdFork: "分叉会话",
250
+ cmdReload: "重载扩展、技能与提示模板(pi /reload)",
251
+ promptType: "模板",
252
+ extensionCmdType: "扩展",
253
+ cmdUnknown: "没有这个命令:/{name}。可用命令见输入框的 / 菜单",
254
+ extensionDialogTag: "扩展",
255
+ extensionStatus: "扩展状态",
256
+ contextUsed: "上下文已用",
257
+ contextUnknown: "上下文用量未知",
258
+ contextSystem: "系统提示词",
259
+ contextMessages: "对话消息",
260
+ contextTools: "工具",
261
+ // 统计条
262
+ turns: "轮次",
263
+ toolCalls: "工具调用",
264
+ cost: "花费",
265
+ duration: "耗时",
266
+ cacheHits: "缓存命中",
267
+ statsCounts: "{turns} 轮 · {steps} 步",
268
+ ttftAverage: "首 token 平均",
269
+ inputTokens: "输入",
270
+ outputTokens: "输出",
271
+ // 视图
272
+ tabChat: "对话",
273
+ tabTrajectory: "轨迹",
274
+ sessionLog: "Session log",
275
+ sessionDetails: "会话详情",
276
+ exportJsonl: "导出 JSONL",
277
+ // 轨迹
278
+ trajTimeline: "时间轴",
279
+ trajModeSeq: "等距",
280
+ trajModeTime: "时间",
281
+ trajModeDur: "间隔",
282
+ trajEmpty: "本会话还没有轨迹记录",
283
+ trajSearchPlaceholder: "搜索轨迹",
284
+ trajNoMatch: "没有匹配的轨迹记录",
285
+ trajInput: "输入",
286
+ trajModel: "模型",
287
+ trajTools: "工具",
288
+ trajOutput: "输出",
289
+ trajThink: "思考",
290
+ trajTime: "时间",
291
+ trajTurn: "轮次",
292
+ trajSystem: "系统",
293
+ trajSession: "会话",
294
+ trajSummary: "摘要",
295
+ trajPreview: "预览",
296
+ trajRaw: "原始",
297
+ trajSource: "来源",
298
+ trajStatus: "状态",
299
+ trajCompleted: "已完成",
300
+ trajFailed: "失败",
301
+ trajStarted: "开始时间",
302
+ trajTokens: "Token 用量",
303
+ trajNoContent: "此记录没有可显示的内容",
304
+ encodingLossWarning: "这段历史工具输出在写入时已经损坏,无法恢复的行已隐藏。当前 Pi SDK 已对新的 PowerShell 输出强制使用 UTF-8。",
305
+ ttft: "首 token",
306
+ decode: "解码",
307
+ inspector: "记录详情",
308
+ // 设置
309
+ setGeneral: "通用设置",
310
+ setModels: "模型",
311
+ enterBehavior: "繁忙时 Enter 键行为",
312
+ enterBehaviorDesc: "仅在 pi 运行时生效;Ctrl/Cmd+Enter 用另一种方式发送",
313
+ enterQueue: "排队:本轮结束后发送",
314
+ enterSteer: "插话:当前工具跑完就送达",
315
+ setSkills: "技能",
316
+ setPlugins: "插件",
317
+ appearance: "外观",
318
+ appearanceMode: "亮暗模式",
319
+ themeLight: "浅色",
320
+ themeDark: "深色",
321
+ themeSystem: "跟随系统",
322
+ themeSilverSteel: "银钢",
323
+ themeLimestoneCoal: "石灰与煤炭",
324
+ themeLinenMoss: "亚麻与苔绿",
325
+ themeNordPaper: "北欧纸墨",
326
+ themePebrel: "Pebrel",
327
+ themeDsh: "海与墨",
328
+ fontSize: "正文字号",
329
+ fontUiSize: "界面字体",
330
+ fontUiSizeDesc: "侧栏、按钮、标签等界面文字",
331
+ fontChatSize: "对话字体",
332
+ fontChatSizeDesc: "消息正文、用户气泡与输入框",
333
+ language: "界面语言",
334
+ openConfigFile: "打开配置文件",
335
+ providerAuthOk: "已配置",
336
+ providerReady: "请求认证可用",
337
+ authUnavailable: "凭据不可用",
338
+ credentialSource: "凭据:{source}",
339
+ authSourceRuntime: "运行时",
340
+ authSourceEnvironment: "环境变量",
341
+ authSourceCommand: "models.json 命令",
342
+ authSourceProvider: "Provider 配置",
343
+ apiKey: "API Key",
344
+ apiKeyStored: "已保存;留空保持不变",
345
+ providerIdImmutable: "Provider ID 创建后不可修改;如需更名,请删除后重建。",
346
+ modelConfigReopen: "模型配置已保存。新建会话或重启 PiWeb 后,当前运行时才能使用新配置。",
347
+ customModelIdentityNotice: "自定义模型 ID 只是发往该 API 地址的路由名;PiWeb 不会自动下载、接入或识别本机 Ollama 模型。",
348
+ customApiKeyHint: "可留空改用 auth.json;Ollama 等无鉴权本地服务仍需填写任意占位值。",
349
+ modelsTitle: "模型",
350
+ modelsDesc: "填入各提供方的 API 密钥即可使用其模型。",
351
+ addProvider: "添加提供方",
352
+ addCustomProvider: "添加自定义提供方",
353
+ customProviderTitle: "自定义提供方",
354
+ edit: "编辑",
355
+ customBadge: "自定义",
356
+ providerLabel: "提供方",
357
+ apiType: "API 类型",
358
+ modelsList: "模型(每行一个 ID)",
359
+ baseUrl: "Base URL",
360
+ apiAddress: "API 地址",
361
+ apiProtocol: "API 协议",
362
+ apiKeyOptional: "输入 API 密钥,或留空使用环境认证",
363
+ customSettings: "自定义设置",
364
+ providerDefault: "提供方默认",
365
+ selectProvider: "选择提供方",
366
+ searchProviders: "搜索提供方名称或 ID",
367
+ noProviderMatches: "没有匹配的提供方",
368
+ modelCount: "{count} 个模型",
369
+ providerId: "Provider ID",
370
+ providerIdHint: "以小写字母开头的标识,在请求中唯一标识该提供方,并用于派生凭据名。",
371
+ providerIdInvalid: "只能使用小写字母、数字和单个连字符分段。",
372
+ providerIdTaken: "该 Provider ID 已存在。",
373
+ displayName: "显示名称",
374
+ displayNameOptional: "显示名称(可选)",
375
+ modelCatalog: "模型目录",
376
+ discoverModels: "获取可用模型",
377
+ discoveringModels: "获取中...",
378
+ usingDefaultModels: "正在使用 Pi SDK 默认模型 · {count} 个",
379
+ customModelsRequired: "至少添加一个可发送的模型 ID",
380
+ modelCatalogEmptyBuiltin: "未添加覆盖模型;模型选择器会继续实时使用 Pi SDK 的官方模型目录。",
381
+ modelCatalogEmptyCustom: "模型选择器中将不显示任何模型;请至少添加一个模型 ID。",
382
+ addModel: "添加模型",
383
+ modelId: "模型 ID",
384
+ createProvider: "创建提供方",
385
+ saving: "保存中...",
386
+ setKey: "保存 Key",
387
+ removeKey: "移除 Key",
388
+ confirmRemoveProvider: "确定删除提供方“{name}”及其配置吗?",
389
+ confirmRemoveKey: "确定移除“{name}”的已保存密钥吗?",
390
+ customProviders: "自定义 Provider(models.json)",
391
+ toolsSection: "工具启用情况",
392
+ toolsSectionDesc: "三档预设决定新会话的默认工具;打开会话后可逐个启停当前会话的工具(仅本会话生效)。",
393
+ toolsCurrentSession: "当前会话",
394
+ toolsActiveCount: "{n}/{total} 已启用",
395
+ toolsNoSession: "打开一个会话后,这里会显示可用工具并支持逐个启停。",
396
+ securityToolPreset: "权限",
397
+ securityToolPresetDesc: "切换当前会话工具集;Workspace Write 包含 bash,并非文件系统沙箱",
398
+ securityTrust: "项目信任",
399
+ securityTrustDesc: "首次进入含 .pi/ 资源的项目时是否自动信任(写入 pi settings.json)",
400
+ trustAsk: "每次询问",
401
+ trustAlways: "总是信任",
402
+ trustNever: "从不信任",
403
+ versionPiweb: "PiWeb 版本",
404
+ versionPiwebDesc: "本 Web 应用的版本,点击打开仓库",
405
+ versionPi: "Pi 版本",
406
+ versionPiDesc: "pi 智能体内核的版本,点击打开仓库",
407
+ checkUpdate: "检查更新",
408
+ checkingUpdate: "检查中…",
409
+ upToDate: "已是最新",
410
+ updateTo: "更新到 {v}",
411
+ updatingNow: "更新中…",
412
+ updatedTo: "已更新到 {v},重启 PiWeb 后生效",
413
+ updateFailed: "更新失败",
414
+ skillsDesc: "关闭后技能不会出现在系统提示中,仅可通过 /skill:名称 手动调用",
415
+ scopeGlobal: "全局",
416
+ scopeProject: "项目",
417
+ scopePackage: "包",
418
+ viewSkillFile: "查看 SKILL.md",
419
+ packages: "已安装的 pi 包",
420
+ packagesEmpty: "尚未安装任何 pi 包",
421
+ addPackage: "安装 pi 包",
422
+ addPackagePlaceholder: "npm:包名 / git:https://… / 本地路径",
423
+ installLocal: "安装到当前项目(-l)",
424
+ install: "安装",
425
+ uninstall: "卸载",
426
+ confirmUninstallPackage: "确定卸载“{source}”吗?",
427
+ update: "更新",
428
+ pluginConfig: "插件配置",
429
+ pluginList: "插件列表",
430
+ pluginPageDesc: "配置和查看本部署已安装的插件。",
431
+ searchPlugins: "搜索插件",
432
+ enabled: "已启用",
433
+ disabled: "已停用",
434
+ enablePlugin: "启用",
435
+ disablePlugin: "停用",
436
+ updating: "正在更新...",
437
+ uninstalling: "正在卸载...",
438
+ updateSuccess: "更新成功",
439
+ uninstallSuccess: "已卸载",
440
+ extensionsEmpty: "没有已加载的扩展",
441
+ extensionLoadError: "加载失败",
442
+ resourceDiagnostics: "资源诊断",
443
+ installing: "正在安装…",
444
+ installSuccess: "已安装并加载",
445
+ reloadedSessions: "已重载:{loaders} 个加载器 · {sessions} 个会话",
446
+ projectTrustBanner: "此项目含 .pi/ 扩展或技能,pi 需要你的信任才会加载并执行它们",
447
+ projectTrustBannerNever: "此项目的 .pi/ 扩展与技能已被设为不信任,不会加载",
448
+ projectTrustAllow: "信任并加载",
449
+ projectTrustDeny: "不信任",
450
+ projectTrustForget: "重新询问",
451
+ projectTrustTrusted: "项目已信任",
452
+ projectTrustUntrusted: "项目未信任",
453
+ resources: "携带",
454
+ toastSaved: "已保存",
455
+ toastError: "操作失败",
456
+ running: "运行中",
457
+ // 项目生长(项目栏 / 文件查看器)
458
+ projectPanel: "项目",
459
+ growthScopeStep: "本步",
460
+ growthScopeSession: "本会话",
461
+ growthOnlyChanges: "只看变更",
462
+ growthFollow: "跟随",
463
+ growthFollowing: "跟随中",
464
+ growthPrev: "上一轮",
465
+ growthNext: "下一轮",
466
+ growthRoundPosition: "第 {current}/{total} 轮",
467
+ growthSnapshotNow: "立即快照",
468
+ growthSnapshotNone: "没有变化",
469
+ growthNoSteps: "还没有快照。发一条消息让 pi 开始工作,项目的变化会在这里逐步出现。",
470
+ growthLoading: "正在加载快照…",
471
+ growthUnrecorded: "此轮发生在生长快照启用前,改动未记录",
472
+ growthNoChangesRound: "本轮无文件改动",
473
+ growthNoSession: "打开或新建一个会话后,这里会显示项目的生长过程。",
474
+ growthUnavailable: "机器上找不到 git,项目生长功能不可用",
475
+ growthStepLabel: "第 {n} 步",
476
+ growthRoundLabel: "第 {n} 轮",
477
+ growthStepsCount: "{n} 步",
478
+ growthKindBaseline: "会话基线",
479
+ growthKindTurn: "回合结束",
480
+ growthKindExternal: "外部修改",
481
+ growthKindManual: "手动快照",
482
+ growthStatA: "新增",
483
+ growthStatM: "修改",
484
+ growthStatD: "删除",
485
+ growthStatR: "重命名",
486
+ growthPending: "生成中",
487
+ growthLazyDir: "当前磁盘条目,不在所选快照中",
488
+ growthTruncated: "这一步变更过多,只显示前 2000 条",
489
+ growthExpandAll: "展开全部",
490
+ growthCollapseAll: "收起全部",
491
+ growthFilter: "筛选…",
492
+ viewerModeDiff: "变更",
493
+ viewerModeContent: "内容",
494
+ viewerModeRender: "渲染",
495
+ viewerFold: "折叠未改动",
496
+ viewerUnfold: "展开未改动",
497
+ viewerFoldedLines: "··· {n} 行未改动 ···",
498
+ viewerPrevChange: "上一处改动",
499
+ viewerNextChange: "下一处改动",
500
+ viewerFullscreen: "全屏",
501
+ viewerExitFullscreen: "退出全屏",
502
+ viewerQuickOpen: "输入文件名打开…",
503
+ viewerQuickOpenEmpty: "没有匹配的文件",
504
+ viewerNoChanges: "这一范围内此文件没有变化",
505
+ viewerDeleted: "此文件在本轮被删除,显示的是删除前的内容",
506
+ viewerHistorical: "此文件已不在当前快照中,显示最近一次记录的内容",
507
+ viewerMissing: "此文件已不在当前快照或磁盘中",
508
+ viewerPatchTruncated: "差异过大,已截断",
509
+ viewerCloseTab: "关闭页签",
510
+ viewerNotInSnapshot: "此文件不在快照里(超过 1MB 或被排除),显示磁盘上的当前内容",
511
+ viewerLoadFailed: "加载失败",
512
+ viewerEmpty: "从左侧树里选择一个文件",
513
+ } as const;
514
+
515
+ type Dict = { [K in keyof typeof zh]: string };
516
+
517
+ const en: Dict = {
518
+ confirm: "Confirm",
519
+ cancel: "Cancel",
520
+ delete: "Delete",
521
+ rename: "Rename",
522
+ renameSession: "Rename session",
523
+ renameWorkspace: "Rename workspace",
524
+ search: "Search",
525
+ save: "Save",
526
+ close: "Close",
527
+ error: "Error",
528
+ copy: "Copy",
529
+ copyFailed: "Copy failed",
530
+ export: "Export",
531
+ settings: "Settings",
532
+ newChat: "New session",
533
+ reconnecting: "Connection lost, reconnecting…",
534
+ sessionListLoadFailed: "Failed to load sessions",
535
+ retry: "Retry",
536
+ compacting: "Compacting context…",
537
+ compactionComplete: "Context compaction complete",
538
+ compactionFailed: "Context compaction failed",
539
+ pickWorkspaceFirst: "Select a workspace first",
540
+ capacityFields: "Capacities",
541
+ contextWindowLabel: "Context window",
542
+ maxTokensLabel: "Max output",
543
+ capacityHint: "blank = default · 256K / 2M accepted",
544
+ capacityInvalid: "Row {n}: capacity must be a number (K/M ok)",
545
+ discoverEmpty: "No recognizable models returned",
546
+ candidateTitle: "Found {count} models — pick ones to add",
547
+ candidateAll: "Select all",
548
+ candidatePicked: "{n} selected",
549
+ candidateAdopt: "Add {n}",
550
+ runningTool: "Running {name}…",
551
+ thinkingLive: "Thinking",
552
+ stepRunning: "Running",
553
+ stepRan: "Ran",
554
+ stepRead: "Read",
555
+ stepSearched: "Searched",
556
+ stepEdited: "Edited",
557
+ stepWrote: "Wrote",
558
+ resultRead: "Read {n} lines",
559
+ resultFound: "Found {n} matches",
560
+ resultWrote: "{n} lines",
561
+ sumThought: "Thought for {d}",
562
+ sumRan: "ran {n} shell commands",
563
+ sumRan1: "ran {n} shell command",
564
+ sumRead: "read {n} files",
565
+ sumRead1: "read {n} file",
566
+ sumSearched: "searched {n} times",
567
+ sumSearched1: "searched once",
568
+ sumJoin: ", ",
569
+ toolLines: "{n} lines",
570
+ toolMatches: "{n} matches",
571
+ toolExit: "exit {code}",
572
+ toolWritten: "written",
573
+ diffSummary: "+{add} −{del} lines",
574
+ backToBottom: "Back to bottom",
575
+ modeSteer: "steer",
576
+ modeQueue: "queue",
577
+ sendSteer: "Steer: delivered after the current tool call",
578
+ sendQueue: "Queue: sent after this turn ends",
579
+ queueEdit: "↑ Edit queued",
580
+ queueDrop: "Discard",
581
+ viewInTrajectory: "View in trajectory",
582
+ turnRanFor: "ran for {duration}",
583
+ durationSeconds: "{seconds}s",
584
+ durationMinutes: "{minutes}m {seconds}s",
585
+ clockMd: "{m}/{d}",
586
+ clockYmd: "{y}/{m}/{d}",
587
+ turnUsageTitle: "Turn usage",
588
+ filesPanel: "Files",
589
+ outline: "Outline",
590
+ moreActions: "More",
591
+ filesFilter: "Filter files…",
592
+ filesShowAll: "Show node_modules etc.",
593
+ filesHideNoise: "Hide node_modules etc.",
594
+ fileReference: "Reference in composer",
595
+ fileOpenEditor: "Open in editor",
596
+ fileChangedByPi: "Modified by pi in this session",
597
+ fileRenderMarkdown: "Render",
598
+ fileRawSource: "Source",
599
+ gitUnavailable: "git command not found. Install it and make sure it is on PATH.",
600
+ gitUpstream: "upstream {name}",
601
+ gitNoUpstream: "no upstream",
602
+ gitConflict: "Conflicts",
603
+ gitAskCommit: "Ask pi to commit",
604
+ gitDetails: "Git details",
605
+ gitAskCommitPrompt: "Review the current changes, group related edits into commits, and write clear commit messages.",
606
+ gitDiffEmpty: "No differences",
607
+ gitDiffTruncated: "Diff truncated",
608
+ gitBinary: "Binary file, no diff shown",
609
+ gitStagedDiff: "Staged diff",
610
+ gitWorktreeDiff: "Working tree diff",
611
+ gitNoCommits: "No commits yet",
612
+ gitBack: "Back",
613
+ gitPanel: "Git",
614
+ panelRefresh: "Refresh",
615
+ panelLoading: "Loading…",
616
+ filesEmpty: "Empty directory",
617
+ filesBack: "Back",
618
+ fileBinary: "Binary file, no preview",
619
+ filePreviewTruncated: "Large file, showing first 256 KB only",
620
+ entriesTruncated: "Too many entries, showing first 2000",
621
+ gitNotRepo: "This workspace is not a Git repository.",
622
+ gitDetached: "detached HEAD",
623
+ gitAhead: "ahead {n}",
624
+ gitBehind: "behind {n}",
625
+ gitStaged: "Staged",
626
+ gitUnstaged: "Unstaged",
627
+ gitUntracked: "Untracked",
628
+ gitNoChanges: "Working tree clean",
629
+ gitStatusUnknown: "Git status unavailable; changes could not be determined",
630
+ gitRecentCommits: "Recent commits",
631
+ toolNoOutput: "no output",
632
+ toolFailed: "failed",
633
+ thinkingClamped: "This model does not support \"{requested}\"; using \"{level}\" instead",
634
+ modelError: "Model returned an error",
635
+ modelErrorTimes: "{n} times in a row",
636
+ modelErrorRateLimit: "Rate limited: too many requests, wait a moment and retry",
637
+ modelErrorBilling: "Insufficient balance or quota",
638
+ modelErrorAuth: "Authentication failed: check this provider's API key",
639
+ modelErrorNotFound: "Model not found or not accessible with this key",
640
+ modelErrorContext: "Context exceeds the model window; try /compact and retry",
641
+ modelErrorTimeout: "Request timed out",
642
+ modelErrorServer: "Provider server error or overloaded",
643
+ modelErrorNetwork: "Network connection failed",
644
+ turnAborted: "Aborted",
645
+ moreLines: "{n} more lines",
646
+ commandLines: "{n}-line script",
647
+ thinkLabel: "Thought",
648
+ expandOutput: "Show full output",
649
+ collapseOutput: "Collapse",
650
+ workspaces: "Workspaces",
651
+ searchSessions: "Search sessions...",
652
+ addWorkspace: "Add workspace",
653
+ groupBy: "Group by",
654
+ sortBy: "Sort by",
655
+ byWorkspace: "Workspace",
656
+ flatList: "Flat list",
657
+ manualOrder: "Created",
658
+ recentUpdated: "Recently updated",
659
+ newSessionHere: "New session here",
660
+ removeWorkspace: "Remove from list",
661
+ deleteWorkspace: "Delete workspace",
662
+ deleteWorkspaceConfirm: "Remove \"{name}\" from the workspace list. Folders and session records will be retained, and its sessions will be displayed under \"Ungrouped\".",
663
+ deleteWorkspacePending: "Deleting workspace...",
664
+ workspaceNameConflict: "A workspace named \"{name}\" already exists.",
665
+ ungrouped: "Ungrouped",
666
+ forkSession: "Fork session",
667
+ archiveSession: "Archive session",
668
+ unarchiveSession: "Unarchive",
669
+ archivedSessions: "Archived",
670
+ deleteAllSessions: "Delete all sessions",
671
+ deleteAllConfirm: "Delete ALL sessions in this workspace? This cannot be undone.",
672
+ contextInject: "Context",
673
+ autoCompact: "Auto compaction",
674
+ settingsLoading: "Loading settings…",
675
+ settingsLoadFailed: "Settings could not be loaded. Defaults are not shown; please retry.",
676
+ settingsSaveFailed: "Settings were not saved. Check the value or connection and retry.",
677
+ settingsRetry: "Retry",
678
+ autoCompactDesc: "Automatically compact history when context exceeds the threshold",
679
+ reserveTokens: "Reserve tokens",
680
+ keepRecentTokens: "Keep recent",
681
+ autoRetry: "Auto retry",
682
+ autoRetryDesc: "Automatically retry failed requests",
683
+ maxRetries: "Max retries",
684
+ baseDelayMs: "Initial delay (ms)",
685
+ reloadExtensions: "Reload all extensions",
686
+ cycleModel: "Cycle model",
687
+ cycleModelHint: "Cycle model (Shift-click for previous)",
688
+ branches: "Branches",
689
+ noBranches: "No branch points available",
690
+ oauthLogin: "OAuth login",
691
+ authMethod: "Authentication",
692
+ loginTitle: "Sign in to PiWeb",
693
+ loginDesc: "Enter the password configured in PI_WEB_PASSWORD to continue",
694
+ loginPassword: "Password",
695
+ loginSubmit: "Sign in",
696
+ loginSubmitting: "Signing in…",
697
+ loginFailed: "Incorrect password",
698
+ webAuth: "Password auth",
699
+ webAuthOn: "Enabled (PI_WEB_PASSWORD)",
700
+ webAuthOff: "Disabled (local access only)",
701
+ logout: "Sign out",
702
+ authMethodApiKey: "API key",
703
+ oauthDevicePrompt: "Finish authorization in your browser",
704
+ oauthOpenAuth: "Open authorization page",
705
+ oauthDeviceCode: "Device code",
706
+ oauthCodeCopied: "Copied",
707
+ usageQuotaLabel: "API quota",
708
+ usageRequests: "Requests",
709
+ usageRefresh: "Refresh quota",
710
+ usageProbe: "Check quota",
711
+ usageProbing: "Checking…",
712
+ usageProbeDisclosure: "Checking sends one minimal request to xAI that may be billed.",
713
+ usageProbeFailed: "Quota check failed; no usage data was returned.",
714
+ oauthWait: "Waiting for authorization…",
715
+ oauthCancel: "Cancel login",
716
+ noSessions: "No sessions yet",
717
+ startWith: "New workspace",
718
+ inputPlaceholder: "Message pi…",
719
+ thinking: "Thinking",
720
+ thinkingOff: "Off",
721
+ model: "Model",
722
+ selectModel: "Select model",
723
+ triggerLoading: "Loading models…",
724
+ blockedComposer: "This model is unavailable — select one to continue",
725
+ emptyModels: "No models available.",
726
+ emptyEfforts: "This model provides no reasoning effort levels.",
727
+ thinkingUnsupported: "Not supported by this model",
728
+ thinkingUnsupportedHint: "The model does not declare reasoning support. For custom models, add \"reasoning\": true (optionally a thinkingLevelMap) to the model in ~/.pi/agent/models.json",
729
+ toolReadonly: "Read Only",
730
+ toolStandard: "Workspace Write",
731
+ toolFull: "Full access",
732
+ stop: "Stop",
733
+ send: "Send",
734
+ imageAttachment: "Image attachment",
735
+ imageTooLarge: "Each image must be 20 MB or smaller",
736
+ imageCountLimit: "You can attach up to 20 images",
737
+ imageTypeUnsupported: "Only JPEG, PNG, WebP, and GIF images are supported",
738
+ dropToAttach: "Drop to attach",
739
+ dropToAttachHint: "Images attach to the message; other files (archives, documents) are saved and referenced by path for the agent to read",
740
+ dropLimits: "Images ≤ 20MB · up to 20 · Other files ≤ 100MB · up to 16",
741
+ uploading: "Uploading…",
742
+ uploadFailed: "Upload failed",
743
+ uploadTooLarge: "Each file must be 100 MB or smaller",
744
+ uploadCountLimit: "You can attach up to 16 files",
745
+ attachmentLine: "Attachment: {path} ({size})",
746
+
747
+ cmdMenu: "Commands",
748
+ slashCatalog: "Commands and skills",
749
+ skillType: "Skill",
750
+ cmdCompact: "Compact older conversation history",
751
+ cmdExport: "Download this session log",
752
+ cmdModel: "Select the model for this session",
753
+ cmdNew: "Start a new session",
754
+ cmdFork: "Fork this session",
755
+ cmdReload: "Reload extensions, skills and prompt templates (pi /reload)",
756
+ promptType: "Template",
757
+ extensionCmdType: "Extension",
758
+ cmdUnknown: "Unknown command: /{name}. See the / menu in the composer for available commands",
759
+ extensionDialogTag: "Extension",
760
+ extensionStatus: "Extension status",
761
+ contextUsed: "context used",
762
+ contextUnknown: "Context usage unknown",
763
+ contextSystem: "System prompt",
764
+ contextMessages: "Messages",
765
+ contextTools: "Tools",
766
+ turns: "turns",
767
+ toolCalls: "tool calls",
768
+ cost: "cost",
769
+ duration: "duration",
770
+ cacheHits: "cache hits",
771
+ statsCounts: "{turns} turns · {steps} steps",
772
+ ttftAverage: "TTFT avg",
773
+ inputTokens: "Input",
774
+ outputTokens: "Output",
775
+ tabChat: "Chat",
776
+ tabTrajectory: "Trajectory",
777
+ sessionLog: "Session log",
778
+ sessionDetails: "Session details",
779
+ exportJsonl: "Export JSONL",
780
+ trajTimeline: "Timeline",
781
+ trajModeSeq: "Sequence",
782
+ trajModeTime: "Time",
783
+ trajModeDur: "Duration",
784
+ trajEmpty: "No trajectory records yet",
785
+ trajSearchPlaceholder: "Search trajectory",
786
+ trajNoMatch: "No matching trajectory records",
787
+ trajInput: "Input",
788
+ trajModel: "Model",
789
+ trajTools: "Tools",
790
+ trajOutput: "Output",
791
+ trajThink: "Think",
792
+ trajTime: "Time",
793
+ trajTurn: "Turn",
794
+ trajSystem: "System",
795
+ trajSession: "Session",
796
+ trajSummary: "Summary",
797
+ trajPreview: "Preview",
798
+ trajRaw: "Raw",
799
+ trajSource: "Source",
800
+ trajStatus: "Status",
801
+ trajCompleted: "Completed",
802
+ trajFailed: "Failed",
803
+ trajStarted: "Started",
804
+ trajTokens: "Token usage",
805
+ trajNoContent: "This record has no displayable content",
806
+ encodingLossWarning: "This historical tool output was already damaged when saved. Unrecoverable lines are hidden; the current Pi SDK forces new PowerShell output to UTF-8.",
807
+ ttft: "TTFT",
808
+ decode: "Decode",
809
+ inspector: "Record inspector",
810
+ setGeneral: "General",
811
+ setModels: "Models",
812
+ enterBehavior: "Enter while busy",
813
+ enterBehaviorDesc: "Only while pi is running; Ctrl/Cmd+Enter sends the other way",
814
+ enterQueue: "Queue: sent after this turn ends",
815
+ enterSteer: "Steer: delivered after the current tool call",
816
+ setSkills: "Skills",
817
+ setPlugins: "Plugins",
818
+ appearance: "Appearance",
819
+ appearanceMode: "Light / Dark",
820
+ themeLight: "Light",
821
+ themeDark: "Dark",
822
+ themeSystem: "System",
823
+ themeSilverSteel: "Silver & Steel",
824
+ themeLimestoneCoal: "Limestone & Coal",
825
+ themeLinenMoss: "Linen & Moss",
826
+ themeNordPaper: "Nord & Paper",
827
+ themePebrel: "Pebrel",
828
+ themeDsh: "Sea & Ink",
829
+ fontSize: "Font size",
830
+ fontUiSize: "UI font size",
831
+ fontUiSizeDesc: "Sidebar, buttons, labels and other UI text",
832
+ fontChatSize: "Chat font size",
833
+ fontChatSizeDesc: "Message body, user bubbles and the composer",
834
+ language: "Language",
835
+ openConfigFile: "Open config file",
836
+ providerAuthOk: "Configured",
837
+ providerReady: "Request authentication ready",
838
+ authUnavailable: "Credentials unavailable",
839
+ credentialSource: "Credential: {source}",
840
+ authSourceRuntime: "runtime",
841
+ authSourceEnvironment: "environment",
842
+ authSourceCommand: "models.json command",
843
+ authSourceProvider: "provider config",
844
+ apiKey: "API Key",
845
+ apiKeyStored: "Saved; leave blank to keep it",
846
+ providerIdImmutable: "A Provider ID cannot be changed after creation. Delete and recreate it to rename it.",
847
+ modelConfigReopen: "Model configuration saved. Start a new session or restart PiWeb before using it in the current runtime.",
848
+ customModelIdentityNotice: "A custom model ID is only a route name sent to that API endpoint. PiWeb does not automatically download, attach, or identify local Ollama models.",
849
+ customApiKeyHint: "Leave blank to use auth.json. Keyless local services such as Ollama still need any placeholder value.",
850
+ modelsTitle: "Models",
851
+ modelsDesc: "Enter an API key for each provider to use its models.",
852
+ addProvider: "Add provider",
853
+ addCustomProvider: "Add custom provider",
854
+ customProviderTitle: "Custom provider",
855
+ edit: "Edit",
856
+ customBadge: "Custom",
857
+ providerLabel: "Provider",
858
+ apiType: "API type",
859
+ modelsList: "Models (one ID per line)",
860
+ baseUrl: "Base URL",
861
+ apiAddress: "API address",
862
+ apiProtocol: "API protocol",
863
+ apiKeyOptional: "Enter an API key, or leave blank to use environment authentication",
864
+ customSettings: "Custom settings",
865
+ providerDefault: "Provider default",
866
+ selectProvider: "Select provider",
867
+ searchProviders: "Search provider name or ID",
868
+ noProviderMatches: "No matching providers",
869
+ modelCount: "{count} models",
870
+ providerId: "Provider ID",
871
+ providerIdHint: "A lowercase identifier that uniquely identifies this provider in requests and derives its credential name.",
872
+ providerIdInvalid: "Use lowercase letters, numbers, and single hyphen-separated segments only.",
873
+ providerIdTaken: "This Provider ID already exists.",
874
+ displayName: "Display name",
875
+ displayNameOptional: "Display name (optional)",
876
+ modelCatalog: "Model catalog",
877
+ discoverModels: "Fetch available models",
878
+ discoveringModels: "Fetching...",
879
+ usingDefaultModels: "Using Pi SDK default models · {count}",
880
+ customModelsRequired: "Add at least one model ID that can be sent",
881
+ modelCatalogEmptyBuiltin: "No model overrides. The model selector will continue using Pi SDK's live official catalog.",
882
+ modelCatalogEmptyCustom: "No models will appear in the selector. Add at least one model ID.",
883
+ addModel: "Add model",
884
+ modelId: "Model ID",
885
+ createProvider: "Create provider",
886
+ saving: "Saving...",
887
+ setKey: "Save key",
888
+ removeKey: "Remove key",
889
+ confirmRemoveProvider: "Delete provider \"{name}\" and its configuration?",
890
+ confirmRemoveKey: "Remove the saved key for \"{name}\"?",
891
+ customProviders: "Custom providers (models.json)",
892
+ toolsSection: "Tools",
893
+ toolsSectionDesc: "The preset picks the default tools for new sessions; with a session open you can toggle its tools individually (current session only).",
894
+ toolsCurrentSession: "Current session",
895
+ toolsActiveCount: "{n}/{total} enabled",
896
+ toolsNoSession: "Open a session to see and toggle its available tools.",
897
+ securityToolPreset: "Permission",
898
+ securityToolPresetDesc: "Switch the current tool set; Workspace Write includes bash and is not a filesystem sandbox",
899
+ securityTrust: "Project trust",
900
+ securityTrustDesc: "Auto-trust projects containing .pi/ resources (writes pi settings.json)",
901
+ trustAsk: "Ask every time",
902
+ trustAlways: "Always trust",
903
+ trustNever: "Never trust",
904
+ versionPiweb: "PiWeb version",
905
+ versionPiwebDesc: "Version of this web app; click to open the repo",
906
+ versionPi: "Pi version",
907
+ versionPiDesc: "Version of the pi agent engine; click to open the repo",
908
+ checkUpdate: "Check for updates",
909
+ checkingUpdate: "Checking…",
910
+ upToDate: "Up to date",
911
+ updateTo: "Update to {v}",
912
+ updatingNow: "Updating…",
913
+ updatedTo: "Updated to {v}; restart PiWeb to apply",
914
+ updateFailed: "Update failed",
915
+ skillsDesc: "Disabled skills are hidden from the system prompt and only callable via /skill:name",
916
+ scopeGlobal: "Global",
917
+ scopeProject: "Project",
918
+ scopePackage: "Package",
919
+ viewSkillFile: "View SKILL.md",
920
+ packages: "Installed pi packages",
921
+ packagesEmpty: "No pi packages installed",
922
+ addPackage: "Install pi package",
923
+ addPackagePlaceholder: "npm:pkg / git:https://… / local path",
924
+ installLocal: "Install into current project (-l)",
925
+ install: "Install",
926
+ uninstall: "Uninstall",
927
+ confirmUninstallPackage: "Uninstall \"{source}\"?",
928
+ update: "Update",
929
+ pluginConfig: "Plugin config",
930
+ pluginList: "Plugin list",
931
+ pluginPageDesc: "Configure and view installed plugins for this deployment.",
932
+ searchPlugins: "Search plugins",
933
+ enabled: "Enabled",
934
+ disabled: "Disabled",
935
+ enablePlugin: "Enable",
936
+ disablePlugin: "Disable",
937
+ updating: "Updating...",
938
+ uninstalling: "Uninstalling...",
939
+ updateSuccess: "Updated successfully",
940
+ uninstallSuccess: "Uninstalled",
941
+ extensionsEmpty: "No loaded extensions",
942
+ extensionLoadError: "Failed to load",
943
+ resourceDiagnostics: "Resource diagnostics",
944
+ installing: "Installing…",
945
+ installSuccess: "Installed and loaded",
946
+ reloadedSessions: "Reloaded: {loaders} loaders · {sessions} sessions",
947
+ projectTrustBanner: "This project has .pi/ extensions or skills; pi loads and runs them only if you trust the project",
948
+ projectTrustBannerNever: "This project's .pi/ extensions and skills are marked untrusted and will not load",
949
+ projectTrustAllow: "Trust and load",
950
+ projectTrustDeny: "Do not trust",
951
+ projectTrustForget: "Ask again",
952
+ projectTrustTrusted: "Project trusted",
953
+ projectTrustUntrusted: "Project not trusted",
954
+ resources: "carries",
955
+ toastSaved: "Saved",
956
+ toastError: "Operation failed",
957
+ running: "Running",
958
+ projectPanel: "Project",
959
+ growthScopeStep: "This step",
960
+ growthScopeSession: "This session",
961
+ growthOnlyChanges: "Changes only",
962
+ growthFollow: "Follow",
963
+ growthFollowing: "Following",
964
+ growthPrev: "Previous round",
965
+ growthNext: "Next round",
966
+ growthRoundPosition: "Round {current}/{total}",
967
+ growthSnapshotNow: "Snapshot now",
968
+ growthSnapshotNone: "No changes",
969
+ growthNoSteps: "No snapshots yet. Send pi a message and the project's changes will show up here step by step.",
970
+ growthLoading: "Loading snapshots…",
971
+ growthUnrecorded: "This round predates growth snapshots; its changes were not recorded",
972
+ growthNoChangesRound: "No file changes in this round",
973
+ growthNoSession: "Open or start a session to watch the project grow here.",
974
+ growthUnavailable: "git was not found on this machine; project growth is unavailable",
975
+ growthStepLabel: "Step {n}",
976
+ growthRoundLabel: "Round {n}",
977
+ growthStepsCount: "{n} steps",
978
+ growthKindBaseline: "Session baseline",
979
+ growthKindTurn: "Turn ended",
980
+ growthKindExternal: "External change",
981
+ growthKindManual: "Manual snapshot",
982
+ growthStatA: "Added",
983
+ growthStatM: "Modified",
984
+ growthStatD: "Deleted",
985
+ growthStatR: "Renamed",
986
+ growthPending: "Writing…",
987
+ growthLazyDir: "Current disk entry, not in the selected snapshot",
988
+ growthTruncated: "Too many changes in this step; showing the first 2000",
989
+ growthExpandAll: "Expand all",
990
+ growthCollapseAll: "Collapse all",
991
+ growthFilter: "Filter…",
992
+ viewerModeDiff: "Changes",
993
+ viewerModeContent: "Content",
994
+ viewerModeRender: "Rendered",
995
+ viewerFold: "Fold unchanged",
996
+ viewerUnfold: "Show unchanged",
997
+ viewerFoldedLines: "··· {n} unchanged lines ···",
998
+ viewerPrevChange: "Previous change",
999
+ viewerNextChange: "Next change",
1000
+ viewerFullscreen: "Fullscreen",
1001
+ viewerExitFullscreen: "Exit fullscreen",
1002
+ viewerQuickOpen: "Type a file name to open…",
1003
+ viewerQuickOpenEmpty: "No matching files",
1004
+ viewerNoChanges: "No changes to this file in this scope",
1005
+ viewerDeleted: "This file was deleted in this round; showing its last content",
1006
+ viewerHistorical: "This file is no longer in the current snapshot; showing its last recorded content",
1007
+ viewerMissing: "This file is no longer in the current snapshot or on disk",
1008
+ viewerPatchTruncated: "Diff too large; truncated",
1009
+ viewerCloseTab: "Close tab",
1010
+ viewerNotInSnapshot: "Not in the snapshot (over 1MB or excluded); showing the current content from disk",
1011
+ viewerLoadFailed: "Failed to load",
1012
+ viewerEmpty: "Pick a file from the tree on the left",
1013
+ };
1014
+
1015
+ const dicts: Record<string, Dict> = { zh, en };
1016
+
1017
+ interface I18nCtx {
1018
+ lang: "zh" | "en";
1019
+ setLang: (l: "zh" | "en") => void;
1020
+ t: Dict;
1021
+ }
1022
+
1023
+ const Ctx = createContext<I18nCtx>({ lang: "zh", setLang: () => {}, t: zh });
1024
+
1025
+ export function I18nProvider({ children }: { children: React.ReactNode }) {
1026
+ const [lang, setLangState] = useState<"zh" | "en">("zh");
1027
+ useEffect(() => {
1028
+ const saved = localStorage.getItem("piweb.lang");
1029
+ if (saved === "en" || saved === "zh") setLangState(saved);
1030
+ }, []);
1031
+ useEffect(() => {
1032
+ document.documentElement.lang = lang === "en" ? "en" : "zh-CN";
1033
+ }, [lang]);
1034
+ const setLang = useCallback((l: "zh" | "en") => {
1035
+ setLangState(l);
1036
+ localStorage.setItem("piweb.lang", l);
1037
+ }, []);
1038
+ return <Ctx.Provider value={{ lang, setLang, t: dicts[lang] }}>{children}</Ctx.Provider>;
1039
+ }
1040
+
1041
+ export function useI18n(): I18nCtx {
1042
+ return useContext(Ctx);
1043
+ }