@chainingintention/pi-web-cn 1.202610.4 → 2.202610.0

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 (299) hide show
  1. package/README.md +2 -2
  2. package/dist/cli.js +31 -7
  3. package/dist/cli.js.map +1 -1
  4. package/dist/client/assets/PiWebApp-BXSziMEg.js +4921 -0
  5. package/dist/client/assets/classic-CyM97Akm.css +54 -0
  6. package/dist/client/assets/external-B9K8duyP.js +2 -0
  7. package/dist/client/assets/graphite-DquaqFXU.css +54 -0
  8. package/dist/client/assets/index-cdtUOfOW.js +2 -0
  9. package/dist/client/assets/paper-CB1oLuRr.css +54 -0
  10. package/dist/client/assets/pi-web-dark-D_KtbM95.css +54 -0
  11. package/dist/client/assets/pi-web-light-DSNLMIBI.css +54 -0
  12. package/dist/client/assets/vendor-editor-core-BfnHL1Dg.js +10 -0
  13. package/dist/client/assets/{vendor-editor-languages-DOCw3vc9.js → vendor-editor-languages-bNquDJP0.js} +1 -1
  14. package/dist/client/index.html +3 -47
  15. package/dist/config.js +11 -2
  16. package/dist/config.js.map +1 -1
  17. package/dist/nativeServices/installedServiceDefinitions.js +10 -7
  18. package/dist/nativeServices/installedServiceDefinitions.js.map +1 -1
  19. package/dist/pi-packages/captains-log/dist/browser/index.js +43 -47
  20. package/dist/pi-packages/captains-log/dist/browser/panel.js +6 -10
  21. package/dist/pi-packages/captains-log/dist/companion.js +1 -1
  22. package/dist/pi-packages/captains-log/package.json +4 -4
  23. package/dist/pi-packages/relays/extensions/index.js +61 -0
  24. package/dist/pi-packages/relays/package.json +10 -1
  25. package/dist/pi-packages/relays/pi-web-plugin.js +52 -2
  26. package/dist/pi-packages/relays/prompts/relay-worktree.md +6 -16
  27. package/dist/pi-packages/relays/prompts/relay.md +6 -33
  28. package/dist/pi-packages/relays/relayDispatch.js +67 -0
  29. package/dist/pi-packages/relays/relayIdentity.js +37 -0
  30. package/dist/pi-packages/relays/relaysPanelElement.js +75 -37
  31. package/dist/pi-packages/relays/skills/relay/SKILL.md +24 -68
  32. package/dist/pi-packages/relays/skills/relay-runner/SKILL.md +40 -219
  33. package/dist/pi-packages/workflows/browser/pi-web-plugin.js +42 -0
  34. package/dist/pi-packages/workflows/browser/worktreeDialog.js +170 -0
  35. package/dist/pi-packages/workflows/package.json +23 -0
  36. package/dist/pi-packages/workflows/prompts/worktree.md +21 -0
  37. package/dist/pi-packages/workflows/server-plugin.js +586 -0
  38. package/dist/pi-packages/workflows/vite.config.mjs +17 -0
  39. package/dist/pi-web-plugins/code-highlight/browser/pi-web-plugin.js +22 -0
  40. package/dist/pi-web-plugins/code-highlight/package.json +13 -0
  41. package/dist/pi-web-plugins/files/browser/pi-web-plugin.js +115 -105
  42. package/dist/pi-web-plugins/git/browser/git-panel.js +60 -46
  43. package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +23 -3
  44. package/dist/pi-web-plugins/git/git-backend.js +20 -1
  45. package/dist/pi-web-plugins/git/server-plugin.js +20 -3
  46. package/dist/pi-web-plugins/git/workspace-discovery-notify.cjs +14 -0
  47. package/dist/pi-web-plugins/git/workspaceDiscoveryHooks.js +186 -0
  48. package/dist/pi-web-plugins/info/infoInternals.js +3 -3
  49. package/dist/pi-web-plugins/info/pi-web-plugin.js +1 -1
  50. package/dist/pi-web-plugins/mermaid/browser/mermaid-engine.js +1087 -422
  51. package/dist/pi-web-plugins/mermaid/browser/pi-web-plugin.js +8 -3
  52. package/dist/pi-web-plugins/terminal/browser/pi-web-plugin.js +39 -33
  53. package/dist/pi-web-plugins/updates/pi-web-plugin.js +13 -13
  54. package/dist/pi-web-plugins/updates/updatesLogic.js +4 -5
  55. package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +21 -1
  56. package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +39 -22
  57. package/dist/pi-web-plugins/zh-cn/bundled.json +44 -1
  58. package/dist/pi-web-plugins/zh-cn/cli.json +60 -1
  59. package/dist/pi-web-plugins/zh-cn/client.json +7 -1
  60. package/dist/pi-web-plugins/zh-cn/components.json +252 -2
  61. package/dist/pi-web-plugins/zh-cn/config-errors.json +17 -1
  62. package/dist/pi-web-plugins/zh-cn/files.json +10 -1
  63. package/dist/pi-web-plugins/zh-cn/main.json +1 -1
  64. package/dist/pi-web-plugins/zh-cn/provider-auth.json +2 -1
  65. package/dist/pi-web-plugins/zh-cn/server.json +83 -1
  66. package/dist/piAi.js +4 -0
  67. package/dist/piAi.js.map +1 -0
  68. package/dist/piRuntime.js +150 -0
  69. package/dist/piRuntime.js.map +1 -0
  70. package/dist/piSdk.js +5 -0
  71. package/dist/piSdk.js.map +1 -0
  72. package/dist/piWebUpdate.js +508 -0
  73. package/dist/piWebUpdate.js.map +1 -0
  74. package/dist/piWebVersionReport.js +43 -1
  75. package/dist/piWebVersionReport.js.map +1 -1
  76. package/dist/plugin-api.d.ts +393 -51
  77. package/dist/server/activity/workspaceActivityService.js +8 -1
  78. package/dist/server/activity/workspaceActivityService.js.map +1 -1
  79. package/dist/server/app.js +19 -4
  80. package/dist/server/app.js.map +1 -1
  81. package/dist/server/browserMessageProjection.js +39 -20
  82. package/dist/server/browserMessageProjection.js.map +1 -1
  83. package/dist/server/configRoutes.js +8 -0
  84. package/dist/server/configRoutes.js.map +1 -1
  85. package/dist/server/index.js +10 -1
  86. package/dist/server/index.js.map +1 -1
  87. package/dist/server/knownAutoInstallPiPackages.js +6 -0
  88. package/dist/server/knownAutoInstallPiPackages.js.map +1 -1
  89. package/dist/server/machines/machineProxyRoutes.js +37 -2
  90. package/dist/server/machines/machineProxyRoutes.js.map +1 -1
  91. package/dist/server/navigationPreferenceRoutes.js +59 -0
  92. package/dist/server/navigationPreferenceRoutes.js.map +1 -0
  93. package/dist/server/piPackageService.js +1 -1
  94. package/dist/server/piPackageService.js.map +1 -1
  95. package/dist/server/piWebPluginCatalog.js +1 -1
  96. package/dist/server/piWebPluginCatalog.js.map +1 -1
  97. package/dist/server/piWebPluginService.js +7 -1
  98. package/dist/server/piWebPluginService.js.map +1 -1
  99. package/dist/server/piWebStatus.js +17 -56
  100. package/dist/server/piWebStatus.js.map +1 -1
  101. package/dist/server/plugins/pluginBackendChannelProxyAdmission.js +1 -1
  102. package/dist/server/plugins/pluginBackendChannelProxyAdmission.js.map +1 -1
  103. package/dist/server/plugins/pluginBackendChannelProxyRoutes.js +40 -42
  104. package/dist/server/plugins/pluginBackendChannelProxyRoutes.js.map +1 -1
  105. package/dist/server/plugins/pluginBackendProxyRoutes.js +40 -44
  106. package/dist/server/plugins/pluginBackendProxyRoutes.js.map +1 -1
  107. package/dist/server/plugins/pluginBackendRegistry.js +66 -35
  108. package/dist/server/plugins/pluginBackendRegistry.js.map +1 -1
  109. package/dist/server/plugins/projectPluginSettings.js +95 -0
  110. package/dist/server/plugins/projectPluginSettings.js.map +1 -0
  111. package/dist/server/plugins/serverPluginCatalogCapability.js +106 -0
  112. package/dist/server/plugins/serverPluginCatalogCapability.js.map +1 -0
  113. package/dist/server/plugins/serverPluginRuntime.js +47 -11
  114. package/dist/server/plugins/serverPluginRuntime.js.map +1 -1
  115. package/dist/server/projectTrustRoutes.js +1 -1
  116. package/dist/server/projectTrustRoutes.js.map +1 -1
  117. package/dist/server/projects/projectLifecycleService.js +17 -7
  118. package/dist/server/projects/projectLifecycleService.js.map +1 -1
  119. package/dist/server/realtime/sessionEventHub.js +22 -9
  120. package/dist/server/realtime/sessionEventHub.js.map +1 -1
  121. package/dist/server/sessiond/agentHttpDispatcher.js +1 -1
  122. package/dist/server/sessiond/agentHttpDispatcher.js.map +1 -1
  123. package/dist/server/sessiond/autoInstallPiPackages.js +3 -3
  124. package/dist/server/sessiond/pluginBackendChannelRoutes.js +27 -14
  125. package/dist/server/sessiond/pluginBackendChannelRoutes.js.map +1 -1
  126. package/dist/server/sessiond/pluginBackendRoutes.js +56 -49
  127. package/dist/server/sessiond/pluginBackendRoutes.js.map +1 -1
  128. package/dist/server/sessiond/pluginCatalogRoutes.js +41 -0
  129. package/dist/server/sessiond/pluginCatalogRoutes.js.map +1 -0
  130. package/dist/server/sessiond/sessionProxyRoutes.js +46 -1
  131. package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
  132. package/dist/server/sessiond/sessionServiceDependencies.js +1 -0
  133. package/dist/server/sessiond/sessionServiceDependencies.js.map +1 -1
  134. package/dist/server/sessiond/workspaceCatalogRoutes.js +6 -2
  135. package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -1
  136. package/dist/server/sessiond/workspaceNotificationRoutes.js +55 -0
  137. package/dist/server/sessiond/workspaceNotificationRoutes.js.map +1 -0
  138. package/dist/server/sessiond.js +58 -8
  139. package/dist/server/sessiond.js.map +1 -1
  140. package/dist/server/sessions/askUserDomain.js +232 -0
  141. package/dist/server/sessions/askUserDomain.js.map +1 -0
  142. package/dist/server/sessions/askUserTool.js +18 -18
  143. package/dist/server/sessions/askUserTool.js.map +1 -1
  144. package/dist/server/sessions/attachmentService.js +1 -1
  145. package/dist/server/sessions/attachmentService.js.map +1 -1
  146. package/dist/server/sessions/authRoutes.js +12 -0
  147. package/dist/server/sessions/authRoutes.js.map +1 -1
  148. package/dist/server/sessions/authService.js +11 -1
  149. package/dist/server/sessions/authService.js.map +1 -1
  150. package/dist/server/sessions/builtinExtensionFactories.js +36 -0
  151. package/dist/server/sessions/builtinExtensionFactories.js.map +1 -0
  152. package/dist/server/sessions/companionBackend.js +286 -0
  153. package/dist/server/sessions/companionBackend.js.map +1 -0
  154. package/dist/server/sessions/dockerEnvironmentFacts.js +16 -1
  155. package/dist/server/sessions/dockerEnvironmentFacts.js.map +1 -1
  156. package/dist/server/sessions/extensionSessionDispatch.js +76 -0
  157. package/dist/server/sessions/extensionSessionDispatch.js.map +1 -0
  158. package/dist/server/sessions/globalProviderPolicy.js +88 -19
  159. package/dist/server/sessions/globalProviderPolicy.js.map +1 -1
  160. package/dist/server/sessions/managementAgentTools.js +2 -2
  161. package/dist/server/sessions/managementAgentTools.js.map +1 -1
  162. package/dist/server/sessions/mcpAuthFlowService.js +289 -0
  163. package/dist/server/sessions/mcpAuthFlowService.js.map +1 -0
  164. package/dist/server/sessions/mcpAuthRoutes.js +104 -0
  165. package/dist/server/sessions/mcpAuthRoutes.js.map +1 -0
  166. package/dist/server/sessions/mcpOAuthCredentialAdapter.js +92 -0
  167. package/dist/server/sessions/mcpOAuthCredentialAdapter.js.map +1 -0
  168. package/dist/server/sessions/messageHistoryTarget.js +79 -0
  169. package/dist/server/sessions/messageHistoryTarget.js.map +1 -0
  170. package/dist/server/sessions/piSessionEventConnections.js +5 -2
  171. package/dist/server/sessions/piSessionEventConnections.js.map +1 -1
  172. package/dist/server/sessions/piSessionManagerGateway.js +32 -27
  173. package/dist/server/sessions/piSessionManagerGateway.js.map +1 -1
  174. package/dist/server/sessions/piSessionService.js +1296 -341
  175. package/dist/server/sessions/piSessionService.js.map +1 -1
  176. package/dist/server/sessions/plainTextTheme.js +1 -1
  177. package/dist/server/sessions/plainTextTheme.js.map +1 -1
  178. package/dist/server/sessions/projectAuthService.js +1 -1
  179. package/dist/server/sessions/projectAuthService.js.map +1 -1
  180. package/dist/server/sessions/projectSettingsScope.js +1 -1
  181. package/dist/server/sessions/projectSettingsScope.js.map +1 -1
  182. package/dist/server/sessions/projectTrust.js +1 -1
  183. package/dist/server/sessions/projectTrust.js.map +1 -1
  184. package/dist/server/sessions/queuedMessageMutation.js +170 -0
  185. package/dist/server/sessions/queuedMessageMutation.js.map +1 -0
  186. package/dist/server/sessions/relaySkill.js +57 -7
  187. package/dist/server/sessions/relaySkill.js.map +1 -1
  188. package/dist/server/sessions/sessionArchiveMapping.js +6 -0
  189. package/dist/server/sessions/sessionArchiveMapping.js.map +1 -1
  190. package/dist/server/sessions/sessionArchiveStore.js +5 -1
  191. package/dist/server/sessions/sessionArchiveStore.js.map +1 -1
  192. package/dist/server/sessions/sessionArchiveTree.js +2 -2
  193. package/dist/server/sessions/sessionArchiveTree.js.map +1 -1
  194. package/dist/server/sessions/sessionCommandService.js +11 -24
  195. package/dist/server/sessions/sessionCommandService.js.map +1 -1
  196. package/dist/server/sessions/sessionImageDimensions.js +31 -0
  197. package/dist/server/sessions/sessionImageDimensions.js.map +1 -0
  198. package/dist/server/sessions/sessionMediaIndex.js +191 -0
  199. package/dist/server/sessions/sessionMediaIndex.js.map +1 -0
  200. package/dist/server/sessions/sessionMetadata.js +51 -0
  201. package/dist/server/sessions/sessionMetadata.js.map +1 -0
  202. package/dist/server/sessions/sessionModelScope.js +2 -2
  203. package/dist/server/sessions/sessionModelScope.js.map +1 -1
  204. package/dist/server/sessions/sessionNameGenerator.js +13 -33
  205. package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
  206. package/dist/server/sessions/sessionReadAccess.js +41 -0
  207. package/dist/server/sessions/sessionReadAccess.js.map +1 -0
  208. package/dist/server/sessions/sessionRoutes.js +61 -6
  209. package/dist/server/sessions/sessionRoutes.js.map +1 -1
  210. package/dist/server/sessions/sessionSummaryScanner.js +62 -5
  211. package/dist/server/sessions/sessionSummaryScanner.js.map +1 -1
  212. package/dist/server/sessions/sessionUiEvents.js +17 -4
  213. package/dist/server/sessions/sessionUiEvents.js.map +1 -1
  214. package/dist/server/sessions/spawnSessionTool.js +11 -3
  215. package/dist/server/sessions/spawnSessionTool.js.map +1 -1
  216. package/dist/server/sessions/spawnSubsessionTool.js +35 -19
  217. package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
  218. package/dist/server/sessions/subsessionCompletionDelivery.js +15 -0
  219. package/dist/server/sessions/subsessionCompletionDelivery.js.map +1 -0
  220. package/dist/server/sessions/subsessionCompletionInbox.js +134 -0
  221. package/dist/server/sessions/subsessionCompletionInbox.js.map +1 -0
  222. package/dist/server/sessions/subsessionProvenance.js +27 -0
  223. package/dist/server/sessions/subsessionProvenance.js.map +1 -0
  224. package/dist/server/sessions/transcriptMarkdown.js +48 -0
  225. package/dist/server/sessions/transcriptMarkdown.js.map +1 -0
  226. package/dist/server/sessions/transcriptMessages.js +3 -0
  227. package/dist/server/sessions/transcriptMessages.js.map +1 -1
  228. package/dist/server/startupLogger.js +13 -0
  229. package/dist/server/startupLogger.js.map +1 -0
  230. package/dist/server/startupUrls.js +27 -0
  231. package/dist/server/startupUrls.js.map +1 -0
  232. package/dist/server/status/machineStatusService.js +15 -9
  233. package/dist/server/status/machineStatusService.js.map +1 -1
  234. package/dist/server/storage/navigationPreferenceStore.js +138 -0
  235. package/dist/server/storage/navigationPreferenceStore.js.map +1 -0
  236. package/dist/server/webSocketBridge.js +9 -0
  237. package/dist/server/webSocketBridge.js.map +1 -1
  238. package/dist/server/workbench/skillSync.js +1 -1
  239. package/dist/server/workbench/skillSync.js.map +1 -1
  240. package/dist/server/workbench/workbenchTools.js +2 -2
  241. package/dist/server/workbench/workbenchTools.js.map +1 -1
  242. package/dist/server/workspaces/filePreviewService.js +5 -2
  243. package/dist/server/workspaces/filePreviewService.js.map +1 -1
  244. package/dist/server/workspaces/projectPiWebConfig.js +87 -6
  245. package/dist/server/workspaces/projectPiWebConfig.js.map +1 -1
  246. package/dist/server/workspaces/workspaceChangeNotifier.js +12 -0
  247. package/dist/server/workspaces/workspaceChangeNotifier.js.map +1 -0
  248. package/dist/server/workspaces/workspaceNotificationCommand.js +64 -0
  249. package/dist/server/workspaces/workspaceNotificationCommand.js.map +1 -0
  250. package/dist/server/workspaces/workspaceProviderRegistry.js +53 -0
  251. package/dist/server/workspaces/workspaceProviderRegistry.js.map +1 -1
  252. package/dist/server-plugin-api.d.ts +83 -15
  253. package/dist/server-plugin-api.js +25 -0
  254. package/dist/server-plugin-api.js.map +1 -1
  255. package/dist/sessiond/sessionDaemonClient.js +27 -3
  256. package/dist/sessiond/sessionDaemonClient.js.map +1 -1
  257. package/dist/shared/apiTypes.js +3 -2
  258. package/dist/shared/apiTypes.js.map +1 -1
  259. package/dist/shared/capabilities.js +3 -0
  260. package/dist/shared/capabilities.js.map +1 -1
  261. package/dist/shared/federatedRoutes.js +25 -5
  262. package/dist/shared/federatedRoutes.js.map +1 -1
  263. package/dist/shared/machineStatus.js +11 -2
  264. package/dist/shared/machineStatus.js.map +1 -1
  265. package/dist/shared/navigationPreferences.js +6 -0
  266. package/dist/shared/navigationPreferences.js.map +1 -0
  267. package/dist/shared/piWebConfigParsing.js +54 -0
  268. package/dist/shared/piWebConfigParsing.js.map +1 -1
  269. package/dist/shared/pluginApiTypes.d.ts +55 -0
  270. package/dist/shared/pluginBackendProtocol.js +56 -1
  271. package/dist/shared/pluginBackendProtocol.js.map +1 -1
  272. package/dist/shared/pluginCatalogTypes.d.ts +49 -0
  273. package/dist/shared/pluginCatalogTypes.js +156 -0
  274. package/dist/shared/pluginCatalogTypes.js.map +1 -0
  275. package/dist/shared/sessionMedia.js +12 -0
  276. package/dist/shared/sessionMedia.js.map +1 -0
  277. package/dist/shared/streamingBehavior.js +8 -0
  278. package/dist/shared/streamingBehavior.js.map +1 -0
  279. package/dist/shared/themePreference.js +24 -0
  280. package/dist/shared/themePreference.js.map +1 -0
  281. package/dist/workspaceNotificationCli.js +95 -0
  282. package/dist/workspaceNotificationCli.js.map +1 -0
  283. package/docs/README.md +31 -0
  284. package/docs/config.md +77 -4
  285. package/docs/plugins.md +60 -11
  286. package/examples/session-bridge-plugin/package.json +2 -2
  287. package/examples/session-bridge-plugin/src/browser/index.ts +1 -1
  288. package/examples/session-bridge-plugin/src/companion.ts +1 -1
  289. package/extensions/pi-web.ts +3 -1
  290. package/package.json +46 -34
  291. package/skills/README.md +10 -9
  292. package/skills/relay/SKILL.md +24 -68
  293. package/skills/relay-runner/SKILL.md +40 -219
  294. package/dist/client/assets/PiWebApp-CN3g7SqA.js +0 -4362
  295. package/dist/client/assets/external-DUGCSDhZ.js +0 -2
  296. package/dist/client/assets/index-JduZlbIF.js +0 -2
  297. package/dist/client/assets/vendor-editor-core-YWog6mAR.js +0 -10
  298. package/dist/server/sessions/pendingAskStore.js +0 -275
  299. package/dist/server/sessions/pendingAskStore.js.map +0 -1
