@chainingintention/pi-web-cn 2.0.0 → 2.202610.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 (584) hide show
  1. package/README.md +61 -106
  2. package/dist/.plugins-ready +1 -0
  3. package/dist/cli.js +331 -174
  4. package/dist/cli.js.map +1 -1
  5. package/dist/client/apple-touch-icon-dev.png +0 -0
  6. package/dist/client/assets/PiWebApp-vueV4eKR.js +4938 -0
  7. package/dist/client/assets/classic-CyM97Akm.css +54 -0
  8. package/dist/client/assets/external-B9K8duyP.js +2 -0
  9. package/dist/client/assets/graphite-DquaqFXU.css +54 -0
  10. package/dist/client/assets/index-C8f0d0CR.js +2 -0
  11. package/dist/client/assets/paper-CB1oLuRr.css +54 -0
  12. package/dist/client/assets/pi-web-dark-D_KtbM95.css +54 -0
  13. package/dist/client/assets/pi-web-light-DSNLMIBI.css +54 -0
  14. package/dist/client/assets/vendor-editor-core-BfnHL1Dg.js +10 -0
  15. package/dist/client/assets/vendor-editor-languages-bNquDJP0.js +28 -0
  16. package/dist/client/favicon-dev.svg +8 -0
  17. package/dist/client/index.html +7 -51
  18. package/dist/client/manifest.webmanifest +2 -1
  19. package/dist/client/pwa-icon-dev-192.png +0 -0
  20. package/dist/client/pwa-icon-dev-512.png +0 -0
  21. package/dist/config.js +55 -8
  22. package/dist/config.js.map +1 -1
  23. package/dist/docker/piWebDockerCommandPlan.js +13 -4
  24. package/dist/docker/piWebDockerCommandPlan.js.map +1 -1
  25. package/dist/environment.js +4 -0
  26. package/dist/environment.js.map +1 -0
  27. package/dist/localization.js +24 -0
  28. package/dist/localization.js.map +1 -0
  29. package/dist/nativeServices/installedServiceDefinitions.js +617 -0
  30. package/dist/nativeServices/installedServiceDefinitions.js.map +1 -0
  31. package/dist/nativeServices/serviceAction.js +78 -20
  32. package/dist/nativeServices/serviceAction.js.map +1 -1
  33. package/dist/nativeServices/serviceDoctor.js +418 -114
  34. package/dist/nativeServices/serviceDoctor.js.map +1 -1
  35. package/dist/nativeServices/servicePlan.js +2 -2
  36. package/dist/nativeServices/servicePlan.js.map +1 -1
  37. package/dist/pi-packages/captains-log/README.md +11 -0
  38. package/dist/pi-packages/captains-log/dist/browser/channelProtocol.js +29 -0
  39. package/dist/pi-packages/captains-log/dist/browser/index.js +143 -0
  40. package/dist/pi-packages/captains-log/dist/browser/markdown.js +68 -0
  41. package/dist/pi-packages/captains-log/dist/browser/panel.js +148 -0
  42. package/dist/pi-packages/captains-log/dist/browser/protocol.js +26 -0
  43. package/dist/pi-packages/captains-log/dist/companion.js +126 -0
  44. package/dist/pi-packages/captains-log/dist/roundtrip.js +62 -0
  45. package/dist/pi-packages/captains-log/dist/server.js +210 -0
  46. package/dist/pi-packages/captains-log/dist/store.js +75 -0
  47. package/dist/pi-packages/captains-log/docs/usage.md +29 -0
  48. package/dist/pi-packages/captains-log/i18n.js +7 -0
  49. package/dist/pi-packages/captains-log/package.json +35 -0
  50. package/dist/pi-packages/captains-log/tsconfig.json +21 -0
  51. package/dist/pi-packages/captains-log/vite.config.mjs +28 -0
  52. package/dist/pi-packages/relays/extensions/index.js +61 -0
  53. package/dist/pi-packages/relays/i18n.js +7 -0
  54. package/dist/{pi-web-plugins → pi-packages}/relays/markdownDocument.js +3 -2
  55. package/dist/pi-packages/relays/package.json +20 -0
  56. package/dist/pi-packages/relays/pi-web-plugin.js +96 -0
  57. package/dist/pi-packages/relays/prompts/relay-worktree.md +18 -0
  58. package/dist/pi-packages/relays/prompts/relay.md +18 -0
  59. package/dist/{pi-web-plugins → pi-packages}/relays/relayDiscovery.js +2 -2
  60. package/dist/pi-packages/relays/relayDispatch.js +67 -0
  61. package/dist/pi-packages/relays/relayIdentity.js +37 -0
  62. package/dist/{pi-web-plugins → pi-packages}/relays/relaysPanelElement.js +98 -59
  63. package/dist/pi-packages/relays/skills/relay/SKILL.md +50 -0
  64. package/dist/pi-packages/relays/skills/relay-runner/SKILL.md +74 -0
  65. package/dist/pi-packages/workflows/browser/pi-web-plugin.js +42 -0
  66. package/dist/pi-packages/workflows/browser/worktreeDialog.js +170 -0
  67. package/dist/pi-packages/workflows/package.json +23 -0
  68. package/dist/pi-packages/workflows/prompts/worktree.md +21 -0
  69. package/dist/pi-packages/workflows/server-plugin.js +586 -0
  70. package/dist/pi-packages/workflows/vite.config.mjs +17 -0
  71. package/dist/pi-web-plugins/code-highlight/browser/pi-web-plugin.js +22 -0
  72. package/dist/pi-web-plugins/code-highlight/package.json +13 -0
  73. package/dist/pi-web-plugins/files/browser/assets/files-icon-DZObYhxb.svg +3 -0
  74. package/dist/pi-web-plugins/files/browser/pi-web-plugin.js +466 -0
  75. package/dist/pi-web-plugins/files/package.json +15 -0
  76. package/dist/pi-web-plugins/git/browser/git-contract.js +22 -11
  77. package/dist/pi-web-plugins/git/browser/git-panel.js +228 -100
  78. package/dist/pi-web-plugins/git/browser/i18n.js +7 -0
  79. package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +28 -4
  80. package/dist/pi-web-plugins/git/git-backend.js +61 -21
  81. package/dist/pi-web-plugins/git/gitStatusCache.js +48 -0
  82. package/dist/pi-web-plugins/git/i18n.js +7 -0
  83. package/dist/pi-web-plugins/git/package.json +1 -0
  84. package/dist/pi-web-plugins/git/server-plugin.js +45 -24
  85. package/dist/pi-web-plugins/git/workspace-discovery-notify.cjs +14 -0
  86. package/dist/pi-web-plugins/git/workspaceDiscoveryHooks.js +186 -0
  87. package/dist/pi-web-plugins/info/i18n.js +7 -0
  88. package/dist/pi-web-plugins/info/infoInternals.js +76 -65
  89. package/dist/pi-web-plugins/info/package.json +1 -1
  90. package/dist/pi-web-plugins/info/pi-web-plugin.js +40 -42
  91. package/dist/pi-web-plugins/mermaid/browser/mermaid-engine.js +4255 -0
  92. package/dist/pi-web-plugins/mermaid/browser/pi-web-plugin.js +11 -0
  93. package/dist/pi-web-plugins/mermaid/package.json +13 -0
  94. package/dist/pi-web-plugins/terminal/browser/pi-web-plugin.js +219 -0
  95. package/dist/pi-web-plugins/terminal/i18n.js +7 -0
  96. package/dist/pi-web-plugins/terminal/package.json +16 -0
  97. package/dist/pi-web-plugins/terminal/server-plugin.js +367 -0
  98. package/dist/pi-web-plugins/terminal/terminalService.js +436 -0
  99. package/dist/pi-web-plugins/updates/i18n.js +7 -0
  100. package/dist/pi-web-plugins/updates/package.json +1 -1
  101. package/dist/pi-web-plugins/updates/pi-web-plugin.js +143 -140
  102. package/dist/pi-web-plugins/updates/updatesLogic.js +24 -24
  103. package/dist/pi-web-plugins/workspace-tasks/config.js +12 -11
  104. package/dist/pi-web-plugins/workspace-tasks/i18n.js +7 -0
  105. package/dist/pi-web-plugins/workspace-tasks/package.json +1 -1
  106. package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +31 -9
  107. package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +54 -36
  108. package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +12 -11
  109. package/dist/pi-web-plugins/zh-cn/auth.json +9 -0
  110. package/dist/pi-web-plugins/zh-cn/bundled.json +219 -0
  111. package/dist/pi-web-plugins/zh-cn/cli.json +230 -0
  112. package/dist/pi-web-plugins/zh-cn/client.json +225 -0
  113. package/dist/pi-web-plugins/zh-cn/components.json +1252 -0
  114. package/dist/pi-web-plugins/zh-cn/config-errors.json +188 -0
  115. package/dist/pi-web-plugins/zh-cn/files.json +50 -0
  116. package/dist/pi-web-plugins/zh-cn/machines.json +28 -0
  117. package/dist/pi-web-plugins/zh-cn/main.json +459 -0
  118. package/dist/pi-web-plugins/zh-cn/management-errors.json +23 -0
  119. package/dist/pi-web-plugins/zh-cn/manifest.webmanifest +25 -0
  120. package/dist/pi-web-plugins/zh-cn/metadata.json +3 -0
  121. package/dist/pi-web-plugins/zh-cn/package.json +10 -0
  122. package/dist/pi-web-plugins/zh-cn/pi-web-plugin.js +16 -0
  123. package/dist/pi-web-plugins/zh-cn/projects.json +6 -0
  124. package/dist/pi-web-plugins/zh-cn/provider-auth.json +18 -0
  125. package/dist/pi-web-plugins/zh-cn/routing.json +68 -0
  126. package/dist/pi-web-plugins/zh-cn/server-main.json +99 -0
  127. package/dist/pi-web-plugins/zh-cn/server.json +256 -0
  128. package/dist/piAi.js +4 -0
  129. package/dist/piAi.js.map +1 -0
  130. package/dist/piRuntime.js +150 -0
  131. package/dist/piRuntime.js.map +1 -0
  132. package/dist/piSdk.js +5 -0
  133. package/dist/piSdk.js.map +1 -0
  134. package/dist/piWebUpdate.js +508 -0
  135. package/dist/piWebUpdate.js.map +1 -0
  136. package/dist/piWebVersionReport.js +109 -41
  137. package/dist/piWebVersionReport.js.map +1 -1
  138. package/dist/plugin-api.d.ts +609 -29
  139. package/dist/plugin-api.js +1 -0
  140. package/dist/pluginRecoveryCli.js +27 -25
  141. package/dist/pluginRecoveryCli.js.map +1 -1
  142. package/dist/server/activity/workspaceActivityService.js +13 -6
  143. package/dist/server/activity/workspaceActivityService.js.map +1 -1
  144. package/dist/server/app.js +158 -89
  145. package/dist/server/app.js.map +1 -1
  146. package/dist/server/audit/managementAuditStore.js +6 -1
  147. package/dist/server/audit/managementAuditStore.js.map +1 -1
  148. package/dist/server/audit/normalToolAuditCli.js +45 -43
  149. package/dist/server/audit/normalToolAuditCli.js.map +1 -1
  150. package/dist/server/browserMessageProjection.js +39 -22
  151. package/dist/server/browserMessageProjection.js.map +1 -1
  152. package/dist/server/configRoutes.js +54 -33
  153. package/dist/server/configRoutes.js.map +1 -1
  154. package/dist/server/deploymentIdentity.js +67 -0
  155. package/dist/server/deploymentIdentity.js.map +1 -0
  156. package/dist/server/deploymentIdentityRoutes.js +22 -0
  157. package/dist/server/deploymentIdentityRoutes.js.map +1 -0
  158. package/dist/server/diagnostics/nodePtyNativeModule.js +7 -6
  159. package/dist/server/diagnostics/nodePtyNativeModule.js.map +1 -1
  160. package/dist/server/diagnostics/nodePtySpawnHelper.js +21 -20
  161. package/dist/server/diagnostics/nodePtySpawnHelper.js.map +1 -1
  162. package/dist/server/index.js +10 -1
  163. package/dist/server/index.js.map +1 -1
  164. package/dist/server/knownAutoInstallPiPackages.js +36 -0
  165. package/dist/server/knownAutoInstallPiPackages.js.map +1 -0
  166. package/dist/server/knownPiPackages.js +12 -0
  167. package/dist/server/knownPiPackages.js.map +1 -0
  168. package/dist/server/machines/machineClient.js +23 -19
  169. package/dist/server/machines/machineClient.js.map +1 -1
  170. package/dist/server/machines/machinePluginProxyRoutes.js +131 -31
  171. package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -1
  172. package/dist/server/machines/machineProxyRoutes.js +138 -47
  173. package/dist/server/machines/machineProxyRoutes.js.map +1 -1
  174. package/dist/server/machines/machineRoutes.js +18 -13
  175. package/dist/server/machines/machineRoutes.js.map +1 -1
  176. package/dist/server/machines/machineService.js +40 -18
  177. package/dist/server/machines/machineService.js.map +1 -1
  178. package/dist/server/managementEmbed.js +149 -30
  179. package/dist/server/managementEmbed.js.map +1 -1
  180. package/dist/server/managementPrivileges.js +21 -0
  181. package/dist/server/managementPrivileges.js.map +1 -0
  182. package/dist/server/managementTerminalProxyRoutes.js +124 -0
  183. package/dist/server/managementTerminalProxyRoutes.js.map +1 -0
  184. package/dist/server/navigationPreferenceRoutes.js +59 -0
  185. package/dist/server/navigationPreferenceRoutes.js.map +1 -0
  186. package/dist/server/normalAuth.js +77 -53
  187. package/dist/server/normalAuth.js.map +1 -1
  188. package/dist/server/notices/serverNoticeRoutes.js +43 -0
  189. package/dist/server/notices/serverNoticeRoutes.js.map +1 -0
  190. package/dist/server/notices/serverNoticeService.js +26 -0
  191. package/dist/server/notices/serverNoticeService.js.map +1 -0
  192. package/dist/server/notices/serverNoticeStore.js +122 -0
  193. package/dist/server/notices/serverNoticeStore.js.map +1 -0
  194. package/dist/server/passwordVerifier.js +91 -0
  195. package/dist/server/passwordVerifier.js.map +1 -0
  196. package/dist/server/piPackageIdentity.js +25 -0
  197. package/dist/server/piPackageIdentity.js.map +1 -0
  198. package/dist/server/piPackageService.js +72 -9
  199. package/dist/server/piPackageService.js.map +1 -1
  200. package/dist/server/piWebPluginCatalog.js +212 -35
  201. package/dist/server/piWebPluginCatalog.js.map +1 -1
  202. package/dist/server/piWebPluginLifecycle.js +29 -3
  203. package/dist/server/piWebPluginLifecycle.js.map +1 -1
  204. package/dist/server/piWebPluginService.js +199 -292
  205. package/dist/server/piWebPluginService.js.map +1 -1
  206. package/dist/server/piWebStatus.js +57 -100
  207. package/dist/server/piWebStatus.js.map +1 -1
  208. package/dist/server/pluginCallbackDrain.js +35 -0
  209. package/dist/server/pluginCallbackDrain.js.map +1 -0
  210. package/dist/server/plugins/pluginBackendChannelProxyAdmission.js +84 -0
  211. package/dist/server/plugins/pluginBackendChannelProxyAdmission.js.map +1 -0
  212. package/dist/server/plugins/pluginBackendChannelProxyCoordinator.js +234 -0
  213. package/dist/server/plugins/pluginBackendChannelProxyCoordinator.js.map +1 -0
  214. package/dist/server/plugins/pluginBackendChannelProxyRoutes.js +61 -0
  215. package/dist/server/plugins/pluginBackendChannelProxyRoutes.js.map +1 -0
  216. package/dist/server/plugins/pluginBackendProxyRoutes.js +47 -57
  217. package/dist/server/plugins/pluginBackendProxyRoutes.js.map +1 -1
  218. package/dist/server/plugins/pluginBackendRegistry.js +804 -0
  219. package/dist/server/plugins/pluginBackendRegistry.js.map +1 -0
  220. package/dist/server/plugins/projectPluginSettings.js +95 -0
  221. package/dist/server/plugins/projectPluginSettings.js.map +1 -0
  222. package/dist/server/plugins/serverPluginCatalogCapability.js +106 -0
  223. package/dist/server/plugins/serverPluginCatalogCapability.js.map +1 -0
  224. package/dist/server/plugins/serverPluginPiSessionEventsCapability.js +34 -0
  225. package/dist/server/plugins/serverPluginPiSessionEventsCapability.js.map +1 -0
  226. package/dist/server/plugins/serverPluginPiSessionsCapability.js +185 -0
  227. package/dist/server/plugins/serverPluginPiSessionsCapability.js.map +1 -0
  228. package/dist/server/plugins/serverPluginRuntime.js +1088 -108
  229. package/dist/server/plugins/serverPluginRuntime.js.map +1 -1
  230. package/dist/server/plugins/serverPluginWorkspacesCapability.js +114 -0
  231. package/dist/server/plugins/serverPluginWorkspacesCapability.js.map +1 -0
  232. package/dist/server/projectTrustRoutes.js +86 -0
  233. package/dist/server/projectTrustRoutes.js.map +1 -0
  234. package/dist/server/projects/projectLifecycleService.js +94 -0
  235. package/dist/server/projects/projectLifecycleService.js.map +1 -0
  236. package/dist/server/projects/projectService.js +7 -4
  237. package/dist/server/projects/projectService.js.map +1 -1
  238. package/dist/server/realtime/sessionEventHub.js +58 -39
  239. package/dist/server/realtime/sessionEventHub.js.map +1 -1
  240. package/dist/server/realtime/sessionEventScope.js +4 -0
  241. package/dist/server/realtime/sessionEventScope.js.map +1 -1
  242. package/dist/server/requestCancellation.js +15 -1
  243. package/dist/server/requestCancellation.js.map +1 -1
  244. package/dist/server/sessiond/agentHttpDispatcher.js +108 -0
  245. package/dist/server/sessiond/agentHttpDispatcher.js.map +1 -0
  246. package/dist/server/sessiond/autoInstallPiPackages.js +63 -0
  247. package/dist/server/sessiond/autoInstallPiPackages.js.map +1 -0
  248. package/dist/server/sessiond/pluginBackendChannelRoutes.js +410 -0
  249. package/dist/server/sessiond/pluginBackendChannelRoutes.js.map +1 -0
  250. package/dist/server/sessiond/pluginBackendRoutes.js +64 -47
  251. package/dist/server/sessiond/pluginBackendRoutes.js.map +1 -1
  252. package/dist/server/sessiond/pluginCatalogRoutes.js +41 -0
  253. package/dist/server/sessiond/pluginCatalogRoutes.js.map +1 -0
  254. package/dist/server/sessiond/projectMutationRoutes.js +39 -0
  255. package/dist/server/sessiond/projectMutationRoutes.js.map +1 -0
  256. package/dist/server/sessiond/sessionDaemonShutdown.js +36 -0
  257. package/dist/server/sessiond/sessionDaemonShutdown.js.map +1 -0
  258. package/dist/server/sessiond/sessionDaemonStartup.js +30 -4
  259. package/dist/server/sessiond/sessionDaemonStartup.js.map +1 -1
  260. package/dist/server/sessiond/sessionProxyRoutes.js +263 -91
  261. package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
  262. package/dist/server/sessiond/sessionServiceDependencies.js +5 -0
  263. package/dist/server/sessiond/sessionServiceDependencies.js.map +1 -1
  264. package/dist/server/sessiond/sessiondStateOwnership.js +174 -39
  265. package/dist/server/sessiond/sessiondStateOwnership.js.map +1 -1
  266. package/dist/server/sessiond/workspaceCatalogRoutes.js +11 -5
  267. package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -1
  268. package/dist/server/sessiond/workspaceNotificationRoutes.js +55 -0
  269. package/dist/server/sessiond/workspaceNotificationRoutes.js.map +1 -0
  270. package/dist/server/sessiond/workspaceRemovalRoutes.js +1 -1
  271. package/dist/server/sessiond/workspaceRemovalRoutes.js.map +1 -1
  272. package/dist/server/sessiond.js +313 -69
  273. package/dist/server/sessiond.js.map +1 -1
  274. package/dist/server/sessions/askUserDomain.js +232 -0
  275. package/dist/server/sessions/askUserDomain.js.map +1 -0
  276. package/dist/server/sessions/askUserTool.js +18 -21
  277. package/dist/server/sessions/askUserTool.js.map +1 -1
  278. package/dist/server/sessions/attachmentService.js +2 -6
  279. package/dist/server/sessions/attachmentService.js.map +1 -1
  280. package/dist/server/sessions/authRoutes.js +32 -19
  281. package/dist/server/sessions/authRoutes.js.map +1 -1
  282. package/dist/server/sessions/authService.js +31 -11
  283. package/dist/server/sessions/authService.js.map +1 -1
  284. package/dist/server/sessions/builtinCommands.js +28 -21
  285. package/dist/server/sessions/builtinCommands.js.map +1 -1
  286. package/dist/server/sessions/builtinExtensionFactories.js +36 -0
  287. package/dist/server/sessions/builtinExtensionFactories.js.map +1 -0
  288. package/dist/server/sessions/clientSessionPreview.js +14 -0
  289. package/dist/server/sessions/clientSessionPreview.js.map +1 -0
  290. package/dist/server/sessions/companionBackend.js +286 -0
  291. package/dist/server/sessions/companionBackend.js.map +1 -0
  292. package/dist/server/sessions/dockerEnvironmentFacts.js +98 -10
  293. package/dist/server/sessions/dockerEnvironmentFacts.js.map +1 -1
  294. package/dist/server/sessions/extensionSessionDispatch.js +76 -0
  295. package/dist/server/sessions/extensionSessionDispatch.js.map +1 -0
  296. package/dist/server/sessions/globalProviderPolicy.js +88 -19
  297. package/dist/server/sessions/globalProviderPolicy.js.map +1 -1
  298. package/dist/server/sessions/managementAgentTools.js +116 -6
  299. package/dist/server/sessions/managementAgentTools.js.map +1 -1
  300. package/dist/server/sessions/managementPermissionSystem.js +36 -14
  301. package/dist/server/sessions/managementPermissionSystem.js.map +1 -1
  302. package/dist/server/sessions/managementSandbox.js +7 -18
  303. package/dist/server/sessions/managementSandbox.js.map +1 -1
  304. package/dist/server/sessions/mcpAuthFlowService.js +289 -0
  305. package/dist/server/sessions/mcpAuthFlowService.js.map +1 -0
  306. package/dist/server/sessions/mcpAuthRoutes.js +104 -0
  307. package/dist/server/sessions/mcpAuthRoutes.js.map +1 -0
  308. package/dist/server/sessions/mcpOAuthCredentialAdapter.js +92 -0
  309. package/dist/server/sessions/mcpOAuthCredentialAdapter.js.map +1 -0
  310. package/dist/server/sessions/messageHistoryTarget.js +79 -0
  311. package/dist/server/sessions/messageHistoryTarget.js.map +1 -0
  312. package/dist/server/sessions/messagePaging.js +2 -2
  313. package/dist/server/sessions/messagePaging.js.map +1 -1
  314. package/dist/server/sessions/modelCatalogRefresher.js +4 -3
  315. package/dist/server/sessions/modelCatalogRefresher.js.map +1 -1
  316. package/dist/server/sessions/oauthLoginFlowService.js +19 -20
  317. package/dist/server/sessions/oauthLoginFlowService.js.map +1 -1
  318. package/dist/server/sessions/piSessionEventConnections.js +68 -0
  319. package/dist/server/sessions/piSessionEventConnections.js.map +1 -0
  320. package/dist/server/sessions/piSessionManagerGateway.js +206 -27
  321. package/dist/server/sessions/piSessionManagerGateway.js.map +1 -1
  322. package/dist/server/sessions/piSessionService.js +2508 -991
  323. package/dist/server/sessions/piSessionService.js.map +1 -1
  324. package/dist/server/sessions/plainTextTheme.js +1 -1
  325. package/dist/server/sessions/plainTextTheme.js.map +1 -1
  326. package/dist/server/sessions/projectAuthService.js +35 -6
  327. package/dist/server/sessions/projectAuthService.js.map +1 -1
  328. package/dist/server/sessions/projectSettingsScope.js +88 -33
  329. package/dist/server/sessions/projectSettingsScope.js.map +1 -1
  330. package/dist/server/sessions/projectTrust.js +119 -0
  331. package/dist/server/sessions/projectTrust.js.map +1 -0
  332. package/dist/server/sessions/queuedMessageMutation.js +170 -0
  333. package/dist/server/sessions/queuedMessageMutation.js.map +1 -0
  334. package/dist/server/sessions/relaySkill.js +169 -0
  335. package/dist/server/sessions/relaySkill.js.map +1 -0
  336. package/dist/server/sessions/sessionActivityMarker.js +105 -0
  337. package/dist/server/sessions/sessionActivityMarker.js.map +1 -0
  338. package/dist/server/sessions/sessionArchiveMapping.js +16 -15
  339. package/dist/server/sessions/sessionArchiveMapping.js.map +1 -1
  340. package/dist/server/sessions/sessionArchiveStore.js +5 -1
  341. package/dist/server/sessions/sessionArchiveStore.js.map +1 -1
  342. package/dist/server/sessions/sessionArchiveTree.js +2 -2
  343. package/dist/server/sessions/sessionArchiveTree.js.map +1 -1
  344. package/dist/server/sessions/sessionCleanup.js +4 -3
  345. package/dist/server/sessions/sessionCleanup.js.map +1 -1
  346. package/dist/server/sessions/sessionCommandService.js +79 -87
  347. package/dist/server/sessions/sessionCommandService.js.map +1 -1
  348. package/dist/server/sessions/sessionEnvironmentFacts.js +5 -4
  349. package/dist/server/sessions/sessionEnvironmentFacts.js.map +1 -1
  350. package/dist/server/sessions/sessionFileHeader.js +41 -0
  351. package/dist/server/sessions/sessionFileHeader.js.map +1 -1
  352. package/dist/server/sessions/sessionImageDimensions.js +31 -0
  353. package/dist/server/sessions/sessionImageDimensions.js.map +1 -0
  354. package/dist/server/sessions/sessionMediaIndex.js +191 -0
  355. package/dist/server/sessions/sessionMediaIndex.js.map +1 -0
  356. package/dist/server/sessions/sessionMetadata.js +51 -0
  357. package/dist/server/sessions/sessionMetadata.js.map +1 -0
  358. package/dist/server/sessions/sessionModelScope.js +160 -0
  359. package/dist/server/sessions/sessionModelScope.js.map +1 -0
  360. package/dist/server/sessions/sessionNameGenerator.js +16 -35
  361. package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
  362. package/dist/server/sessions/sessionNotificationStore.js +14 -11
  363. package/dist/server/sessions/sessionNotificationStore.js.map +1 -1
  364. package/dist/server/sessions/sessionReadAccess.js +41 -0
  365. package/dist/server/sessions/sessionReadAccess.js.map +1 -0
  366. package/dist/server/sessions/sessionRoutes.js +221 -78
  367. package/dist/server/sessions/sessionRoutes.js.map +1 -1
  368. package/dist/server/sessions/sessionSummaryScanner.js +62 -5
  369. package/dist/server/sessions/sessionSummaryScanner.js.map +1 -1
  370. package/dist/server/sessions/sessionTreeProjection.js +50 -49
  371. package/dist/server/sessions/sessionTreeProjection.js.map +1 -1
  372. package/dist/server/sessions/sessionUiEvents.js +22 -10
  373. package/dist/server/sessions/sessionUiEvents.js.map +1 -1
  374. package/dist/server/sessions/sessionUnreadStore.js +53 -3
  375. package/dist/server/sessions/sessionUnreadStore.js.map +1 -1
  376. package/dist/server/sessions/spawnSessionTool.js +14 -6
  377. package/dist/server/sessions/spawnSessionTool.js.map +1 -1
  378. package/dist/server/sessions/spawnSubsessionTool.js +40 -24
  379. package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
  380. package/dist/server/sessions/spawnTargetResolver.js +1 -1
  381. package/dist/server/sessions/subsessionCompletionDelivery.js +15 -0
  382. package/dist/server/sessions/subsessionCompletionDelivery.js.map +1 -0
  383. package/dist/server/sessions/subsessionCompletionInbox.js +134 -0
  384. package/dist/server/sessions/subsessionCompletionInbox.js.map +1 -0
  385. package/dist/server/sessions/subsessionProvenance.js +27 -0
  386. package/dist/server/sessions/subsessionProvenance.js.map +1 -0
  387. package/dist/server/sessions/transcriptBranchCache.js +81 -0
  388. package/dist/server/sessions/transcriptBranchCache.js.map +1 -0
  389. package/dist/server/sessions/transcriptMarkdown.js +48 -0
  390. package/dist/server/sessions/transcriptMarkdown.js.map +1 -0
  391. package/dist/server/sessions/transcriptMessages.js +57 -0
  392. package/dist/server/sessions/transcriptMessages.js.map +1 -0
  393. package/dist/server/startupLogger.js +13 -0
  394. package/dist/server/startupLogger.js.map +1 -0
  395. package/dist/server/startupUrls.js +27 -0
  396. package/dist/server/startupUrls.js.map +1 -0
  397. package/dist/server/status/machineStatusService.js +15 -7
  398. package/dist/server/status/machineStatusService.js.map +1 -1
  399. package/dist/server/storage/navigationPreferenceStore.js +138 -0
  400. package/dist/server/storage/navigationPreferenceStore.js.map +1 -0
  401. package/dist/server/storage/piPackageDismissalStore.js +78 -0
  402. package/dist/server/storage/piPackageDismissalStore.js.map +1 -0
  403. package/dist/server/terminals/{terminalService.js → managementCommandRunService.js} +98 -102
  404. package/dist/server/terminals/managementCommandRunService.js.map +1 -0
  405. package/dist/server/terminals/managementTerminalRoutes.js +91 -0
  406. package/dist/server/terminals/managementTerminalRoutes.js.map +1 -0
  407. package/dist/server/terminals/requiredTerminalService.js +103 -0
  408. package/dist/server/terminals/requiredTerminalService.js.map +1 -0
  409. package/dist/server/webSocketBridge.js +348 -0
  410. package/dist/server/webSocketBridge.js.map +1 -1
  411. package/dist/server/workbench/accessStateStore.js +33 -5
  412. package/dist/server/workbench/accessStateStore.js.map +1 -1
  413. package/dist/server/workbench/capabilitySearch.js +3 -2
  414. package/dist/server/workbench/capabilitySearch.js.map +1 -1
  415. package/dist/server/workbench/gatewayIntegration.js +40 -13
  416. package/dist/server/workbench/gatewayIntegration.js.map +1 -1
  417. package/dist/server/workbench/knowledgeSearch.js +100 -0
  418. package/dist/server/workbench/knowledgeSearch.js.map +1 -0
  419. package/dist/server/workbench/mcpClient.js +41 -8
  420. package/dist/server/workbench/mcpClient.js.map +1 -1
  421. package/dist/server/workbench/skillSync.js +11 -3
  422. package/dist/server/workbench/skillSync.js.map +1 -1
  423. package/dist/server/workbench/workbenchClient.js +130 -7
  424. package/dist/server/workbench/workbenchClient.js.map +1 -1
  425. package/dist/server/workbench/workbenchTools.js +196 -14
  426. package/dist/server/workbench/workbenchTools.js.map +1 -1
  427. package/dist/server/workingDirectory.js +3 -2
  428. package/dist/server/workingDirectory.js.map +1 -1
  429. package/dist/server/workspaceExplorerRoutes.js +53 -21
  430. package/dist/server/workspaceExplorerRoutes.js.map +1 -1
  431. package/dist/server/workspaces/fileContentService.js +31 -16
  432. package/dist/server/workspaces/fileContentService.js.map +1 -1
  433. package/dist/server/workspaces/fileOperationService.js +11 -9
  434. package/dist/server/workspaces/fileOperationService.js.map +1 -1
  435. package/dist/server/workspaces/filePreviewService.js +10 -6
  436. package/dist/server/workspaces/filePreviewService.js.map +1 -1
  437. package/dist/server/workspaces/fileSuggestions.js +77 -10
  438. package/dist/server/workspaces/fileSuggestions.js.map +1 -1
  439. package/dist/server/workspaces/fileTreeService.js +103 -15
  440. package/dist/server/workspaces/fileTreeService.js.map +1 -1
  441. package/dist/server/workspaces/normalProjectCwdResolver.js +35 -0
  442. package/dist/server/workspaces/normalProjectCwdResolver.js.map +1 -0
  443. package/dist/server/workspaces/pathAccessPolicy.js +24 -18
  444. package/dist/server/workspaces/pathAccessPolicy.js.map +1 -1
  445. package/dist/server/workspaces/pathSafety.js +6 -5
  446. package/dist/server/workspaces/pathSafety.js.map +1 -1
  447. package/dist/server/workspaces/projectPiWebConfig.js +95 -8
  448. package/dist/server/workspaces/projectPiWebConfig.js.map +1 -1
  449. package/dist/server/workspaces/projectWorkspaceCwds.js +0 -5
  450. package/dist/server/workspaces/projectWorkspaceCwds.js.map +1 -1
  451. package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js +37 -22
  452. package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js.map +1 -1
  453. package/dist/server/workspaces/workspaceCatalog.js +6 -4
  454. package/dist/server/workspaces/workspaceCatalog.js.map +1 -1
  455. package/dist/server/workspaces/workspaceChangeNotifier.js +12 -0
  456. package/dist/server/workspaces/workspaceChangeNotifier.js.map +1 -0
  457. package/dist/server/workspaces/workspaceDeletionRoutes.js +9 -70
  458. package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -1
  459. package/dist/server/workspaces/workspaceNotificationCommand.js +64 -0
  460. package/dist/server/workspaces/workspaceNotificationCommand.js.map +1 -0
  461. package/dist/server/workspaces/workspaceProviderRegistry.js +128 -24
  462. package/dist/server/workspaces/workspaceProviderRegistry.js.map +1 -1
  463. package/dist/server/workspaces/workspaceRemovalService.js +41 -7
  464. package/dist/server/workspaces/workspaceRemovalService.js.map +1 -1
  465. package/dist/server/workspaces/workspaceRouteContext.js +1 -1
  466. package/dist/server/workspaces/workspaceRouteContext.js.map +1 -1
  467. package/dist/server/workspaces/workspaceRouteErrors.js +4 -2
  468. package/dist/server/workspaces/workspaceRouteErrors.js.map +1 -1
  469. package/dist/server/workspaces/workspaceUserError.js +18 -0
  470. package/dist/server/workspaces/workspaceUserError.js.map +1 -0
  471. package/dist/server-plugin-api.d.ts +349 -49
  472. package/dist/server-plugin-api.js +344 -2
  473. package/dist/server-plugin-api.js.map +1 -1
  474. package/dist/serverPluginRecovery.js +6 -1
  475. package/dist/serverPluginRecovery.js.map +1 -1
  476. package/dist/sessiond/activeAgentProfile.js +27 -2
  477. package/dist/sessiond/activeAgentProfile.js.map +1 -1
  478. package/dist/sessiond/config.js +4 -3
  479. package/dist/sessiond/config.js.map +1 -1
  480. package/dist/sessiond/sessionDaemonClient.js +75 -19
  481. package/dist/sessiond/sessionDaemonClient.js.map +1 -1
  482. package/dist/sessiond/sessionDaemonErrors.js +49 -0
  483. package/dist/sessiond/sessionDaemonErrors.js.map +1 -0
  484. package/dist/shared/activeAgentProfile.js +2 -34
  485. package/dist/shared/activeAgentProfile.js.map +1 -1
  486. package/dist/shared/activity.js +0 -3
  487. package/dist/shared/activity.js.map +1 -1
  488. package/dist/shared/apiTypes.js +10 -3
  489. package/dist/shared/apiTypes.js.map +1 -1
  490. package/dist/shared/capabilities.js +8 -0
  491. package/dist/shared/capabilities.js.map +1 -1
  492. package/dist/shared/federatedRoutes.js +77 -11
  493. package/dist/shared/federatedRoutes.js.map +1 -1
  494. package/dist/shared/i18n.js +41 -0
  495. package/dist/shared/i18n.js.map +1 -0
  496. package/dist/shared/machinePluginIds.js +30 -7
  497. package/dist/shared/machinePluginIds.js.map +1 -1
  498. package/dist/shared/machineStatus.js +46 -3
  499. package/dist/shared/machineStatus.js.map +1 -1
  500. package/dist/shared/navigationPreferences.js +6 -0
  501. package/dist/shared/navigationPreferences.js.map +1 -0
  502. package/dist/shared/piWebConfigParsing.js +118 -49
  503. package/dist/shared/piWebConfigParsing.js.map +1 -1
  504. package/dist/shared/piWebStatusParsing.js +33 -0
  505. package/dist/shared/piWebStatusParsing.js.map +1 -1
  506. package/dist/shared/pluginApiTypes.d.ts +87 -8
  507. package/dist/shared/pluginApiTypes.js +2 -0
  508. package/dist/shared/pluginApiTypes.js.map +1 -0
  509. package/dist/shared/pluginBackendProtocol.js +218 -2
  510. package/dist/shared/pluginBackendProtocol.js.map +1 -1
  511. package/dist/shared/pluginCatalogTypes.d.ts +49 -0
  512. package/dist/shared/pluginCatalogTypes.js +156 -0
  513. package/dist/shared/pluginCatalogTypes.js.map +1 -0
  514. package/dist/shared/pluginIds.js +10 -1
  515. package/dist/shared/pluginIds.js.map +1 -1
  516. package/dist/shared/requiredTerminalPlugin.js +6 -0
  517. package/dist/shared/requiredTerminalPlugin.js.map +1 -0
  518. package/dist/shared/serverNoticeContract.js +88 -0
  519. package/dist/shared/serverNoticeContract.js.map +1 -0
  520. package/dist/shared/sessionDefaults.js +42 -0
  521. package/dist/shared/sessionDefaults.js.map +1 -0
  522. package/dist/shared/sessionMedia.js +12 -0
  523. package/dist/shared/sessionMedia.js.map +1 -0
  524. package/dist/shared/streamingBehavior.js +8 -0
  525. package/dist/shared/streamingBehavior.js.map +1 -0
  526. package/dist/shared/themePreference.js +24 -0
  527. package/dist/shared/themePreference.js.map +1 -0
  528. package/dist/shared/thinkingLevels.js +17 -16
  529. package/dist/shared/thinkingLevels.js.map +1 -1
  530. package/dist/shared/workspaceFiles.js.map +1 -1
  531. package/dist/workspaceNotificationCli.js +95 -0
  532. package/dist/workspaceNotificationCli.js.map +1 -0
  533. package/docs/README.md +31 -0
  534. package/docs/config.md +344 -277
  535. package/docs/plugins.md +204 -930
  536. package/examples/session-bridge-plugin/README.md +20 -0
  537. package/examples/session-bridge-plugin/docs/usage.md +54 -0
  538. package/examples/session-bridge-plugin/package.json +26 -0
  539. package/examples/session-bridge-plugin/src/browser/index.ts +87 -0
  540. package/examples/session-bridge-plugin/src/browser/protocol.ts +24 -0
  541. package/examples/session-bridge-plugin/src/companion.ts +65 -0
  542. package/examples/session-bridge-plugin/src/reviewRun.ts +39 -0
  543. package/examples/session-bridge-plugin/src/server.ts +85 -0
  544. package/examples/session-bridge-plugin/src/store.ts +80 -0
  545. package/examples/session-bridge-plugin/tsconfig.json +21 -0
  546. package/examples/workspace-provider-plugin/README.md +39 -0
  547. package/examples/workspace-provider-plugin/package.json +25 -0
  548. package/examples/workspace-provider-plugin/src/browser/index.ts +69 -0
  549. package/examples/workspace-provider-plugin/src/server.ts +68 -0
  550. package/examples/workspace-provider-plugin/tsconfig.json +21 -0
  551. package/extensions/pi-web.ts +3 -1
  552. package/package.json +59 -36
  553. package/skills/README.md +28 -2
  554. package/skills/relay/SKILL.md +24 -89
  555. package/skills/relay-runner/SKILL.md +74 -0
  556. package/dist/client/assets/CodeViewer-DCl56K0Z.js +0 -4
  557. package/dist/client/assets/TerminalPanel-DCvoEjUF.js +0 -187
  558. package/dist/client/assets/index-CMvms5cF.js +0 -4325
  559. package/dist/client/assets/vendor-editor-core-vUi74DnD.js +0 -12
  560. package/dist/client/assets/vendor-editor-languages-DoaXUodB.js +0 -46
  561. package/dist/client/assets/vendor-editor-legacy-CYBnW6ZU.js +0 -1
  562. package/dist/client/assets/vendor-terminal-BrP-ENHg.css +0 -1
  563. package/dist/client/assets/vendor-terminal-D8k4UKM2.js +0 -35
  564. package/dist/pi-web-plugins/relays/package.json +0 -9
  565. package/dist/pi-web-plugins/relays/pi-web-plugin.js +0 -44
  566. package/dist/server/git/gitService.js +0 -290
  567. package/dist/server/git/gitService.js.map +0 -1
  568. package/dist/server/gitRoutes.js +0 -23
  569. package/dist/server/gitRoutes.js.map +0 -1
  570. package/dist/server/sessions/pendingAskStore.js +0 -278
  571. package/dist/server/sessions/pendingAskStore.js.map +0 -1
  572. package/dist/server/terminalProxyRoutes.js +0 -178
  573. package/dist/server/terminalProxyRoutes.js.map +0 -1
  574. package/dist/server/terminals/terminalRoutes.js +0 -164
  575. package/dist/server/terminals/terminalRoutes.js.map +0 -1
  576. package/dist/server/terminals/terminalService.js.map +0 -1
  577. package/dist/server/terminals/terminalSize.js +0 -17
  578. package/dist/server/terminals/terminalSize.js.map +0 -1
  579. package/dist/server/workspaces/gitWorktreeDiscovery.js +0 -43
  580. package/dist/server/workspaces/gitWorktreeDiscovery.js.map +0 -1
  581. package/dist/server/workspaces/workspaceService.js +0 -52
  582. package/dist/server/workspaces/workspaceService.js.map +0 -1
  583. /package/dist/{pi-web-plugins → pi-packages}/relays/vendor/README.md +0 -0
  584. /package/dist/{pi-web-plugins → pi-packages}/relays/vendor/marked.esm.js +0 -0
