@vincenthanxiaodu/pi-web 1.202608.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 (376) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +185 -0
  3. package/dist/cli.js +1149 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/client/apple-touch-icon.png +0 -0
  6. package/dist/client/assets/CodeViewer-D_Q6ljLV.js +4 -0
  7. package/dist/client/assets/TerminalPanel-CTGixJIz.js +187 -0
  8. package/dist/client/assets/index-C2phil_t.js +5637 -0
  9. package/dist/client/assets/vendor-editor-core-CXO8gGab.js +12 -0
  10. package/dist/client/assets/vendor-editor-languages-CpW4sJsX.js +46 -0
  11. package/dist/client/assets/vendor-editor-legacy-CYBnW6ZU.js +1 -0
  12. package/dist/client/assets/vendor-terminal-BrP-ENHg.css +1 -0
  13. package/dist/client/assets/vendor-terminal-D8k4UKM2.js +35 -0
  14. package/dist/client/favicon.svg +11 -0
  15. package/dist/client/index.html +124 -0
  16. package/dist/client/manifest.webmanifest +24 -0
  17. package/dist/client/pwa-icon-192.png +0 -0
  18. package/dist/client/pwa-icon-512.png +0 -0
  19. package/dist/config.js +505 -0
  20. package/dist/config.js.map +1 -0
  21. package/dist/docker/piWebDockerCommandPlan.js +212 -0
  22. package/dist/docker/piWebDockerCommandPlan.js.map +1 -0
  23. package/dist/environment.js +4 -0
  24. package/dist/environment.js.map +1 -0
  25. package/dist/nativeServices/installedServiceDefinitions.js +602 -0
  26. package/dist/nativeServices/installedServiceDefinitions.js.map +1 -0
  27. package/dist/nativeServices/serviceAction.js +174 -0
  28. package/dist/nativeServices/serviceAction.js.map +1 -0
  29. package/dist/nativeServices/serviceDoctor.js +783 -0
  30. package/dist/nativeServices/serviceDoctor.js.map +1 -0
  31. package/dist/nativeServices/serviceInstall.js +35 -0
  32. package/dist/nativeServices/serviceInstall.js.map +1 -0
  33. package/dist/nativeServices/servicePlan.js +358 -0
  34. package/dist/nativeServices/servicePlan.js.map +1 -0
  35. package/dist/nativeServices/serviceProbe.js +447 -0
  36. package/dist/nativeServices/serviceProbe.js.map +1 -0
  37. package/dist/nativeServices/serviceRendering.js +132 -0
  38. package/dist/nativeServices/serviceRendering.js.map +1 -0
  39. package/dist/pi-web-plugins/git/browser/git-contract.js +108 -0
  40. package/dist/pi-web-plugins/git/browser/git-panel.js +609 -0
  41. package/dist/pi-web-plugins/git/browser/gitFileList.js +43 -0
  42. package/dist/pi-web-plugins/git/browser/gitFileShared.js +16 -0
  43. package/dist/pi-web-plugins/git/browser/gitFileTree.js +81 -0
  44. package/dist/pi-web-plugins/git/browser/gitFileViewPreference.js +35 -0
  45. package/dist/pi-web-plugins/git/browser/gitRoute.js +42 -0
  46. package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +10 -0
  47. package/dist/pi-web-plugins/git/browser/unifiedDiff.js +301 -0
  48. package/dist/pi-web-plugins/git/git-backend.js +439 -0
  49. package/dist/pi-web-plugins/git/package.json +16 -0
  50. package/dist/pi-web-plugins/git/server-plugin.js +176 -0
  51. package/dist/pi-web-plugins/info/infoInternals.js +222 -0
  52. package/dist/pi-web-plugins/info/package.json +9 -0
  53. package/dist/pi-web-plugins/info/pi-web-plugin.js +48 -0
  54. package/dist/pi-web-plugins/relays/markdownDocument.js +81 -0
  55. package/dist/pi-web-plugins/relays/package.json +9 -0
  56. package/dist/pi-web-plugins/relays/pi-web-plugin.js +44 -0
  57. package/dist/pi-web-plugins/relays/relayDiscovery.js +228 -0
  58. package/dist/pi-web-plugins/relays/relaysPanelElement.js +550 -0
  59. package/dist/pi-web-plugins/relays/vendor/README.md +24 -0
  60. package/dist/pi-web-plugins/relays/vendor/marked.esm.js +76 -0
  61. package/dist/pi-web-plugins/updates/package.json +9 -0
  62. package/dist/pi-web-plugins/updates/pi-web-plugin.js +185 -0
  63. package/dist/pi-web-plugins/updates/updatesLogic.js +97 -0
  64. package/dist/pi-web-plugins/workspace-tasks/config.js +91 -0
  65. package/dist/pi-web-plugins/workspace-tasks/package.json +9 -0
  66. package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +48 -0
  67. package/dist/pi-web-plugins/workspace-tasks/taskRunner.js +12 -0
  68. package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +288 -0
  69. package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +47 -0
  70. package/dist/piWebVersionReport.js +278 -0
  71. package/dist/piWebVersionReport.js.map +1 -0
  72. package/dist/plugin-api.d.ts +222 -0
  73. package/dist/pluginRecoveryCli.js +172 -0
  74. package/dist/pluginRecoveryCli.js.map +1 -0
  75. package/dist/server/activeAgentProfileProvider.js +25 -0
  76. package/dist/server/activeAgentProfileProvider.js.map +1 -0
  77. package/dist/server/activity/workspaceActivityService.js +106 -0
  78. package/dist/server/activity/workspaceActivityService.js.map +1 -0
  79. package/dist/server/app.js +218 -0
  80. package/dist/server/app.js.map +1 -0
  81. package/dist/server/browserMessageProjection.js +54 -0
  82. package/dist/server/browserMessageProjection.js.map +1 -0
  83. package/dist/server/configRoutes.js +293 -0
  84. package/dist/server/configRoutes.js.map +1 -0
  85. package/dist/server/diagnostics/nodePtyNativeModule.js +36 -0
  86. package/dist/server/diagnostics/nodePtyNativeModule.js.map +1 -0
  87. package/dist/server/diagnostics/nodePtySpawnHelper.js +135 -0
  88. package/dist/server/diagnostics/nodePtySpawnHelper.js.map +1 -0
  89. package/dist/server/git/gitEnv.js +15 -0
  90. package/dist/server/git/gitEnv.js.map +1 -0
  91. package/dist/server/goals/goalArchive.js +184 -0
  92. package/dist/server/goals/goalArchive.js.map +1 -0
  93. package/dist/server/goals/goalFile.js +200 -0
  94. package/dist/server/goals/goalFile.js.map +1 -0
  95. package/dist/server/goals/goalStore.js +65 -0
  96. package/dist/server/goals/goalStore.js.map +1 -0
  97. package/dist/server/index.js +7 -0
  98. package/dist/server/index.js.map +1 -0
  99. package/dist/server/machines/machineClient.js +191 -0
  100. package/dist/server/machines/machineClient.js.map +1 -0
  101. package/dist/server/machines/machinePluginProxyRoutes.js +247 -0
  102. package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -0
  103. package/dist/server/machines/machineProxyRoutes.js +318 -0
  104. package/dist/server/machines/machineProxyRoutes.js.map +1 -0
  105. package/dist/server/machines/machineRoutes.js +56 -0
  106. package/dist/server/machines/machineRoutes.js.map +1 -0
  107. package/dist/server/machines/machineService.js +274 -0
  108. package/dist/server/machines/machineService.js.map +1 -0
  109. package/dist/server/machines/machineStore.js +143 -0
  110. package/dist/server/machines/machineStore.js.map +1 -0
  111. package/dist/server/piPackageRoutes.js +91 -0
  112. package/dist/server/piPackageRoutes.js.map +1 -0
  113. package/dist/server/piPackageService.js +101 -0
  114. package/dist/server/piPackageService.js.map +1 -0
  115. package/dist/server/piWebPluginCatalog.js +584 -0
  116. package/dist/server/piWebPluginCatalog.js.map +1 -0
  117. package/dist/server/piWebPluginLifecycle.js +162 -0
  118. package/dist/server/piWebPluginLifecycle.js.map +1 -0
  119. package/dist/server/piWebPluginService.js +224 -0
  120. package/dist/server/piWebPluginService.js.map +1 -0
  121. package/dist/server/piWebReleaseLookupCache.js +37 -0
  122. package/dist/server/piWebReleaseLookupCache.js.map +1 -0
  123. package/dist/server/piWebStatus.js +624 -0
  124. package/dist/server/piWebStatus.js.map +1 -0
  125. package/dist/server/piWebStatusCache.js +45 -0
  126. package/dist/server/piWebStatusCache.js.map +1 -0
  127. package/dist/server/plugins/pluginBackendProxyRoutes.js +69 -0
  128. package/dist/server/plugins/pluginBackendProxyRoutes.js.map +1 -0
  129. package/dist/server/plugins/serverPluginExec.js +184 -0
  130. package/dist/server/plugins/serverPluginExec.js.map +1 -0
  131. package/dist/server/plugins/serverPluginRuntime.js +480 -0
  132. package/dist/server/plugins/serverPluginRuntime.js.map +1 -0
  133. package/dist/server/projectTrustRoutes.js +80 -0
  134. package/dist/server/projectTrustRoutes.js.map +1 -0
  135. package/dist/server/projects/directorySuggestions.js +207 -0
  136. package/dist/server/projects/directorySuggestions.js.map +1 -0
  137. package/dist/server/projects/projectService.js +33 -0
  138. package/dist/server/projects/projectService.js.map +1 -0
  139. package/dist/server/realtime/sessionEventHub.js +93 -0
  140. package/dist/server/realtime/sessionEventHub.js.map +1 -0
  141. package/dist/server/requestCancellation.js +32 -0
  142. package/dist/server/requestCancellation.js.map +1 -0
  143. package/dist/server/sessiond/agentHttpDispatcher.js +108 -0
  144. package/dist/server/sessiond/agentHttpDispatcher.js.map +1 -0
  145. package/dist/server/sessiond/agentProcessEnvironment.js +61 -0
  146. package/dist/server/sessiond/agentProcessEnvironment.js.map +1 -0
  147. package/dist/server/sessiond/pluginBackendRoutes.js +64 -0
  148. package/dist/server/sessiond/pluginBackendRoutes.js.map +1 -0
  149. package/dist/server/sessiond/sessionDaemonShutdown.js +31 -0
  150. package/dist/server/sessiond/sessionDaemonShutdown.js.map +1 -0
  151. package/dist/server/sessiond/sessionProxyRoutes.js +61 -0
  152. package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -0
  153. package/dist/server/sessiond/sessionServiceDependencies.js +34 -0
  154. package/dist/server/sessiond/sessionServiceDependencies.js.map +1 -0
  155. package/dist/server/sessiond/sessiondStateOwnership.js +235 -0
  156. package/dist/server/sessiond/sessiondStateOwnership.js.map +1 -0
  157. package/dist/server/sessiond/workspaceCatalogRoutes.js +31 -0
  158. package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -0
  159. package/dist/server/sessiond/workspaceRemovalRoutes.js +41 -0
  160. package/dist/server/sessiond/workspaceRemovalRoutes.js.map +1 -0
  161. package/dist/server/sessiond.js +387 -0
  162. package/dist/server/sessiond.js.map +1 -0
  163. package/dist/server/sessions/askUserTool.js +102 -0
  164. package/dist/server/sessions/askUserTool.js.map +1 -0
  165. package/dist/server/sessions/attachmentService.js +119 -0
  166. package/dist/server/sessions/attachmentService.js.map +1 -0
  167. package/dist/server/sessions/authProviderOptions.js +50 -0
  168. package/dist/server/sessions/authProviderOptions.js.map +1 -0
  169. package/dist/server/sessions/authRoutes.js +59 -0
  170. package/dist/server/sessions/authRoutes.js.map +1 -0
  171. package/dist/server/sessions/authService.js +122 -0
  172. package/dist/server/sessions/authService.js.map +1 -0
  173. package/dist/server/sessions/builtinCommands.js +27 -0
  174. package/dist/server/sessions/builtinCommands.js.map +1 -0
  175. package/dist/server/sessions/dockerEnvironmentFacts.js +254 -0
  176. package/dist/server/sessions/dockerEnvironmentFacts.js.map +1 -0
  177. package/dist/server/sessions/editPreview.js +196 -0
  178. package/dist/server/sessions/editPreview.js.map +1 -0
  179. package/dist/server/sessions/extensionDialogWaiters.js +76 -0
  180. package/dist/server/sessions/extensionDialogWaiters.js.map +1 -0
  181. package/dist/server/sessions/globalProviderPolicy.js +167 -0
  182. package/dist/server/sessions/globalProviderPolicy.js.map +1 -0
  183. package/dist/server/sessions/interruptedRunStore.js +147 -0
  184. package/dist/server/sessions/interruptedRunStore.js.map +1 -0
  185. package/dist/server/sessions/messagePaging.js +43 -0
  186. package/dist/server/sessions/messagePaging.js.map +1 -0
  187. package/dist/server/sessions/modelCatalogRefresher.js +193 -0
  188. package/dist/server/sessions/modelCatalogRefresher.js.map +1 -0
  189. package/dist/server/sessions/oauthLoginFlowService.js +346 -0
  190. package/dist/server/sessions/oauthLoginFlowService.js.map +1 -0
  191. package/dist/server/sessions/pendingAskStore.js +275 -0
  192. package/dist/server/sessions/pendingAskStore.js.map +1 -0
  193. package/dist/server/sessions/pendingExtensionDialogStore.js +196 -0
  194. package/dist/server/sessions/pendingExtensionDialogStore.js.map +1 -0
  195. package/dist/server/sessions/piSessionManagerGateway.js +246 -0
  196. package/dist/server/sessions/piSessionManagerGateway.js.map +1 -0
  197. package/dist/server/sessions/piSessionService.js +4059 -0
  198. package/dist/server/sessions/piSessionService.js.map +1 -0
  199. package/dist/server/sessions/plainTextTheme.js +112 -0
  200. package/dist/server/sessions/plainTextTheme.js.map +1 -0
  201. package/dist/server/sessions/sessionArchiveStore.js +273 -0
  202. package/dist/server/sessions/sessionArchiveStore.js.map +1 -0
  203. package/dist/server/sessions/sessionArchiveTree.js +35 -0
  204. package/dist/server/sessions/sessionArchiveTree.js.map +1 -0
  205. package/dist/server/sessions/sessionCleanup.js +157 -0
  206. package/dist/server/sessions/sessionCleanup.js.map +1 -0
  207. package/dist/server/sessions/sessionCommandService.js +336 -0
  208. package/dist/server/sessions/sessionCommandService.js.map +1 -0
  209. package/dist/server/sessions/sessionEnvironmentFacts.js +48 -0
  210. package/dist/server/sessions/sessionEnvironmentFacts.js.map +1 -0
  211. package/dist/server/sessions/sessionFileFormat.js +27 -0
  212. package/dist/server/sessions/sessionFileFormat.js.map +1 -0
  213. package/dist/server/sessions/sessionFileHeader.js +104 -0
  214. package/dist/server/sessions/sessionFileHeader.js.map +1 -0
  215. package/dist/server/sessions/sessionModelScope.js +141 -0
  216. package/dist/server/sessions/sessionModelScope.js.map +1 -0
  217. package/dist/server/sessions/sessionNameGenerator.js +90 -0
  218. package/dist/server/sessions/sessionNameGenerator.js.map +1 -0
  219. package/dist/server/sessions/sessionNotificationStore.js +484 -0
  220. package/dist/server/sessions/sessionNotificationStore.js.map +1 -0
  221. package/dist/server/sessions/sessionRoutes.js +744 -0
  222. package/dist/server/sessions/sessionRoutes.js.map +1 -0
  223. package/dist/server/sessions/sessionRuntimeStore.js +2 -0
  224. package/dist/server/sessions/sessionRuntimeStore.js.map +1 -0
  225. package/dist/server/sessions/sessionService.js +2 -0
  226. package/dist/server/sessions/sessionService.js.map +1 -0
  227. package/dist/server/sessions/sessionSummaryScanner.js +491 -0
  228. package/dist/server/sessions/sessionSummaryScanner.js.map +1 -0
  229. package/dist/server/sessions/sessionTreeProjection.js +250 -0
  230. package/dist/server/sessions/sessionTreeProjection.js.map +1 -0
  231. package/dist/server/sessions/sessionUnreadStore.js +520 -0
  232. package/dist/server/sessions/sessionUnreadStore.js.map +1 -0
  233. package/dist/server/sessions/shutdownDrain.js +73 -0
  234. package/dist/server/sessions/shutdownDrain.js.map +1 -0
  235. package/dist/server/sessions/spawnSessionTool.js +48 -0
  236. package/dist/server/sessions/spawnSessionTool.js.map +1 -0
  237. package/dist/server/sessions/spawnSubsessionTool.js +216 -0
  238. package/dist/server/sessions/spawnSubsessionTool.js.map +1 -0
  239. package/dist/server/sessions/spawnTargetResolver.js +23 -0
  240. package/dist/server/sessions/spawnTargetResolver.js.map +1 -0
  241. package/dist/server/sessions/subsessionTranscript.js +235 -0
  242. package/dist/server/sessions/subsessionTranscript.js.map +1 -0
  243. package/dist/server/status/machineStatusRoutes.js +8 -0
  244. package/dist/server/status/machineStatusRoutes.js.map +1 -0
  245. package/dist/server/status/machineStatusService.js +181 -0
  246. package/dist/server/status/machineStatusService.js.map +1 -0
  247. package/dist/server/status/workspaceAttribution.js +87 -0
  248. package/dist/server/status/workspaceAttribution.js.map +1 -0
  249. package/dist/server/storage/projectStore.js +88 -0
  250. package/dist/server/storage/projectStore.js.map +1 -0
  251. package/dist/server/terminalProxyRoutes.js +141 -0
  252. package/dist/server/terminalProxyRoutes.js.map +1 -0
  253. package/dist/server/terminals/terminalRoutes.js +155 -0
  254. package/dist/server/terminals/terminalRoutes.js.map +1 -0
  255. package/dist/server/terminals/terminalService.js +305 -0
  256. package/dist/server/terminals/terminalService.js.map +1 -0
  257. package/dist/server/terminals/terminalSize.js +17 -0
  258. package/dist/server/terminals/terminalSize.js.map +1 -0
  259. package/dist/server/types.js +2 -0
  260. package/dist/server/types.js.map +1 -0
  261. package/dist/server/updates/fleetRoutes.js +111 -0
  262. package/dist/server/updates/fleetRoutes.js.map +1 -0
  263. package/dist/server/updates/restartRoutes.js +48 -0
  264. package/dist/server/updates/restartRoutes.js.map +1 -0
  265. package/dist/server/updates/selfUpdateRoutes.js +145 -0
  266. package/dist/server/updates/selfUpdateRoutes.js.map +1 -0
  267. package/dist/server/webSocketBridge.js +32 -0
  268. package/dist/server/webSocketBridge.js.map +1 -0
  269. package/dist/server/workingDirectory.js +44 -0
  270. package/dist/server/workingDirectory.js.map +1 -0
  271. package/dist/server/workspaceExplorerRoutes.js +147 -0
  272. package/dist/server/workspaceExplorerRoutes.js.map +1 -0
  273. package/dist/server/workspaces/effectivePathAccess.js +8 -0
  274. package/dist/server/workspaces/effectivePathAccess.js.map +1 -0
  275. package/dist/server/workspaces/fileContentService.js +190 -0
  276. package/dist/server/workspaces/fileContentService.js.map +1 -0
  277. package/dist/server/workspaces/filePreviewResponseHeaders.js +18 -0
  278. package/dist/server/workspaces/filePreviewResponseHeaders.js.map +1 -0
  279. package/dist/server/workspaces/filePreviewResponsePolicy.js +55 -0
  280. package/dist/server/workspaces/filePreviewResponsePolicy.js.map +1 -0
  281. package/dist/server/workspaces/filePreviewService.js +81 -0
  282. package/dist/server/workspaces/filePreviewService.js.map +1 -0
  283. package/dist/server/workspaces/fileSuggestions.js +520 -0
  284. package/dist/server/workspaces/fileSuggestions.js.map +1 -0
  285. package/dist/server/workspaces/fileTreeService.js +35 -0
  286. package/dist/server/workspaces/fileTreeService.js.map +1 -0
  287. package/dist/server/workspaces/pathAccessPolicy.js +90 -0
  288. package/dist/server/workspaces/pathAccessPolicy.js.map +1 -0
  289. package/dist/server/workspaces/pathSafety.js +45 -0
  290. package/dist/server/workspaces/pathSafety.js.map +1 -0
  291. package/dist/server/workspaces/projectPiWebConfig.js +61 -0
  292. package/dist/server/workspaces/projectPiWebConfig.js.map +1 -0
  293. package/dist/server/workspaces/projectWorkspaceCwds.js +17 -0
  294. package/dist/server/workspaces/projectWorkspaceCwds.js.map +1 -0
  295. package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js +402 -0
  296. package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js.map +1 -0
  297. package/dist/server/workspaces/workspaceCatalog.js +47 -0
  298. package/dist/server/workspaces/workspaceCatalog.js.map +1 -0
  299. package/dist/server/workspaces/workspaceContext.js +6 -0
  300. package/dist/server/workspaces/workspaceContext.js.map +1 -0
  301. package/dist/server/workspaces/workspaceDeletionRoutes.js +49 -0
  302. package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -0
  303. package/dist/server/workspaces/workspaceProviderRegistry.js +651 -0
  304. package/dist/server/workspaces/workspaceProviderRegistry.js.map +1 -0
  305. package/dist/server/workspaces/workspaceRemovalService.js +256 -0
  306. package/dist/server/workspaces/workspaceRemovalService.js.map +1 -0
  307. package/dist/server/workspaces/workspaceRouteErrors.js +7 -0
  308. package/dist/server/workspaces/workspaceRouteErrors.js.map +1 -0
  309. package/dist/server/workspaces/worktreePreRemoveHook.js +39 -0
  310. package/dist/server/workspaces/worktreePreRemoveHook.js.map +1 -0
  311. package/dist/server-plugin-api.d.ts +140 -0
  312. package/dist/server-plugin-api.js +2 -0
  313. package/dist/server-plugin-api.js.map +1 -0
  314. package/dist/serverPluginRecovery.js +138 -0
  315. package/dist/serverPluginRecovery.js.map +1 -0
  316. package/dist/sessiond/activeAgentProfile.js +12 -0
  317. package/dist/sessiond/activeAgentProfile.js.map +1 -0
  318. package/dist/sessiond/config.js +20 -0
  319. package/dist/sessiond/config.js.map +1 -0
  320. package/dist/sessiond/sessionDaemonClient.js +105 -0
  321. package/dist/sessiond/sessionDaemonClient.js.map +1 -0
  322. package/dist/shared/activeAgentProfile.js +37 -0
  323. package/dist/shared/activeAgentProfile.js.map +1 -0
  324. package/dist/shared/activity.js +16 -0
  325. package/dist/shared/activity.js.map +1 -0
  326. package/dist/shared/apiTypes.js +41 -0
  327. package/dist/shared/apiTypes.js.map +1 -0
  328. package/dist/shared/capabilities.js +37 -0
  329. package/dist/shared/capabilities.js.map +1 -0
  330. package/dist/shared/federatedRoutes.js +127 -0
  331. package/dist/shared/federatedRoutes.js.map +1 -0
  332. package/dist/shared/machinePluginIds.js +43 -0
  333. package/dist/shared/machinePluginIds.js.map +1 -0
  334. package/dist/shared/machineStatus.js +94 -0
  335. package/dist/shared/machineStatus.js.map +1 -0
  336. package/dist/shared/piWebStatusParsing.js +141 -0
  337. package/dist/shared/piWebStatusParsing.js.map +1 -0
  338. package/dist/shared/pluginApiTypes.d.ts +150 -0
  339. package/dist/shared/pluginApiTypes.js +3 -0
  340. package/dist/shared/pluginApiTypes.js.map +1 -0
  341. package/dist/shared/pluginBackendProtocol.js +110 -0
  342. package/dist/shared/pluginBackendProtocol.js.map +1 -0
  343. package/dist/shared/pluginIds.js +10 -0
  344. package/dist/shared/pluginIds.js.map +1 -0
  345. package/dist/shared/pluginRecoveryCommands.js +14 -0
  346. package/dist/shared/pluginRecoveryCommands.js.map +1 -0
  347. package/dist/shared/promptAttachments.js +92 -0
  348. package/dist/shared/promptAttachments.js.map +1 -0
  349. package/dist/shared/selfUpdate.js +3 -0
  350. package/dist/shared/selfUpdate.js.map +1 -0
  351. package/dist/shared/thinkingLevels.js +31 -0
  352. package/dist/shared/thinkingLevels.js.map +1 -0
  353. package/dist/shared/workspaceDeletion.js +12 -0
  354. package/dist/shared/workspaceDeletion.js.map +1 -0
  355. package/dist/shared/workspaceFiles.js +42 -0
  356. package/dist/shared/workspaceFiles.js.map +1 -0
  357. package/dist/shared/workspaceRemovalProtocol.js +24 -0
  358. package/dist/shared/workspaceRemovalProtocol.js.map +1 -0
  359. package/docs/assets/favicon.svg +11 -0
  360. package/docs/assets/pi-web-banner.png +0 -0
  361. package/docs/assets/pi-web-desktop.png +0 -0
  362. package/docs/assets/pi-web-mobile.png +0 -0
  363. package/docs/assets/pi-web-tablet.png +0 -0
  364. package/docs/config.md +444 -0
  365. package/docs/plugins.md +1305 -0
  366. package/examples/workspace-provider-plugin/README.md +52 -0
  367. package/examples/workspace-provider-plugin/package.json +25 -0
  368. package/examples/workspace-provider-plugin/src/browser/index.ts +69 -0
  369. package/examples/workspace-provider-plugin/src/server.ts +64 -0
  370. package/examples/workspace-provider-plugin/tsconfig.json +21 -0
  371. package/extensions/README-pi-web-restart-migration.md +45 -0
  372. package/extensions/pi-web.ts +324 -0
  373. package/install.sh +5 -0
  374. package/package.json +173 -0
  375. package/plugin-api.d.ts +1 -0
  376. package/server-plugin-api.d.ts +1 -0