@@ -0,0 +1,95 @@
1
+ import { isAbsolute, resolve } from "node:path";
2
+ import { loadProjectPiWebConfig, snapshotPluginSettings } from "../workspaces/projectPiWebConfig.js";
3
+ /**
4
+ * Daemon-lifetime project overrides, including absent files and scope errors.
5
+ * Only a new instance observes edits; each invocation supplies its own global base.
6
+ */
7
+ export class ProjectPluginSettingsSnapshots {
8
+ constructor(projects, { timeoutMs = 5_000, loadConfig = loadProjectPiWebConfig } = {}) {
9
+ this.projects = projects;
10
+ this.scopes = new Map();
11
+ if (!Number.isInteger(timeoutMs) || timeoutMs <= 0)
12
+ throw new Error("Project config timeoutMs must be a positive integer");
13
+ this.timeoutMs = timeoutMs;
14
+ this.loadConfig = loadConfig;
15
+ }
16
+ /** Optional startup preload. Bad or timed-out scopes are retained without rejecting startup. */
17
+ async initialize(projects) {
18
+ await Promise.all(projects.map(async ({ id }) => {
19
+ const registered = await this.requireProject(id);
20
+ await this.scopeSnapshot(registered);
21
+ }));
22
+ }
23
+ async resolve(pluginId, globalSettings, project, signal) {
24
+ signal.throwIfAborted();
25
+ // Capture before yielding: callers cannot change the base during project I/O.
26
+ const base = snapshotPluginSettings(globalSettings, `Global settings for server plugin ${pluginId}`);
27
+ try {
28
+ const registered = await this.requireProject(project.id);
29
+ signal.throwIfAborted();
30
+ const snapshot = await this.scopeSnapshot(registered);
31
+ signal.throwIfAborted();
32
+ if ("error" in snapshot)
33
+ throw snapshot.error;
34
+ const overrides = Object.hasOwn(snapshot.settings, pluginId) ? snapshot.settings[pluginId] : undefined;
35
+ return snapshotPluginSettings({ ...base, ...overrides }, `Project settings for server plugin ${pluginId}`);
36
+ }
37
+ finally {
38
+ signal.throwIfAborted();
39
+ }
40
+ }
41
+ async requireProject(id) {
42
+ if (id === "")
43
+ throw new Error("PI WEB plugin settings require a registered project id");
44
+ const project = await this.projects.requireProject(id);
45
+ if (project.id !== id)
46
+ throw new Error("PI WEB plugin settings resolved a mismatched project id");
47
+ if (!isAbsolute(project.path))
48
+ throw new Error("PI WEB plugin settings require an absolute registered project path");
49
+ // Never read a caller-supplied path, even for an already cached id.
50
+ return { id, path: resolve(project.path) };
51
+ }
52
+ scopeSnapshot(project) {
53
+ const key = JSON.stringify([project.id, project.path]);
54
+ let snapshot = this.scopes.get(key);
55
+ if (snapshot === undefined) {
56
+ snapshot = this.loadScope(project);
57
+ this.scopes.set(key, snapshot);
58
+ }
59
+ return snapshot;
60
+ }
61
+ async loadScope(project) {
62
+ // This deadline belongs to the shared snapshot, not to any one caller.
63
+ const controller = new AbortController();
64
+ let timeout;
65
+ const deadline = new Promise((_resolve, reject) => {
66
+ timeout = setTimeout(() => {
67
+ const error = new Error(`Project config read timed out after ${String(this.timeoutMs)}ms`);
68
+ reject(error);
69
+ controller.abort(error);
70
+ }, this.timeoutMs);
71
+ timeout.unref();
72
+ });
73
+ try {
74
+ // Race as well as abort: stat/open and an uncooperative reader may not
75
+ // settle on cancellation. A late result must never replace this snapshot.
76
+ const loaded = await Promise.race([
77
+ Promise.resolve().then(() => this.loadConfig(project.path, controller.signal)),
78
+ deadline,
79
+ ]);
80
+ const settings = Object.freeze(Object.fromEntries(Object.entries(loaded.config.plugins ?? {})
81
+ .flatMap(([pluginId, config]) => config.settings === undefined ? [] : [[pluginId, config.settings]])));
82
+ return Object.freeze({ settings });
83
+ }
84
+ catch (error) {
85
+ // Fulfilled error snapshots avoid unhandled preload rejections and fail only
86
+ // consumers of this project. They must not fall back to global settings.
87
+ const message = error instanceof Error ? error.message : String(error);
88
+ return Object.freeze({ error: new Error(`PI WEB plugin settings for project ${project.id} (${project.path}) could not be loaded: ${message}`, { cause: error }) });
89
+ }
90
+ finally {
91
+ clearTimeout(timeout);
92
+ }
93
+ }
94
+ }
95
+ //# sourceMappingURL=projectPluginSettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectPluginSettings.js","sourceRoot":"","sources":["../../../src/server/plugins/projectPluginSettings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ import { isAbsolute, resolve } from "node:path";
2
+ import { PI_WEB_HOST_CATALOG_CAPABILITY, } from "../../shared/pluginCatalogTypes.js";
3
+ /** Register after provider topology settles, alongside the workspace authority factory. */
4
+ export function createServerPluginCatalogCapabilityFactory(options) {
5
+ return Object.freeze({
6
+ capability: PI_WEB_HOST_CATALOG_CAPABILITY,
7
+ create(context) {
8
+ const disposal = new AbortController();
9
+ const lifetime = AbortSignal.any([context.lifetimeSignal, disposal.signal]);
10
+ function signalFor(read) {
11
+ return read?.signal === undefined ? lifetime : AbortSignal.any([lifetime, read.signal]);
12
+ }
13
+ function assertActive(signal) {
14
+ if (lifetime.aborted)
15
+ throw new Error(`PI WEB host catalog for server plugin ${context.pluginId} is no longer active`, { cause: lifetime.reason });
16
+ signal.throwIfAborted();
17
+ }
18
+ async function read(requested, operation) {
19
+ const signal = signalFor(requested);
20
+ assertActive(signal);
21
+ try {
22
+ const result = await operation(signal);
23
+ assertActive(signal);
24
+ return result;
25
+ }
26
+ catch (error) {
27
+ assertActive(signal);
28
+ throw error;
29
+ }
30
+ }
31
+ async function project(projectId, signal) {
32
+ assertActive(signal);
33
+ const result = await options.projects.requireProject(projectId);
34
+ assertActive(signal);
35
+ if (result.id !== projectId)
36
+ throw new Error("Catalog project authority returned a mismatched project");
37
+ return result;
38
+ }
39
+ async function workspaces(projectId, signal) {
40
+ const selected = await project(projectId, signal);
41
+ const resolution = await options.workspaces.resolve(selected, signal);
42
+ assertActive(signal);
43
+ if (resolution.projectId !== projectId)
44
+ throw new Error("Catalog workspace authority returned a mismatched project");
45
+ return resolution.workspaces.map((workspace) => {
46
+ if (workspace.projectId !== projectId)
47
+ throw new Error("Catalog workspace is outside selected project");
48
+ return {
49
+ id: workspace.id, projectId, path: absolutePath(workspace.path), label: workspace.label, isMain: workspace.isMain,
50
+ ...(workspace.provider === undefined ? {} : { provider: workspace.provider }),
51
+ ...(workspace.removal === undefined ? {} : { removal: workspace.removal }),
52
+ };
53
+ });
54
+ }
55
+ async function workspace(selection, signal) {
56
+ const result = (await workspaces(selection.projectId, signal)).find(({ id }) => id === selection.workspaceId);
57
+ if (result === undefined)
58
+ throw new Error("Catalog selected workspace is stale or unavailable");
59
+ return result;
60
+ }
61
+ async function sessions(selection, signal) {
62
+ const selected = await workspace(selection, signal);
63
+ const rows = await options.sessions.listCatalogSessions(selected.path, signal);
64
+ assertActive(signal);
65
+ // A reader must not supply records from a different workspace, even for get-by-id.
66
+ if (rows.some((row) => absolutePath(row.cwd) !== selected.path))
67
+ throw new Error("Catalog session is outside selected workspace");
68
+ return rows;
69
+ }
70
+ const value = PI_WEB_HOST_CATALOG_CAPABILITY.parse({
71
+ version: 1,
72
+ projects: {
73
+ list: (requested) => read(requested, async (signal) => {
74
+ const rows = await options.projects.list();
75
+ assertActive(signal);
76
+ return rows.map(projectSnapshot);
77
+ }),
78
+ get: (id, requested) => read(requested, async (signal) => projectSnapshot(await project(id, signal))),
79
+ },
80
+ workspaces: {
81
+ list: (id, requested) => read(requested, (signal) => workspaces(id, signal)),
82
+ get: (selection, requested) => read(requested, (signal) => workspace(selection, signal)),
83
+ },
84
+ sessions: {
85
+ list: (selection, requested) => read(requested, (signal) => sessions(selection, signal)),
86
+ get: (selection, requested) => read(requested, async (signal) => {
87
+ const result = (await sessions({ projectId: selection.projectId, workspaceId: selection.workspaceId }, signal)).find(({ id }) => id === selection.sessionId);
88
+ if (result === undefined)
89
+ throw new Error("Catalog selected session is stale or unavailable");
90
+ return result;
91
+ }),
92
+ },
93
+ });
94
+ return Object.freeze({ value, dispose: () => { disposal.abort(); } });
95
+ },
96
+ });
97
+ }
98
+ function absolutePath(path) {
99
+ if (!isAbsolute(path))
100
+ throw new Error("Catalog authority returned a non-absolute path");
101
+ return resolve(path);
102
+ }
103
+ function projectSnapshot(project) {
104
+ return { id: project.id, name: project.name, path: absolutePath(project.path) };
105
+ }
106
+ //# sourceMappingURL=serverPluginCatalogCapability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverPluginCatalogCapability.js","sourceRoot":"","sources":["../../../src/server/plugins/serverPluginCatalogCapability.ts"],"names":[],"mappings":"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"}
@@ -22,13 +22,15 @@ export async function createServerPluginRuntime(options) {
22
22
  return await ServerPluginRuntime.activate(snapshot, options);
23
23
  }