package/dist/cli.js CHANGED
@@ -1,20 +1,26 @@
1
1
  #!/usr/bin/env node
2
+ import { loadNodeTranslator } from "./localization.js";
3
+ import { runPiWebUpdate } from "./piWebUpdate.js";
4
+ import { createTranslator } from "./shared/i18n.js";
2
5
  import { spawnSync } from "node:child_process";
3
6
  import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
4
7
  import { mkdir, rm, writeFile } from "node:fs/promises";
5
8
  import { homedir, userInfo } from "node:os";
6
9
  import { basename, dirname, join, resolve } from "node:path";
7
10
  import { fileURLToPath } from "node:url";
8
- import { defaultPiWebConfigPath, defaultPiWebDataDir, effectivePiWebConfig, examplePiWebConfig } from "./config.js";
11
+ import { defaultPiWebConfigPath, defaultPiWebDataDir, examplePiWebConfig } from "./config.js";
9
12
  import { piWebDockerCommand } from "./docker/piWebDockerCommandPlan.js";
13
+ import { ownEnvironmentValue } from "./environment.js";
14
+ import { PI_WEB_PI_PACKAGE_DIR_ENV } from "./piRuntime.js";
10
15
  import { runPluginRecoveryCli } from "./pluginRecoveryCli.js";
