@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,387 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, rm } from "node:fs/promises";
3
+ import { dirname } from "node:path";
4
+ import Fastify from "fastify";
5
+ import fastifyWebsocket from "@fastify/websocket";
6
+ import { WorkspaceActivityService } from "./activity/workspaceActivityService.js";
7
+ import { MachineStatusService } from "./status/machineStatusService.js";
8
+ import { registerMachineStatusRoutes } from "./status/machineStatusRoutes.js";
9
+ import { CachedWorkspaceAttribution } from "./status/workspaceAttribution.js";
10
+ import { SessionEventHub } from "./realtime/sessionEventHub.js";
11
+ import { drainActiveWork, resolveDrainTimeoutMs } from "./sessions/shutdownDrain.js";
12
+ import { recordInterruptedRuns, takeInterruptedRuns } from "./sessions/interruptedRunStore.js";
13
+ import { AuthService } from "./sessions/authService.js";
14
+ import { bootstrapAndFreezeGlobalExtensionProviders } from "./sessions/globalProviderPolicy.js";
15
+ import { registerAuthRoutes } from "./sessions/authRoutes.js";
16
+ import { ModelCatalogRefresher } from "./sessions/modelCatalogRefresher.js";
17
+ import { PiSessionService } from "./sessions/piSessionService.js";
18
+ import { createPiSessionManagerGateway } from "./sessions/piSessionManagerGateway.js";
19
+ import { registerSessionRoutes } from "./sessions/sessionRoutes.js";
20
+ import { SessionNotificationStore } from "./sessions/sessionNotificationStore.js";
21
+ import { SessionArchiveStore, defaultSessionArchiveFilePath } from "./sessions/sessionArchiveStore.js";
22
+ import { FileSessionUnreadPersistence, SessionUnreadStore, defaultSessionUnreadFilePath } from "./sessions/sessionUnreadStore.js";
23
+ import { ProjectScopedSpawnTargetResolver } from "./sessions/spawnTargetResolver.js";
24
+ import { ProjectService } from "./projects/projectService.js";
25
+ import { ProjectStore, projectStorePath } from "./storage/projectStore.js";
26
+ import { eligibleWorkspaceProviderContributions, WorkspaceProviderRegistry, } from "./workspaces/workspaceProviderRegistry.js";
27
+ import { sessiondSocketPath } from "../sessiond/config.js";
28
+ import { TerminalService } from "./terminals/terminalService.js";
29
+ import { registerTerminalRoutes } from "./terminals/terminalRoutes.js";
30
+ import { getPiWebRuntimeComponent } from "./piWebStatus.js";
31
+ import { SESSIOND_RUNTIME_CAPABILITIES } from "../shared/capabilities.js";
32
+ import { agentSessionDirEnvOverride, effectivePiWebConfig, maxUploadBytes, offlineModeEnabled, PI_CODING_AGENT_DIR_ENV, PI_CODING_AGENT_SESSION_DIR_ENV } from "../config.js";
33
+ import { createActiveAgentProfileDescriptor } from "../sessiond/activeAgentProfile.js";
34
+ import { loadServerPluginRecoveryConfig } from "../serverPluginRecovery.js";
35
+ import { PiWebPluginCatalog } from "./piWebPluginCatalog.js";
36
+ import { applyAgentHttpIdleTimeout } from "./sessiond/agentHttpDispatcher.js";
37
+ import { scrubNonAgentVisibleEnvKeys } from "./sessiond/agentProcessEnvironment.js";
38
+ import { claimSessiondStateOwnership } from "./sessiond/sessiondStateOwnership.js";
39
+ import { dockerEnvironmentPromptSections } from "./sessions/dockerEnvironmentFacts.js";
40
+ import { PI_WEB_SESSION_ENV, sessionEnvironmentPromptSections } from "./sessions/sessionEnvironmentFacts.js";
41
+ import { createServerPluginExecFile } from "./plugins/serverPluginExec.js";
42
+ import { createServerPluginRuntime } from "./plugins/serverPluginRuntime.js";
43
+ import { runSessionDaemonShutdown } from "./sessiond/sessionDaemonShutdown.js";
44
+ import { sessionServiceDependencies } from "./sessiond/sessionServiceDependencies.js";
45
+ import { registerWorkspaceCatalogRoutes } from "./sessiond/workspaceCatalogRoutes.js";
46
+ import { registerPluginBackendRoutes } from "./sessiond/pluginBackendRoutes.js";
47
+ import { registerWorkspaceRemovalRoutes } from "./sessiond/workspaceRemovalRoutes.js";
48
+ import { createWorkspaceProviderRuntimeSnapshot } from "./workspaces/workspaceCatalog.js";
49
+ import { WorkspaceRemovalService } from "./workspaces/workspaceRemovalService.js";
50
+ const daemonEnvironment = Object.freeze({ ...process.env });
51
+ const serverPluginRecovery = loadServerPluginRecoveryConfig({ env: daemonEnvironment });
52
+ const { config, deprecatedAgentInputs } = effectivePiWebConfig({ env: daemonEnvironment });
53
+ const activeAgentProfile = createActiveAgentProfileDescriptor(config.agent);
54
+ // Normalize the resolved agent state locations into the canonical pi SDK env
55
+ // vars before anything agent-visible can spawn: the embedded SDK's own
56
+ // resolution (getAgentDir(), its session-dir override), terminals, the bash
57
+ // tool, and subsessions then all observe the same values by inheritance. The
58
+ // exported canonical values are fully resolved, so agent processes that also
59
+ // inherit the deprecated PI_WEB_AGENT_* aliases still resolve to the same
60
+ // locations.
61
+ process.env[PI_CODING_AGENT_DIR_ENV] = activeAgentProfile.dir;
62
+ const agentSessionDirOverride = agentSessionDirEnvOverride(daemonEnvironment);
63
+ if (agentSessionDirOverride !== undefined) {
64
+ process.env[PI_CODING_AGENT_SESSION_DIR_ENV] = agentSessionDirOverride;
65
+ }
66
+ // Deliberately agent-visible nesting marker: every process spawned from a
67
+ // session can tell it runs inside this pi-web instance. The session
68
+ // environment facts below explain the precautions that follow from it.
69
+ process.env[PI_WEB_SESSION_ENV] = "1";
70
+ const app = Fastify({ logger: true, bodyLimit: maxUploadBytes(daemonEnvironment, config) });
71
+ if (deprecatedAgentInputs.length > 0) {
72
+ app.log.warn({ deprecatedAgentInputs }, "deprecated agent configuration inputs detected; support will be removed in a future release");
73
+ }
74
+ if (serverPluginRecovery.safeStartDiagnostic !== undefined) {
75
+ app.log.error({ component: "server-plugins", configPath: serverPluginRecovery.path }, serverPluginRecovery.safeStartDiagnostic);
76
+ }
77
+ await app.register(fastifyWebsocket);
78
+ let serverQuiescing = false;
79
+ app.addHook("onRequest", (_request, reply, done) => {
80
+ if (!serverQuiescing) {
81
+ done();
82
+ return;
83
+ }
84
+ void reply.code(503).send({ error: "Session daemon is shutting down" });
85
+ });
86
+ const serverPluginCatalog = new PiWebPluginCatalog({
87
+ cwd: process.cwd(),
88
+ agentDir: activeAgentProfile.dir,
89
+ configProvider: () => config,
90
+ warningSink: (message) => { app.log.warn({ component: "server-plugins" }, message); },
91
+ });
92
+ let runtimeShutdown;
93
+ let pendingShutdownSignal;
94
+ let shutdownStarted = false;
95
+ async function requestShutdown(signal) {
96
+ if (shutdownStarted)
97
+ return;
98
+ if (runtimeShutdown === undefined) {
99
+ pendingShutdownSignal = signal;
100
+ return;
101
+ }
102
+ shutdownStarted = true;
103
+ app.log.info({ signal }, "shutting down session daemon");
104
+ await runtimeShutdown();
105
+ }
106
+ process.once("SIGINT", (signal) => { void requestShutdown(signal); });
107
+ process.once("SIGTERM", (signal) => { void requestShutdown(signal); });
108
+ // Agent-executed processes (bash tool, terminals, subsessions) are spawned from
109
+ // this process and inherit its environment. The scrub removes only the keys
110
+ // that silently distort the tools agents run; the daemon's PI_WEB_* wiring
111
+ // stays visible on purpose, because a nested instance resolving the same state
112
+ // now fails loudly through the ownership claim below instead of corrupting it
113
+ // silently. The daemon keeps using the captured daemonEnvironment above; its
114
+ // runtime stores resolve their paths from it explicitly below.
115
+ const scrubbedEnvKeys = scrubNonAgentVisibleEnvKeys(process.env);
116
+ app.log.info({ scrubbedEnvKeys }, "daemon-only environment keys hidden from agent processes");
117
+ // Claim ownership of the instance's durable state before any runtime store can
118
+ // touch it: a second daemon resolving the same data directory finds a live
119
+ // owner here and fails with an actionable error. Service and tsx-watch
120
+ // restarts briefly overlap the outgoing daemon, so the claim waits out a short
121
+ // grace for it to release first. The web/API process of this instance shares
122
+ // the data directory but never claims it.
123
+ const stateOwnership = await claimSessiondStateOwnership({ env: daemonEnvironment, logger: app.log });
124
+ const runtime = await createSessionDaemonRuntime();
125
+ try {
126
+ registerSessionDaemonRoutes(runtime);
127
+ await listenSessionDaemon(runtime);
128
+ }
129
+ catch (error) {
130
+ try {
131
+ await runtime.shutdown();
132
+ }
133
+ catch (disposeError) {
134
+ app.log.error({ err: disposeError }, "session daemon startup failed and runtime disposal was incomplete");
135
+ }
136
+ throw error;
137
+ }
138
+ async function createSessionDaemonRuntime() {
139
+ // Apply the active agent profile's httpIdleTimeoutMs before any other
140
+ // startup work so even catalog-refresh fetches run under the configured
141
+ // HTTP idle timeouts (issue #113).
142
+ const appliedHttpIdleTimeout = applyAgentHttpIdleTimeout({ agentDir: activeAgentProfile.dir, cwd: process.cwd() });
143
+ if (appliedHttpIdleTimeout.warning !== undefined) {
144
+ app.log.warn({ httpIdleTimeoutMs: appliedHttpIdleTimeout.timeoutMs }, appliedHttpIdleTimeout.warning);
145
+ }
146
+ else {
147
+ app.log.info({ httpIdleTimeoutMs: appliedHttpIdleTimeout.timeoutMs }, "applied agent profile HTTP idle timeout to the session daemon HTTP stack");
148
+ }
149
+ const serverPlugins = await createServerPluginRuntime({
150
+ catalog: serverPluginCatalog,
151
+ ...(serverPluginRecovery.safeStart === undefined ? {} : { safeStart: serverPluginRecovery.safeStart }),
152
+ logger: app.log,
153
+ execFile: createServerPluginExecFile({ env: daemonEnvironment }),
154
+ });
155
+ try {
156
+ const eventHub = new SessionEventHub();
157
+ const notificationStore = new SessionNotificationStore();
158
+ const unreadStore = new SessionUnreadStore({
159
+ persistence: new FileSessionUnreadPersistence(defaultSessionUnreadFilePath(daemonEnvironment)),
160
+ onPersistenceError(operation, error) {
161
+ app.log.error({ err: error, operation }, "session unread persistence failed");
162
+ },
163
+ });
164
+ await unreadStore.load();
165
+ // Activity and status are mutually dependent by design: the record notifies
166
+ // the projection, the projection reads the record. The notification runs
167
+ // long after both are constructed.
168
+ const workspaceActivity = new WorkspaceActivityService(() => { machineStatus.notifyChanged(); });
169
+ const auth = await AuthService.create({ agentDir: activeAgentProfile.dir, logger: app.log });
170
+ // Capture providers registered by global extensions while the runtime is
171
+ // still mutable, then freeze every later extension-provider mutation before
172
+ // any real session can load project resources.
173
+ await bootstrapAndFreezeGlobalExtensionProviders(auth.runtime, activeAgentProfile.dir, app.log);
174
+ // The shared model runtime is constructed offline so request paths never
175
+ // wait on provider-catalog fetches; this is the single bounded network
176
+ // refresher, and auth changes (login/logout) ask it for a prompt run. It
177
+ // stays fully inert when the operator asked for offline behavior.
178
+ const catalogRefresher = new ModelCatalogRefresher({
179
+ runtime: auth.runtime,
180
+ logger: app.log,
181
+ offline: offlineModeEnabled(daemonEnvironment),
182
+ });
183
+ catalogRefresher.start();
184
+ auth.subscribe(() => { catalogRefresher.requestRefresh(); });
185
+ const projects = new ProjectService(new ProjectStore(projectStorePath(daemonEnvironment)));
186
+ const providerHealth = await serverPlugins.inspectHealth();
187
+ const workspaceProviders = new WorkspaceProviderRegistry({
188
+ contributions: eligibleWorkspaceProviderContributions(serverPlugins.providerContributions(), providerHealth),
189
+ logger: app.log,
190
+ });
191
+ const workspaceProviderRuntime = createWorkspaceProviderRuntimeSnapshot(serverPlugins.healthRecords(), providerHealth, serverPlugins.safeStartLevel(), serverPlugins.catalogDiagnostics());
192
+ const statusAttribution = new CachedWorkspaceAttribution({
193
+ projects,
194
+ workspaces: workspaceProviders,
195
+ logger: app.log,
196
+ });
197
+ const machineStatus = new MachineStatusService({
198
+ activity: workspaceActivity,
199
+ unread: unreadStore,
200
+ attribution: statusAttribution,
201
+ publisher: { publish: (snapshot) => { eventHub.publishRealtime({ type: "machine.status", status: snapshot }); } },
202
+ logger: app.log,
203
+ });
204
+ // Every global subscriber is handed the current projection on connect, so a
205
+ // browser never has to reconcile a snapshot fetch against live frames.
206
+ eventHub.setGlobalJoinFrame(() => ({ type: "machine.status", status: machineStatus.snapshot() }));
207
+ // Unread state was loaded from disk above, so the projection is computed
208
+ // once at startup instead of waiting for the first change. It is not
209
+ // awaited: resolving it lists workspaces through provider plugins, and
210
+ // daemon startup must not depend on how long that takes.
211
+ machineStatus.notifyChanged();
212
+ const projectWorkspaceDeps = { projects, workspaces: workspaceProviders };
213
+ const spawnTargets = config.spawnSessions ? new ProjectScopedSpawnTargetResolver(projectWorkspaceDeps) : undefined;
214
+ const sessions = new PiSessionService(eventHub, sessionServiceDependencies({
215
+ modelRuntime: auth.runtime,
216
+ agentDir: activeAgentProfile.dir,
217
+ archiveStore: new SessionArchiveStore(defaultSessionArchiveFilePath(daemonEnvironment)),
218
+ workspaceActivity,
219
+ logger: app.log,
220
+ ...(spawnTargets === undefined ? {} : { spawnTargets }),
221
+ subsessionsEnabled: config.subsessions,
222
+ askUserEnabled: config.askUser,
223
+ appendSystemPromptSections: [
224
+ // Sessions always run nested in this daemon, so they always get the
225
+ // session environment facts; Docker deployments add their container
226
+ // facts on top. Resolved once here, from the captured daemon
227
+ // environment, because the deployment cannot change while the daemon
228
+ // runs.
229
+ ...sessionEnvironmentPromptSections({
230
+ env: daemonEnvironment,
231
+ enabled: config.environmentFacts,
232
+ }),
233
+ ...dockerEnvironmentPromptSections({
234
+ env: daemonEnvironment,
235
+ enabled: config.environmentFacts,
236
+ logger: app.log,
237
+ }),
238
+ ],
239
+ extensionDialogsTimeoutMs: config.extensionDialogsTimeoutMs,
240
+ notificationStore,
241
+ unreadStore,
242
+ onUnreadChanged: () => { machineStatus.notifyChanged(); },
243
+ catalogRefreshStatus: catalogRefresher,
244
+ sessionManager: createPiSessionManagerGateway({
245
+ agentDir: activeAgentProfile.dir,
246
+ env: daemonEnvironment,
247
+ }),
248
+ }));
249
+ auth.subscribe((change) => { sessions.applyAuthChange(change); });
250
+ const terminals = new TerminalService(eventHub, workspaceActivity);
251
+ const workspaceRemovals = new WorkspaceRemovalService(workspaceProviders, terminals);
252
+ const runtimeComponent = Object.freeze({
253
+ // The deprecated-input report is fixed at startup: it was detected from
254
+ // the captured pre-scrub daemon environment and the config snapshot this
255
+ // daemon actually honors, so it stays accurate for this daemon lifetime
256
+ // and clears only when the inputs are removed and the daemon restarts.
257
+ ...getPiWebRuntimeComponent("sessiond", SESSIOND_RUNTIME_CAPABILITIES, deprecatedAgentInputs),
258
+ activeAgentProfile,
259
+ });
260
+ let disposed = false;
261
+ const shutdown = async () => {
262
+ if (disposed)
263
+ return;
264
+ disposed = true;
265
+ await runSessionDaemonShutdown({
266
+ logger: app.log,
267
+ dependencies: {
268
+ quiesceServer: () => { serverQuiescing = true; },
269
+ // Give agent turns already in flight a bounded chance to finish, so
270
+ // updating or restarting does not cut work off mid-run. Disable with
271
+ // PI_WEB_SHUTDOWN_DRAIN_MS=0.
272
+ drainActiveWork: async () => {
273
+ const timeoutMs = resolveDrainTimeoutMs(daemonEnvironment);
274
+ const startedAt = Date.now();
275
+ const decision = await drainActiveWork(timeoutMs, {
276
+ activeSessionIds: () => sessions.activeWorkSessionIds(),
277
+ elapsedMs: () => Date.now() - startedAt,
278
+ wait: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
279
+ });
280
+ if (decision.reason === "deadline-reached") {
281
+ // Named, not swallowed: these are the runs the restart cut off.
282
+ app.log.warn({ activeSessionIds: decision.activeSessionIds, timeoutMs }, "shutdown drain deadline reached with work still running");
283
+ // Recorded so the next start can say which conversations were cut
284
+ // off. The drain deadline is deliberately shorter than systemd's
285
+ // TimeoutStopSec, so there is still time to write this before the
286
+ // process is killed outright.
287
+ const interrupted = new Set(decision.activeSessionIds);
288
+ await recordInterruptedRuns(sessions
289
+ .activeWorkSessions()
290
+ .filter(({ sessionId }) => interrupted.has(sessionId))
291
+ .map(({ sessionId, cwd }) => ({ sessionId, cwd, interruptedAt: new Date().toISOString() })));
292
+ }
293
+ else if (decision.reason === "waiting-for-active-work" || decision.reason === "no-active-work") {
294
+ app.log.info({ waitedMs: Date.now() - startedAt }, "shutdown drain finished");
295
+ }
296
+ },
297
+ serverPlugins,
298
+ terminals,
299
+ catalogRefresher,
300
+ auth,
301
+ sessions,
302
+ unreadStore,
303
+ closeServer: () => app.close(),
304
+ },
305
+ onFailure: () => { process.exitCode = 1; },
306
+ });
307
+ // Release last: the daemon owns the instance state until everything that
308
+ // writes it is down. Best-effort; a leftover marker goes stale and the
309
+ // next start discards it.
310
+ await stateOwnership.release();
311
+ };
312
+ return { eventHub, machineStatus, statusAttribution, auth, sessions, terminals, unreadStore, activeAgentProfile, runtimeComponent, catalogRefresher, serverPlugins, projects, workspaceProviders, workspaceProviderRuntime, workspaceRemovals, shutdown };
313
+ }
314
+ catch (error) {
315
+ try {
316
+ await serverPlugins.stop();
317
+ }
318
+ catch (disposeError) {
319
+ app.log.error({ err: disposeError }, "session daemon construction failed and server plugin disposal was incomplete");
320
+ }
321
+ throw error;
322
+ }
323
+ }
324
+ function registerSessionDaemonRoutes({ eventHub, machineStatus, statusAttribution, auth, sessions, terminals, runtimeComponent, projects, workspaceProviders, workspaceProviderRuntime, workspaceRemovals }) {
325
+ registerMachineStatusRoutes(app, machineStatus);
326
+ registerAuthRoutes(app, auth);
327
+ registerSessionRoutes(app, sessions, eventHub);
328
+ registerTerminalRoutes(app, terminals);
329
+ registerWorkspaceCatalogRoutes(app, {
330
+ projects,
331
+ workspaces: workspaceProviders,
332
+ providerRuntime: workspaceProviderRuntime,
333
+ });
334
+ registerPluginBackendRoutes(app, {
335
+ projects,
336
+ backends: workspaceProviders,
337
+ onWorkspacesMutated: () => { statusAttribution.invalidate(); },
338
+ });
339
+ registerWorkspaceRemovalRoutes(app, {
340
+ projects,
341
+ removals: workspaceRemovals,
342
+ onWorkspacesMutated: () => { statusAttribution.invalidate(); },
343
+ });
344
+ app.get("/health", () => ({
345
+ ok: true,
346
+ activeSessions: sessions.activeCount(),
347
+ checkedAt: new Date().toISOString(),
348
+ version: {
349
+ component: runtimeComponent.component,
350
+ label: runtimeComponent.label,
351
+ ...(runtimeComponent.runtimeVersion === undefined ? {} : { runtimeVersion: runtimeComponent.runtimeVersion }),
352
+ ...(runtimeComponent.piVersion === undefined ? {} : { piVersion: runtimeComponent.piVersion }),
353
+ stale: false,
354
+ available: runtimeComponent.available,
355
+ },
356
+ }));
357
+ app.get("/runtime", () => runtimeComponent);
358
+ }
359
+ async function listenSessionDaemon({ shutdown }) {
360
+ runtimeShutdown = shutdown;
361
+ if (pendingShutdownSignal !== undefined) {
362
+ await requestShutdown(pendingShutdownSignal);
363
+ return;
364
+ }
365
+ // Anything still marked in flight belongs to the previous process, which is
366
+ // gone -- so it did not finish. Promoted into the record the API serves, and
367
+ // cleared, so a restart cannot report the same interruption forever.
368
+ const leftOverRuns = await takeInterruptedRuns();
369
+ if (leftOverRuns.length > 0) {
370
+ app.log.warn({ sessionIds: leftOverRuns.map((run) => run.sessionId) }, "runs were in flight when the previous session daemon exited");
371
+ await recordInterruptedRuns(leftOverRuns);
372
+ }
373
+ const portValue = daemonEnvironment["PI_WEB_SESSIOND_PORT"];
374
+ const port = portValue !== undefined && portValue !== "" ? Number(portValue) : undefined;
375
+ const host = daemonEnvironment["PI_WEB_SESSIOND_HOST"] ?? "127.0.0.1";
376
+ if (port !== undefined) {
377
+ await app.listen({ port, host });
378
+ }
379
+ else {
380
+ const path = sessiondSocketPath(daemonEnvironment);
381
+ await mkdir(dirname(path), { recursive: true });
382
+ await rm(path, { force: true });
383
+ await app.listen({ path });
384
+ process.on("exit", () => void rm(path, { force: true }));
385
+ }
386
+ }
387
+ //# sourceMappingURL=sessiond.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessiond.js","sourceRoot":"","sources":["../../src/server/sessiond.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import { Type } from "typebox";
2
+ import { defineTool } from "@earendil-works/pi-coding-agent";
3
+ import { ASK_USER_ID_MAX_LENGTH, ASK_USER_OPTION_LIMIT, ASK_USER_QUESTION_LIMIT, ASK_USER_TEXT_MAX_LENGTH, } from "../../shared/apiTypes.js";
4
+ import { renderSupersededAskText } from "./pendingAskStore.js";
5
+ const AskUserOptionParams = Type.Object({
6
+ value: Type.String({
7
+ maxLength: ASK_USER_ID_MAX_LENGTH,
8
+ description: "Stable machine value reported back to you when the user picks this option.",
9
+ }),
10
+ label: Type.String({
11
+ maxLength: ASK_USER_TEXT_MAX_LENGTH,
12
+ description: "Short label the user reads, ideally a few words.",
13
+ }),
14
+ detail: Type.Optional(Type.String({
15
+ maxLength: ASK_USER_TEXT_MAX_LENGTH,
16
+ description: "Optional clarification shown under the label.",
17
+ })),
18
+ });
19
+ const AskUserQuestionParams = Type.Object({
20
+ id: Type.String({
21
+ maxLength: ASK_USER_ID_MAX_LENGTH,
22
+ description: "Unique within this call; used as the answer key reported back to you.",
23
+ }),
24
+ question: Type.String({
25
+ maxLength: ASK_USER_TEXT_MAX_LENGTH,
26
+ description: "The question itself, as one plain-text line.",
27
+ }),
28
+ detail: Type.Optional(Type.String({
29
+ maxLength: ASK_USER_TEXT_MAX_LENGTH,
30
+ description: "Optional supporting context shown under the question.",
31
+ })),
32
+ options: Type.Optional(Type.Array(AskUserOptionParams, {
33
+ maxItems: ASK_USER_OPTION_LIMIT,
34
+ description: "Options to choose from. Omit when free text is the whole answer; the browser always adds a Custom choice.",
35
+ })),
36
+ multiple: Type.Optional(Type.Boolean({
37
+ description: "Allow several options at once. Default: one answer per question.",
38
+ })),
39
+ });
40
+ const AskUserParams = Type.Object({
41
+ questions: Type.Array(AskUserQuestionParams, {
42
+ minItems: 1,
43
+ maxItems: ASK_USER_QUESTION_LIMIT,
44
+ description: "The questions to post, in the order the user should read them. Every question may be left unanswered.",
45
+ }),
46
+ });
47
+ /** Shapes one schema question into the domain question; the store owns validation. */
48
+ function toQuestion(param) {
49
+ const { detail, options, multiple } = param;
50
+ return {
51
+ id: param.id,
52
+ question: param.question,
53
+ ...(detail === undefined ? {} : { detail }),
54
+ options: (options ?? []).map(toOption),
55
+ ...(multiple === undefined ? {} : { multiple }),
56
+ };
57
+ }
58
+ function toOption(param) {
59
+ const { detail } = param;
60
+ return { value: param.value, label: param.label, ...(detail === undefined ? {} : { detail }) };
61
+ }
62
+ function postedText(result) {
63
+ const count = result.ask.questions.length;
64
+ const posted = `Posted ${count.toString()} question${count === 1 ? "" : "s"} to the user as ask ${result.ask.askId}. Ending this run; the answers arrive as a follow-up message that wakes you, naming every question the user left unanswered. Do not repost these questions.`;
65
+ return result.superseded === undefined ? posted : `${posted}\n\n${renderSupersededAskText(result.superseded)}`;
66
+ }
67
+ /**
68
+ * Custom tool that posts a question set to the user's browser as interactive UI.
69
+ *
70
+ * It deliberately does **not** await the user. Awaiting would pin the agent run
71
+ * for an unbounded human-scale wait, keep the session streaming, and leave a
72
+ * dangling tool call if the runtime were replaced meanwhile. Instead the ask
73
+ * becomes daemon-owned state, the tool terminates the run, and the submitted
74
+ * answers return later as a follow-up message that wakes the session.
75
+ *
76
+ * Rejected question sets throw: the agent loop turns the thrown message into an
77
+ * error tool result, so the model can fix the ask and post it again.
78
+ */
79
+ export function createAskUserToolDefinition(deps) {
80
+ return defineTool({
81
+ name: "ask_user",
82
+ label: "Ask user",
83
+ description: "Post a set of questions to the user as a browser form and end this run. Answers arrive later as a follow-up message; the user may leave any question unanswered.",
84
+ promptSnippet: "ask_user: post a question set to the user; ends the run, answers return as a follow-up",
85
+ promptGuidelines: [
86
+ "When you need decisions from the user, post them together with ask_user instead of asking in prose one at a time. It ends the run and the answers, including the questions the user left unanswered, come back as a follow-up message that wakes you. Call it alone and last, and do not repost the same questions or poll for answers.",
87
+ ],
88
+ parameters: AskUserParams,
89
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
90
+ const result = await deps.open({
91
+ sessionId: ctx.sessionManager.getSessionId(),
92
+ questions: params.questions.map(toQuestion),
93
+ });
94
+ return {
95
+ content: [{ type: "text", text: postedText(result) }],
96
+ details: result,
97
+ terminate: true,
98
+ };
99
+ },
100
+ });
101
+ }
102
+ //# sourceMappingURL=askUserTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"askUserTool.js","sourceRoot":"","sources":["../../../src/server/sessions/askUserTool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import { mkdir, realpath, writeFile } from "node:fs/promises";
2
+ import { basename, extname, join } from "node:path";
3
+ import { formatDimensionNote, resizeImage } from "@earendil-works/pi-coding-agent";
4
+ import { extensionForImageMimeType } from "../../shared/promptAttachments.js";
5
+ import { ensureInside, isNodeErrorWithCode, resolveParentInsideWorkspace } from "../workspaces/pathSafety.js";
6
+ /**
7
+ * Default workspace-relative folder used when saving pasted/dropped
8
+ * attachments for the agent to read with its own tools.
9
+ */
10
+ export const DEFAULT_ATTACHMENT_FOLDER = ".pi-web/attachments";
11
+ /**
12
+ * Convert validated attachments into pi-compatible inline image content.
13
+ *
14
+ * Mirrors pi's own CLI/TUI behaviour: each image is run through pi's
15
+ * `resizeImage` so it fits within pi's max dimensions and inline byte budget
16
+ * (2000x2000, ~4.5MB base64). Images that cannot be resized below the limit
17
+ * are dropped, matching pi's `[Image omitted]` behaviour.
18
+ */
19
+ export async function attachmentsToInlineImages(attachments) {
20
+ const results = [];
21
+ for (const attachment of attachments) {
22
+ const bytes = Buffer.from(attachment.data, "base64");
23
+ const resized = await resizeImage(bytes, attachment.mimeType);
24
+ if (resized === null)
25
+ continue;
26
+ const note = formatDimensionNote(resized);
27
+ results.push({
28
+ image: { type: "image", data: resized.data, mimeType: resized.mimeType },
29
+ ...(note === undefined ? {} : { dimensionNote: note }),
30
+ });
31
+ }
32
+ return results;
33
+ }
34
+ /**
35
+ * Write attachments into a workspace folder and return their relative paths.
36
+ * Filenames are collision-safe and stay inside the workspace root.
37
+ */
38
+ export async function saveAttachmentsToWorkspace(cwd, attachments, options = {}) {
39
+ const folder = options.folder ?? DEFAULT_ATTACHMENT_FOLDER;
40
+ const now = options.now ?? (() => new Date());
41
+ const { root, target: requestedFolderTarget, relativePath: normalizedFolder } = await resolveParentInsideWorkspace(cwd, folder);
42
+ await mkdir(requestedFolderTarget, { recursive: true });
43
+ const folderTarget = await realpath(requestedFolderTarget);
44
+ ensureInside(root, folderTarget);
45
+ const stamp = timestamp(now());
46
+ const saved = [];
47
+ for (const [index, attachment] of attachments.entries()) {
48
+ const bytes = Buffer.from(attachment.data, "base64");
49
+ const filename = await writeUniqueAttachmentFile(folderTarget, attachmentFilename(attachment, stamp, index), bytes);
50
+ const relativePath = normalizedFolder === "" ? filename : `${normalizedFolder}/${filename}`;
51
+ saved.push({ path: relativePath, mimeType: attachment.mimeType, size: bytes.byteLength });
52
+ }
53
+ return saved;
54
+ }
55
+ async function writeUniqueAttachmentFile(folderTarget, filename, bytes) {
56
+ for (let attempt = 0; attempt < 100; attempt += 1) {
57
+ const candidate = attempt === 0 ? filename : addCollisionSuffix(filename, attempt + 1);
58
+ try {
59
+ await writeFile(join(folderTarget, candidate), bytes, { flag: "wx" });
60
+ return candidate;
61
+ }
62
+ catch (error) {
63
+ if (!isNodeErrorWithCode(error, "EEXIST"))
64
+ throw error;
65
+ }
66
+ }
67
+ throw new Error("Unable to choose a unique attachment filename");
68
+ }
69
+ function addCollisionSuffix(filename, suffix) {
70
+ const extension = extname(filename);
71
+ const stem = filename.slice(0, filename.length - extension.length);
72
+ return `${stem}-${String(suffix)}${extension}`;
73
+ }
74
+ function attachmentFilename(attachment, stamp, index) {
75
+ const originalName = sanitizeOriginalFilename(attachment.name) ?? fallbackAttachmentFilename(attachment);
76
+ return `attachment-${stamp}-${String(index + 1)}-${originalName}`;
77
+ }
78
+ function fallbackAttachmentFilename(attachment) {
79
+ if (attachment.kind === "image")
80
+ return `image.${extensionForImageMimeType(attachment.mimeType)}`;
81
+ return "file.bin";
82
+ }
83
+ const MAX_ORIGINAL_FILENAME_LENGTH = 96;
84
+ function sanitizeOriginalFilename(name) {
85
+ const trimmed = name?.trim();
86
+ if (trimmed === undefined || trimmed === "")
87
+ return undefined;
88
+ const leaf = basename(trimmed.replace(/\\/g, "/"));
89
+ const sanitized = stripControlCharacters(leaf)
90
+ .normalize("NFKC")
91
+ .replace(/[^A-Za-z0-9._-]+/g, "-")
92
+ .replace(/-+/g, "-")
93
+ .replace(/-+\./g, ".")
94
+ .replace(/^\.+/, "")
95
+ .replace(/[.-]+$/, "");
96
+ if (sanitized === "")
97
+ return undefined;
98
+ return truncateFilename(sanitized, MAX_ORIGINAL_FILENAME_LENGTH);
99
+ }
100
+ function stripControlCharacters(value) {
101
+ return Array.from(value).filter((character) => {
102
+ const codePoint = character.codePointAt(0);
103
+ return codePoint !== undefined && codePoint > 0x1f && codePoint !== 0x7f;
104
+ }).join("");
105
+ }
106
+ function truncateFilename(filename, maxLength) {
107
+ if (filename.length <= maxLength)
108
+ return filename;
109
+ const extension = extname(filename);
110
+ if (extension.length >= maxLength)
111
+ return filename.slice(0, maxLength);
112
+ const stem = filename.slice(0, filename.length - extension.length);
113
+ return `${stem.slice(0, maxLength - extension.length)}${extension}`;
114
+ }
115
+ function timestamp(date) {
116
+ const pad = (value, length = 2) => String(value).padStart(length, "0");
117
+ return `${String(date.getFullYear())}${pad(date.getMonth() + 1)}${pad(date.getDate())}-${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}-${pad(date.getMilliseconds(), 3)}`;
118
+ }
119
+ //# sourceMappingURL=attachmentService.js.map