24
24
  export class ServerPluginRuntime {
25
- constructor(dataDir, safeStart, diagnostics, logger, importer, execFile, lifecycleTimeoutMs, noticeSink, hostCapabilities, hostCapabilityFactories, lateHostCapabilities, enforceRequiredTerminal, translator) {
25
+ constructor(dataDir, safeStart, diagnostics, logger, importer, execFile, projectSettingsResolver, workspaceNotificationsFactory, lifecycleTimeoutMs, noticeSink, hostCapabilities, hostCapabilityFactories, lateHostCapabilities, enforceRequiredTerminal, translator) {
26
26
  this.dataDir = dataDir;
27
27
  this.safeStart = safeStart;
28
28
  this.diagnostics = diagnostics;
29
29
  this.logger = logger;
30
30
  this.importer = importer;
31
31
  this.execFile = execFile;
32
+ this.projectSettingsResolver = projectSettingsResolver;
33
+ this.workspaceNotificationsFactory = workspaceNotificationsFactory;
32
34
  this.lifecycleTimeoutMs = lifecycleTimeoutMs;
33
35
  this.noticeSink = noticeSink;
34
36
  this.enforceRequiredTerminal = enforceRequiredTerminal;
@@ -51,7 +53,7 @@ export class ServerPluginRuntime {
51
53
  this.registerHostCapability(capability);
52
54
  }
53
55
  static async activate(snapshot, options) {
54
- const runtime = new ServerPluginRuntime(resolve(options.dataDir), options.safeStart, Object.freeze(snapshot.diagnostics.map((diagnostic) => Object.freeze({ ...diagnostic }))), options.logger, options.importer ?? importServerPluginModule, options.execFile ?? createServerPluginExecFile(), positiveInteger(options.lifecycleTimeoutMs, DEFAULT_LIFECYCLE_TIMEOUT_MS, "lifecycleTimeoutMs"), options.noticeSink, snapshotHostCapabilities(options.hostCapabilities), snapshotHostCapabilityFactories(options.hostCapabilityFactories), snapshotLateHostCapabilities(options.lateHostCapabilities), options.enforceRequiredTerminal !== false && options.safeStart !== "none", options.translator);
56
+ const runtime = new ServerPluginRuntime(resolve(options.dataDir), options.safeStart, Object.freeze(snapshot.diagnostics.map((diagnostic) => Object.freeze({ ...diagnostic }))), options.logger, options.importer ?? importServerPluginModule, options.execFile ?? createServerPluginExecFile(), options.projectSettingsResolver, options.workspaceNotificationsFactory, positiveInteger(options.lifecycleTimeoutMs, DEFAULT_LIFECYCLE_TIMEOUT_MS, "lifecycleTimeoutMs"), options.noticeSink, snapshotHostCapabilities(options.hostCapabilities), snapshotHostCapabilityFactories(options.hostCapabilityFactories), snapshotLateHostCapabilities(options.lateHostCapabilities), options.enforceRequiredTerminal !== false && options.safeStart !== "none", options.translator);
55
57
  try {
56
58
  await runtime.start(snapshot.plugins);
57
59
  return runtime;
@@ -224,14 +226,21 @@ export class ServerPluginRuntime {
224
226
  const dataDirectory = resolve(this.dataDir, "plugin-data", entry.id);
225
227
  await mkdir(dataDirectory, { recursive: true });
226
228
  const scopedLogger = createScopedLogger(entry.id, this.logger);
229
+ if (loadedPlugin.apiVersion === 3) {
230
+ this.logger.warn({ pluginId: entry.id, apiVersion: 3 }, "Server plugin API v3 is deprecated; migrate to API v5");
231
+ }
227
232
  noticeReporter = createScopedNoticeReporter(entry.id, this.noticeSink);
233
+ const resolveProjectSettings = this.projectSettingsResolver?.bind(undefined, entry.id, settings);
234
+ const workspaceNotifications = this.workspaceNotificationsFactory?.(entry.id);
228
235
  const activationValue = await runBounded(entry.id, phase, this.lifecycleTimeoutMs, (signal) => loadedPlugin.activate(Object.freeze({
229
- apiVersion: 3,
236
+ apiVersion: loadedPlugin.apiVersion,
230
237
  pluginId: entry.id,
231
238
  packageRoot: entry.packageRoot,
232
239
  dataDirectory,
233
240
  logger: scopedLogger,
234
241
  settings,
242
+ ...(resolveProjectSettings === undefined ? {} : { resolveProjectSettings }),
243
+ ...(workspaceNotifications === undefined ? {} : { workspaceNotifications }),
235
244
  ...(noticeReporter === undefined ? {} : { notices: noticeReporter.reporter }),
236
245
  execFile: this.execFile,
237
246
  signal,
@@ -240,7 +249,7 @@ export class ServerPluginRuntime {
240
249
  })));
241
250
  rollbackDispose = activationDisposeForRollback(activationValue);
242
251
  phase = "validate";
243
- const loadedActivation = parseActivation(activationValue, entry.id);
252
+ const loadedActivation = parseActivation(activationValue, entry.id, loadedPlugin.apiVersion);
244
253
  if (this.enforceRequiredTerminal && entry.id === REQUIRED_TERMINAL_PLUGIN_ID) {
245
254
  requireTerminalActivation(loadedActivation);
246
255
  }
@@ -475,6 +484,7 @@ export class ServerPluginRuntime {
475
484
  source: staged.entry.source,
476
485
  scope: staged.entry.scope,
477
486
  moduleRevision: requireServerModule(staged.entry).revision,
487
+ apiVersion: staged.plugin.apiVersion,
478
488
  backend: staged.activation.peer,
479
489
  requires: this.resolvedCapabilityRequirements(staged),
480
490
  });
@@ -681,7 +691,7 @@ function parsePluginExport(imported) {
681
691
  const apiVersion = plugin["apiVersion"];
682
692
  const name = plugin["name"];
683
693
  const activateValue = plugin["activate"];
684
- if (apiVersion !== 3) {
694
+ if (apiVersion !== 3 && apiVersion !== 5) {
685
695
  throw new IncompatibleServerPluginError(`Unsupported server plugin API version: ${formatUnknown(apiVersion)}`);
686
696
  }
687
697
  if (typeof name !== "string" || name === "") {
@@ -692,6 +702,7 @@ function parsePluginExport(imported) {
692
702
  }
693
703
  const requires = snapshotCapabilityRequirements(plugin["requires"], `Server plugin ${name} requirements`);
694
704
  return Object.freeze({
705
+ apiVersion,
695
706
  name,
696
707
  ...(requires.length === 0 ? {} : { requires }),
697
708
  activate(context) {
@@ -710,7 +721,7 @@ function activationDisposeForRollback(value) {
710
721
  await Reflect.apply(dispose, value, [signal]);
711
722
  };
712
723
  }
713
- function parseActivation(value, pluginId) {
724
+ function parseActivation(value, pluginId, apiVersion) {
714
725
  if (!isRecord(value))
715
726
  throw new IncompatibleServerPluginError("Server plugin activation must be an object");
716
727
  if (value["workspaceProviders"] !== undefined) {
@@ -727,7 +738,7 @@ function parseActivation(value, pluginId) {
727
738
  const provides = snapshotCapabilityProvisions(value["provides"], pluginId, `Server plugin ${pluginId} provisions`);
728
739
  const candidate = {
729
740
  workspaceProvider: workspaceProviderValue === undefined ? undefined : snapshotWorkspaceProvider(workspaceProviderValue),
730
- peer: peerValue === undefined ? undefined : snapshotPluginPeer(peerValue),
741
+ peer: peerValue === undefined ? undefined : snapshotPluginPeer(peerValue, apiVersion),
731
742
  provides,
732
743
  start: value["start"],
733
744
  dispose: value["dispose"],
@@ -1041,7 +1052,7 @@ function combinedDisposalError(pluginError, hostCleanupError) {
1041
1052
  return pluginError;
1042
1053
  return new AggregateError([pluginError, hostCleanupError], `${errorMessage(pluginError)}; host capability cleanup failed: ${errorMessage(hostCleanupError)}`);
1043
1054
  }
1044
- function snapshotPluginPeer(value) {
1055
+ function snapshotPluginPeer(value, apiVersion) {
1045
1056
  if (!isPluginPeer(value)) {
1046
1057
  throw new IncompatibleServerPluginError("Server plugin peer must include a request or channel handler");
1047
1058
  }
@@ -1049,10 +1060,10 @@ function snapshotPluginPeer(value) {
1049
1060
  const openChannel = value.openChannel?.bind(value);
1050
1061
  const snapshotRequest = request === undefined
1051
1062
  ? undefined
1052
- : (context) => request(context);
1063
+ : (context) => request(peerContextForVersion(context, apiVersion));
1053
1064
  const snapshotOpenChannel = openChannel === undefined
1054
1065
  ? undefined
1055
- : async (context) => (snapshotPluginPeerChannel(await openChannel(context)));
1066
+ : async (context) => (snapshotPluginPeerChannel(await openChannel(peerContextForVersion(context, apiVersion))));
1056
1067
  if (snapshotRequest !== undefined && snapshotOpenChannel !== undefined) {
1057
1068
  return Object.freeze({ request: snapshotRequest, openChannel: snapshotOpenChannel });
1058
1069
  }
@@ -1062,6 +1073,14 @@ function snapshotPluginPeer(value) {
1062
1073
  return Object.freeze({ openChannel: snapshotOpenChannel });
1063
1074
  throw new IncompatibleServerPluginError("Server plugin peer must include a request or channel handler");
1064
1075
  }
1076
+ function peerContextForVersion(context, apiVersion) {
1077
+ if (apiVersion === 5)
1078
+ return context;
1079
+ if (context.scope.kind !== "workspace")
1080
+ throw new Error("Server plugin API v3 requires workspace scope");
1081
+ const { scope, ...invocation } = context;
1082
+ return Object.freeze({ ...invocation, project: scope.project, workspace: scope.workspace });
1083
+ }
1065
1084
  function isPluginPeer(value) {
1066
1085
  if (!isRecord(value))
1067
1086
  return false;
@@ -1101,17 +1120,20 @@ function snapshotWorkspaceProvider(value) {
1101
1120
  probe: value["probe"],
1102
1121
  list: value["list"],
1103
1122
  prepareRemove: value["prepareRemove"],
1123
+ integration: value["integration"],
1104
1124
  };
1105
1125
  if (!isWorkspaceProvider(candidate))
1106
1126
  throw new IncompatibleServerPluginError("Server plugin workspaceProvider is invalid");
1107
1127
  const probe = candidate.probe.bind(value);
1108
1128
  const list = candidate.list.bind(value);
1109
1129
  const prepareRemove = candidate.prepareRemove?.bind(value);
1130
+ const integration = snapshotWorkspaceProviderIntegration(candidate.integration);
1110
1131
  return Object.freeze({
1111
1132
  ...(candidate.fallback === undefined ? {} : { fallback: candidate.fallback }),
1112
1133
  probe: (project, signal) => probe(project, signal),
1113
1134
  list: (project, signal) => list(project, signal),
1114
1135
  ...(prepareRemove === undefined ? {} : { prepareRemove: (context) => prepareRemove(context) }),
1136
+ ...(integration === undefined ? {} : { integration }),
1115
1137
  });
1116
1138
  }
1117
1139
  function isWorkspaceProvider(value) {
@@ -1124,7 +1146,21 @@ function isWorkspaceProvider(value) {
1124
1146
  return (fallback === undefined || typeof fallback === "boolean")
1125
1147
  && typeof probe === "function"
1126
1148
  && typeof list === "function"
1127
- && (prepareRemove === undefined || typeof prepareRemove === "function");
1149
+ && (prepareRemove === undefined || typeof prepareRemove === "function")
1150
+ && (value["integration"] === undefined || isWorkspaceProviderIntegration(value["integration"]));
1151
+ }
1152
+ function isWorkspaceProviderIntegration(value) {
1153
+ return isRecord(value) && typeof value["reconcile"] === "function" && typeof value["acceptNotification"] === "function";
1154
+ }
1155
+ function snapshotWorkspaceProviderIntegration(value) {
1156
+ if (value === undefined)
1157
+ return undefined;
1158
+ const reconcile = value.reconcile.bind(value);
1159
+ const acceptNotification = value.acceptNotification.bind(value);
1160
+ return Object.freeze({
1161
+ reconcile: (project, signal) => reconcile(project, signal),
1162
+ acceptNotification: (project, signal) => acceptNotification(project, signal),
1163
+ });
1128
1164
  }
1129
1165
  function parseHealth(value) {
1130
1166
  if (!isRecord(value))