11
- import { packageVersion, printPiWebVersionReport, probeRunningComponentReady, runningComponentsReady } from "./piWebVersionReport.js";
16
+ import { packageVersion, printPiWebVersionReport, probeRunningComponentReady, runningComponentsReady, } from "./piWebVersionReport.js";
12
17
  import { checkNodePtyDarwinSpawnHelper, formatNodePtyDarwinSpawnHelperCheck } from "./server/diagnostics/nodePtySpawnHelper.js";
13
18
  import { checkNodePtyNativeModule, formatNodePtyNativeModuleCheck } from "./server/diagnostics/nodePtyNativeModule.js";
14
- import { launchdBootoutArgs, launchdServiceTarget, orderServices, performServiceAction, serviceStartOrder, serviceStopOrder, settleLaunchdServiceUnload, startLaunchdService, } from "./nativeServices/serviceAction.js";
15
19
  import { installNativeServiceCandidate, nativeServiceInstallFailureNeedsPathAdvice, } from "./nativeServices/serviceInstall.js";
20
+ import { launchdBootoutArgs, launchdServiceTarget, orderServices, performServiceAction, serviceStartOrder, serviceStopOrder, settleLaunchdServiceUnload, startLaunchdService, } from "./nativeServices/serviceAction.js";
16
21
  import { minimumSupportedNodeVersion, nativeServiceManagerRefs, productionNativeServiceIds, } from "./nativeServices/servicePlan.js";