@@ -0,0 +1,207 @@
1
+ import { homedir } from "node:os";
2
+ import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
3
+ import { readdir, stat } from "node:fs/promises";
4
+ /**
5
+ * Project folder suggestions.
6
+ *
7
+ * The picker is the only place a project path is typed, usually on a phone
8
+ * keyboard, so a strict same-directory prefix match is a poor fit: it forces
9
+ * the exact spelling of every intermediate segment. Instead this behaves like
10
+ * a zoxide-style jump list — type a fragment, search downward from the typed
11
+ * parent, rank the best folders first — while keeping plain browsing (a query
12
+ * ending in a separator) as an unfiltered listing of that directory.
13
+ */
14
+ const MAX_SUGGESTIONS = 80;
15
+ const MAX_SCANNED_DIRECTORIES = 4_000;
16
+ const MAX_SEARCH_DEPTH = 3;
17
+ const MAX_MISSING_ANCESTORS = 8;
18
+ /**
19
+ * Directories that are almost never a project root but are extremely common
20
+ * and very large. Descending into them would spend the scan budget before
21
+ * reaching the folders the user is actually looking for.
22
+ */
23
+ const SKIPPED_DIRECTORY_NAMES = new Set([
24
+ ".bzr",
25
+ ".cache",
26
+ ".git",
27
+ ".hg",
28
+ ".gradle",
29
+ ".idea",
30
+ ".mypy_cache",
31
+ ".next",
32
+ ".nuxt",
33
+ ".pnpm-store",
34
+ ".pytest_cache",
35
+ ".ruff_cache",
36
+ ".svn",
37
+ ".terraform",
38
+ ".tox",
39
+ ".venv",
40
+ ".vscode",
41
+ "__pycache__",
42
+ "bower_components",
43
+ "node_modules",
44
+ "site-packages",
45
+ "vendor",
46
+ "venv",
47
+ ]);
48
+ export function expandUserPath(path) {
49
+ if (path === "" || path === "~")
50
+ return homedir();
51
+ if (path.startsWith(`~${sep}`) || path.startsWith("~/"))
52
+ return resolve(homedir(), path.slice(2));
53
+ return isAbsolute(path) ? resolve(path) : resolve(process.cwd(), path);
54
+ }
55
+ export async function listDirectorySuggestions(query = "") {
56
+ const raw = query.trim();
57
+ const expanded = expandUserPath(raw);
58
+ const target = isDirectoryListingQuery(raw)
59
+ ? { base: expanded, search: "" }
60
+ : await resolveSearchBase(expanded);
61
+ if (target === undefined)
62
+ return [];
63
+ // Browsing shows one level, exactly like a file manager. A search term is
64
+ // what unlocks the downward scan.
65
+ const candidates = await collectDirectories(target.base, target.search === "" ? 0 : MAX_SEARCH_DEPTH);
66
+ const ranked = target.search === "" ? sortByPath(candidates) : rankDirectories(candidates, target.search);
67
+ return ranked.slice(0, MAX_SUGGESTIONS).map((candidate) => ({ path: `${candidate.path}/`, kind: "other" }));
68
+ }
69
+ function isDirectoryListingQuery(raw) {
70
+ return raw === "" || raw === "~" || raw.endsWith("/") || raw.endsWith("\\");
71
+ }
72
+ /**
73
+ * Anchor the search at the deepest directory that actually exists and treat
74
+ * everything the user typed below it as the search term. Typing
75
+ * `~/work/playria` when `~/work` does not exist is a search for
76
+ * `work/playria` under `~`, not an error — which is what makes partially
77
+ * remembered paths usable.
78
+ */
79
+ async function resolveSearchBase(expanded) {
80
+ const segments = [basename(expanded)];
81
+ let base = dirname(expanded);
82
+ for (let attempt = 0; attempt <= MAX_MISSING_ANCESTORS; attempt += 1) {
83
+ if (await isDirectory(base))
84
+ return { base, search: segments.join("/") };
85
+ const parent = dirname(base);
86
+ if (parent === base)
87
+ return undefined;
88
+ segments.unshift(basename(base));
89
+ base = parent;
90
+ }
91
+ return undefined;
92
+ }
93
+ async function isDirectory(path) {
94
+ try {
95
+ return (await stat(path)).isDirectory();
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
101
+ /**
102
+ * Breadth-first so shallow directories are always gathered before the scan
103
+ * budget can be exhausted by one deep branch.
104
+ */
105
+ async function collectDirectories(parent, maxDepth) {
106
+ const collected = [];
107
+ let frontier = [{ path: parent, relativePath: "", depth: -1 }];
108
+ let scanned = 0;
109
+ while (frontier.length > 0 && scanned < MAX_SCANNED_DIRECTORIES) {
110
+ const next = [];
111
+ for (const directory of frontier) {
112
+ if (scanned >= MAX_SCANNED_DIRECTORIES)
113
+ break;
114
+ scanned += 1;
115
+ for (const child of await readChildDirectories(directory.path)) {
116
+ const depth = directory.depth + 1;
117
+ const relativePath = directory.relativePath === "" ? child : `${directory.relativePath}/${child}`;
118
+ const candidate = { path: join(directory.path, child), relativePath, depth };
119
+ collected.push(candidate);
120
+ if (depth < maxDepth && !SKIPPED_DIRECTORY_NAMES.has(child)) {
121
+ next.push({ path: candidate.path, relativePath, depth });
122
+ }
123
+ }
124
+ }
125
+ frontier = next;
126
+ }
127
+ return collected;
128
+ }
129
+ async function readChildDirectories(directory) {
130
+ let entries;
131
+ try {
132
+ entries = await readdir(directory, { withFileTypes: true });
133
+ }
134
+ catch {
135
+ // A missing or unreadable directory is a normal state while typing a path
136
+ // that does not exist yet; it must not fail the whole suggestion request.
137
+ return [];
138
+ }
139
+ const names = [];
140
+ for (const entry of entries) {
141
+ if (entry.isDirectory()) {
142
+ names.push(entry.name);
143
+ continue;
144
+ }
145
+ if (!entry.isSymbolicLink())
146
+ continue;
147
+ try {
148
+ if ((await stat(join(directory, entry.name))).isDirectory())
149
+ names.push(entry.name);
150
+ }
151
+ catch {
152
+ // Broken symlink: not a usable project folder.
153
+ }
154
+ }
155
+ return names.sort((a, b) => a.localeCompare(b));
156
+ }
157
+ function sortByPath(candidates) {
158
+ return [...candidates].sort((a, b) => a.depth - b.depth || a.path.localeCompare(b.path));
159
+ }
160
+ function rankDirectories(candidates, search) {
161
+ const query = search.toLowerCase();
162
+ return candidates
163
+ .map((candidate) => ({ candidate, score: directoryScore(candidate, query) }))
164
+ .filter(({ score }) => score > 0)
165
+ .sort((a, b) => b.score - a.score
166
+ || a.candidate.depth - b.candidate.depth
167
+ || a.candidate.path.length - b.candidate.path.length
168
+ || a.candidate.path.localeCompare(b.candidate.path))
169
+ .map(({ candidate }) => candidate);
170
+ }
171
+ /**
172
+ * Depth is a penalty rather than a filter: a nested exact name still beats a
173
+ * shallow fuzzy match, but two equally good matches prefer the shallower one.
174
+ */
175
+ function directoryScore(candidate, query) {
176
+ const name = basename(candidate.path).toLowerCase();
177
+ const relativePath = candidate.relativePath.toLowerCase();
178
+ const depthPenalty = candidate.depth * 40;
179
+ if (name === query)
180
+ return 1000 - depthPenalty;
181
+ if (name.startsWith(query))
182
+ return 900 - depthPenalty;
183
+ if (relativePath === query)
184
+ return 880 - depthPenalty;
185
+ if (relativePath.startsWith(query))
186
+ return 850 - depthPenalty;
187
+ if (name.includes(query))
188
+ return 750 - depthPenalty;
189
+ if (relativePath.includes(query))
190
+ return 650 - depthPenalty;
191
+ const tokens = query.split(/[\s/\\-_.]+/u).filter(Boolean);
192
+ if (tokens.length > 1 && tokens.every((token) => relativePath.includes(token))) {
193
+ return 550 + tokens.filter((token) => name.includes(token)).length * 25 - depthPenalty;
194
+ }
195
+ return isSubsequence(query, relativePath) ? Math.max(1, 200 - depthPenalty) : 0;
196
+ }
197
+ function isSubsequence(needle, haystack) {
198
+ let index = 0;
199
+ for (const character of needle) {
200
+ index = haystack.indexOf(character, index);
201
+ if (index === -1)
202
+ return false;
203
+ index += character.length;
204
+ }
205
+ return true;
206
+ }
207
+ //# sourceMappingURL=directorySuggestions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directorySuggestions.js","sourceRoot":"","sources":["../../../src/server/projects/directorySuggestions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { mkdir, realpath, stat } from "node:fs/promises";
2
+ import { expandUserPath } from "./directorySuggestions.js";
3
+ export class ProjectService {
4
+ constructor(store) {
5
+ this.store = store;
6
+ }
7
+ list() {
8
+ return this.store.list();
9
+ }
10
+ async add(input) {
11
+ // Trim so stray whitespace cannot diverge the stored path from the
12
+ // trimmed key the trust lookup (projectTrustRoutes) previews decisions for.
13
+ const requestedPath = expandUserPath(input.path.trim());
14
+ if (input.create === true)
15
+ await mkdir(requestedPath, { recursive: true });
16
+ const resolved = await realpath(requestedPath);
17
+ const s = await stat(resolved);
18
+ if (!s.isDirectory())
19
+ throw new Error("Project path must be a directory");
20
+ return this.store.add(input.name === undefined ? { path: resolved } : { name: input.name, path: resolved });
21
+ }
22
+ async close(id) {
23
+ if (!(await this.store.remove(id)))
24
+ throw new Error("Project not found");
25
+ }
26
+ async requireProject(id) {
27
+ const project = await this.store.get(id);
28
+ if (!project)
29
+ throw new Error("Project not found");
30
+ return project;
31
+ }
32
+ }
33
+ //# sourceMappingURL=projectService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectService.js","sourceRoot":"","sources":["../../../src/server/projects/projectService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGzD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,MAAM,OAAO,cAAc;IACzB,YAA6B,KAAmB;QAAnB,UAAK,GAAL,KAAK,CAAc;IAAG,CAAC;IAEpD,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAwD;QAChE,mEAAmE;QACnE,4EAA4E;QAC5E,MAAM,aAAa,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACxD,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI;YAAE,MAAM,KAAK,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3E,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,CAAC;QAC/C,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAC1E,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC9G,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,EAAU;QACpB,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,EAAU;QAC7B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACnD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,93 @@
1
+ import { projectBrowserSessionEvent } from "../browserMessageProjection.js";
2
+ export class SessionEventHub {
3
+ constructor() {
4
+ this.socketsBySession = new Map();
5
+ this.globalSockets = new Set();
6
+ this.seqBySession = new Map();
7
+ }
8
+ add(sessionId, socket) {
9
+ let sockets = this.socketsBySession.get(sessionId);
10
+ if (!sockets) {
11
+ sockets = new Set();
12
+ this.socketsBySession.set(sessionId, sockets);
13
+ }
14
+ sockets.add(socket);
15
+ socket.on("close", () => {
16
+ sockets.delete(socket);
17
+ });
18
+ }
19
+ /**
20
+ * Frame sent to each global subscriber the moment it joins, before any live
21
+ * event. It closes the join race for state the browser would otherwise only
22
+ * fetch over HTTP: with two proxy hops in federation, that fetch can resolve
23
+ * before the upstream subscription exists and then be clobbered by a stale
24
+ * value.
25
+ */
26
+ setGlobalJoinFrame(frame) {
27
+ this.globalJoinFrame = frame;
28
+ }
29
+ addGlobal(socket) {
30
+ this.globalSockets.add(socket);
31
+ socket.on("close", () => this.globalSockets.delete(socket));
32
+ const joinFrame = this.globalJoinFrame?.();
33
+ if (joinFrame !== undefined)
34
+ this.sendToSocket(this.globalSockets, socket, JSON.stringify(joinFrame));
35
+ }
36
+ publish(sessionId, event) {
37
+ const seq = (this.seqBySession.get(sessionId) ?? 0) + 1;
38
+ this.seqBySession.set(sessionId, seq);
39
+ // Keep seq monotonic (join-time watermark) but skip serialization when no
40
+ // browser is subscribed: stringifying every delta/tool event on the
41
+ // agent's event loop with zero listeners was measurable overhead.
42
+ const sockets = this.socketsBySession.get(sessionId);
43
+ if (sockets === undefined || sockets.size === 0)
44
+ return;
45
+ const payload = JSON.stringify({ ...projectBrowserSessionEvent(event), seq });
46
+ this.sendToSockets(sockets, payload);
47
+ }
48
+ /**
49
+ * Last per-session sequence number stamped by {@link publish} (0 before any
50
+ * event). Callers building a join-time stream snapshot read this as the
51
+ * watermark: buffered live events with `seq <= currentSeq` are already
52
+ * reflected in the snapshot's partial and must be dropped by the client.
53
+ */
54
+ currentSeq(sessionId) {
55
+ return this.seqBySession.get(sessionId) ?? 0;
56
+ }
57
+ publishGlobal(event) {
58
+ this.publishRealtime(event);
59
+ }
60
+ publishNotificationSummary(event) {
61
+ const payload = JSON.stringify(event);
62
+ this.sendToSockets(this.globalSockets, payload);
63
+ }
64
+ publishRealtime(event) {
65
+ if (this.globalSockets.size === 0)
66
+ return;
67
+ const payload = JSON.stringify(event);
68
+ this.sendToSockets(this.globalSockets, payload);
69
+ }
70
+ sendToSockets(sockets, payload) {
71
+ if (sockets === undefined)
72
+ return;
73
+ for (const socket of sockets)
74
+ this.sendToSocket(sockets, socket, payload);
75
+ }
76
+ sendToSocket(sockets, socket, payload) {
77
+ if (socket.readyState !== socket.OPEN)
78
+ return;
79
+ try {
80
+ socket.send(payload);
81
+ }
82
+ catch {
83
+ sockets.delete(socket);
84
+ try {
85
+ socket.terminate();
86
+ }
87
+ catch {
88
+ // Removal is authoritative; cleanup failure must not block healthy sockets.
89
+ }
90
+ }
91
+ }
92
+ }
93
+ //# sourceMappingURL=sessionEventHub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionEventHub.js","sourceRoot":"","sources":["../../../src/server/realtime/sessionEventHub.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Turns an inbound HTTP disconnect into cooperative cancellation for a bounded
3
+ * downstream operation. A normal completed response never aborts the signal.
4
+ */
5
+ export function requestCancellation(request, reply) {
6
+ const controller = new AbortController();
7
+ const abort = () => {
8
+ if (!controller.signal.aborted) {
9
+ controller.abort(new DOMException("HTTP request cancelled", "AbortError"));
10
+ }
11
+ };
12
+ const abortOnPrematureResponseClose = () => {
13
+ if (!reply.raw.writableEnded)
14
+ abort();
15
+ };
16
+ request.raw.once("aborted", abort);
17
+ reply.raw.once("close", abortOnPrematureResponseClose);
18
+ // Node auto-destroys the request stream once its body has been fully read, so
19
+ // `request.raw.destroyed` alone does not mean the client went away. Only an
20
+ // incomplete request stream, or a response closed before it was written, is a
21
+ // real disconnect that happened before this cancellation was installed.
22
+ if ((request.raw.destroyed && !request.raw.complete) || (reply.raw.destroyed && !reply.raw.writableEnded))
23
+ abort();
24
+ return {
25
+ signal: controller.signal,
26
+ dispose() {
27
+ request.raw.removeListener("aborted", abort);
28
+ reply.raw.removeListener("close", abortOnPrematureResponseClose);
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=requestCancellation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requestCancellation.js","sourceRoot":"","sources":["../../src/server/requestCancellation.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAuB,EAAE,KAAmB;IAC9E,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAC/B,UAAU,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC,CAAC;IACF,MAAM,6BAA6B,GAAG,GAAS,EAAE;QAC/C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa;YAAE,KAAK,EAAE,CAAC;IACxC,CAAC,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACnC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC;IACvD,8EAA8E;IAC9E,4EAA4E;IAC5E,8EAA8E;IAC9E,wEAAwE;IACxE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC;QAAE,KAAK,EAAE,CAAC;IAEnH,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,OAAO;YACL,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC7C,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC;QACnE,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,108 @@
1
+ import { EventEmitter } from "node:events";
2
+ import { SettingsManager } from "@earendil-works/pi-coding-agent";
3
+ import { Client, EnvHttpProxyAgent, Pool, setGlobalDispatcher } from "undici";
4
+ /**
5
+ * HTTP idle timeout for the session daemon's embedded Pi runtime.
6
+ *
7
+ * undici's global dispatcher caps `bodyTimeout` and `headersTimeout` at
8
+ * 300_000 ms by default, so any model response that stays idle for 5 minutes
9
+ * (slow local backends such as vLLM producing a single chunk) dies with
10
+ * `TypeError: terminated` — surfaced as "(SYSTEM) Model response failed:
11
+ * terminated" (issue #113).
12
+ *
13
+ * The pi CLI avoids this by calling
14
+ * `configureHttpDispatcher(settingsManager.getHttpIdleTimeoutMs())` at
15
+ * bootstrap; the Pi SDK setting `httpIdleTimeoutMs` (agent profile
16
+ * `settings.json`, default 300_000, `0` disables the idle timers) was simply
17
+ * never applied by PI WEB's embedded session runtime. This module is that
18
+ * missing step for the session daemon.
19
+ *
20
+ * The SDK's own `configureHttpDispatcher` lives in
21
+ * `@earendil-works/pi-coding-agent/dist/core/http-dispatcher.js`, but the
22
+ * package `exports` map blocks deep imports (`ERR_PACKAGE_PATH_NOT_EXPORTED`)
23
+ * and nothing equivalent is re-exported, so the semantics are mirrored here.
24
+ * The one deliberate deviation is skipping the SDK's `undici.install()` step,
25
+ * which replaces `globalThis.fetch` with npm undici's fetch to work around
26
+ * Node 26.0's bundled fetch failing to decompress responses read through an
27
+ * npm dispatcher. A long-lived shared daemon should change the dispatcher,
28
+ * not the fetch implementation every in-process consumer sees; built-in
29
+ * fetch on Node 22/24 honors the global dispatcher without it. If a future
30
+ * Node reintroduces the mismatch (symptom: `response.json()` failing on
31
+ * compressed bodies), revisit. If the SDK ever exports
32
+ * `configureHttpDispatcher`, prefer delegating to it.
33
+ *
34
+ * The value is applied once, at daemon start; changing `httpIdleTimeoutMs`
35
+ * requires restarting the session daemon.
36
+ */
37
+ const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 300_000;
38
+ /**
39
+ * Read the active agent profile's `httpIdleTimeoutMs` through the SDK
40
+ * `SettingsManager`, reusing its parsing, validation, and defaults
41
+ * (`"disabled"` → 0, absent → 300_000, invalid → throws).
42
+ */
43
+ export function resolveAgentHttpIdleTimeoutMs({ agentDir, cwd }) {
44
+ return SettingsManager.create(cwd, agentDir).getHttpIdleTimeoutMs();
45
+ }
46
+ // Undici can emit an internal Client "error" while terminating a mid-stream
47
+ // fetch body. The body stream still rejects through the response reader; this
48
+ // listener only prevents EventEmitter's unhandled "error" special case from
49
+ // crashing the daemon. `Dispatcher`'s typed event overloads hide the generic
50
+ // `EventEmitter.on`, so the listener is attached through the prototype.
51
+ const ignoreUndiciDispatcherError = () => { };
52
+ function withUndiciErrorListener(dispatcher) {
53
+ EventEmitter.prototype.on.call(dispatcher, "error", ignoreUndiciDispatcherError);
54
+ return dispatcher;
55
+ }
56
+ function createUndiciClient(origin, options) {
57
+ return withUndiciErrorListener(new Client(origin, options));
58
+ }
59
+ function createUndiciOriginDispatcher(origin, options) {
60
+ if (options.connections === 1) {
61
+ return createUndiciClient(origin, options);
62
+ }
63
+ return withUndiciErrorListener(new Pool(origin, {
64
+ ...options,
65
+ factory: createUndiciClient,
66
+ }));
67
+ }
68
+ /**
69
+ * Install a global undici dispatcher that applies `timeoutMs` to both
70
+ * `bodyTimeout` and `headersTimeout`, mirroring the SDK's
71
+ * `configureHttpDispatcher`. `0` disables the idle timers (undici semantics).
72
+ */
73
+ export function configureAgentHttpDispatcher(timeoutMs) {
74
+ if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
75
+ throw new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);
76
+ }
77
+ const normalizedTimeoutMs = Math.floor(timeoutMs);
78
+ const dispatcher = withUndiciErrorListener(new EnvHttpProxyAgent({
79
+ allowH2: false,
80
+ bodyTimeout: normalizedTimeoutMs,
81
+ headersTimeout: normalizedTimeoutMs,
82
+ clientFactory: createUndiciClient,
83
+ factory: createUndiciOriginDispatcher,
84
+ }));
85
+ setGlobalDispatcher(dispatcher);
86
+ }
87
+ /**
88
+ * Resolve the agent profile's `httpIdleTimeoutMs` and install it on the
89
+ * global dispatcher. Never throws: an unreadable or invalid setting falls
90
+ * back to the 300_000 ms default and reports a warning for logging, so a bad
91
+ * settings file cannot keep the daemon from starting.
92
+ */
93
+ export function applyAgentHttpIdleTimeout({ agentDir, cwd }) {
94
+ let timeoutMs = DEFAULT_HTTP_IDLE_TIMEOUT_MS;
95
+ let warning;
96
+ try {
97
+ timeoutMs = resolveAgentHttpIdleTimeoutMs({ agentDir, cwd });
98
+ }
99
+ catch (error) {
100
+ warning = `Falling back to the ${String(DEFAULT_HTTP_IDLE_TIMEOUT_MS)} ms HTTP idle default because the agent profile httpIdleTimeoutMs could not be applied: ${describeError(error)}`;
101
+ }
102
+ configureAgentHttpDispatcher(timeoutMs);
103
+ return warning === undefined ? { timeoutMs } : { timeoutMs, warning };
104
+ }
105
+ function describeError(error) {
106
+ return error instanceof Error ? error.message : String(error);
107
+ }
108
+ //# sourceMappingURL=agentHttpDispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentHttpDispatcher.js","sourceRoot":"","sources":["../../../src/server/sessiond/agentHttpDispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,mBAAmB,EAAmB,MAAM,QAAQ,CAAC;AAE/F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,MAAM,4BAA4B,GAAG,OAAO,CAAC;AAc7C;;;;GAIG;AACH,MAAM,UAAU,6BAA6B,CAAC,EAAE,QAAQ,EAAE,GAAG,EAA4B;IACvF,OAAO,eAAe,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,oBAAoB,EAAE,CAAC;AACtE,CAAC;AAED,4EAA4E;AAC5E,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,wEAAwE;AACxE,MAAM,2BAA2B,GAAG,GAAS,EAAE,GAAkD,CAAC,CAAC;AAEnG,SAAS,uBAAuB,CAAuB,UAAa;IAClE,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,2BAA2B,CAAC,CAAC;IACjF,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAW,EAAE,OAAuB;IAC9D,OAAO,uBAAuB,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,4BAA4B,CAAC,MAAW,EAAE,OAAqB;IACtE,IAAI,OAAO,CAAC,WAAW,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,uBAAuB,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE;QAC9C,GAAG,OAAO;QACV,OAAO,EAAE,kBAAkB;KAC5B,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAAC,SAAiB;IAC5D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,uBAAuB,CAAC,IAAI,iBAAiB,CAAC;QAC/D,OAAO,EAAE,KAAK;QACd,WAAW,EAAE,mBAAmB;QAChC,cAAc,EAAE,mBAAmB;QACnC,aAAa,EAAE,kBAAkB;QACjC,OAAO,EAAE,4BAA4B;KACtC,CAAC,CAAC,CAAC;IACJ,mBAAmB,CAAC,UAAU,CAAC,CAAC;AAClC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,EAAE,QAAQ,EAAE,GAAG,EAA4B;IACnF,IAAI,SAAS,GAAG,4BAA4B,CAAC;IAC7C,IAAI,OAA2B,CAAC;IAChC,IAAI,CAAC;QACH,SAAS,GAAG,6BAA6B,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,uBAAuB,MAAM,CAAC,4BAA4B,CAAC,2FAA2F,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;IACzL,CAAC;IACD,4BAA4B,CAAC,SAAS,CAAC,CAAC;IACxC,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AACxE,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Environment hygiene for agent-executed processes.
3
+ *
4
+ * Sessions run inside the session daemon process, so everything agents can
5
+ * spawn — the bash tool, terminals, subsessions — inherits the daemon's
6
+ * environment by default. That inheritance is deliberate: the daemon's
7
+ * `PI_WEB_*` wiring stays visible so agent-facing tooling keeps working, and
8
+ * a second PI WEB instance started from inside a session resolves the same
9
+ * state and fails loudly at startup (see `sessiondStateOwnership`) instead of
10
+ * silently corrupting the live daemon's data. `PI_WEB_SESSION=1` and the
11
+ * session environment facts tell agents they are nested and which precautions
12
+ * apply.
13
+ *
14
+ * The daemon captures its environment once at startup for its own use and
15
+ * then removes the handful of keys that silently distort the tools agents
16
+ * run, so all later spawns inherit a clean environment without per-call-site
17
+ * filtering. Visibility rules:
18
+ *
19
+ * - Ordinary variables (`PATH`, `HOME`, `XDG_CONFIG_HOME`, proxy keys, …)
20
+ * stay.
21
+ * - `PI_WEB_*` keys stay — including `PI_WEB_DOCKER_*` deployment descriptors
22
+ * the agent-facing `pi-web-docker` CLI reads, and the deprecated
23
+ * `PI_WEB_AGENT_*` aliases: the canonical `PI_CODING_AGENT_*` vars are
24
+ * exported with the fully resolved values, so both names resolve
25
+ * identically for anything started from here.
26
+ * - `HOSTEXEC_*` stays: agents use `hostexec`.
27
+ * - `PI_CODING_AGENT_DIR` stays so agent-spawned `pi` CLIs find the profile's
28
+ * auth and models; `PI_CODING_AGENT_SESSION_DIR` stays for the same reason:
29
+ * it is documented `pi` configuration, not daemon wiring, so a deployment
30
+ * that sets it wants every `pi` process — whether daemon-spawned or started
31
+ * by an agent — using the same session storage.
32
+ * - `NODE_ENV` and `PORT` are app-runtime configuration and the only removals:
33
+ * `NODE_ENV=production` makes npm skip devDependencies and flips Node
34
+ * package-export conditions, and `PORT` leaks into the listener
35
+ * configuration of tools agents run.
36
+ */
37
+ /**
38
+ * Keys that configure the daemon or app runtime in ways that silently break
39
+ * the tools agents run. Daemon configuration belongs in `PI_WEB_`-prefixed
40
+ * keys, which stay visible; a key only belongs here when it cannot carry the
41
+ * prefix (deployment conventions like `NODE_ENV`).
42
+ */
43
+ const DAEMON_ONLY_ENV_KEYS = new Set(["NODE_ENV", "PORT"]);
44
+ export function isAgentVisibleEnvKey(key) {
45
+ return !DAEMON_ONLY_ENV_KEYS.has(key);
46
+ }
47
+ /**
48
+ * Delete every non-agent-visible key from `env` — the daemon's `process.env`
49
+ * at startup — and return the removed key names, sorted, for logging.
50
+ */
51
+ export function scrubNonAgentVisibleEnvKeys(env) {
52
+ const scrubbed = Object.keys(env).filter((key) => !isAgentVisibleEnvKey(key));
53
+ for (const key of scrubbed) {
54
+ // process.env is a dynamic key/value bag; deleting the daemon-only keys is
55
+ // the whole point of the scrub, and the keys cannot be known statically.
56
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
57
+ delete env[key];
58
+ }
59
+ return scrubbed.sort();
60
+ }
61
+ //# sourceMappingURL=agentProcessEnvironment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentProcessEnvironment.js","sourceRoot":"","sources":["../../../src/server/sessiond/agentProcessEnvironment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;AAE3D,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAAC,GAAsB;IAChE,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9E,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,2EAA2E;QAC3E,yEAAyE;QACzE,gEAAgE;QAChE,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { isPiWebPluginId } from "../../shared/pluginIds.js";
2
+ import { parsePluginBackendRequestEnvelope, PLUGIN_BACKEND_REQUEST_BODY_MAX_BYTES, PLUGIN_BACKEND_RESPONSE_JSON_MAX_BYTES, requirePluginBackendOperation, serializeBoundedPluginBackendJson, } from "../../shared/pluginBackendProtocol.js";
3
+ import { WorkspaceProviderRequestError, } from "../workspaces/workspaceProviderRegistry.js";
4
+ /** JSON-only sessiond boundary for the active owner of one current workspace. */
5
+ export function registerPluginBackendRoutes(app, dependencies, prefix = "/plugin-backends") {
6
+ app.post(`${prefix}/:pluginId/projects/:projectId/workspaces/:workspaceId/:operation`, { bodyLimit: PLUGIN_BACKEND_REQUEST_BODY_MAX_BYTES }, async (request, reply) => {
7
+ const { pluginId, projectId, workspaceId } = request.params;
8
+ let operation = request.params.operation;
9
+ let envelope;
10
+ try {
11
+ if (!isPiWebPluginId(pluginId))
12
+ throw new Error(`Invalid PI WEB plugin id: ${pluginId}`);
13
+ operation = requirePluginBackendOperation(operation);
14
+ if (projectId === "")
15
+ throw new Error("Project id is required");
16
+ if (workspaceId === "")
17
+ throw new Error("Workspace id is required");
18
+ envelope = parsePluginBackendRequestEnvelope(request.body);
19
+ }
20
+ catch (error) {
21
+ return attributedError(reply, 400, boundedErrorMessage(error), "invalid-request", pluginId, operation);
22
+ }
23
+ let project;
24
+ try {
25
+ project = await dependencies.projects.requireProject(projectId);
26
+ }
27
+ catch (error) {
28
+ const message = boundedErrorMessage(error);
29
+ return attributedError(reply, message === "Project not found" ? 404 : 500, message, message === "Project not found" ? "project-not-found" : "project-resolution-failed", pluginId, operation);
30
+ }
31
+ try {
32
+ const result = await dependencies.backends.request({
33
+ pluginId,
34
+ moduleRevision: envelope.revision,
35
+ project,
36
+ workspaceId,
37
+ operation,
38
+ input: envelope.input,
39
+ });
40
+ const serialized = serializeBoundedPluginBackendJson(result, `Server plugin ${pluginId} operation ${operation} result`, PLUGIN_BACKEND_RESPONSE_JSON_MAX_BYTES);
41
+ return await reply.type("application/json; charset=utf-8").send(serialized);
42
+ }
43
+ catch (error) {
44
+ return await pluginBackendRequestFailed(reply, error, pluginId, operation);
45
+ }
46
+ finally {
47
+ dependencies.onWorkspacesMutated();
48
+ }
49
+ });
50
+ }
51
+ function pluginBackendRequestFailed(reply, error, pluginId, operation) {
52
+ if (error instanceof WorkspaceProviderRequestError) {
53
+ return attributedError(reply, error.statusCode, error.message, error.code, pluginId, operation);
54
+ }
55
+ return attributedError(reply, 502, `Plugin backend request failed: ${boundedErrorMessage(error)}`, "request-failed", pluginId, operation);
56
+ }
57
+ function attributedError(reply, statusCode, message, code, pluginId, operation) {
58
+ return reply.code(statusCode).send({ error: message, code, pluginId, operation });
59
+ }
60
+ function boundedErrorMessage(error) {
61
+ const message = error instanceof Error ? error.message : String(error);
62
+ return message.length <= 2_048 ? message : `${message.slice(0, 2_045)}...`;
63
+ }
64
+ //# sourceMappingURL=pluginBackendRoutes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pluginBackendRoutes.js","sourceRoot":"","sources":["../../../src/server/sessiond/pluginBackendRoutes.ts"],"names":[],"mappings":"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"}