@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,609 @@
1
+ // Generated from pi-web-plugins/git/browser/git-panel.ts. Do not edit directly.
2
+ import { GIT_DIFF_OPERATION, GIT_STATUS_OPERATION, parseGitDiffResponse, parseGitStatusResponse, } from "./git-contract.js";
3
+ import { buildGitFileList } from "./gitFileList.js";
4
+ import { buildGitFileTree, collectGitFileTreeDirectoryPaths } from "./gitFileTree.js";
5
+ import { readGitFileView, writeGitFileView } from "./gitFileViewPreference.js";
6
+ import { createGitDiffRoute } from "./gitRoute.js";
7
+ import { parseUnifiedDiff } from "./unifiedDiff.js";
8
+ const GIT_PANEL_LOCAL_ID = "workspace.git";
9
+ const GIT_POLL_INTERVAL_MS = 8_000;
10
+ // Keep navigation state for a few recent workspaces; heavy diff views are
11
+ // released as soon as another machine/workspace becomes active.
12
+ const GIT_WORKSPACE_STATE_LIMIT = 8;
13
+ const activityElementTag = "pi-web-git-panel-activity";
14
+ const EMPTY_LIST_MODEL = { submodules: [], files: [] };
15
+ const EMPTY_VIEW_STATE = { nodes: [], listModel: EMPTY_LIST_MODEL, expandablePaths: [] };
16
+ export function createGitBrowserContributions(sourcePluginId, runtimePluginId, html, svg) {
17
+ const panelId = `${runtimePluginId}:${GIT_PANEL_LOCAL_ID}`;
18
+ const controller = new GitUiController(sourcePluginId, createGitDiffRoute(panelId));
19
+ defineGitPanelActivityElement();
20
+ return {
21
+ actions: createGitActions(panelId, controller),
22
+ workspacePanels: [createGitPanel(html, svg, controller)],
23
+ };
24
+ }
25
+ class GitUiController {
26
+ sourcePluginId;
27
+ route;
28
+ states = new Map();
29
+ activeWorkspaceKey;
30
+ connectedWorkspaceKey;
31
+ routeNavigationPending = true;
32
+ view = readGitFileView();
33
+ constructor(sourcePluginId, route) {
34
+ this.sourcePluginId = sourcePluginId;
35
+ this.route = route;
36
+ }
37
+ isOwnedWorkspace(workspace) {
38
+ return workspace?.provider?.pluginId === this.sourcePluginId;
39
+ }
40
+ state(context) {
41
+ return this.stateFor(context);
42
+ }
43
+ connect(context) {
44
+ const key = workspaceContextKey(context);
45
+ const changedWorkspace = this.activeWorkspaceKey !== key;
46
+ if (changedWorkspace)
47
+ this.releaseInactiveDiff();
48
+ const state = this.stateFor(context);
49
+ this.activeWorkspaceKey = key;
50
+ this.connectedWorkspaceKey = key;
51
+ this.synchronizeRoute(state, changedWorkspace);
52
+ if (state.status === undefined && state.statusRequest === undefined)
53
+ void this.refresh(context);
54
+ else if (state.selectedDiffPath !== undefined && (state.selectedDiff === undefined || state.selectedStagedDiff === undefined) && !state.diffLoading) {
55
+ if (state.status?.files.some((file) => file.path === state.selectedDiffPath) === true)
56
+ void this.refreshDiff(state, state.selectedDiffPath, context);
57
+ else
58
+ this.clearSelection(state, true);
59
+ }
60
+ }
61
+ disconnect(context) {
62
+ if (this.connectedWorkspaceKey === workspaceContextKey(context))
63
+ this.connectedWorkspaceKey = undefined;
64
+ }
65
+ handlePopState(context) {
66
+ this.routeNavigationPending = true;
67
+ if (!this.route.matches(context))
68
+ return;
69
+ this.connect(context);
70
+ this.requestRender(this.stateFor(context));
71
+ }
72
+ poll(context) {
73
+ void this.refresh(context);
74
+ }
75
+ invalidate(context) {
76
+ if (!this.isOwnedWorkspace(context.workspace))
77
+ return Promise.resolve();
78
+ const state = this.stateFor(context);
79
+ state.stale = state.status !== undefined;
80
+ this.requestRender(state);
81
+ return this.refresh(context);
82
+ }
83
+ refresh(context) {
84
+ const state = this.stateFor(context);
85
+ if (state.statusRequest !== undefined)
86
+ return state.statusRequest;
87
+ state.statusLoading = true;
88
+ this.requestRender(state);
89
+ const request = requestGitBackend(context, GIT_STATUS_OPERATION, null)
90
+ .then(parseGitStatusResponse)
91
+ .then(async (status) => {
92
+ if (!state.retained)
93
+ return;
94
+ state.status = state.status?.hash === status.hash ? state.status : status;
95
+ state.stale = false;
96
+ state.error = undefined;
97
+ const path = state.selectedDiffPath;
98
+ if (path === undefined)
99
+ return;
100
+ if (!status.files.some((file) => file.path === path))
101
+ this.clearSelection(state, true);
102
+ else if (this.connectedWorkspaceKey === workspaceContextKey(context))
103
+ await this.refreshDiff(state, path, context);
104
+ })
105
+ .catch((error) => {
106
+ if (state.retained)
107
+ state.error = errorMessage(error);
108
+ })
109
+ .finally(() => {
110
+ if (state.statusRequest !== request)
111
+ return;
112
+ state.statusRequest = undefined;
113
+ state.statusLoading = false;
114
+ this.requestRender(state);
115
+ });
116
+ state.statusRequest = request;
117
+ return request;
118
+ }
119
+ selectDiff(context, path) {
120
+ const state = this.stateFor(context);
121
+ state.selectedDiffPath = path;
122
+ state.selectedDiff = undefined;
123
+ state.selectedStagedDiff = undefined;
124
+ state.diffLoading = true;
125
+ state.error = undefined;
126
+ if (this.route.matches(context))
127
+ this.route.write(path);
128
+ this.requestRender(state);
129
+ void this.refreshDiff(state, path, context);
130
+ }
131
+ setView(context, view) {
132
+ if (this.view === view)
133
+ return;
134
+ this.view = view;
135
+ writeGitFileView(view);
136
+ for (const state of this.states.values()) {
137
+ state.expandedDirectories = new Set();
138
+ state.viewStateCache = undefined;
139
+ }
140
+ this.requestRender(this.stateFor(context));
141
+ }
142
+ currentView() {
143
+ return this.view;
144
+ }
145
+ viewState(state) {
146
+ const cached = state.viewStateCache;
147
+ if (cached !== undefined && cached.status === state.status && cached.view === this.view)
148
+ return cached.viewState;
149
+ const viewState = buildViewState(state.status, this.view);
150
+ state.viewStateCache = { status: state.status, view: this.view, viewState };
151
+ return viewState;
152
+ }
153
+ toggleDirectory(context, path) {
154
+ const state = this.stateFor(context);
155
+ const next = new Set(state.expandedDirectories);
156
+ if (next.has(path))
157
+ next.delete(path);
158
+ else
159
+ next.add(path);
160
+ state.expandedDirectories = next;
161
+ this.requestRender(state);
162
+ }
163
+ toggleExpandAll(context, paths, collapse) {
164
+ const state = this.stateFor(context);
165
+ state.expandedDirectories = collapse ? new Set() : new Set(paths);
166
+ this.requestRender(state);
167
+ }
168
+ stateFor(context) {
169
+ const key = workspaceContextKey(context);
170
+ const existing = this.states.get(key);
171
+ if (existing !== undefined) {
172
+ existing.context = context;
173
+ this.states.delete(key);
174
+ this.states.set(key, existing);
175
+ return existing;
176
+ }
177
+ this.evictOldestState();
178
+ const created = {
179
+ context,
180
+ retained: true,
181
+ routeInitialized: false,
182
+ status: undefined,
183
+ statusLoading: false,
184
+ stale: false,
185
+ selectedDiffPath: undefined,
186
+ selectedDiff: undefined,
187
+ selectedStagedDiff: undefined,
188
+ diffLoading: false,
189
+ error: undefined,
190
+ expandedDirectories: new Set(),
191
+ statusRequest: undefined,
192
+ diffRequestSequence: 0,
193
+ viewStateCache: undefined,
194
+ };
195
+ this.states.set(key, created);
196
+ return created;
197
+ }
198
+ releaseInactiveDiff() {
199
+ if (this.activeWorkspaceKey === undefined)
200
+ return;
201
+ const state = this.states.get(this.activeWorkspaceKey);
202
+ if (state === undefined)
203
+ return;
204
+ state.selectedDiff = undefined;
205
+ state.selectedStagedDiff = undefined;
206
+ state.diffLoading = false;
207
+ state.diffRequestSequence += 1;
208
+ }
209
+ evictOldestState() {
210
+ if (this.states.size < GIT_WORKSPACE_STATE_LIMIT)
211
+ return;
212
+ const key = [...this.states.keys()].find((candidate) => candidate !== this.connectedWorkspaceKey) ?? this.states.keys().next().value;
213
+ if (key === undefined)
214
+ return;
215
+ const state = this.states.get(key);
216
+ if (state !== undefined) {
217
+ state.retained = false;
218
+ state.diffRequestSequence += 1;
219
+ }
220
+ this.states.delete(key);
221
+ }
222
+ synchronizeRoute(state, changedWorkspace) {
223
+ if (!this.route.matches(state.context))
224
+ return;
225
+ const routePath = this.route.read();
226
+ if (this.routeNavigationPending || !state.routeInitialized || (!changedWorkspace && routePath !== state.selectedDiffPath)) {
227
+ this.routeNavigationPending = false;
228
+ state.routeInitialized = true;
229
+ this.applyRouteSelection(state, routePath);
230
+ this.route.write(routePath, { replace: true });
231
+ return;
232
+ }
233
+ if (changedWorkspace)
234
+ this.route.write(state.selectedDiffPath, { replace: true });
235
+ }
236
+ applyRouteSelection(state, path) {
237
+ if (state.selectedDiffPath === path)
238
+ return;
239
+ state.selectedDiffPath = path;
240
+ state.selectedDiff = undefined;
241
+ state.selectedStagedDiff = undefined;
242
+ state.diffLoading = false;
243
+ state.diffRequestSequence += 1;
244
+ }
245
+ clearSelection(state, replaceUrl) {
246
+ this.applyRouteSelection(state, undefined);
247
+ if (replaceUrl && this.connectedWorkspaceKey === workspaceContextKey(state.context) && this.route.matches(state.context)) {
248
+ this.route.write(undefined, { replace: true });
249
+ }
250
+ }
251
+ async refreshDiff(state, path, context) {
252
+ const sequence = state.diffRequestSequence + 1;
253
+ state.diffRequestSequence = sequence;
254
+ state.diffLoading = true;
255
+ this.requestRender(state);
256
+ try {
257
+ const [selectedDiff, selectedStagedDiff] = await Promise.all([
258
+ requestGitBackend(context, GIT_DIFF_OPERATION, { path }).then(parseGitDiffResponse),
259
+ requestGitBackend(context, GIT_DIFF_OPERATION, { path, staged: true }).then(parseGitDiffResponse),
260
+ ]);
261
+ if (!state.retained || state.diffRequestSequence !== sequence || state.selectedDiffPath !== path)
262
+ return;
263
+ state.selectedDiff = createDiffView(selectedDiff, state.selectedDiff);
264
+ state.selectedStagedDiff = createDiffView(selectedStagedDiff, state.selectedStagedDiff);
265
+ state.error = undefined;
266
+ }
267
+ catch (error) {
268
+ if (!state.retained || state.diffRequestSequence !== sequence || state.selectedDiffPath !== path)
269
+ return;
270
+ state.error = errorMessage(error);
271
+ }
272
+ finally {
273
+ if (state.retained && state.diffRequestSequence === sequence && state.selectedDiffPath === path) {
274
+ state.diffLoading = false;
275
+ this.requestRender(state);
276
+ }
277
+ }
278
+ }
279
+ requestRender(state) {
280
+ if (state.retained)
281
+ state.context.host.requestRender();
282
+ }
283
+ }
284
+ function createGitActions(panelId, controller) {
285
+ const hasGitWorkspace = (context) => controller.isOwnedWorkspace(context.state.selectedWorkspace);
286
+ return [
287
+ {
288
+ id: "view.git",
289
+ title: "Go to Git",
290
+ shortcut: "mod+3",
291
+ shortcutAliases: ["core:view.git"],
292
+ group: "Navigation",
293
+ enabled: hasGitWorkspace,
294
+ run: (context) => { context.selectMainView(panelId); },
295
+ },
296
+ {
297
+ id: "workspace.refresh-git",
298
+ title: "Refresh Git",
299
+ shortcut: "mod+shift+g",
300
+ shortcutAliases: ["core:workspace.refresh-git"],
301
+ group: "Workspace",
302
+ enabled: hasGitWorkspace,
303
+ run: (context) => context.refreshWorkspacePanels(panelId),
304
+ },
305
+ ];
306
+ }
307
+ function createGitPanel(html, svg, controller) {
308
+ return {
309
+ id: GIT_PANEL_LOCAL_ID,
310
+ title: "Git",
311
+ icon: svg `
312
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
313
+ <circle cx="6" cy="6" r="2"></circle>
314
+ <circle cx="18" cy="6" r="2"></circle>
315
+ <circle cx="12" cy="18" r="2"></circle>
316
+ <path d="M8 6h6"></path>
317
+ <path d="M6 8v2a6 6 0 0 0 6 6"></path>
318
+ <path d="M18 8v2a6 6 0 0 1-6 6"></path>
319
+ </svg>
320
+ `,
321
+ order: 20,
322
+ routeAliases: ["git", "core:workspace.git"],
323
+ visible: (context) => controller.isOwnedWorkspace(context.workspace),
324
+ onInvalidate: (context) => controller.invalidate(context),
325
+ render: (context) => renderGitPanel(html, controller, context),
326
+ };
327
+ }
328
+ function requestGitBackend(context, operation, input) {
329
+ if (context.backend === undefined || context.workspace.provider?.capabilities.request === false) {
330
+ return Promise.reject(new Error("Git workspace backend is unavailable. Update and restart PI WEB on this machine, then reload the browser."));
331
+ }
332
+ return context.backend.request(operation, input);
333
+ }
334
+ function renderGitPanel(html, controller, context) {
335
+ const state = controller.state(context);
336
+ const viewState = controller.viewState(state);
337
+ return html `
338
+ <section class="git-panel">
339
+ <style .textContent=${gitPanelStyles}></style>
340
+ <pi-web-git-panel-activity .controller=${controller} .context=${context}></pi-web-git-panel-activity>
341
+ <section class="git-toolbar">
342
+ <strong>Git</strong>
343
+ ${state.stale ? html `<span class="git-stale">stale</span>` : null}
344
+ <div class="git-toolbar-actions">
345
+ ${viewState.expandablePaths.length === 0 ? null : renderExpandCollapseAll(html, controller, context, state, viewState.expandablePaths)}
346
+ ${renderViewToggle(html, controller, context)}
347
+ <button type="button" ?disabled=${state.statusLoading} @click=${() => { void controller.refresh(context); }}>Refresh</button>
348
+ </div>
349
+ </section>
350
+ ${state.error === undefined ? null : html `<div class="git-error" role="alert">${state.error}</div>`}
351
+ <section class="git-split">
352
+ <div class="git-file-list">${renderFileList(html, controller, context, state, viewState)}</div>
353
+ <div class="git-viewer">${renderDiffViewer(html, state)}</div>
354
+ </section>
355
+ </section>
356
+ `;
357
+ }
358
+ function renderViewToggle(html, controller, context) {
359
+ return html `
360
+ <div class="git-view-toggle" role="group" aria-label="Changed files view">
361
+ ${renderViewToggleButton(html, controller, context, "list", "List")}
362
+ ${renderViewToggleButton(html, controller, context, "tree", "Tree")}
363
+ </div>
364
+ `;
365
+ }
366
+ function renderViewToggleButton(html, controller, context, view, label) {
367
+ const active = controller.currentView() === view;
368
+ return html `<button type="button" class=${active ? "is-selected" : ""} aria-pressed=${String(active)} @click=${() => { controller.setView(context, view); }}>${label}</button>`;
369
+ }
370
+ function renderExpandCollapseAll(html, controller, context, state, expandablePaths) {
371
+ const allExpanded = expandablePaths.every((path) => state.expandedDirectories.has(path));
372
+ return html `<button type="button" @click=${() => { controller.toggleExpandAll(context, expandablePaths, allExpanded); }}>${allExpanded ? "Collapse all" : "Expand all"}</button>`;
373
+ }
374
+ function renderFileList(html, controller, context, state, viewState) {
375
+ const status = state.status;
376
+ if (status === undefined)
377
+ return html `<p class="git-muted">${state.error === undefined ? "Loading status…" : "Status unavailable."}</p>`;
378
+ if (!status.isGitRepo)
379
+ return html `<p class="git-muted">Not a git repository.</p>`;
380
+ const summary = html `<p class="git-summary">${gitSummary(status)}</p>`;
381
+ if (status.files.length === 0)
382
+ return html `${summary}<p class="git-muted">No changes.</p>`;
383
+ const body = controller.currentView() === "tree"
384
+ ? viewState.nodes.map((node) => renderTreeNode(html, controller, context, state, node, 0))
385
+ : renderListBody(html, controller, context, state, viewState.listModel);
386
+ return html `${summary}${body}`;
387
+ }
388
+ function renderListBody(html, controller, context, state, model) {
389
+ return html `
390
+ ${model.submodules.map((group) => renderSubmoduleGroup(html, controller, context, state, group))}
391
+ ${model.files.map((file) => renderFileRow(html, controller, context, state, file))}
392
+ `;
393
+ }
394
+ function renderSubmoduleGroup(html, controller, context, state, group) {
395
+ const expanded = state.expandedDirectories.has(group.path);
396
+ return html `
397
+ <button type="button" class="git-row" style="--depth:0" aria-expanded=${String(expanded)} @click=${() => { controller.toggleDirectory(context, group.path); }}>
398
+ <span class="git-twisty">${expanded ? "▾" : "▸"}</span>
399
+ <span>${group.name}${submoduleBadge(html)}</span>
400
+ </button>
401
+ ${expanded ? html `
402
+ ${group.pointer === undefined ? null : renderSelectableRow(html, controller, context, state, group.path, group.pointer.name, group.pointer.file, 1)}
403
+ ${group.files.map((entry) => renderSubmoduleFileRow(html, controller, context, state, entry))}
404
+ ` : null}
405
+ `;
406
+ }
407
+ function renderSubmoduleFileRow(html, controller, context, state, entry) {
408
+ return renderSelectableRow(html, controller, context, state, entry.path, entry.relativePath, entry.file, 1);
409
+ }
410
+ function renderTreeNode(html, controller, context, state, node, depth) {
411
+ if (node.kind === "directory") {
412
+ const expanded = state.expandedDirectories.has(node.path);
413
+ return html `
414
+ <button type="button" class="git-row" style=${`--depth:${String(depth)}`} aria-expanded=${String(expanded)} @click=${() => { controller.toggleDirectory(context, node.path); }}>
415
+ <span class="git-twisty">${expanded ? "▾" : "▸"}</span>
416
+ <span>${node.name}${node.isSubmodule === true ? submoduleBadge(html) : null}</span>
417
+ </button>
418
+ ${expanded ? node.children.map((child) => renderTreeNode(html, controller, context, state, child, depth + 1)) : null}
419
+ `;
420
+ }
421
+ return renderSelectableRow(html, controller, context, state, node.path, node.name, node.file, depth);
422
+ }
423
+ function renderFileRow(html, controller, context, state, file) {
424
+ return renderSelectableRow(html, controller, context, state, file.path, file.path, file, 0);
425
+ }
426
+ function renderSelectableRow(html, controller, context, state, path, label, file, depth) {
427
+ const selected = state.selectedDiffPath === path;
428
+ return html `
429
+ <button type="button" class=${selected ? "git-row is-selected" : "git-row"} style=${`--depth:${String(depth)}`} @click=${() => { controller.selectDiff(context, path); }}>
430
+ <span>${stateLabel(file.index, file.workingTree)}</span>
431
+ <span>${label}</span>
432
+ </button>
433
+ `;
434
+ }
435
+ function renderDiffViewer(html, state) {
436
+ if (state.selectedDiffPath === undefined)
437
+ return html `<p class="git-muted">Select a changed file.</p>`;
438
+ const unstaged = state.selectedDiff;
439
+ const staged = state.selectedStagedDiff;
440
+ if (unstaged === undefined || staged === undefined)
441
+ return html `<p class="git-muted">Loading diff…</p>`;
442
+ const diffs = [staged, unstaged].filter((diff) => diff.response.diff !== "");
443
+ if (diffs.length === 0)
444
+ return html `<p class="git-muted">No staged or unstaged diff.</p>`;
445
+ return html `<div class=${diffs.length === 1 ? "git-diffs is-single" : "git-diffs"}>${diffs.map((diff) => renderDiffSection(html, diff))}</div>`;
446
+ }
447
+ function renderDiffSection(html, view) {
448
+ const diff = view.response;
449
+ const lines = view.lines ??= parseUnifiedDiff(diff.diff);
450
+ return html `
451
+ <section class="git-diff-section">
452
+ <div class="git-viewer-header"><strong>${diff.path ?? "diff"}</strong><small>${diff.staged ? "staged" : "unstaged"}${diff.truncated ? " · truncated" : ""}</small></div>
453
+ ${lines.length === 0 ? html `<p class="git-muted">No diff.</p>` : html `
454
+ <div class="git-diff-scroller">
455
+ <div class="git-diff-grid" role="table" aria-label="Unified diff">
456
+ ${lines.map((line) => renderDiffLine(html, line))}
457
+ </div>
458
+ </div>
459
+ `}
460
+ </section>
461
+ `;
462
+ }
463
+ function renderDiffLine(html, line) {
464
+ return html `
465
+ <div class="git-diff-line" role="row">
466
+ <span class=${`git-diff-cell git-line-number ${line.kind}`} role="cell">${formatLineNumber(line.oldLineNumber)}</span>
467
+ <span class=${`git-diff-cell git-line-number ${line.kind}`} role="cell">${formatLineNumber(line.newLineNumber)}</span>
468
+ <span class=${`git-diff-cell git-prefix ${line.kind}`} role="cell">${line.prefix}</span>
469
+ <span class=${`git-diff-cell git-content ${line.kind}`} role="cell">${renderDiffSpans(html, line.spans)}</span>
470
+ </div>
471
+ `;
472
+ }
473
+ function renderDiffSpans(html, spans) {
474
+ return spans.map((span) => html `<span class=${span.changed ? "inline-change" : ""}>${span.text}</span>`);
475
+ }
476
+ function buildViewState(status, view) {
477
+ if (status === undefined || !status.isGitRepo || status.files.length === 0)
478
+ return EMPTY_VIEW_STATE;
479
+ if (view === "tree") {
480
+ const nodes = buildGitFileTree(status.files, status.submodules);
481
+ return { nodes, listModel: EMPTY_LIST_MODEL, expandablePaths: collectGitFileTreeDirectoryPaths(nodes) };
482
+ }
483
+ const listModel = buildGitFileList(status.files, status.submodules);
484
+ return { nodes: [], listModel, expandablePaths: listModel.submodules.map((group) => group.path) };
485
+ }
486
+ function defineGitPanelActivityElement() {
487
+ if (typeof customElements === "undefined" || typeof HTMLElement === "undefined" || customElements.get(activityElementTag) !== undefined)
488
+ return;
489
+ class GitPanelActivityElement extends HTMLElement {
490
+ controllerValue;
491
+ contextValue;
492
+ pollTimer;
493
+ set controller(value) {
494
+ if (this.controllerValue === value)
495
+ return;
496
+ this.controllerValue = value;
497
+ this.restart();
498
+ }
499
+ set context(value) {
500
+ const previousKey = this.contextValue === undefined ? undefined : workspaceContextKey(this.contextValue);
501
+ this.contextValue = value;
502
+ if (previousKey !== (value === undefined ? undefined : workspaceContextKey(value)))
503
+ this.restart();
504
+ }
505
+ connectedCallback() {
506
+ window.addEventListener("popstate", this.onPopState);
507
+ this.restart();
508
+ }
509
+ disconnectedCallback() {
510
+ window.removeEventListener("popstate", this.onPopState);
511
+ if (this.controllerValue !== undefined && this.contextValue !== undefined)
512
+ this.controllerValue.disconnect(this.contextValue);
513
+ this.stopTimer();
514
+ }
515
+ restart() {
516
+ this.stopTimer();
517
+ if (!this.isConnected || this.controllerValue === undefined || this.contextValue === undefined)
518
+ return;
519
+ this.controllerValue.connect(this.contextValue);
520
+ this.pollTimer = window.setInterval(() => {
521
+ if (this.controllerValue !== undefined && this.contextValue !== undefined)
522
+ this.controllerValue.poll(this.contextValue);
523
+ }, GIT_POLL_INTERVAL_MS);
524
+ }
525
+ stopTimer() {
526
+ if (this.pollTimer !== undefined)
527
+ window.clearInterval(this.pollTimer);
528
+ this.pollTimer = undefined;
529
+ }
530
+ onPopState = () => {
531
+ if (this.controllerValue !== undefined && this.contextValue !== undefined)
532
+ this.controllerValue.handlePopState(this.contextValue);
533
+ };
534
+ }
535
+ customElements.define(activityElementTag, GitPanelActivityElement);
536
+ }
537
+ function submoduleBadge(html) {
538
+ return html `<span class="submodule-badge">submodule</span>`;
539
+ }
540
+ function gitSummary(status) {
541
+ const branch = status.branch ?? "detached";
542
+ const ahead = status.ahead ?? 0;
543
+ const behind = status.behind ?? 0;
544
+ return ahead === 0 && behind === 0 ? branch : `${branch} · ↑${String(ahead)} ↓${String(behind)}`;
545
+ }
546
+ function stateLabel(index, workingTree) {
547
+ const label = workingTree !== "unmodified" ? workingTree : index;
548
+ return label.slice(0, 1).toUpperCase();
549
+ }
550
+ function formatLineNumber(lineNumber) {
551
+ return lineNumber === undefined ? "" : String(lineNumber);
552
+ }
553
+ function createDiffView(response, previous) {
554
+ return {
555
+ response,
556
+ lines: previous?.response.hash === response.hash ? previous.lines : undefined,
557
+ };
558
+ }
559
+ function workspaceContextKey(context) {
560
+ return JSON.stringify([context.machine.id, context.workspace.projectId, context.workspace.id]);
561
+ }
562
+ function errorMessage(error) {
563
+ return error instanceof Error ? error.message : String(error);
564
+ }
565
+ const gitPanelStyles = `
566
+ .git-panel { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; color: var(--pi-text); background: var(--pi-bg); font: 13px system-ui, sans-serif; }
567
+ .git-panel ${activityElementTag} { display: none; }
568
+ .git-panel button { display: inline-flex; align-items: center; gap: 5px; border: 1px solid var(--pi-border); border-radius: 7px; background: var(--pi-surface); color: var(--pi-text); padding: 5px 7px; cursor: pointer; }
569
+ .git-panel button:disabled { cursor: wait; opacity: .65; }
570
+ .git-panel small, .git-panel .git-muted { color: var(--pi-muted); }
571
+ .git-panel p { margin: 10px; }
572
+ .git-panel .git-toolbar { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; padding: 8px; border-bottom: 1px solid var(--pi-border-muted); }
573
+ .git-panel .git-toolbar-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
574
+ .git-panel .git-view-toggle { display: inline-flex; }
575
+ .git-panel .git-view-toggle button { border-radius: 0; }
576
+ .git-panel .git-view-toggle button:first-child { border-top-left-radius: 7px; border-bottom-left-radius: 7px; }
577
+ .git-panel .git-view-toggle button:last-child { margin-left: -1px; border-top-right-radius: 7px; border-bottom-right-radius: 7px; }
578
+ .git-panel .git-view-toggle button.is-selected { position: relative; z-index: 1; border-color: var(--pi-accent); background: var(--pi-selection-bg); }
579
+ .git-panel .git-stale { border: 1px solid var(--pi-warning-border); border-radius: 999px; color: var(--pi-warning); padding: 1px 6px; font-size: 12px; }
580
+ .git-panel .git-error { flex: 0 0 auto; margin: 8px; border: 1px solid var(--pi-danger); border-radius: 7px; color: var(--pi-danger); padding: 8px; }
581
+ .git-panel .git-split { flex: 1 1 auto; min-height: 0; display: grid; grid-template-rows: minmax(160px, 34%) minmax(0, 1fr); }
582
+ .git-panel .git-file-list { min-height: 0; overflow: auto; border-bottom: 1px solid var(--pi-border); padding: 6px; }
583
+ .git-panel .git-row { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 4px; width: 100%; border: 0; border-radius: 5px; background: transparent; text-align: left; padding: 4px 6px 4px calc(6px + var(--depth, 0) * 14px); }
584
+ .git-panel .git-row:hover, .git-panel .git-row.is-selected { background: var(--pi-selection-bg); }
585
+ .git-panel .git-row span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
586
+ .git-panel .git-twisty { color: var(--pi-dim, var(--pi-muted)); }
587
+ .git-panel .git-summary { margin: 4px 6px 8px; color: var(--pi-muted); }
588
+ .git-panel .submodule-badge { display: inline-block; margin-left: 6px; border: 1px solid var(--pi-border); border-radius: 999px; color: var(--pi-muted); padding: 0 5px; font-size: 11px; font-weight: 400; vertical-align: baseline; }
589
+ .git-panel .git-viewer { min-height: 0; overflow: auto; display: flex; flex-direction: column; }
590
+ .git-panel .git-diffs { flex: 1 1 auto; min-height: 0; overflow: auto; display: grid; grid-template-rows: minmax(120px, 1fr) minmax(120px, 1fr); }
591
+ .git-panel .git-diffs.is-single { grid-template-rows: minmax(0, 1fr); }
592
+ .git-panel .git-diff-section { min-height: 0; display: flex; flex-direction: column; border-bottom: 1px solid var(--pi-border); }
593
+ .git-panel .git-diff-section:last-child { border-bottom: 0; }
594
+ .git-panel .git-viewer-header { position: sticky; top: 0; display: flex; justify-content: space-between; gap: 8px; padding: 8px; border-bottom: 1px solid var(--pi-border-muted); background: var(--pi-bg); }
595
+ .git-panel .git-viewer-header strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
596
+ .git-panel .git-diff-scroller { flex: 1 1 auto; min-height: 0; overflow: auto; background: var(--pi-bg); }
597
+ .git-panel .git-diff-grid { display: grid; grid-template-columns: max-content max-content 2ch max-content; width: max-content; min-width: 100%; padding: 6px 0; font: 12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; line-height: 1.45; }
598
+ .git-panel .git-diff-line { display: contents; }
599
+ .git-panel .git-diff-cell { min-height: 1.45em; white-space: pre; }
600
+ .git-panel .git-line-number { min-width: 4ch; padding: 0 8px; border-right: 1px solid var(--pi-border-muted); color: var(--pi-dim); text-align: right; user-select: none; }
601
+ .git-panel .git-prefix { padding: 0 4px; color: var(--pi-dim); text-align: center; user-select: none; }
602
+ .git-panel .git-content { padding: 0 12px 0 4px; }
603
+ .git-panel .git-diff-cell.meta, .git-panel .git-diff-cell.marker { color: var(--pi-dim); }
604
+ .git-panel .git-diff-cell.hunk { background: color-mix(in srgb, var(--pi-accent) 9%, transparent); color: var(--pi-accent); }
605
+ .git-panel .git-diff-cell.add { background: color-mix(in srgb, var(--pi-success) 12%, transparent); }
606
+ .git-panel .git-diff-cell.remove { background: color-mix(in srgb, var(--pi-danger) 12%, transparent); }
607
+ .git-panel .git-content.add .inline-change { border-radius: 2px; background: color-mix(in srgb, var(--pi-success) 36%, transparent); color: var(--pi-text); }
608
+ .git-panel .git-content.remove .inline-change { border-radius: 2px; background: color-mix(in srgb, var(--pi-danger) 36%, transparent); color: var(--pi-text); }
609
+ `;
@@ -0,0 +1,43 @@
1
+ // Generated from pi-web-plugins/git/browser/gitFileList.ts. Do not edit directly.
2
+ import { pointerName, segmentName } from "./gitFileShared.js";
3
+ /**
4
+ * Group the flat changed-file list for list view. Unlike the tree, submodule
5
+ * contents are flattened: each submodule becomes one expandable group holding
6
+ * its pointer row and its changed files, and everything else stays a flat list.
7
+ */
8
+ export function buildGitFileList(files, submodules = []) {
9
+ const submoduleSet = new Set(submodules);
10
+ const pointers = new Map();
11
+ const grouped = new Map();
12
+ for (const submodule of submodules)
13
+ grouped.set(submodule, []);
14
+ const flat = [];
15
+ for (const file of files) {
16
+ if (submoduleSet.has(file.path)) {
17
+ pointers.set(file.path, { name: pointerName(file), file });
18
+ continue;
19
+ }
20
+ const owner = ownerSubmodule(file.path, submodules);
21
+ if (owner !== undefined) {
22
+ grouped.get(owner)?.push({ path: file.path, relativePath: file.path.slice(owner.length + 1), file });
23
+ continue;
24
+ }
25
+ flat.push(file);
26
+ }
27
+ const groups = submodules
28
+ .map((submodule) => {
29
+ const pointer = pointers.get(submodule);
30
+ const inner = grouped.get(submodule) ?? [];
31
+ return { path: submodule, name: segmentName(submodule), ...(pointer === undefined ? {} : { pointer }), files: [...inner].sort((left, right) => left.relativePath.localeCompare(right.relativePath)) };
32
+ })
33
+ .sort((left, right) => left.name.localeCompare(right.name));
34
+ return { submodules: groups, files: flat };
35
+ }
36
+ function ownerSubmodule(path, submodules) {
37
+ let best;
38
+ for (const submodule of submodules) {
39
+ if (submodule !== "" && path.startsWith(`${submodule}/`) && (best === undefined || submodule.length > best.length))
40
+ best = submodule;
41
+ }
42
+ return best;
43
+ }
@@ -0,0 +1,16 @@
1
+ // Generated from pi-web-plugins/git/browser/gitFileShared.ts. Do not edit directly.
2
+ /**
3
+ * Display label for a submodule commit-pointer row: the `<old> → <new>`
4
+ * short-SHA summary, or "commit" when the server did not resolve both ends.
5
+ */
6
+ export function pointerName(file) {
7
+ const from = file.submoduleFromCommit;
8
+ const to = file.submoduleToCommit;
9
+ return from !== undefined && to !== undefined ? `${from} → ${to}` : "commit";
10
+ }
11
+ /** Final segment of a path, used as the display name for tree/list rows. */
12
+ export function segmentName(path) {
13
+ const segments = path.split("/");
14
+ const last = segments[segments.length - 1];
15
+ return last ?? path;
16
+ }