17
- import { formatNativeServiceDoctorResult, inferInstalledNativeServiceMode, inspectInstalledDevelopmentServiceInput, inspectInstalledProductionServiceContext, runNativeServiceDoctor, } from "./nativeServices/serviceDoctor.js";
22
+ import { inspectInstalledNativeServiceDefinitions, } from "./nativeServices/installedServiceDefinitions.js";
23
+ import { formatNativeServiceDoctorResult, inferInstalledNativeServiceMode, inspectInstalledDevelopmentServiceInput, inspectInstalledProductionServiceContext, runNativeServiceDoctor, selectManagedNativeServiceConfig, } from "./nativeServices/serviceDoctor.js";
18
24
  import { createNativeServiceAuthoritativeProbe, nativeServicePrerequisiteShellCheck, } from "./nativeServices/serviceProbe.js";
19
25
  import { renderLaunchdPlist, renderSystemdUnit } from "./nativeServices/serviceRendering.js";
20
26
  const PI_WEB_PACKAGE_NAME = "@chainingintention/pi-web-cn";
@@ -46,25 +52,22 @@ export function serviceBackendForPlatform(platform) {
46
52
  function currentServiceBackend() {
47
53
  return serviceBackendForPlatform(process.platform);
48
54
  }
49
- function requireServiceBackend(command) {
55
+ function requireServiceBackend(command, t = createTranslator("en", {})) {
50
56
  const backend = currentServiceBackend();
51
57
  if (backend !== undefined)
52
58
  return backend;
53
- throw new Error(`\`${command}\` requires a supported per-user service manager (systemd user services or LaunchAgents) and is not supported on ${platformLabel()}.\n\n${manualRunAdvice()}`);
59
+ throw new Error(t("service.unsupported", "`{command}` requires a supported per-user service manager (systemd user services or LaunchAgents) and is not supported on {platform}.\n\n{advice}", { command, platform: platformLabel(), advice: manualRunAdvice(t) }));
54
60
  }
55
- function supportsSystemdUserServices() {
56
- return currentServiceBackend()?.kind === "systemd";
57
- }
58
- function manualRunAdvice() {
61
+ function manualRunAdvice(t = createTranslator("en", {})) {
59
62
  return [
60
- "Run PI WEB manually from a checkout:",
63
+ t("manual.checkout", "Run PI WEB manually from a checkout:"),
61
64
  " npm run start:sessiond",
62
65
  " PI_WEB_PORT=8504 npm start",
63
66
  "",
64
- "For development in one terminal:",
67
+ t("manual.singleTerminal", "For development in one terminal:"),
65
68
  " npm run dev",
66
69
  "",
67
- "For split development, keep sessiond separate and run web/API plus Vite UI separately:",
70
+ t("manual.split", "For split development, keep sessiond separate and run web/API plus Vite UI separately:"),
68
71
  " npm run dev:sessiond",
69
72
  " npm run dev:web",
70
73
  " npm run dev:client",
@@ -86,6 +89,15 @@ function capture(command, args) {
86
89
  const stderr = outputText(result.stderr);
87
90
  return { status: result.status ?? 1, stdout: outputText(result.stdout), stderr: stderr === "" ? errorMessage : stderr };
88
91
  }
92
+ function captureInstalledServiceDefinitionCommand(command, args) {
93
+ const result = spawnSync(command, args);
94
+ return {
95
+ status: result.status ?? 1,
96
+ stdout: result.stdout,
97
+ stderr: result.stderr,
98
+ spawnError: result.error instanceof Error ? result.error.message : "",
99
+ };
100
+ }
89
101
  function runQuiet(command, args) {
90
102
  return capture(command, args).status;
91
103
  }
@@ -105,7 +117,7 @@ function isLingerEnabled() {
105
117
  return false;
106
118
  return undefined;
107
119
  }
108
- function parseInstallOptions(args) {
120
+ function parseInstallOptions(args, t = createTranslator("en", {})) {
109
121
  const options = { host: "127.0.0.1", port: "8504", mode: "production" };
110
122
  for (let i = 0; i < args.length; i += 1) {
111
123
  const arg = args[i];
@@ -114,7 +126,7 @@ function parseInstallOptions(args) {
114
126
  if (arg === "--host") {
115
127
  const value = args[i + 1];
116
128
  if (value === undefined)
117
- throw new Error("--host requires a value");
129
+ throw new Error(t("install.hostRequired", "--host requires a value"));
118
130
  options.host = value;
119
131
  i += 1;
120
132
  }
@@ -124,7 +136,7 @@ function parseInstallOptions(args) {
124
136
  else if (arg === "--port") {
125
137
  const value = args[i + 1];
126
138
  if (value === undefined)
127
- throw new Error("--port requires a value");
139
+ throw new Error(t("install.portRequired", "--port requires a value"));
128
140
  options.port = value;
129
141
  i += 1;
130
142
  }
@@ -134,7 +146,7 @@ function parseInstallOptions(args) {
134
146
  else if (arg === "--config") {
135
147
  const value = args[i + 1];
136
148
  if (value === undefined)
137
- throw new Error("--config requires a value");
149
+ throw new Error(t("install.configRequired", "--config requires a value"));
138
150
  options.config = value;
139
151
  i += 1;
140
152
  }
@@ -148,7 +160,7 @@ function parseInstallOptions(args) {
148
160
  // Accepted for backwards-compatible readability; PI WEB chooses the native user service backend automatically.
149
161
  }
150
162
  else {
151
- throw new Error(`Unknown install option: ${arg}`);
163
+ throw new Error(t("install.unknownOption", "Unknown install option: {arg}", { arg: arg }));
152
164
  }
153
165
  }
154
166
  return options;
@@ -204,8 +216,12 @@ function describeServiceShell() {
204
216
  }
205
217
  return shell.detectedExecutable === null ? shell.name : `${shell.name} (${shell.detectedExecutable})`;
206
218
  }
207
- function configEnvironment(options, configPath) {
208
- return options.config === undefined ? {} : { PI_WEB_CONFIG: configPath };
219
+ export function nativeServiceEnvironment(configPath, env = process.env) {
220
+ const environment = configPath === undefined ? {} : { PI_WEB_CONFIG: configPath };
221
+ const piPackageDir = ownEnvironmentValue(env, PI_WEB_PI_PACKAGE_DIR_ENV);
222
+ if (piPackageDir !== undefined && piPackageDir !== "")
223
+ environment[PI_WEB_PI_PACKAGE_DIR_ENV] = piPackageDir;
224
+ return environment;
209
225
  }
210
226
  function serviceRefList(ids) {
211
227
  return ids.map((id) => serviceRefs[id]);
@@ -225,14 +241,14 @@ function stopOrder(refs) {
225
241
  function devRootPath() {
226
242
  return resolve(process.cwd());
227
243
  }
228
- function validateDevCheckout(root) {
244
+ function validateDevCheckout(root, t) {
229
245
  const packageJsonPath = join(root, "package.json");
230
246
  if (!existsSync(packageJsonPath)) {
231
- throw new Error(`Development mode must be installed from a PI WEB checkout. Missing package.json: ${packageJsonPath}`);
247
+ throw new Error(t("install.checkoutMissing", "Development mode must be installed from a PI WEB checkout. Missing package.json: {path}", { path: packageJsonPath }));
232
248
  }
233
249
  const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
234
250
  if (!isRecord(parsed) || parsed["name"] !== PI_WEB_PACKAGE_NAME) {
235
- throw new Error(`Development mode must be installed from a PI WEB checkout. ${packageJsonPath} is not ${PI_WEB_PACKAGE_NAME}.`);
251
+ throw new Error(t("install.checkoutWrong", "Development mode must be installed from a PI WEB checkout. {path} is not {packageName}.", { path: packageJsonPath, packageName: PI_WEB_PACKAGE_NAME }));
236
252
  }
237
253
  }
238
254
  function launchdLogPath(ref) {
@@ -291,15 +307,15 @@ function currentLaunchdServiceTarget(ref) {
291
307
  function launchdActionContext() {
292
308
  return { domain: launchdDomain(), plistPath: launchdPlistPath };
293
309
  }
294
- function serviceActionDeps(backend) {
310
+ function serviceActionDeps(backend, probeEnvironment = process.env) {
295
311
  return {
296
312
  run: (command, args) => run(command, args),
297
313
  runQuiet,
298
- sleep: (ms) => new Promise((resolvePromise) => {
299
- setTimeout(resolvePromise, ms);
314
+ sleep: (ms) => new Promise((resolve) => {
315
+ setTimeout(resolve, ms);
300
316
  }),
301
317
  isServiceRunning: (ref) => runtimeStatus(backend, ref).health === "running",
302
- isComponentReady: probeRunningComponentReady,
318
+ isComponentReady: (component) => probeRunningComponentReady(component, { configEnv: probeEnvironment }),
303
319
  };
304
320
  }
305
321
  async function installLaunchdServices(plan) {
@@ -316,8 +332,11 @@ async function installLaunchdServices(plan) {
316
332
  const plistPath = join(launchdServiceDir, service.manager.launchdPlistName);
317
333
  await writeFile(plistPath, renderLaunchdPlist(plan, service, logDir));
318
334
  }
335
+ // Settle each bootout before deciding bootstrap vs kickstart: acting on a
336
+ // label launchd is still asynchronously unloading races the teardown and can
337
+ // lose the service entirely (the same defect the restart path had).
319
338
  const context = launchdActionContext();
320
- const deps = serviceActionDeps(plan.backend);
339
+ const deps = serviceActionDeps(plan.backend, { ...process.env, ...plan.services[0]?.environment });
321
340
  for (const service of plan.services) {
322
341
  const ref = serviceRefFromPlan(service.id, service.manager);
323
342
  await settleLaunchdServiceUnload(currentLaunchdServiceTarget(ref), deps);
@@ -352,12 +371,12 @@ async function uninstallNativeServices(backend) {
352
371
  else
353
372
  await uninstallLaunchdServices();
354
373
  }
355
- function serviceDisplayName(ref) {
374
+ function serviceDisplayName(ref, t = createTranslator("en", {})) {
356
375
  if (ref.id === "sessiond")
357
- return "session daemon";
376
+ return t("service.sessiond", "session daemon");
358
377
  if (ref.id === "uiDev")
359
- return "UI/API dev server";
360
- return "web server";
378
+ return t("service.uiDev", "UI/API dev server");
379
+ return t("service.web", "web server");
361
380
  }
362
381
  function statusServiceRefs(backend) {
363
382
  const ids = installedServiceIds(backend);
@@ -371,20 +390,20 @@ function statusServiceRefs(backend) {
371
390
  return productionServiceRefs();
372
391
  return serviceRefList(["sessiond"]);
373
392
  }
374
- function serviceInstallMode(backend) {
393
+ function serviceInstallMode(backend, t) {
375
394
  const ids = installedServiceIds(backend);
376
395
  if (ids.size === 0)
377
- return "not installed";
396
+ return t("service.notInstalled", "not installed");
378
397
  const hasSessiond = ids.has("sessiond");
379
398
  const hasWeb = ids.has("web");
380
399
  const hasUiDev = ids.has("uiDev");
381
400
  if (hasWeb && hasUiDev)
382
- return "mixed";
401
+ return t("service.mixed", "mixed");
383
402
  if (hasUiDev)
384
- return hasSessiond ? "development" : "development (incomplete)";
403
+ return hasSessiond ? t("service.development", "development") : t("service.developmentIncomplete", "development (incomplete)");
385
404
  if (hasWeb)
386
- return hasSessiond ? "production" : "production (incomplete)";
387
- return "partial";
405
+ return hasSessiond ? t("service.production", "production") : t("service.productionIncomplete", "production (incomplete)");
406
+ return t("service.partial", "partial");
388
407
  }
389
408
  function makeServiceRuntimeStatus(ref, health, detail, target, filePath, pid) {
390
409
  return {
@@ -451,25 +470,25 @@ function launchdRuntimeStatus(backend, ref) {
451
470
  function runtimeStatus(backend, ref) {
452
471
  return backend.kind === "systemd" ? systemdRuntimeStatus(backend, ref) : launchdRuntimeStatus(backend, ref);
453
472
  }
454
- function printServiceStatus(status) {
473
+ function printServiceStatus(status, t = createTranslator("en", {})) {
455
474
  const icon = status.health === "running" ? "✓" : "✗";
456
475
  const pid = status.pid === undefined ? "" : `, pid ${status.pid}`;
457
- console.log(`${icon} ${serviceDisplayName(status.ref)}: ${status.detail} (${status.target}${pid})`);
476
+ console.log(`${icon} ${serviceDisplayName(status.ref, t)}: ${status.detail} (${status.target}${pid})`);
458
477
  if (status.health === "not-installed")
459
- console.log(` missing service file: ${status.filePath}`);
478
+ console.log(t("status.missingFile", " missing service file: {filePath}", { filePath: status.filePath }));
460
479
  }
461
- function printServiceStatusReport(backend) {
480
+ function printServiceStatusReport(backend, t = createTranslator("en", {})) {
462
481
  const refs = statusServiceRefs(backend);
463
- console.log(`PI WEB services: ${serviceInstallMode(backend)} (${backend.label})`);
482
+ console.log(t("status.services", "PI WEB services: {mode} ({backend})", { mode: serviceInstallMode(backend, t), backend: backend.label }));
464
483
  if (refs.length === 0) {
465
- console.log("✗ no PI WEB service files found");
466
- console.log(" Run `pi-web install` or `pi-web install --dev`.");
484
+ console.log(t("status.noServices", "✗ no PI WEB service files found"));
485
+ console.log(t("status.installAdvice", " Run `pi-web install` or `pi-web install --dev`."));
467
486
  return false;
468
487
  }
469
488
  const statuses = refs.map((ref) => runtimeStatus(backend, ref));
470
489
  for (const status of statuses)
471
- printServiceStatus(status);
472
- console.log("\nUse `pi-web logs` for service logs.");
490
+ printServiceStatus(status, t);
491
+ console.log(t("status.logsAdvice", "\nUse `pi-web logs` for service logs."));
473
492
  return statuses.every((status) => status.health === "running");
474
493
  }
475
494
  function configuredServiceCommand(name) {
@@ -497,7 +516,7 @@ function productionNativeServicePlanInput(backend, shell, environment) {
497
516
  }
498
517
  function nativeServiceInstallCandidate(options, backend, configPath, devRoot) {
499
518
  const shell = detectServiceShell();
500
- const environment = configEnvironment(options, configPath);
519
+ const environment = nativeServiceEnvironment(options.config === undefined ? undefined : configPath);
501
520
  if (options.mode === "production") {
502
521
  return {
503
522
  mode: "production",
@@ -516,17 +535,17 @@ function nativeServiceInstallCandidate(options, backend, configPath, devRoot) {
516
535
  },
517
536
  };
518
537
  }
519
- function printNativeServiceInstallFailure(failure) {
538
+ function printNativeServiceInstallFailure(failure, t) {
520
539
  if (failure.kind === "plan-resolution") {
521
540
  for (const item of failure.failures) {
522
541
  if (item.kind === "probe-infrastructure") {
523
- console.log(`✗ Service-manager probe infrastructure failure (${item.reason}): ${item.message}`);
542
+ console.log(t("install.probeFailure", "✗ Service-manager probe infrastructure failure ({reason}): {message}", { reason: item.reason, message: item.message }));
524
543
  }
525
544
  else if (item.kind === "entrypoint-inspection-failure") {
526
- console.log(`✗ Could not inspect bundled ${item.serviceId} entrypoint ${item.entrypointPath}: ${item.message}`);
545
+ console.log(t("install.entrypointFailure", "✗ Could not inspect bundled {service} entrypoint {path}: {message}", { service: item.serviceId, path: item.entrypointPath, message: item.message }));
527
546
  }
528
547
  else {
529
- console.log(`✗ ${item.namedCommand} is unavailable to the service manager, and bundled entrypoint ${item.bundledEntrypointPath} is missing.`);
548
+ console.log(t("install.commandMissing", "✗ {command} is unavailable to the service manager, and bundled entrypoint {path} is missing.", { command: item.namedCommand, path: item.bundledEntrypointPath }));
530
549
  if (item.namedCommandFailure !== null)
531
550
  console.log(` ${item.namedCommandFailure}`);
532
551
  }
@@ -535,7 +554,7 @@ function printNativeServiceInstallFailure(failure) {
535
554
  }
536
555
  for (const item of failure.failures) {
537
556
  if (item.kind === "probe-infrastructure") {
538
- console.log(`✗ Service-manager probe infrastructure failure (${item.reason}): ${item.message}`);
557
+ console.log(t("install.probeFailure", "✗ Service-manager probe infrastructure failure ({reason}): {message}", { reason: item.reason, message: item.message }));
539
558
  }
540
559
  else {
541
560
  console.log(`✗ ${item.prerequisite.description}`);
@@ -544,19 +563,19 @@ function printNativeServiceInstallFailure(failure) {
544
563
  }
545
564
  }
546
565
  }
547
- async function install(args) {
548
- const backend = requireServiceBackend("pi-web install");
549
- const options = parseInstallOptions(args);
566
+ async function install(args, t = createTranslator("en", {})) {
567
+ const backend = requireServiceBackend("pi-web install", t);
568
+ const options = parseInstallOptions(args, t);
550
569
  const devRoot = options.mode === "dev" ? devRootPath() : undefined;
551
570
  if (devRoot !== undefined)
552
- validateDevCheckout(devRoot);
571
+ validateDevCheckout(devRoot, t);
553
572
  const configPath = installConfigPath(options);
554
573
  const candidate = nativeServiceInstallCandidate(options, backend, configPath, devRoot);
555
- console.log(`Running PI WEB ${options.mode} install preflight checks...`);
556
- console.log(`Service backend: ${backend.label}`);
557
- console.log(`Service shell: ${describeServiceShell()}`);
558
- if (!printNodePtyNativeModuleCheck()) {
559
- throw new Error("Install preflight checks failed without changing config or services. Fix the failure above, then run `pi-web doctor` for more detail.");
574
+ console.log(t("install.preflight", "Running PI WEB {mode} install preflight checks...", { mode: options.mode }));
575
+ console.log(t("service.backend", "Service backend: {label}", { label: backend.label }));
576
+ console.log(t("service.shell", "Service shell: {value}", { value: describeServiceShell() }));
577
+ if (!printNodePtyNativeModuleCheck(t)) {
578
+ throw new Error(t("install.preflightFailed", "Install preflight checks failed without changing config or services. Fix the failure above, then run `pi-web doctor` for more detail."));
560
579
  }
561
580
  const result = await installNativeServiceCandidate(candidate, {
562
581
  probe: createNativeServiceAuthoritativeProbe(),
@@ -565,53 +584,56 @@ async function install(args) {
565
584
  replaceServices: installNativeServices,
566
585
  });
567
586
  if (!result.ok) {
568
- printNativeServiceInstallFailure(result.failure);
587
+ printNativeServiceInstallFailure(result.failure, t);
569
588
  if (nativeServiceInstallFailureNeedsPathAdvice(result.failure))
570
- printPathSetupAdvice();
571
- throw new Error("Install preflight checks failed without changing config or services. Fix the failure above, then run `pi-web doctor` for more detail.");
589
+ printPathSetupAdvice(undefined, t);
590
+ throw new Error(t("install.preflightFailed", "Install preflight checks failed without changing config or services. Fix the failure above, then run `pi-web doctor` for more detail."));
572
591
  }
573
592
  for (const service of result.plan.services.filter((item) => item.strategy.kind === "configured-override")) {
574
- console.log(`! ${service.description} uses a configured command override; preflight did not execute that arbitrary command.`);
593
+ console.log(t("install.overrideSkipped", "! {service} uses a configured command override; preflight did not execute that arbitrary command.", { service: service.description }));
575
594
  }
576
- console.log(`\nPI WEB ${options.mode} services are installed and starting.`);
577
- console.log(`Config: ${configPath}`);
595
+ console.log(t("install.started", "\nPI WEB {mode} services are installed and starting.", { mode: options.mode }));
596
+ console.log(t("install.config", "Config: {configPath}", { configPath: configPath }));
578
597
  if (options.mode === "dev") {
579
- console.log("Open: http://127.0.0.1:8505");
598
+ console.log(t("install.open", "Open: {url}", { url: "http://127.0.0.1:8505" }));
580
599
  }
581
600
  else {
582
- console.log(`Open: http://${options.host === "0.0.0.0" ? "127.0.0.1" : options.host}:${options.port}`);
601
+ console.log(t("install.open", "Open: {url}", { url: `http://${options.host === "0.0.0.0" ? "127.0.0.1" : options.host}:${options.port}` }));
583
602
  }
584
603
  if (backend.kind === "systemd") {
585
604
  const linger = isLingerEnabled();
586
605
  if (linger === false) {
587
- console.log("\nRecommended for server use: keep user services running after logout/reboot:");
606
+ console.log(t("install.lingerAdvice", "\nRecommended for server use: keep user services running after logout/reboot:"));
588
607
  console.log(` sudo loginctl enable-linger ${userInfo().username}`);
589
608
  }
590
609
  else if (linger === undefined) {
591
- console.log("\nRecommended for server use: enable systemd user lingering so services survive logout/reboot:");
610
+ console.log(t("install.enableLinger", "\nRecommended for server use: enable systemd user lingering so services survive logout/reboot:"));
592
611
  console.log(` sudo loginctl enable-linger ${userInfo().username}`);
593
612
  }
594
613
  }
595
- console.log("\nUseful commands:");
614
+ console.log(t("install.commands", "\nUseful commands:"));
596
615
  console.log(" pi-web status");
597
616
  console.log(" pi-web logs");
598
617
  console.log(" pi-web restart");
599
618
  }
600
- async function uninstall() {
601
- const backend = requireServiceBackend("pi-web uninstall");
619
+ async function uninstall(t = createTranslator("en", {})) {
620
+ const backend = requireServiceBackend("pi-web uninstall", t);
602
621
  await uninstallNativeServices(backend);
603
- console.log(`PI WEB ${backend.label} removed. Production and development service files were removed; config and data were left in place.`);
622
+ console.log(t("uninstall.done", "PI WEB {label} removed. Production and development service files were removed; config and data were left in place.", { label: backend.label }));
604
623
  }
605
- async function serviceAction(action) {
624
+ async function serviceAction(action, t = createTranslator("en", {})) {
606
625
  const backend = requireServiceBackend(`pi-web ${action}`);
607
626
  if (action === "status") {
608
- if (!printServiceStatusReport(backend))
627
+ if (!printServiceStatusReport(backend, t))
609
628
  process.exitCode = 1;
610
629
  return;
611
630
  }
631
+ await performLifecycleServiceAction(backend, action, process.env);
632
+ }
633
+ async function performLifecycleServiceAction(backend, action, probeEnvironment) {
612
634
  const refs = installedServiceRefs(backend);
613
635
  const input = { backend, action, refs, launchdContext: launchdActionContext() };
614
- const result = await performServiceAction(input, serviceActionDeps(backend));
636
+ const result = await performServiceAction(input, serviceActionDeps(backend, probeEnvironment));
615
637
  if (result.unreadyServices.length > 0) {
616
638
  for (const ref of result.unreadyServices) {
617
639
  const target = backend.kind === "systemd" ? ref.systemdName : currentLaunchdServiceTarget(ref);
@@ -633,9 +655,10 @@ export function sessionDaemonRestartPlan(options = {}) {
633
655
  const dockerMode = activeDockerMode(env);
634
656
  const runCommand = options.runCommand ?? ((command, args) => { run(command, args, { check: true }); });
635
657
  if (dockerMode !== undefined) {
658
+ const command = piWebDockerCommand(dockerMode, "restart-sessiond");
636
659
  return {
637
660
  kind: "automatic",
638
- command: piWebDockerCommand(dockerMode, "restart-sessiond"),
661
+ command,
639
662
  guidance: "Run the Docker control command from the PI WEB Docker host.",
640
663
  perform: () => {
641
664
  runCommand("pi-web-docker", [...(dockerMode === "dev" ? ["--dev"] : []), "restart-sessiond"]);
@@ -669,15 +692,17 @@ export function sessionDaemonRestartPlan(options = {}) {
669
692
  };
670
693
  }
671
694
  function activeDockerMode(env) {
672
- if (!truthyEnvValue(env["PI_WEB_DOCKER_RUNTIME"]))
695
+ if (!truthyEnvValue(ownEnvironmentValue(env, "PI_WEB_DOCKER_RUNTIME")))
673
696
  return undefined;
674
- return env["PI_WEB_DOCKER_MODE"] === "dev" ? "dev" : "runtime";
697
+ if (ownEnvironmentValue(env, "PI_WEB_DOCKER_MODE") === "dev")
698
+ return "dev";
699
+ return "runtime";
675
700
  }
676
701
  function truthyEnvValue(value) {
677
702
  return value !== undefined && value !== "" && value !== "0" && value.toLowerCase() !== "false";
678
703
  }
679
- function logs() {
680
- const backend = requireServiceBackend("pi-web logs");
704
+ function logs(t = createTranslator("en", {})) {
705
+ const backend = requireServiceBackend("pi-web logs", t);
681
706
  const refs = installedServiceRefs(backend);
682
707
  if (backend.kind === "systemd") {
683
708
  run("journalctl", ["--user", ...refs.flatMap((ref) => ["-u", ref.systemdName]), "-f"]);
@@ -708,16 +733,14 @@ export function nodeVersionCheck() {
708
733
  description: `node >= ${minimumSupportedNodeVersion}`,
709
734
  });
710
735
  }
711
- export function agentCommandForChecks(env = process.env) {
712
- return effectivePiWebConfig({ env }).config.agent.command;
713
- }
714
- function generalDoctorChecks() {
736
+ export function generalDoctorChecks() {
715
737
  const shell = serviceShellLabel();
716
- const agentCommand = agentCommandForChecks();
717
738
  return [
718
739
  [`Caller login ${shell} can find node >= ${minimumSupportedNodeVersion}`, serviceShellCommand(nodeVersionCheck())],
719
740
  [`Caller login ${shell} can find npm`, serviceShellCommand(commandWithVersionCheck("npm"))],
720
- [`Caller login ${shell} can find ${agentCommand}`, serviceShellCommand(commandWithVersionCheck(agentCommand))],
741
+ // Sessions run on the bundled pi SDK; the only CLI check is a hardcoded
742
+ // `pi` PATH probe — nothing names or locates a configurable command.
743
+ [`Caller login ${shell} can find pi`, serviceShellCommand(commandWithVersionCheck("pi"))],
721
744
  ];
722
745
  }
723
746
  function runChecks(checks) {
@@ -748,7 +771,7 @@ function optionalDoctorChecks() {
748
771
  const shell = serviceShellLabel();
749
772
  return [[`Caller login ${shell} can find optional ripgrep (rg)`, serviceShellCommand(commandCheck("rg"))]];
750
773
  }
751
- function printOptionalDoctorChecks() {
774
+ function printOptionalDoctorChecks(t = createTranslator("en", {})) {
752
775
  let missingOptionalTool = false;
753
776
  for (const [label, command] of optionalDoctorChecks()) {
754
777
  const [bin, ...args] = command;
@@ -761,30 +784,145 @@ function printOptionalDoctorChecks() {
761
784
  printCheckOutput(result.stdout || result.stderr);
762
785
  }
763
786
  if (missingOptionalTool) {
764
- console.log(" Install ripgrep, or make rg visible to the service shell, for faster all-file @ suggestions.");
765
- console.log(" PI WEB falls back to a bounded filesystem scan when rg is unavailable.");
787
+ console.log(t("doctor.ripgrep", " Install ripgrep, or make rg visible to the service shell, for faster all-file @ suggestions."));
788
+ console.log(t("doctor.scanFallback", " PI WEB falls back to a bounded filesystem scan when rg is unavailable."));
766
789
  }
767
790
  }
768
- function installedServiceDefinitions(backend, ids) {
769
- return ids.map((id) => ({
791
+ function installedServiceDefinitions(backend, ids, purpose, warn = (message) => { console.warn(`! ${message}`); }) {
792
+ const sources = ids.map((id) => ({
770
793
  id,
771
- contents: readFileSync(serviceFilePath(backend, serviceRefs[id]), "utf8"),
794
+ path: serviceFilePath(backend, serviceRefs[id]),
795
+ systemdName: serviceRefs[id].systemdName,
796
+ launchdTarget: currentLaunchdServiceTarget(serviceRefs[id]),
772
797
  }));
798
+ return inspectInstalledNativeServiceDefinitions(backend, sources, {
799
+ readFile: (path) => readFileSync(path),
800
+ realpath: realpathSync,
801
+ capture: captureInstalledServiceDefinitionCommand,
802
+ warn,
803
+ }, purpose);
804
+ }
805
+ /** Build an isolated probe environment without mutating the caller or process. */
806
+ export function managedServiceProbeEnvironment(backend, definitions, callerEnvironment) {
807
+ const selection = selectManagedNativeServiceConfig(backend, definitions, ownEnvironmentValue(callerEnvironment, "PI_WEB_CONFIG"));
808
+ if (!selection.ok)
809
+ return selection;
810
+ if (selection.value.source === "installed") {
811
+ return {
812
+ ok: true,
813
+ value: { ...callerEnvironment, PI_WEB_CONFIG: selection.value.configPath },
814
+ };
815
+ }
816
+ if (selection.value.source === "default" && definitions.length > 0) {
817
+ // An own empty value preserves default resolution while masking any
818
+ // prototype-inherited PI_WEB_CONFIG from downstream environment lookups.
819
+ return { ok: true, value: { ...callerEnvironment, PI_WEB_CONFIG: "" } };
820
+ }
821
+ return { ok: true, value: callerEnvironment };
822
+ }
823
+ export function installedServiceProbeEnvironment(backend, ids, callerEnvironment, purpose, inspectDefinitions = installedServiceDefinitions) {
824
+ // The explicit caller override wins without requiring installed definitions
825
+ // to be readable or canonical.
826
+ const callerConfigPath = ownEnvironmentValue(callerEnvironment, "PI_WEB_CONFIG");
827
+ if (callerConfigPath !== undefined && callerConfigPath !== "") {
828
+ return { ok: true, value: callerEnvironment };
829
+ }
830
+ if (ids.size === 0)
831
+ return { ok: true, value: callerEnvironment };
832
+ const definitions = inspectDefinitions(backend, [...ids], purpose);
833
+ if (!definitions.ok)
834
+ return definitions;
835
+ return managedServiceProbeEnvironment(backend, definitions.value, callerEnvironment);
773
836
  }
774
- function nativeServiceDoctorTarget(backend) {
775
- const ids = installedServiceIds(backend);
837
+ function managedServiceProbeFailure(backend, message) {
838
+ return [
839
+ `Could not select managed PI_WEB_CONFIG from installed ${backend.label}: ${message}`,
840
+ "Repair the reported service-manager override or definition, then re-run `pi-web install` (or `pi-web install --dev`); a nonempty PI_WEB_CONFIG explicitly overrides managed config selection for this command.",
841
+ ].join("\n");
842
+ }
843
+ /**
844
+ * Dispatch commands whose probes may need managed config. The service-manager,
845
+ * definition, lifecycle, doctor, and version boundaries are injected so this
846
+ * exact orchestration can be tested without mutating live services or process
847
+ * environment.
848
+ */
849
+ export async function runReadinessCliCommand(command, dependencies) {
850
+ if (command === "version") {
851
+ await dependencies.printVersion();
852
+ return;
853
+ }
854
+ const environment = dependencies.environment;
855
+ if (command === "start" || command === "restart") {
856
+ const backend = dependencies.requireBackend(`pi-web ${command}`);
857
+ const installedIds = dependencies.installedServiceIds(backend);
858
+ const probeEnvironment = installedServiceProbeEnvironment(backend, installedIds, environment, command, dependencies.inspectDefinitions);
859
+ if (!probeEnvironment.ok)
860
+ throw new Error(managedServiceProbeFailure(backend, probeEnvironment.message));
861
+ await dependencies.runLifecycle(backend, command, probeEnvironment.value);
862
+ return;
863
+ }
864
+ const backend = dependencies.currentBackend();
865
+ const installedIds = backend === undefined
866
+ ? new Set()
867
+ : dependencies.installedServiceIds(backend);
868
+ let versionReportOptions = { configEnv: environment };
869
+ let managedInspectionFailed = false;
870
+ if (backend !== undefined && activeDockerMode(environment) === undefined) {
871
+ const probeEnvironment = installedServiceProbeEnvironment(backend, installedIds, environment, "doctor", dependencies.inspectDefinitions);
872
+ if (probeEnvironment.ok) {
873
+ versionReportOptions = { configEnv: probeEnvironment.value };
874
+ }
875
+ else {
876
+ managedInspectionFailed = true;
877
+ versionReportOptions = { webEndpointError: managedServiceProbeFailure(backend, probeEnvironment.message) };
878
+ }
879
+ }
880
+ await dependencies.runDoctor({
881
+ backend,
882
+ installedIds,
883
+ environment,
884
+ versionReportOptions,
885
+ managedInspectionFailed,
886
+ });
887
+ }
888
+ export function parseVersionOptions(args, t = createTranslator("en", {})) {
889
+ if (args.length === 0)
890
+ return {};
891
+ if (args.length === 1 && args[0] === "--check")
892
+ return { check: true };
893
+ throw new Error(t("version.usage", "Usage: pi-web version [--check]"));
894
+ }
895
+ function readinessCliCommandDependencies(t = createTranslator("en", {}), versionOptions = {}) {
896
+ return {
897
+ environment: process.env,
898
+ currentBackend: currentServiceBackend,
899
+ requireBackend: requireServiceBackend,
900
+ installedServiceIds,
901
+ // Doctor inspects again when building its native-service checks. Report
902
+ // warnings there, including when an explicit config bypasses selection here.
903
+ inspectDefinitions: (backend, ids, purpose) => installedServiceDefinitions(backend, ids, purpose, purpose === "doctor" ? () => { } : undefined),
904
+ runLifecycle: performLifecycleServiceAction,
905
+ runDoctor: (context) => doctor(context, t),
906
+ printVersion: async () => {
907
+ const report = await printPiWebVersionReport({ ...versionOptions, translator: t });
908
+ if (report.release?.status === "error")
909
+ process.exitCode = 1;
910
+ },
911
+ };
912
+ }
913
+ function nativeServiceDoctorTarget(backend, ids, t = createTranslator("en", {})) {
776
914
  const mode = inferInstalledNativeServiceMode(ids);
777
915
  if (mode === "ambiguous") {
778
916
  return {
779
917
  kind: "inspection-failure",
780
- message: `installed service IDs do not identify one mode (${[...ids].join(", ") || "none"}).`,
918
+ message: t("doctor.ambiguousMode", "installed service IDs do not identify one mode ({ids}).", { ids: [...ids].join(", ") || "none" }),
781
919
  };
782
920
  }
783
921
  if (mode === "none") {
784
922
  return {
785
923
  kind: "prospective-production",
786
924
  input: productionNativeServicePlanInput(backend, detectServiceShell(), {}),
787
- reason: "no installed service strategy is available",
925
+ reason: t("doctor.noStrategy", "no installed service strategy is available"),
788
926
  };
789
927
  }
790
928
  const expectedIds = mode === "production"
@@ -794,46 +932,39 @@ function nativeServiceDoctorTarget(backend) {
794
932
  if (missingId !== undefined) {
795
933
  return {
796
934
  kind: "inspection-failure",
797
- message: `installed ${mode} service set is incomplete; ${missingId} is missing.`,
798
- };
799
- }
800
- let definitions;
801
- try {
802
- definitions = installedServiceDefinitions(backend, expectedIds);
803
- }
804
- catch (error) {
805
- return {
806
- kind: "inspection-failure",
807
- message: error instanceof Error ? error.message : String(error),
935
+ message: t("doctor.incompleteSet", "installed {mode} service set is incomplete; {service} is missing.", { mode, service: missingId }),
808
936
  };
809
937
  }
938
+ const definitions = installedServiceDefinitions(backend, expectedIds, "doctor");
939
+ if (!definitions.ok)
940
+ return { kind: "inspection-failure", message: definitions.message };
810
941
  if (mode === "development") {
811
- const inspection = inspectInstalledDevelopmentServiceInput(backend, definitions);
942
+ const inspection = inspectInstalledDevelopmentServiceInput(backend, definitions.value);
812
943
  return inspection.ok
813
944
  ? { kind: "installed-development", input: inspection.value }
814
945
  : { kind: "inspection-failure", message: inspection.message };
815
946
  }
816
- const inspection = inspectInstalledProductionServiceContext(backend, definitions);
947
+ const inspection = inspectInstalledProductionServiceContext(backend, definitions.value);
817
948
  return inspection.ok
818
949
  ? {
819
950
  kind: "prospective-production",
820
951
  input: productionNativeServicePlanInput(backend, inspection.value.shell, inspection.value.environment),
821
- reason: "installed executable strategy is not recorded",
952
+ reason: t("doctor.unrecordedStrategy", "installed executable strategy is not recorded"),
822
953
  }
823
954
  : { kind: "inspection-failure", message: inspection.message };
824
955
  }
825
- async function printNativeServiceDoctorChecks(backend) {
826
- const result = await runNativeServiceDoctor(nativeServiceDoctorTarget(backend), {
956
+ async function printNativeServiceDoctorChecks(backend, installedIds, t = createTranslator("en", {})) {
957
+ const result = await runNativeServiceDoctor(nativeServiceDoctorTarget(backend, installedIds, t), {
827
958
  probe: createNativeServiceAuthoritativeProbe(),
828
959
  fileExists: regularFileExists,
829
960
  });
830
- const report = formatNativeServiceDoctorResult(result);
961
+ const report = formatNativeServiceDoctorResult(result, t);
831
962
  for (const line of report.lines)
832
963
  console.log(line);
833
- printCallerContextComparisons(report);
964
+ printCallerContextComparisons(report, t);
834
965
  return report;
835
966
  }
836
- function printCallerContextComparisons(report) {
967
+ function printCallerContextComparisons(report, t) {
837
968
  if (report.plan === null || report.failedPrerequisites.length === 0)
838
969
  return;
839
970
  const seen = new Set();
@@ -844,7 +975,11 @@ function printCallerContextComparisons(report) {
844
975
  const service = report.plan.services.find((candidate) => candidate.prerequisites.some((item) => item.id === prerequisite.id));
845
976
  const command = nativeServicePrerequisiteShellCheck(report.plan.shell.name, prerequisite);
846
977
  const result = captureServiceShell(report.plan.shell, command, service?.workingDirectory ?? null);
847
- console.log(` Caller-invoked ${report.plan.shell.name} -lc ${result.status === 0 ? "satisfies" : "also does not satisfy"} ${prerequisite.description}; the service-manager result is authoritative.`);
978
+ console.log(t("doctor.callerComparison", " Caller-invoked {shell} -lc {outcome} {requirement}; the service-manager result is authoritative.", {
979
+ shell: report.plan.shell.name,
980
+ outcome: result.status === 0 ? t("doctor.satisfies", "satisfies") : t("doctor.unsatisfied", "also does not satisfy"),
981
+ requirement: prerequisite.description,
982
+ }));
848
983
  }
849
984
  }
850
985
  function captureServiceShell(shell, command, workingDirectory) {
@@ -856,25 +991,31 @@ function captureServiceShell(shell, command, workingDirectory) {
856
991
  function shellQuoteFor(shell, value) {
857
992
  return shell === "fish" ? fishSingleQuote(value) : shellSingleQuote(value);
858
993
  }
859
- function printPathSetupAdvice(shell = detectServiceShell()) {
860
- console.log("\nPATH setup advice:");
994
+ function printPathSetupAdvice(shell = detectServiceShell(), t = createTranslator("en", {})) {
995
+ console.log(t("doctor.pathAdvice", "\nPATH setup advice:"));
861
996
  if (shell.name === "bash") {
862
- console.log(" Detected bash. Put PATH setup for node/version managers/tools in ~/.bash_profile or ~/.profile.");
863
- console.log(" If ~/.bash_profile exists, bash will not read ~/.profile unless you source it from ~/.bash_profile.");
864
- console.log(" Do not rely only on ~/.bashrc or prompt hooks for tools needed by services or agents.");
997
+ console.log(t("doctor.bashPath", " Detected bash. Put PATH setup for node/version managers/tools in ~/.bash_profile or ~/.profile."));
998
+ console.log(t("doctor.bashProfile", " If ~/.bash_profile exists, bash will not read ~/.profile unless you source it from ~/.bash_profile."));
999
+ console.log(t("doctor.bashHooks", " Do not rely only on ~/.bashrc or prompt hooks for tools needed by services or agents."));
865
1000
  }
866
1001
  else if (shell.name === "zsh") {
867
- console.log(" Detected zsh. Put PATH setup for node/version managers/tools in ~/.zprofile, not only ~/.zshrc.");
868
- console.log(" Avoid relying on prompt hooks; PI WEB services run non-interactive login shells.");
1002
+ console.log(t("doctor.zshPath", " Detected zsh. Put PATH setup for node/version managers/tools in ~/.zprofile, not only ~/.zshrc."));
1003
+ console.log(t("doctor.promptHooks", " Avoid relying on prompt hooks; PI WEB services run non-interactive login shells."));
869
1004
  }
870
1005
  else {
871
- console.log(" Detected fish. Prefer universal PATH setup such as `fish_add_path -U ...` for tools needed by services or agents.");
872
- console.log(" Avoid relying on prompt hooks; PI WEB services run non-interactive login shells.");
1006
+ console.log(t("doctor.fishPath", " Detected fish. Prefer universal PATH setup such as `fish_add_path -U ...` for tools needed by services or agents."));
1007
+ console.log(t("doctor.promptHooks", " Avoid relying on prompt hooks; PI WEB services run non-interactive login shells."));
873
1008
  }
874
1009
  }
875
- export function doctorExitCode(generalReadinessOk, nativeServicePlanOk, nodePtyRuntimeOk, runningComponentsOk) {
876
- return generalReadinessOk && nativeServicePlanOk && nodePtyRuntimeOk && runningComponentsOk ? 0 : 1;
877
- }
1010
+ /**
1011
+ * Running components an installed deployment must keep ready: the API-serving
1012
+ * component whenever the web or UI dev service file is installed (the version
1013
+ * endpoint probes the API port in both modes), and the session daemon whenever
1014
+ * its service file is installed. Docker deployments have no native service
1015
+ * files, so the Docker runtime marker expects both components. A machine with
1016
+ * nothing installed expects nothing: doctor's manual-run guidance stays a
1017
+ * passing outcome there.
1018
+ */
878
1019
  export function expectedRunningComponents(installedServices, env) {
879
1020
  if (activeDockerMode(env) !== undefined)
880
1021
  return ["web", "sessiond"];
@@ -885,76 +1026,85 @@ export function expectedRunningComponents(installedServices, env) {
885
1026
  expected.push("sessiond");
886
1027
  return expected;
887
1028
  }
888
- async function doctor() {
889
- const backend = currentServiceBackend();
1029
+ export function doctorExitCode(generalReadinessOk, nativeServicePlanOk, nodePtyRuntimeOk, runningComponentsOk) {
1030
+ return generalReadinessOk && nativeServicePlanOk && nodePtyRuntimeOk && runningComponentsOk ? 0 : 1;
1031
+ }
1032
+ async function doctor(context, t = createTranslator("en", {})) {
1033
+ const { backend, installedIds, environment, versionReportOptions, managedInspectionFailed } = context;
890
1034
  console.log(`Platform: ${platformLabel()}`);
891
1035
  console.log(`Service backend: ${backend?.label ?? "manual run only"}`);
892
1036
  console.log(`Service shell: ${describeServiceShell()}`);
893
1037
  if (backend === undefined) {
894
- console.log(`- Native user service plan checks skipped on ${platformLabel()}; no native-service drift is reported.`);
1038
+ console.log(t("doctor.nativeSkipped", "- Native user service plan checks skipped on {value}; no native-service drift is reported.", { value: platformLabel() }));
895
1039
  }
896
1040
  console.log("");
897
- const runningVersionInfo = await printPiWebVersionReport();
898
- const expectedComponents = expectedRunningComponents(backend === undefined ? new Set() : installedServiceIds(backend), process.env);
1041
+ const runningVersionInfo = await printPiWebVersionReport(versionReportOptions);
1042
+ const expectedComponents = expectedRunningComponents(installedIds, environment);
899
1043
  const runningComponentsOk = runningComponentsReady(runningVersionInfo, expectedComponents);
900
1044
  if (!runningComponentsOk) {
901
1045
  console.log("\n✗ Installed PI WEB services are unavailable or stale (see \"Running services\" above).");
902
1046
  console.log(" Run `pi-web restart`, then check `pi-web status`.");
903
1047
  }
904
- console.log("\nGeneral login-shell readiness (separate from native-service requirements):");
1048
+ console.log(t("doctor.loginShell", "\nGeneral login-shell readiness (separate from native-service requirements):"));
905
1049
  const generalReadinessOk = runChecks(generalDoctorChecks());
906
- printOptionalDoctorChecks();
907
- console.log("\nNative terminal runtime readiness:");
908
- const nodePtyNativeModuleOk = printNodePtyNativeModuleCheck();
909
- const nodePtySpawnHelperOk = nodePtyNativeModuleOk ? printNodePtyDarwinSpawnHelperCheck() : true;
1050
+ printOptionalDoctorChecks(t);
1051
+ console.log(t("doctor.terminal", "\nNative terminal runtime readiness:"));
1052
+ const nodePtyNativeModuleOk = printNodePtyNativeModuleCheck(t);
1053
+ const nodePtySpawnHelperOk = nodePtyNativeModuleOk ? printNodePtyDarwinSpawnHelperCheck(t) : true;
910
1054
  let nativeServiceReport = null;
911
1055
  if (backend !== undefined) {
912
1056
  console.log("\nNative service plan checks (service-manager context):");
913
- nativeServiceReport = await printNativeServiceDoctorChecks(backend);
1057
+ if (managedInspectionFailed) {
1058
+ console.log("✗ Installed native-service plan could not be inspected consistently with the readiness probe (see \"Running services\" above).");
1059
+ console.log(" Repair the reported service-manager definition before relying on doctor results.");
1060
+ }
1061
+ else {
1062
+ nativeServiceReport = await printNativeServiceDoctorChecks(backend, installedIds, t);
1063
+ }
914
1064
  }
915
- if (supportsSystemdUserServices()) {
1065
+ if (backend?.kind === "systemd") {
916
1066
  const linger = isLingerEnabled();
917
1067
  if (linger === true) {
918
- console.log("✓ systemd user lingering enabled");
1068
+ console.log(t("doctor.lingerEnabled", "✓ systemd user lingering enabled"));
919
1069
  }
920
1070
  else if (linger === false) {
921
- console.log("✗ systemd user lingering disabled");
922
- console.log(` Recommended on servers: sudo loginctl enable-linger ${userInfo().username}`);
1071
+ console.log(t("doctor.lingerDisabled", "✗ systemd user lingering disabled"));
1072
+ console.log(t("doctor.lingerCommand", " Recommended on servers: sudo loginctl enable-linger {username}", { username: userInfo().username }));
923
1073
  }
924
1074
  else {
925
- console.log("? systemd user lingering unknown");
926
- console.log(` Recommended on servers: sudo loginctl enable-linger ${userInfo().username}`);
1075
+ console.log(t("doctor.lingerUnknown", "? systemd user lingering unknown"));
1076
+ console.log(t("doctor.lingerCommand", " Recommended on servers: sudo loginctl enable-linger {username}", { username: userInfo().username }));
927
1077
  }
928
1078
  }
929
1079
  else if (backend?.kind === "launchd") {
930
- console.log("- user services start at login with LaunchAgents");
1080
+ console.log(t("doctor.launchAgents", "- user services start at login with LaunchAgents"));
931
1081
  }
932
1082
  else {
933
- console.log(`- systemd user lingering skipped on ${platformLabel()}`);
1083
+ console.log(t("doctor.lingerSkipped", "- systemd user lingering skipped on {value}", { value: platformLabel() }));
934
1084
  }
935
- const nativeServicePlanOk = nativeServiceReport?.ok ?? true;
1085
+ const nativeServicePlanOk = !managedInspectionFailed && (nativeServiceReport?.ok ?? true);
936
1086
  const pathFailure = !generalReadinessOk || nativeServiceReport?.pathAdviceRecommended === true;
937
1087
  if (pathFailure) {
938
- console.log("\nIf a command works in your terminal but fails in the service-manager check, compare the caller and manager contexts above.");
1088
+ console.log(t("doctor.compareContexts", "\nIf a command works in your terminal but fails in the service-manager check, compare the caller and manager contexts above."));
939
1089
  const adviceShell = nativeServiceReport?.pathAdviceRecommended === true && nativeServiceReport.adviceShell !== null
940
1090
  ? nativeServiceReport.adviceShell
941
1091
  : detectServiceShell();
942
- printPathSetupAdvice(adviceShell);
1092
+ printPathSetupAdvice(adviceShell, t);
943
1093
  }
944
1094
  if (generalReadinessOk && backend === undefined) {
945
- console.log(`\n${manualRunAdvice()}`);
1095
+ console.log(`\n${manualRunAdvice(t)}`);
946
1096
  }
947
1097
  if (doctorExitCode(generalReadinessOk, nativeServicePlanOk, nodePtyNativeModuleOk && nodePtySpawnHelperOk, runningComponentsOk) !== 0)
948
1098
  process.exitCode = 1;
949
1099
  }
950
- function printNodePtyNativeModuleCheck() {
951
- const result = formatNodePtyNativeModuleCheck(checkNodePtyNativeModule());
1100
+ function printNodePtyNativeModuleCheck(t) {
1101
+ const result = formatNodePtyNativeModuleCheck(checkNodePtyNativeModule(), t);
952
1102
  for (const line of result.lines)
953
1103
  console.log(line);
954
1104
  return result.ok;
955
1105
  }
956
- function printNodePtyDarwinSpawnHelperCheck() {
957
- const result = formatNodePtyDarwinSpawnHelperCheck(checkNodePtyDarwinSpawnHelper());
1106
+ function printNodePtyDarwinSpawnHelperCheck(t) {
1107
+ const result = formatNodePtyDarwinSpawnHelperCheck(checkNodePtyDarwinSpawnHelper(), t);
958
1108
  for (const line of result.lines)
959
1109
  console.log(line);
960
1110
  return result.ok;
@@ -962,8 +1112,8 @@ function printNodePtyDarwinSpawnHelperCheck() {
962
1112
  function isRecord(value) {
963
1113
  return typeof value === "object" && value !== null && !Array.isArray(value);
964
1114
  }
965
- function help() {
966
- console.log(`PI WEB
1115
+ export function cliHelp(t) {
1116
+ return t("help", `PI WEB
967
1117
 
968
1118
  Usage:
969
1119
  pi-web install [--dev] [--host 127.0.0.1] [--port 8504] [--config ~/.config/pi-web/config.json]
@@ -973,7 +1123,8 @@ Usage:
973
1123
  pi-web plugins safe-start show|clear|set <bundled-only|none> [--config <path>] [--restart]
974
1124
  pi-web audit <command> [options]
975
1125
  pi-web doctor
976
- pi-web version
1126
+ pi-web update [--yes] [--force]
1127
+ pi-web version [--check]
977
1128
 
978
1129
  Audit commands:
979
1130
  pi-web audit list|stats|export|prune|vacuum
@@ -987,31 +1138,37 @@ Development service install from a checkout:
987
1138
  `);
988
1139
  }
989
1140
  async function main() {
1141
+ const t = loadNodeTranslator("cli");
990
1142
  const [command = "help", ...args] = process.argv.slice(2);
991
1143
  if (command === "install")
992
- await install(args);
1144
+ await install(args, t);
993
1145
  else if (command === "uninstall")
994
- await uninstall();
995
- else if (command === "start" || command === "stop" || command === "restart" || command === "status")
996
- await serviceAction(command);
1146
+ await uninstall(t);
1147
+ else if (command === "update")
1148
+ await runPiWebUpdate(args);
1149
+ else if (command === "start" || command === "restart" || command === "doctor" || command === "version") {
1150
+ await runReadinessCliCommand(command, readinessCliCommandDependencies(t, command === "version" ? parseVersionOptions(args, t) : {}));
1151
+ }
1152
+ else if (command === "stop" || command === "status")
1153
+ await serviceAction(command, t);
997
1154
  else if (command === "logs")
998
- logs();
1155
+ logs(t);
1156
+ else if (command === "workspaces") {
1157
+ const { runWorkspaceNotificationCli } = await import("./workspaceNotificationCli.js");
1158
+ await runWorkspaceNotificationCli(args);
1159
+ }
999
1160
  else if (command === "audit") {
1000
1161
  const { runNormalToolAuditCommand } = await import("./server/audit/normalToolAuditCli.js");
1001
1162
  runNormalToolAuditCommand(args);
1002
1163
  }
1003
1164
  else if (command === "plugins")
1004
- runPluginRecoveryCli(args, { restartPlan: (context) => sessionDaemonRestartPlan(context) });
1005
- else if (command === "doctor")
1006
- await doctor();
1007
- else if (command === "version")
1008
- await printPiWebVersionReport();
1165
+ runPluginRecoveryCli(args, { restartPlan: (context) => sessionDaemonRestartPlan(context) }, t);
1009
1166
  else if (command === "--version" || command === "-v")
1010
1167
  console.log(packageVersion());
1011
1168
  else if (command === "help" || command === "--help" || command === "-h")
1012
- help();
1169
+ console.log(cliHelp(t));
1013
1170
  else
1014
- throw new Error(`Unknown command: ${command}`);
1171
+ throw new Error(t("cli.unknownCommand", "Unknown command: {command}", { command: command }));
1015
1172
  }
1016
1173
  export function isCliEntrypoint(entrypoint = process.argv[1], modulePath = fileURLToPath(import.meta.url)) {
1017
1174
  if (entrypoint === undefined)