@chainingintention/pi-web-cn 2.0.0 → 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 (584) hide show
  1. package/README.md +61 -106
  2. package/dist/.plugins-ready +1 -0
  3. package/dist/cli.js +331 -174
  4. package/dist/cli.js.map +1 -1
  5. package/dist/client/apple-touch-icon-dev.png +0 -0
  6. package/dist/client/assets/PiWebApp-BXSziMEg.js +4921 -0
  7. package/dist/client/assets/classic-CyM97Akm.css +54 -0
  8. package/dist/client/assets/external-B9K8duyP.js +2 -0
  9. package/dist/client/assets/graphite-DquaqFXU.css +54 -0
  10. package/dist/client/assets/index-cdtUOfOW.js +2 -0
  11. package/dist/client/assets/paper-CB1oLuRr.css +54 -0
  12. package/dist/client/assets/pi-web-dark-D_KtbM95.css +54 -0
  13. package/dist/client/assets/pi-web-light-DSNLMIBI.css +54 -0
  14. package/dist/client/assets/vendor-editor-core-BfnHL1Dg.js +10 -0
  15. package/dist/client/assets/vendor-editor-languages-bNquDJP0.js +28 -0
  16. package/dist/client/favicon-dev.svg +8 -0
  17. package/dist/client/index.html +7 -51
  18. package/dist/client/manifest.webmanifest +2 -1
  19. package/dist/client/pwa-icon-dev-192.png +0 -0
  20. package/dist/client/pwa-icon-dev-512.png +0 -0
  21. package/dist/config.js +55 -8
  22. package/dist/config.js.map +1 -1
  23. package/dist/docker/piWebDockerCommandPlan.js +13 -4
  24. package/dist/docker/piWebDockerCommandPlan.js.map +1 -1
  25. package/dist/environment.js +4 -0
  26. package/dist/environment.js.map +1 -0
  27. package/dist/localization.js +24 -0
  28. package/dist/localization.js.map +1 -0
  29. package/dist/nativeServices/installedServiceDefinitions.js +617 -0
  30. package/dist/nativeServices/installedServiceDefinitions.js.map +1 -0
  31. package/dist/nativeServices/serviceAction.js +78 -20
  32. package/dist/nativeServices/serviceAction.js.map +1 -1
  33. package/dist/nativeServices/serviceDoctor.js +418 -114
  34. package/dist/nativeServices/serviceDoctor.js.map +1 -1
  35. package/dist/nativeServices/servicePlan.js +2 -2
  36. package/dist/nativeServices/servicePlan.js.map +1 -1
  37. package/dist/pi-packages/captains-log/README.md +11 -0
  38. package/dist/pi-packages/captains-log/dist/browser/channelProtocol.js +29 -0
  39. package/dist/pi-packages/captains-log/dist/browser/index.js +143 -0
  40. package/dist/pi-packages/captains-log/dist/browser/markdown.js +68 -0
  41. package/dist/pi-packages/captains-log/dist/browser/panel.js +148 -0
  42. package/dist/pi-packages/captains-log/dist/browser/protocol.js +26 -0
  43. package/dist/pi-packages/captains-log/dist/companion.js +126 -0
  44. package/dist/pi-packages/captains-log/dist/roundtrip.js +62 -0
  45. package/dist/pi-packages/captains-log/dist/server.js +210 -0
  46. package/dist/pi-packages/captains-log/dist/store.js +75 -0
  47. package/dist/pi-packages/captains-log/docs/usage.md +29 -0
  48. package/dist/pi-packages/captains-log/i18n.js +7 -0
  49. package/dist/pi-packages/captains-log/package.json +35 -0
  50. package/dist/pi-packages/captains-log/tsconfig.json +21 -0
  51. package/dist/pi-packages/captains-log/vite.config.mjs +28 -0
  52. package/dist/pi-packages/relays/extensions/index.js +61 -0
  53. package/dist/pi-packages/relays/i18n.js +7 -0
  54. package/dist/{pi-web-plugins → pi-packages}/relays/markdownDocument.js +3 -2
  55. package/dist/pi-packages/relays/package.json +20 -0
  56. package/dist/pi-packages/relays/pi-web-plugin.js +96 -0
  57. package/dist/pi-packages/relays/prompts/relay-worktree.md +18 -0
  58. package/dist/pi-packages/relays/prompts/relay.md +18 -0
  59. package/dist/{pi-web-plugins → pi-packages}/relays/relayDiscovery.js +2 -2
  60. package/dist/pi-packages/relays/relayDispatch.js +67 -0
  61. package/dist/pi-packages/relays/relayIdentity.js +37 -0
  62. package/dist/{pi-web-plugins → pi-packages}/relays/relaysPanelElement.js +98 -59
  63. package/dist/pi-packages/relays/skills/relay/SKILL.md +50 -0
  64. package/dist/pi-packages/relays/skills/relay-runner/SKILL.md +74 -0
  65. package/dist/pi-packages/workflows/browser/pi-web-plugin.js +42 -0
  66. package/dist/pi-packages/workflows/browser/worktreeDialog.js +170 -0
  67. package/dist/pi-packages/workflows/package.json +23 -0
  68. package/dist/pi-packages/workflows/prompts/worktree.md +21 -0
  69. package/dist/pi-packages/workflows/server-plugin.js +586 -0
  70. package/dist/pi-packages/workflows/vite.config.mjs +17 -0
  71. package/dist/pi-web-plugins/code-highlight/browser/pi-web-plugin.js +22 -0
  72. package/dist/pi-web-plugins/code-highlight/package.json +13 -0
  73. package/dist/pi-web-plugins/files/browser/assets/files-icon-DZObYhxb.svg +3 -0
  74. package/dist/pi-web-plugins/files/browser/pi-web-plugin.js +466 -0
  75. package/dist/pi-web-plugins/files/package.json +15 -0
  76. package/dist/pi-web-plugins/git/browser/git-contract.js +22 -11
  77. package/dist/pi-web-plugins/git/browser/git-panel.js +228 -100
  78. package/dist/pi-web-plugins/git/browser/i18n.js +7 -0
  79. package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +28 -4
  80. package/dist/pi-web-plugins/git/git-backend.js +61 -21
  81. package/dist/pi-web-plugins/git/gitStatusCache.js +48 -0
  82. package/dist/pi-web-plugins/git/i18n.js +7 -0
  83. package/dist/pi-web-plugins/git/package.json +1 -0
  84. package/dist/pi-web-plugins/git/server-plugin.js +45 -24
  85. package/dist/pi-web-plugins/git/workspace-discovery-notify.cjs +14 -0
  86. package/dist/pi-web-plugins/git/workspaceDiscoveryHooks.js +186 -0
  87. package/dist/pi-web-plugins/info/i18n.js +7 -0
  88. package/dist/pi-web-plugins/info/infoInternals.js +76 -65
  89. package/dist/pi-web-plugins/info/package.json +1 -1
  90. package/dist/pi-web-plugins/info/pi-web-plugin.js +40 -42
  91. package/dist/pi-web-plugins/mermaid/browser/mermaid-engine.js +4255 -0
  92. package/dist/pi-web-plugins/mermaid/browser/pi-web-plugin.js +11 -0
  93. package/dist/pi-web-plugins/mermaid/package.json +13 -0
  94. package/dist/pi-web-plugins/terminal/browser/pi-web-plugin.js +219 -0
  95. package/dist/pi-web-plugins/terminal/i18n.js +7 -0
  96. package/dist/pi-web-plugins/terminal/package.json +16 -0
  97. package/dist/pi-web-plugins/terminal/server-plugin.js +367 -0
  98. package/dist/pi-web-plugins/terminal/terminalService.js +436 -0
  99. package/dist/pi-web-plugins/updates/i18n.js +7 -0
  100. package/dist/pi-web-plugins/updates/package.json +1 -1
  101. package/dist/pi-web-plugins/updates/pi-web-plugin.js +143 -140
  102. package/dist/pi-web-plugins/updates/updatesLogic.js +24 -24
  103. package/dist/pi-web-plugins/workspace-tasks/config.js +12 -11
  104. package/dist/pi-web-plugins/workspace-tasks/i18n.js +7 -0
  105. package/dist/pi-web-plugins/workspace-tasks/package.json +1 -1
  106. package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +31 -9
  107. package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +54 -36
  108. package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +12 -11
  109. package/dist/pi-web-plugins/zh-cn/auth.json +9 -0
  110. package/dist/pi-web-plugins/zh-cn/bundled.json +219 -0
  111. package/dist/pi-web-plugins/zh-cn/cli.json +230 -0
  112. package/dist/pi-web-plugins/zh-cn/client.json +225 -0
  113. package/dist/pi-web-plugins/zh-cn/components.json +1252 -0
  114. package/dist/pi-web-plugins/zh-cn/config-errors.json +188 -0
  115. package/dist/pi-web-plugins/zh-cn/files.json +50 -0
  116. package/dist/pi-web-plugins/zh-cn/machines.json +28 -0
  117. package/dist/pi-web-plugins/zh-cn/main.json +459 -0
  118. package/dist/pi-web-plugins/zh-cn/management-errors.json +23 -0
  119. package/dist/pi-web-plugins/zh-cn/manifest.webmanifest +25 -0
  120. package/dist/pi-web-plugins/zh-cn/metadata.json +3 -0
  121. package/dist/pi-web-plugins/zh-cn/package.json +10 -0
  122. package/dist/pi-web-plugins/zh-cn/pi-web-plugin.js +16 -0
  123. package/dist/pi-web-plugins/zh-cn/projects.json +6 -0
  124. package/dist/pi-web-plugins/zh-cn/provider-auth.json +18 -0
  125. package/dist/pi-web-plugins/zh-cn/routing.json +68 -0
  126. package/dist/pi-web-plugins/zh-cn/server-main.json +99 -0
  127. package/dist/pi-web-plugins/zh-cn/server.json +256 -0
  128. package/dist/piAi.js +4 -0
  129. package/dist/piAi.js.map +1 -0
  130. package/dist/piRuntime.js +150 -0
  131. package/dist/piRuntime.js.map +1 -0
  132. package/dist/piSdk.js +5 -0
  133. package/dist/piSdk.js.map +1 -0
  134. package/dist/piWebUpdate.js +508 -0
  135. package/dist/piWebUpdate.js.map +1 -0
  136. package/dist/piWebVersionReport.js +109 -41
  137. package/dist/piWebVersionReport.js.map +1 -1
  138. package/dist/plugin-api.d.ts +609 -29
  139. package/dist/plugin-api.js +1 -0
  140. package/dist/pluginRecoveryCli.js +27 -25
  141. package/dist/pluginRecoveryCli.js.map +1 -1
  142. package/dist/server/activity/workspaceActivityService.js +13 -6
  143. package/dist/server/activity/workspaceActivityService.js.map +1 -1
  144. package/dist/server/app.js +155 -77
  145. package/dist/server/app.js.map +1 -1
  146. package/dist/server/audit/managementAuditStore.js +6 -1
  147. package/dist/server/audit/managementAuditStore.js.map +1 -1
  148. package/dist/server/audit/normalToolAuditCli.js +45 -43
  149. package/dist/server/audit/normalToolAuditCli.js.map +1 -1
  150. package/dist/server/browserMessageProjection.js +39 -22
  151. package/dist/server/browserMessageProjection.js.map +1 -1
  152. package/dist/server/configRoutes.js +54 -33
  153. package/dist/server/configRoutes.js.map +1 -1
  154. package/dist/server/deploymentIdentity.js +67 -0
  155. package/dist/server/deploymentIdentity.js.map +1 -0
  156. package/dist/server/deploymentIdentityRoutes.js +22 -0
  157. package/dist/server/deploymentIdentityRoutes.js.map +1 -0
  158. package/dist/server/diagnostics/nodePtyNativeModule.js +7 -6
  159. package/dist/server/diagnostics/nodePtyNativeModule.js.map +1 -1
  160. package/dist/server/diagnostics/nodePtySpawnHelper.js +21 -20
  161. package/dist/server/diagnostics/nodePtySpawnHelper.js.map +1 -1
  162. package/dist/server/index.js +10 -1
  163. package/dist/server/index.js.map +1 -1
  164. package/dist/server/knownAutoInstallPiPackages.js +36 -0
  165. package/dist/server/knownAutoInstallPiPackages.js.map +1 -0
  166. package/dist/server/knownPiPackages.js +12 -0
  167. package/dist/server/knownPiPackages.js.map +1 -0
  168. package/dist/server/machines/machineClient.js +23 -19
  169. package/dist/server/machines/machineClient.js.map +1 -1
  170. package/dist/server/machines/machinePluginProxyRoutes.js +131 -31
  171. package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -1
  172. package/dist/server/machines/machineProxyRoutes.js +138 -47
  173. package/dist/server/machines/machineProxyRoutes.js.map +1 -1
  174. package/dist/server/machines/machineRoutes.js +18 -13
  175. package/dist/server/machines/machineRoutes.js.map +1 -1
  176. package/dist/server/machines/machineService.js +40 -18
  177. package/dist/server/machines/machineService.js.map +1 -1
  178. package/dist/server/managementEmbed.js +149 -30
  179. package/dist/server/managementEmbed.js.map +1 -1
  180. package/dist/server/managementPrivileges.js +21 -0
  181. package/dist/server/managementPrivileges.js.map +1 -0
  182. package/dist/server/managementTerminalProxyRoutes.js +124 -0
  183. package/dist/server/managementTerminalProxyRoutes.js.map +1 -0
  184. package/dist/server/navigationPreferenceRoutes.js +59 -0
  185. package/dist/server/navigationPreferenceRoutes.js.map +1 -0
  186. package/dist/server/normalAuth.js +77 -53
  187. package/dist/server/normalAuth.js.map +1 -1
  188. package/dist/server/notices/serverNoticeRoutes.js +43 -0
  189. package/dist/server/notices/serverNoticeRoutes.js.map +1 -0
  190. package/dist/server/notices/serverNoticeService.js +26 -0
  191. package/dist/server/notices/serverNoticeService.js.map +1 -0
  192. package/dist/server/notices/serverNoticeStore.js +122 -0
  193. package/dist/server/notices/serverNoticeStore.js.map +1 -0
  194. package/dist/server/passwordVerifier.js +91 -0
  195. package/dist/server/passwordVerifier.js.map +1 -0
  196. package/dist/server/piPackageIdentity.js +25 -0
  197. package/dist/server/piPackageIdentity.js.map +1 -0
  198. package/dist/server/piPackageService.js +72 -9
  199. package/dist/server/piPackageService.js.map +1 -1
  200. package/dist/server/piWebPluginCatalog.js +212 -35
  201. package/dist/server/piWebPluginCatalog.js.map +1 -1
  202. package/dist/server/piWebPluginLifecycle.js +29 -3
  203. package/dist/server/piWebPluginLifecycle.js.map +1 -1
  204. package/dist/server/piWebPluginService.js +199 -292
  205. package/dist/server/piWebPluginService.js.map +1 -1
  206. package/dist/server/piWebStatus.js +57 -100
  207. package/dist/server/piWebStatus.js.map +1 -1
  208. package/dist/server/pluginCallbackDrain.js +35 -0
  209. package/dist/server/pluginCallbackDrain.js.map +1 -0
  210. package/dist/server/plugins/pluginBackendChannelProxyAdmission.js +84 -0
  211. package/dist/server/plugins/pluginBackendChannelProxyAdmission.js.map +1 -0
  212. package/dist/server/plugins/pluginBackendChannelProxyCoordinator.js +234 -0
  213. package/dist/server/plugins/pluginBackendChannelProxyCoordinator.js.map +1 -0
  214. package/dist/server/plugins/pluginBackendChannelProxyRoutes.js +61 -0
  215. package/dist/server/plugins/pluginBackendChannelProxyRoutes.js.map +1 -0
  216. package/dist/server/plugins/pluginBackendProxyRoutes.js +47 -57
  217. package/dist/server/plugins/pluginBackendProxyRoutes.js.map +1 -1
  218. package/dist/server/plugins/pluginBackendRegistry.js +804 -0
  219. package/dist/server/plugins/pluginBackendRegistry.js.map +1 -0
  220. package/dist/server/plugins/projectPluginSettings.js +95 -0
  221. package/dist/server/plugins/projectPluginSettings.js.map +1 -0
  222. package/dist/server/plugins/serverPluginCatalogCapability.js +106 -0
  223. package/dist/server/plugins/serverPluginCatalogCapability.js.map +1 -0
  224. package/dist/server/plugins/serverPluginPiSessionEventsCapability.js +34 -0
  225. package/dist/server/plugins/serverPluginPiSessionEventsCapability.js.map +1 -0
  226. package/dist/server/plugins/serverPluginPiSessionsCapability.js +185 -0
  227. package/dist/server/plugins/serverPluginPiSessionsCapability.js.map +1 -0
  228. package/dist/server/plugins/serverPluginRuntime.js +1088 -108
  229. package/dist/server/plugins/serverPluginRuntime.js.map +1 -1
  230. package/dist/server/plugins/serverPluginWorkspacesCapability.js +114 -0
  231. package/dist/server/plugins/serverPluginWorkspacesCapability.js.map +1 -0
  232. package/dist/server/projectTrustRoutes.js +86 -0
  233. package/dist/server/projectTrustRoutes.js.map +1 -0
  234. package/dist/server/projects/projectLifecycleService.js +94 -0
  235. package/dist/server/projects/projectLifecycleService.js.map +1 -0
  236. package/dist/server/projects/projectService.js +7 -4
  237. package/dist/server/projects/projectService.js.map +1 -1
  238. package/dist/server/realtime/sessionEventHub.js +58 -39
  239. package/dist/server/realtime/sessionEventHub.js.map +1 -1
  240. package/dist/server/realtime/sessionEventScope.js +4 -0
  241. package/dist/server/realtime/sessionEventScope.js.map +1 -1
  242. package/dist/server/requestCancellation.js +15 -1
  243. package/dist/server/requestCancellation.js.map +1 -1
  244. package/dist/server/sessiond/agentHttpDispatcher.js +108 -0
  245. package/dist/server/sessiond/agentHttpDispatcher.js.map +1 -0
  246. package/dist/server/sessiond/autoInstallPiPackages.js +63 -0
  247. package/dist/server/sessiond/autoInstallPiPackages.js.map +1 -0
  248. package/dist/server/sessiond/pluginBackendChannelRoutes.js +410 -0
  249. package/dist/server/sessiond/pluginBackendChannelRoutes.js.map +1 -0
  250. package/dist/server/sessiond/pluginBackendRoutes.js +64 -47
  251. package/dist/server/sessiond/pluginBackendRoutes.js.map +1 -1
  252. package/dist/server/sessiond/pluginCatalogRoutes.js +41 -0
  253. package/dist/server/sessiond/pluginCatalogRoutes.js.map +1 -0
  254. package/dist/server/sessiond/projectMutationRoutes.js +39 -0
  255. package/dist/server/sessiond/projectMutationRoutes.js.map +1 -0
  256. package/dist/server/sessiond/sessionDaemonShutdown.js +36 -0
  257. package/dist/server/sessiond/sessionDaemonShutdown.js.map +1 -0
  258. package/dist/server/sessiond/sessionDaemonStartup.js +30 -4
  259. package/dist/server/sessiond/sessionDaemonStartup.js.map +1 -1
  260. package/dist/server/sessiond/sessionProxyRoutes.js +263 -91
  261. package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
  262. package/dist/server/sessiond/sessionServiceDependencies.js +5 -0
  263. package/dist/server/sessiond/sessionServiceDependencies.js.map +1 -1
  264. package/dist/server/sessiond/sessiondStateOwnership.js +174 -39
  265. package/dist/server/sessiond/sessiondStateOwnership.js.map +1 -1
  266. package/dist/server/sessiond/workspaceCatalogRoutes.js +11 -5
  267. package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -1
  268. package/dist/server/sessiond/workspaceNotificationRoutes.js +55 -0
  269. package/dist/server/sessiond/workspaceNotificationRoutes.js.map +1 -0
  270. package/dist/server/sessiond/workspaceRemovalRoutes.js +1 -1
  271. package/dist/server/sessiond/workspaceRemovalRoutes.js.map +1 -1
  272. package/dist/server/sessiond.js +313 -69
  273. package/dist/server/sessiond.js.map +1 -1
  274. package/dist/server/sessions/askUserDomain.js +232 -0
  275. package/dist/server/sessions/askUserDomain.js.map +1 -0
  276. package/dist/server/sessions/askUserTool.js +18 -21
  277. package/dist/server/sessions/askUserTool.js.map +1 -1
  278. package/dist/server/sessions/attachmentService.js +2 -6
  279. package/dist/server/sessions/attachmentService.js.map +1 -1
  280. package/dist/server/sessions/authRoutes.js +32 -19
  281. package/dist/server/sessions/authRoutes.js.map +1 -1
  282. package/dist/server/sessions/authService.js +31 -11
  283. package/dist/server/sessions/authService.js.map +1 -1
  284. package/dist/server/sessions/builtinCommands.js +28 -21
  285. package/dist/server/sessions/builtinCommands.js.map +1 -1
  286. package/dist/server/sessions/builtinExtensionFactories.js +36 -0
  287. package/dist/server/sessions/builtinExtensionFactories.js.map +1 -0
  288. package/dist/server/sessions/clientSessionPreview.js +14 -0
  289. package/dist/server/sessions/clientSessionPreview.js.map +1 -0
  290. package/dist/server/sessions/companionBackend.js +286 -0
  291. package/dist/server/sessions/companionBackend.js.map +1 -0
  292. package/dist/server/sessions/dockerEnvironmentFacts.js +98 -10
  293. package/dist/server/sessions/dockerEnvironmentFacts.js.map +1 -1
  294. package/dist/server/sessions/extensionSessionDispatch.js +76 -0
  295. package/dist/server/sessions/extensionSessionDispatch.js.map +1 -0
  296. package/dist/server/sessions/globalProviderPolicy.js +88 -19
  297. package/dist/server/sessions/globalProviderPolicy.js.map +1 -1
  298. package/dist/server/sessions/managementAgentTools.js +116 -6
  299. package/dist/server/sessions/managementAgentTools.js.map +1 -1
  300. package/dist/server/sessions/managementPermissionSystem.js +36 -14
  301. package/dist/server/sessions/managementPermissionSystem.js.map +1 -1
  302. package/dist/server/sessions/managementSandbox.js +7 -18
  303. package/dist/server/sessions/managementSandbox.js.map +1 -1
  304. package/dist/server/sessions/mcpAuthFlowService.js +289 -0
  305. package/dist/server/sessions/mcpAuthFlowService.js.map +1 -0
  306. package/dist/server/sessions/mcpAuthRoutes.js +104 -0
  307. package/dist/server/sessions/mcpAuthRoutes.js.map +1 -0
  308. package/dist/server/sessions/mcpOAuthCredentialAdapter.js +92 -0
  309. package/dist/server/sessions/mcpOAuthCredentialAdapter.js.map +1 -0
  310. package/dist/server/sessions/messageHistoryTarget.js +79 -0
  311. package/dist/server/sessions/messageHistoryTarget.js.map +1 -0
  312. package/dist/server/sessions/messagePaging.js +2 -2
  313. package/dist/server/sessions/messagePaging.js.map +1 -1
  314. package/dist/server/sessions/modelCatalogRefresher.js +4 -3
  315. package/dist/server/sessions/modelCatalogRefresher.js.map +1 -1
  316. package/dist/server/sessions/oauthLoginFlowService.js +19 -20
  317. package/dist/server/sessions/oauthLoginFlowService.js.map +1 -1
  318. package/dist/server/sessions/piSessionEventConnections.js +68 -0
  319. package/dist/server/sessions/piSessionEventConnections.js.map +1 -0
  320. package/dist/server/sessions/piSessionManagerGateway.js +206 -27
  321. package/dist/server/sessions/piSessionManagerGateway.js.map +1 -1
  322. package/dist/server/sessions/piSessionService.js +2508 -991
  323. package/dist/server/sessions/piSessionService.js.map +1 -1
  324. package/dist/server/sessions/plainTextTheme.js +1 -1
  325. package/dist/server/sessions/plainTextTheme.js.map +1 -1
  326. package/dist/server/sessions/projectAuthService.js +35 -6
  327. package/dist/server/sessions/projectAuthService.js.map +1 -1
  328. package/dist/server/sessions/projectSettingsScope.js +88 -33
  329. package/dist/server/sessions/projectSettingsScope.js.map +1 -1
  330. package/dist/server/sessions/projectTrust.js +119 -0
  331. package/dist/server/sessions/projectTrust.js.map +1 -0
  332. package/dist/server/sessions/queuedMessageMutation.js +170 -0
  333. package/dist/server/sessions/queuedMessageMutation.js.map +1 -0
  334. package/dist/server/sessions/relaySkill.js +169 -0
  335. package/dist/server/sessions/relaySkill.js.map +1 -0
  336. package/dist/server/sessions/sessionActivityMarker.js +105 -0
  337. package/dist/server/sessions/sessionActivityMarker.js.map +1 -0
  338. package/dist/server/sessions/sessionArchiveMapping.js +16 -15
  339. package/dist/server/sessions/sessionArchiveMapping.js.map +1 -1
  340. package/dist/server/sessions/sessionArchiveStore.js +5 -1
  341. package/dist/server/sessions/sessionArchiveStore.js.map +1 -1
  342. package/dist/server/sessions/sessionArchiveTree.js +2 -2
  343. package/dist/server/sessions/sessionArchiveTree.js.map +1 -1
  344. package/dist/server/sessions/sessionCleanup.js +4 -3
  345. package/dist/server/sessions/sessionCleanup.js.map +1 -1
  346. package/dist/server/sessions/sessionCommandService.js +79 -87
  347. package/dist/server/sessions/sessionCommandService.js.map +1 -1
  348. package/dist/server/sessions/sessionEnvironmentFacts.js +5 -4
  349. package/dist/server/sessions/sessionEnvironmentFacts.js.map +1 -1
  350. package/dist/server/sessions/sessionFileHeader.js +41 -0
  351. package/dist/server/sessions/sessionFileHeader.js.map +1 -1
  352. package/dist/server/sessions/sessionImageDimensions.js +31 -0
  353. package/dist/server/sessions/sessionImageDimensions.js.map +1 -0
  354. package/dist/server/sessions/sessionMediaIndex.js +191 -0
  355. package/dist/server/sessions/sessionMediaIndex.js.map +1 -0
  356. package/dist/server/sessions/sessionMetadata.js +51 -0
  357. package/dist/server/sessions/sessionMetadata.js.map +1 -0
  358. package/dist/server/sessions/sessionModelScope.js +160 -0
  359. package/dist/server/sessions/sessionModelScope.js.map +1 -0
  360. package/dist/server/sessions/sessionNameGenerator.js +16 -35
  361. package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
  362. package/dist/server/sessions/sessionNotificationStore.js +14 -11
  363. package/dist/server/sessions/sessionNotificationStore.js.map +1 -1
  364. package/dist/server/sessions/sessionReadAccess.js +41 -0
  365. package/dist/server/sessions/sessionReadAccess.js.map +1 -0
  366. package/dist/server/sessions/sessionRoutes.js +221 -78
  367. package/dist/server/sessions/sessionRoutes.js.map +1 -1
  368. package/dist/server/sessions/sessionSummaryScanner.js +62 -5
  369. package/dist/server/sessions/sessionSummaryScanner.js.map +1 -1
  370. package/dist/server/sessions/sessionTreeProjection.js +50 -49
  371. package/dist/server/sessions/sessionTreeProjection.js.map +1 -1
  372. package/dist/server/sessions/sessionUiEvents.js +22 -10
  373. package/dist/server/sessions/sessionUiEvents.js.map +1 -1
  374. package/dist/server/sessions/sessionUnreadStore.js +53 -3
  375. package/dist/server/sessions/sessionUnreadStore.js.map +1 -1
  376. package/dist/server/sessions/spawnSessionTool.js +14 -6
  377. package/dist/server/sessions/spawnSessionTool.js.map +1 -1
  378. package/dist/server/sessions/spawnSubsessionTool.js +40 -24
  379. package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
  380. package/dist/server/sessions/spawnTargetResolver.js +1 -1
  381. package/dist/server/sessions/subsessionCompletionDelivery.js +15 -0
  382. package/dist/server/sessions/subsessionCompletionDelivery.js.map +1 -0
  383. package/dist/server/sessions/subsessionCompletionInbox.js +134 -0
  384. package/dist/server/sessions/subsessionCompletionInbox.js.map +1 -0
  385. package/dist/server/sessions/subsessionProvenance.js +27 -0
  386. package/dist/server/sessions/subsessionProvenance.js.map +1 -0
  387. package/dist/server/sessions/transcriptBranchCache.js +81 -0
  388. package/dist/server/sessions/transcriptBranchCache.js.map +1 -0
  389. package/dist/server/sessions/transcriptMarkdown.js +48 -0
  390. package/dist/server/sessions/transcriptMarkdown.js.map +1 -0
  391. package/dist/server/sessions/transcriptMessages.js +57 -0
  392. package/dist/server/sessions/transcriptMessages.js.map +1 -0
  393. package/dist/server/startupLogger.js +13 -0
  394. package/dist/server/startupLogger.js.map +1 -0
  395. package/dist/server/startupUrls.js +27 -0
  396. package/dist/server/startupUrls.js.map +1 -0
  397. package/dist/server/status/machineStatusService.js +15 -7
  398. package/dist/server/status/machineStatusService.js.map +1 -1
  399. package/dist/server/storage/navigationPreferenceStore.js +138 -0
  400. package/dist/server/storage/navigationPreferenceStore.js.map +1 -0
  401. package/dist/server/storage/piPackageDismissalStore.js +78 -0
  402. package/dist/server/storage/piPackageDismissalStore.js.map +1 -0
  403. package/dist/server/terminals/{terminalService.js → managementCommandRunService.js} +98 -102
  404. package/dist/server/terminals/managementCommandRunService.js.map +1 -0
  405. package/dist/server/terminals/managementTerminalRoutes.js +91 -0
  406. package/dist/server/terminals/managementTerminalRoutes.js.map +1 -0
  407. package/dist/server/terminals/requiredTerminalService.js +103 -0
  408. package/dist/server/terminals/requiredTerminalService.js.map +1 -0
  409. package/dist/server/webSocketBridge.js +348 -0
  410. package/dist/server/webSocketBridge.js.map +1 -1
  411. package/dist/server/workbench/accessStateStore.js +33 -5
  412. package/dist/server/workbench/accessStateStore.js.map +1 -1
  413. package/dist/server/workbench/capabilitySearch.js +3 -2
  414. package/dist/server/workbench/capabilitySearch.js.map +1 -1
  415. package/dist/server/workbench/gatewayIntegration.js +40 -13
  416. package/dist/server/workbench/gatewayIntegration.js.map +1 -1
  417. package/dist/server/workbench/knowledgeSearch.js +100 -0
  418. package/dist/server/workbench/knowledgeSearch.js.map +1 -0
  419. package/dist/server/workbench/mcpClient.js +41 -8
  420. package/dist/server/workbench/mcpClient.js.map +1 -1
  421. package/dist/server/workbench/skillSync.js +11 -3
  422. package/dist/server/workbench/skillSync.js.map +1 -1
  423. package/dist/server/workbench/workbenchClient.js +130 -7
  424. package/dist/server/workbench/workbenchClient.js.map +1 -1
  425. package/dist/server/workbench/workbenchTools.js +196 -14
  426. package/dist/server/workbench/workbenchTools.js.map +1 -1
  427. package/dist/server/workingDirectory.js +3 -2
  428. package/dist/server/workingDirectory.js.map +1 -1
  429. package/dist/server/workspaceExplorerRoutes.js +53 -21
  430. package/dist/server/workspaceExplorerRoutes.js.map +1 -1
  431. package/dist/server/workspaces/fileContentService.js +31 -16
  432. package/dist/server/workspaces/fileContentService.js.map +1 -1
  433. package/dist/server/workspaces/fileOperationService.js +11 -9
  434. package/dist/server/workspaces/fileOperationService.js.map +1 -1
  435. package/dist/server/workspaces/filePreviewService.js +10 -6
  436. package/dist/server/workspaces/filePreviewService.js.map +1 -1
  437. package/dist/server/workspaces/fileSuggestions.js +77 -10
  438. package/dist/server/workspaces/fileSuggestions.js.map +1 -1
  439. package/dist/server/workspaces/fileTreeService.js +103 -15
  440. package/dist/server/workspaces/fileTreeService.js.map +1 -1
  441. package/dist/server/workspaces/normalProjectCwdResolver.js +35 -0
  442. package/dist/server/workspaces/normalProjectCwdResolver.js.map +1 -0
  443. package/dist/server/workspaces/pathAccessPolicy.js +24 -18
  444. package/dist/server/workspaces/pathAccessPolicy.js.map +1 -1
  445. package/dist/server/workspaces/pathSafety.js +6 -5
  446. package/dist/server/workspaces/pathSafety.js.map +1 -1
  447. package/dist/server/workspaces/projectPiWebConfig.js +95 -8
  448. package/dist/server/workspaces/projectPiWebConfig.js.map +1 -1
  449. package/dist/server/workspaces/projectWorkspaceCwds.js +0 -5
  450. package/dist/server/workspaces/projectWorkspaceCwds.js.map +1 -1
  451. package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js +37 -22
  452. package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js.map +1 -1
  453. package/dist/server/workspaces/workspaceCatalog.js +6 -4
  454. package/dist/server/workspaces/workspaceCatalog.js.map +1 -1
  455. package/dist/server/workspaces/workspaceChangeNotifier.js +12 -0
  456. package/dist/server/workspaces/workspaceChangeNotifier.js.map +1 -0
  457. package/dist/server/workspaces/workspaceDeletionRoutes.js +9 -70
  458. package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -1
  459. package/dist/server/workspaces/workspaceNotificationCommand.js +64 -0
  460. package/dist/server/workspaces/workspaceNotificationCommand.js.map +1 -0
  461. package/dist/server/workspaces/workspaceProviderRegistry.js +128 -24
  462. package/dist/server/workspaces/workspaceProviderRegistry.js.map +1 -1
  463. package/dist/server/workspaces/workspaceRemovalService.js +41 -7
  464. package/dist/server/workspaces/workspaceRemovalService.js.map +1 -1
  465. package/dist/server/workspaces/workspaceRouteContext.js +1 -1
  466. package/dist/server/workspaces/workspaceRouteContext.js.map +1 -1
  467. package/dist/server/workspaces/workspaceRouteErrors.js +4 -2
  468. package/dist/server/workspaces/workspaceRouteErrors.js.map +1 -1
  469. package/dist/server/workspaces/workspaceUserError.js +18 -0
  470. package/dist/server/workspaces/workspaceUserError.js.map +1 -0
  471. package/dist/server-plugin-api.d.ts +349 -49
  472. package/dist/server-plugin-api.js +344 -2
  473. package/dist/server-plugin-api.js.map +1 -1
  474. package/dist/serverPluginRecovery.js +6 -1
  475. package/dist/serverPluginRecovery.js.map +1 -1
  476. package/dist/sessiond/activeAgentProfile.js +27 -2
  477. package/dist/sessiond/activeAgentProfile.js.map +1 -1
  478. package/dist/sessiond/config.js +4 -3
  479. package/dist/sessiond/config.js.map +1 -1
  480. package/dist/sessiond/sessionDaemonClient.js +75 -19
  481. package/dist/sessiond/sessionDaemonClient.js.map +1 -1
  482. package/dist/sessiond/sessionDaemonErrors.js +49 -0
  483. package/dist/sessiond/sessionDaemonErrors.js.map +1 -0
  484. package/dist/shared/activeAgentProfile.js +2 -34
  485. package/dist/shared/activeAgentProfile.js.map +1 -1
  486. package/dist/shared/activity.js +0 -3
  487. package/dist/shared/activity.js.map +1 -1
  488. package/dist/shared/apiTypes.js +10 -3
  489. package/dist/shared/apiTypes.js.map +1 -1
  490. package/dist/shared/capabilities.js +8 -0
  491. package/dist/shared/capabilities.js.map +1 -1
  492. package/dist/shared/federatedRoutes.js +77 -11
  493. package/dist/shared/federatedRoutes.js.map +1 -1
  494. package/dist/shared/i18n.js +41 -0
  495. package/dist/shared/i18n.js.map +1 -0
  496. package/dist/shared/machinePluginIds.js +30 -7
  497. package/dist/shared/machinePluginIds.js.map +1 -1
  498. package/dist/shared/machineStatus.js +46 -3
  499. package/dist/shared/machineStatus.js.map +1 -1
  500. package/dist/shared/navigationPreferences.js +6 -0
  501. package/dist/shared/navigationPreferences.js.map +1 -0
  502. package/dist/shared/piWebConfigParsing.js +118 -49
  503. package/dist/shared/piWebConfigParsing.js.map +1 -1
  504. package/dist/shared/piWebStatusParsing.js +33 -0
  505. package/dist/shared/piWebStatusParsing.js.map +1 -1
  506. package/dist/shared/pluginApiTypes.d.ts +87 -8
  507. package/dist/shared/pluginApiTypes.js +2 -0
  508. package/dist/shared/pluginApiTypes.js.map +1 -0
  509. package/dist/shared/pluginBackendProtocol.js +218 -2
  510. package/dist/shared/pluginBackendProtocol.js.map +1 -1
  511. package/dist/shared/pluginCatalogTypes.d.ts +49 -0
  512. package/dist/shared/pluginCatalogTypes.js +156 -0
  513. package/dist/shared/pluginCatalogTypes.js.map +1 -0
  514. package/dist/shared/pluginIds.js +10 -1
  515. package/dist/shared/pluginIds.js.map +1 -1
  516. package/dist/shared/requiredTerminalPlugin.js +6 -0
  517. package/dist/shared/requiredTerminalPlugin.js.map +1 -0
  518. package/dist/shared/serverNoticeContract.js +88 -0
  519. package/dist/shared/serverNoticeContract.js.map +1 -0
  520. package/dist/shared/sessionDefaults.js +42 -0
  521. package/dist/shared/sessionDefaults.js.map +1 -0
  522. package/dist/shared/sessionMedia.js +12 -0
  523. package/dist/shared/sessionMedia.js.map +1 -0
  524. package/dist/shared/streamingBehavior.js +8 -0
  525. package/dist/shared/streamingBehavior.js.map +1 -0
  526. package/dist/shared/themePreference.js +24 -0
  527. package/dist/shared/themePreference.js.map +1 -0
  528. package/dist/shared/thinkingLevels.js +17 -16
  529. package/dist/shared/thinkingLevels.js.map +1 -1
  530. package/dist/shared/workspaceFiles.js.map +1 -1
  531. package/dist/workspaceNotificationCli.js +95 -0
  532. package/dist/workspaceNotificationCli.js.map +1 -0
  533. package/docs/README.md +31 -0
  534. package/docs/config.md +344 -277
  535. package/docs/plugins.md +204 -930
  536. package/examples/session-bridge-plugin/README.md +20 -0
  537. package/examples/session-bridge-plugin/docs/usage.md +54 -0
  538. package/examples/session-bridge-plugin/package.json +26 -0
  539. package/examples/session-bridge-plugin/src/browser/index.ts +87 -0
  540. package/examples/session-bridge-plugin/src/browser/protocol.ts +24 -0
  541. package/examples/session-bridge-plugin/src/companion.ts +65 -0
  542. package/examples/session-bridge-plugin/src/reviewRun.ts +39 -0
  543. package/examples/session-bridge-plugin/src/server.ts +85 -0
  544. package/examples/session-bridge-plugin/src/store.ts +80 -0
  545. package/examples/session-bridge-plugin/tsconfig.json +21 -0
  546. package/examples/workspace-provider-plugin/README.md +39 -0
  547. package/examples/workspace-provider-plugin/package.json +25 -0
  548. package/examples/workspace-provider-plugin/src/browser/index.ts +69 -0
  549. package/examples/workspace-provider-plugin/src/server.ts +68 -0
  550. package/examples/workspace-provider-plugin/tsconfig.json +21 -0
  551. package/extensions/pi-web.ts +3 -1
  552. package/package.json +59 -36
  553. package/skills/README.md +28 -2
  554. package/skills/relay/SKILL.md +24 -89
  555. package/skills/relay-runner/SKILL.md +74 -0
  556. package/dist/client/assets/CodeViewer-DCl56K0Z.js +0 -4
  557. package/dist/client/assets/TerminalPanel-DCvoEjUF.js +0 -187
  558. package/dist/client/assets/index-CMvms5cF.js +0 -4325
  559. package/dist/client/assets/vendor-editor-core-vUi74DnD.js +0 -12
  560. package/dist/client/assets/vendor-editor-languages-DoaXUodB.js +0 -46
  561. package/dist/client/assets/vendor-editor-legacy-CYBnW6ZU.js +0 -1
  562. package/dist/client/assets/vendor-terminal-BrP-ENHg.css +0 -1
  563. package/dist/client/assets/vendor-terminal-D8k4UKM2.js +0 -35
  564. package/dist/pi-web-plugins/relays/package.json +0 -9
  565. package/dist/pi-web-plugins/relays/pi-web-plugin.js +0 -44
  566. package/dist/server/git/gitService.js +0 -290
  567. package/dist/server/git/gitService.js.map +0 -1
  568. package/dist/server/gitRoutes.js +0 -23
  569. package/dist/server/gitRoutes.js.map +0 -1
  570. package/dist/server/sessions/pendingAskStore.js +0 -278
  571. package/dist/server/sessions/pendingAskStore.js.map +0 -1
  572. package/dist/server/terminalProxyRoutes.js +0 -178
  573. package/dist/server/terminalProxyRoutes.js.map +0 -1
  574. package/dist/server/terminals/terminalRoutes.js +0 -164
  575. package/dist/server/terminals/terminalRoutes.js.map +0 -1
  576. package/dist/server/terminals/terminalService.js.map +0 -1
  577. package/dist/server/terminals/terminalSize.js +0 -17
  578. package/dist/server/terminals/terminalSize.js.map +0 -1
  579. package/dist/server/workspaces/gitWorktreeDiscovery.js +0 -43
  580. package/dist/server/workspaces/gitWorktreeDiscovery.js.map +0 -1
  581. package/dist/server/workspaces/workspaceService.js +0 -52
  582. package/dist/server/workspaces/workspaceService.js.map +0 -1
  583. /package/dist/{pi-web-plugins → pi-packages}/relays/vendor/README.md +0 -0
  584. /package/dist/{pi-web-plugins → pi-packages}/relays/vendor/marked.esm.js +0 -0
@@ -1,7 +1,10 @@
1
- // Generated from pi-web-plugins/relays/relaysPanelElement.ts. Do not edit directly.
1
+ // Generated from pi-packages/relays/relaysPanelElement.ts. Do not edit directly.
2
+ import { t } from "./i18n.js";
2
3
  import { isMarkdownDocumentPath, renderRelayDocumentHtml } from "./markdownDocument.js";
4
+ import { isRelayPacketPath } from "./relayIdentity.js";
3
5
  import { ancestorDirectoryPaths, collectDirectoryPaths, defaultRelayDocument, flattenRelayTree, listRelayDocumentTree, listWorkspaceRelays, readRelayDocument, RELAYS_ROOT, } from "./relayDiscovery.js";
4
6
  export const relaysPanelTagName = "pi-web-relays-panel";
7
+ export const RELAY_SELECTION_QUERY_KEY = "relay";
5
8
  export function defineRelaysPanelElement() {
6
9
  if (!customElements.get(relaysPanelTagName))
7
10
  customElements.define(relaysPanelTagName, PiWebRelaysPanel);
@@ -20,6 +23,24 @@ export function defineRelaysPanelElement() {
20
23
  * horizontal scroll position and keyboard focus survive document switches.
21
24
  */
22
25
  class PiWebRelaysPanel extends HTMLElement {
26
+ integration;
27
+ releaseStyles;
28
+ set stylesheetIntegration(value) {
29
+ if (value === this.integration)
30
+ return;
31
+ this.releaseStyles?.();
32
+ this.releaseStyles = undefined;
33
+ this.integration = value;
34
+ if (this.isConnected)
35
+ this.releaseStyles = value?.registerRoot(this.root, { sharedUi: true });
36
+ }
37
+ connectedCallback() {
38
+ this.releaseStyles ??= this.integration?.registerRoot(this.root, { sharedUi: true });
39
+ }
40
+ disconnectedCallback() {
41
+ this.releaseStyles?.();
42
+ this.releaseStyles = undefined;
43
+ }
23
44
  contextValue;
24
45
  listing;
25
46
  selectedRelayPath;
@@ -37,9 +58,9 @@ class PiWebRelaysPanel extends HTMLElement {
37
58
  this.root = this.attachShadow({ mode: "open" });
38
59
  this.root.innerHTML = `
39
60
  ${relaysStyles()}
40
- <section class="toolbar" hidden></section>
41
- <nav class="document-tabs" aria-label="中继文档" hidden></nav>
42
- <section class="viewer"><div class="empty">请选择工作区。</div></section>
61
+ <section class="toolbar ui-toolbar" hidden></section>
62
+ <nav class="document-tabs ui-tabs" aria-label="${escapeAttr(t("bundled.relays.relay.documents.91711b", "Relay documents"))}" hidden></nav>
63
+ <section class="viewer"><div class="empty">${escapeHtml(t("bundled.relays.select.a.workspace.234859", "Select a workspace."))}</div></section>
43
64
  `;
44
65
  this.toolbar = requiredRegion(this.root, ".toolbar");
45
66
  this.tabStrip = requiredRegion(this.root, "nav.document-tabs");
@@ -80,32 +101,51 @@ class PiWebRelaysPanel extends HTMLElement {
80
101
  set context(value) {
81
102
  const previousKey = this.contextValue === undefined ? undefined : contextKey(this.contextValue);
82
103
  const nextKey = value === undefined ? undefined : contextKey(value);
104
+ const previousRelay = linkedRelayPath(this.contextValue);
105
+ const nextRelay = linkedRelayPath(value);
83
106
  this.contextValue = value;
84
- // Parent app updates should not rescan or re-render this panel for the
85
- // same workspace (mirrors the workspace-tasks panel).
86
- if (previousKey === nextKey)
107
+ // Unrelated host renders should not rescan. A picker already starts its
108
+ // load before publishing navigation, so adopting that route does not load twice.
109
+ if (previousKey === nextKey && (previousRelay === nextRelay
110
+ || (nextRelay !== undefined && nextRelay === this.selectedRelayPath)))
87
111
  return;
88
112
  this.expandedDirs = new Set();
89
113
  if (value === undefined) {
114
+ ++this.scanToken;
90
115
  this.resetScanState();
91
116
  this.renderAll();
92
117
  return;
93
118
  }
94
- void this.scan(value, {});
119
+ void this.scan(value, { relayPath: nextRelay });
95
120
  }
96
121
  /** Rescan relays, then reload the selected relay's documents and the open document. */
97
122
  async scan(context, selection) {
98
123
  const token = ++this.scanToken;
99
124
  this.resetScanState();
100
125
  this.renderAll();
126
+ const requestedPath = selection.relayPath ?? linkedRelayPath(context);
127
+ if (requestedPath !== undefined && !isRelayPacketPath(requestedPath)) {
128
+ this.listing = { kind: "unavailable", detail: t("bundled.relays.invalid.packet.link", "Relay links must select a normalized workspace-relative packet directory.") };
129
+ this.renderAll();
130
+ return;
131
+ }
101
132
  const listing = await listWorkspaceRelays(context.files);
102
133
  if (!this.isCurrentScan(context, token))
103
134
  return;
104
- this.listing = listing;
105
- // listWorkspaceRelays returns most recently modified first, so the first
106
- // relay is the default pre-selection.
107
- const relay = listing.kind === "loaded"
108
- ? listing.relays.find((candidate) => candidate.path === selection.relayPath) ?? listing.relays[0]
135
+ // An exact link need not be under the discovery root. Keep that packet in
136
+ // the picker even if the default root is absent/unavailable, and let its
137
+ // own document load report a missing or unreadable target rather than
138
+ // silently substituting another relay.
139
+ const discovered = listing.kind === "loaded" ? listing.relays : [];
140
+ this.listing = requestedPath === undefined ? listing : {
141
+ kind: "loaded",
142
+ relays: discovered.some((relay) => relay.path === requestedPath) ? discovered : [
143
+ { name: documentName(requestedPath), path: requestedPath }, ...discovered,
144
+ ],
145
+ };
146
+ // Default discovery remains most recently modified first.
147
+ const relay = this.listing.kind === "loaded"
148
+ ? this.listing.relays.find((candidate) => candidate.path === requestedPath) ?? this.listing.relays[0]
109
149
  : undefined;
110
150
  this.selectedRelayPath = relay?.path;
111
151
  this.renderToolbar();
@@ -119,6 +159,7 @@ class PiWebRelaysPanel extends HTMLElement {
119
159
  const token = ++this.scanToken;
120
160
  this.selectedRelayPath = relayPath;
121
161
  this.expandedDirs = new Set();
162
+ context.navigation?.set(RELAY_SELECTION_QUERY_KEY, relayPath);
122
163
  await this.loadDocuments(context, token, relayPath, undefined);
123
164
  }
124
165
  toggleDirectory(directoryPath) {
@@ -247,10 +288,10 @@ class PiWebRelaysPanel extends HTMLElement {
247
288
  }
248
289
  this.toolbar.hidden = false;
249
290
  this.toolbar.innerHTML = `
250
- <strong>中继</strong>
251
- <span class="toolbar-actions">
291
+ <strong class="ui-toolbar-title">${escapeHtml(t("bundled.relays.relays.715ce8", "Relays"))}</strong>
292
+ <span class="toolbar-actions ui-toolbar-group">
252
293
  ${this.renderRelayPicker()}
253
- <button class="icon-button" data-refresh aria-label="刷新" title="刷新">${refreshIconSvg()}</button>
294
+ <button type="button" class="ui-button ui-button--compact ui-button--icon" data-refresh aria-label="${escapeAttr(t("bundled.relays.refresh.aee887", "Refresh"))}" title="${escapeAttr(t("bundled.relays.refresh.aee887", "Refresh"))}">${refreshIconSvg()}</button>
254
295
  </span>
255
296
  `;
256
297
  }
@@ -267,7 +308,7 @@ class PiWebRelaysPanel extends HTMLElement {
267
308
  const selected = relay.path === this.selectedRelayPath ? " selected" : "";
268
309
  return `<option value="${escapeAttr(relay.path)}"${selected}>${escapeHtml(relay.name)}</option>`;
269
310
  }).join("");
270
- return `<select data-relay-picker aria-label="中继">${options}</select>`;
311
+ return `<select class="ui-select" data-relay-picker aria-label="${escapeAttr(t("bundled.relays.relays.715ce8", "Relays"))}">${options}</select>`;
271
312
  }
272
313
  renderTabs() {
273
314
  const documents = this.documents;
@@ -293,26 +334,26 @@ class PiWebRelaysPanel extends HTMLElement {
293
334
  const chip = this.renderDirectoryChip(node, containsActivePath);
294
335
  if (!this.expandedDirs.has(node.path) || node.children.length === 0)
295
336
  return chip;
296
- return `<span class="directory-group">${chip}${this.renderStripNodes(node.children, containsActivePath)}</span>`;
337
+ return `<span class="directory-group ui-toolbar-group">${chip}${this.renderStripNodes(node.children, containsActivePath)}</span>`;
297
338
  }).join("");
298
339
  }
299
340
  renderFileTab(file) {
300
341
  const active = file.path === this.selectedDocumentPath;
301
- return `<button class="document-tab${active ? " active" : ""}" data-document-path="${escapeAttr(file.path)}" title="${escapeAttr(file.relativePath)}"${active ? ' aria-current="true"' : ""}>${escapeHtml(file.name)}</button>`;
342
+ return `<button type="button" class="ui-button ui-tab document-tab${active ? " selected" : ""}" data-document-path="${escapeAttr(file.path)}" title="${escapeAttr(file.relativePath)}"${active ? ' aria-current="page"' : ""}>${escapeHtml(file.name)}</button>`;
302
343
  }
303
344
  renderDirectoryChip(directory, containsActivePath) {
304
345
  const expanded = this.expandedDirs.has(directory.path);
305
346
  const containsActive = directory.path === containsActivePath;
306
- const title = containsActive ? "包含当前打开的文档" : directory.relativePath;
307
- return `<button class="document-tab directory-tab${containsActive ? " contains-active" : ""}" data-directory-path="${escapeAttr(directory.path)}" title="${escapeAttr(title)}" aria-expanded="${expanded ? "true" : "false"}">${chevronSvg()}${escapeHtml(directory.name)}</button>`;
347
+ const title = containsActive ? t("ui.main.6a634d20bc86", "Contains the open document") : directory.relativePath;
348
+ return `<button type="button" class="ui-button ui-tab document-tab directory-tab${containsActive ? " contains-active" : ""}" data-directory-path="${escapeAttr(directory.path)}" title="${escapeAttr(title)}" aria-expanded="${expanded ? "true" : "false"}">${chevronSvg()}${escapeHtml(directory.name)}</button>`;
308
349
  }
309
350
  /** Move the active marker between the mounted tab buttons without rebuilding them. */
310
351
  updateActiveTab() {
311
352
  for (const tab of this.tabStrip.querySelectorAll("button[data-document-path]")) {
312
353
  const active = tab.getAttribute("data-document-path") === this.selectedDocumentPath;
313
- tab.classList.toggle("active", active);
354
+ tab.classList.toggle("selected", active);
314
355
  if (active)
315
- tab.setAttribute("aria-current", "true");
356
+ tab.setAttribute("aria-current", "page");
316
357
  else
317
358
  tab.removeAttribute("aria-current");
318
359
  }
@@ -321,7 +362,7 @@ class PiWebRelaysPanel extends HTMLElement {
321
362
  }
322
363
  renderViewer() {
323
364
  if (this.contextValue === undefined) {
324
- this.viewer.innerHTML = `<div class="empty">请选择工作区。</div>`;
365
+ this.viewer.innerHTML = `<div class="empty">${escapeHtml(t("bundled.relays.select.a.workspace.234859", "Select a workspace."))}</div>`;
325
366
  return;
326
367
  }
327
368
  this.viewer.innerHTML = this.renderViewerContent();
@@ -329,9 +370,9 @@ class PiWebRelaysPanel extends HTMLElement {
329
370
  renderViewerContent() {
330
371
  const listing = this.listing;
331
372
  if (listing === undefined)
332
- return `<p class="muted">正在扫描 ${escapeHtml(RELAYS_ROOT)}…</p>`;
373
+ return `<p class="muted">${escapeHtml(t("bundled.relays.scanning.d7c334", "Scanning {value1}...", { value1: RELAYS_ROOT }))}</p>`;
333
374
  if (listing.kind === "unavailable")
334
- return renderErrorState("无法扫描工作区中继。", listing.detail);
375
+ return renderErrorState(t("bundled.relays.could.not.scan.workspace.relays.d8b2bc", "Could not scan workspace relays."), listing.detail);
335
376
  if (listing.kind === "missing" || listing.relays.length === 0)
336
377
  return renderEmptyState();
337
378
  return this.renderSelectedRelay();
@@ -339,20 +380,20 @@ class PiWebRelaysPanel extends HTMLElement {
339
380
  renderSelectedRelay() {
340
381
  const documents = this.documents;
341
382
  if (documents === undefined)
342
- return `<p class="muted">正在加载中继文档…</p>`;
383
+ return `<p class="muted">${escapeHtml(t("bundled.relays.loading.relay.documents.94db7f", "Loading relay documents..."))}</p>`;
343
384
  if (documents.kind === "unavailable")
344
- return renderErrorState("无法列出此中继的文档。", documents.detail);
385
+ return renderErrorState(t("bundled.relays.could.not.list.documents.for.this.relay.cad056", "Could not list documents for this relay."), documents.detail);
345
386
  if (documents.kind === "missing") {
346
- return `<div class="empty-state"><strong>此中继已不存在。</strong><p>点击“刷新”重新扫描 ${escapeHtml(RELAYS_ROOT)}。</p></div>`;
387
+ return `<div class="empty-state"><strong>${escapeHtml(t("bundled.relays.this.relay.no.longer.exists.f8d39d", "This relay no longer exists."))}</strong><p>${escapeHtml(t("bundled.relays.click.refresh.to.rescan.7a2ef0", "Click Refresh to rescan {value1}.", { value1: RELAYS_ROOT }))}</p></div>`;
347
388
  }
348
389
  const partialNotice = documents.partial
349
- ? `<div class="status info">部分嵌套内容未列出:此中继目录树超过了面板的深度或数量限制。</div>`
390
+ ? `<div class="status info">${escapeHtml(t("bundled.relays.partial", "Some nested content is omitted because this relay exceeds the panel depth or count limit."))}</div>`
350
391
  : "";
351
392
  if (documents.documentCount === 0) {
352
393
  return `${partialNotice}
353
394
  <div class="empty-state">
354
- <strong>此中继还没有文档。</strong>
355
- <p>中继包通常包含 <code>status.md</code>、<code>charter.md</code> 和 <code>log.md</code>。</p>
395
+ <strong>${escapeHtml(t("bundled.relays.this.relay.has.no.documents.yet.d5948c", "This relay has no documents yet."))}</strong>
396
+ <p>${escapeHtml(t("bundled.relays.packet.documents", "Relay packets contain charter.md (goal), status.md (current baton), and log.md (history). An optional decisions.md keeps consequential decisions and their reasons."))}</p>
356
397
  </div>
357
398
  `;
358
399
  }
@@ -362,19 +403,19 @@ class PiWebRelaysPanel extends HTMLElement {
362
403
  const documentPath = this.selectedDocumentPath;
363
404
  const content = this.documentContent;
364
405
  if (documentPath === undefined)
365
- return `<p class="muted">请选择文档。</p>`;
406
+ return `<p class="muted">${escapeHtml(t("bundled.relays.select.a.document.1c46a5", "Select a document."))}</p>`;
366
407
  if (content === undefined)
367
- return `<p class="muted">正在加载 ${escapeHtml(documentName(documentPath))}…</p>`;
408
+ return `<p class="muted">${escapeHtml(t("bundled.relays.loading.9f624f", "Loading {value1}...", { value1: documentName(documentPath) }))}</p>`;
368
409
  if (content.kind === "unavailable")
369
- return renderErrorState("无法读取此文档。", content.detail);
410
+ return renderErrorState(t("bundled.relays.could.not.read.this.document.7cd2d0", "Could not read this document."), content.detail);
370
411
  if (content.kind === "missing") {
371
- return `<div class="empty-state"><strong>此文档已不存在。</strong><p>点击“刷新”重新扫描中继。</p></div>`;
412
+ return `<div class="empty-state"><strong>${escapeHtml(t("bundled.relays.this.document.no.longer.exists.6d4a00", "This document no longer exists."))}</strong><p>${escapeHtml(t("bundled.relays.click.refresh.to.rescan.relays.2fe15f", "Click Refresh to rescan relays."))}</p></div>`;
372
413
  }
373
414
  if (content.binary) {
374
- return `<div class="empty-state"><strong>二进制文件:${escapeHtml(documentName(documentPath))}</strong><p>二进制文档无法提供文本预览。</p></div>`;
415
+ return `<div class="empty-state"><strong>${escapeHtml(t("bundled.relays.binary.file.f080cb", "Binary file: {value1}", { value1: documentName(documentPath) }))}</strong><p>${escapeHtml(t("bundled.relays.binary.documents.cannot.be.previewed.as.text.535534", "Binary documents cannot be previewed as text."))}</p></div>`;
375
416
  }
376
417
  const truncation = content.truncated
377
- ? `<div class="status info">此文档已截断,仅显示开头内容。</div>`
418
+ ? `<div class="status info">${escapeHtml(t("bundled.relays.this.document.is.truncated.only.the.beginning.is.shown.bf465f", "This document was truncated; only its beginning is shown."))}</div>`
378
419
  : "";
379
420
  if (isMarkdownDocumentPath(documentPath)) {
380
421
  return `${truncation}<div class="document markdown">${renderRelayDocumentHtml(content.content)}</div>`;
@@ -424,7 +465,11 @@ function chevronSvg() {
424
465
  return `<svg class="chevron" viewBox="0 0 16 16" aria-hidden="true" focusable="false"><path d="M6 4l4 4-4 4"></path></svg>`;
425
466
  }
426
467
  function contextKey(context) {
427
- return `${context.machine.id}:${context.workspace.projectId}:${context.workspace.id}`;
468
+ return JSON.stringify([context.machine.id, context.workspace.projectId, context.workspace.id]);
469
+ }
470
+ function linkedRelayPath(context) {
471
+ const value = context?.navigation?.query[RELAY_SELECTION_QUERY_KEY];
472
+ return typeof value === "string" ? value : value?.[0];
428
473
  }
429
474
  function documentName(path) {
430
475
  return path.slice(path.lastIndexOf("/") + 1);
@@ -432,8 +477,8 @@ function documentName(path) {
432
477
  function renderEmptyState() {
433
478
  return `
434
479
  <div class="empty-state">
435
- <strong>此工作区中没有中继。</strong>
436
- <p>中继包存放在 <code>${escapeHtml(RELAYS_ROOT)}/&lt;name&gt;/</code>,此工作区目前还没有中继包。</p>
480
+ <strong>${escapeHtml(t("bundled.relays.no.relays.in.this.workspace.6ba356", "No relays in this workspace."))}</strong>
481
+ <p>${escapeHtml(t("bundled.relays.empty.location", "Relay packages are stored in {path}. This workspace has none yet.", { path: `${RELAYS_ROOT}/<name>/` }))}</p>
437
482
  </div>
438
483
  `;
439
484
  }
@@ -448,30 +493,24 @@ function relaysStyles() {
448
493
  (the app container is a fixed-height flex column; with shrink enabled
449
494
  the viewer's huge content basis starves them down to a sliver once a
450
495
  tall document renders). The viewer absorbs all shrinking instead. */
451
- .toolbar { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--pi-border-muted); }
496
+ .toolbar { flex: 0 0 auto; justify-content: space-between; padding-inline-start: 10px; }
452
497
  .toolbar[hidden], .document-tabs[hidden] { display: none; }
453
- .toolbar-actions { display: inline-flex; align-items: center; flex-wrap: nowrap; justify-content: flex-end; gap: 8px; min-width: 0; }
498
+ .toolbar-actions { justify-content: flex-end; }
454
499
  .relay-name { min-width: 0; color: var(--pi-text-secondary); overflow-wrap: anywhere; }
455
- /* Bottom padding (not viewer margin) so the gap below the tabs persists
456
- when the viewer's content scrolls up against its top edge. */
457
- .document-tabs { flex: 0 0 auto; display: flex; flex-wrap: nowrap; gap: 6px; padding: 8px 12px; overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; scrollbar-width: thin; }
500
+ .document-tabs { flex: 0 0 auto; overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; scrollbar-width: thin; }
458
501
  .viewer { flex: 1 1 auto; box-sizing: border-box; display: grid; align-content: start; gap: 12px; min-height: 0; overflow: auto; padding: 12px; }
459
502
  /* Grid children default to min-width: auto; without these caps a wide code
460
503
  block or table would silently stretch the whole viewer track. */
461
504
  .viewer > * { box-sizing: border-box; min-width: 0; max-width: 100%; }
462
- button, select { border: 1px solid var(--pi-border); border-radius: 7px; background: var(--pi-surface); color: var(--pi-text); font: inherit; }
463
- button { cursor: pointer; padding: 6px 10px; }
464
- button.icon-button { flex: 0 0 auto; display: inline-grid; place-items: center; width: 30px; height: 30px; padding: 0; }
465
- button.icon-button svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; pointer-events: none; }
466
- select { min-width: 0; max-width: 240px; padding: 5px 6px; }
467
- .document-tab { flex: 0 0 auto; white-space: nowrap; font-size: 12px; padding: 4px 10px; }
468
- .document-tab.active { border-color: var(--pi-accent-border); background: var(--pi-accent); color: var(--pi-bg); }
469
- .directory-group { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; min-width: 0; border: 1px solid var(--pi-border-muted); border-radius: 10px; background: var(--pi-bg-overlay-soft); padding: 0; margin: -1px 0; }
470
- .directory-tab { display: inline-flex; align-items: center; gap: 5px; }
471
- .directory-tab .chevron { flex: 0 0 auto; width: 9px; height: 9px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.12s ease; }
472
- .directory-tab[aria-expanded="true"] .chevron { transform: rotate(90deg); }
473
- .directory-tab.contains-active { border-color: var(--pi-accent-border); color: var(--pi-accent); }
474
- .directory-tab.contains-active::after { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--pi-accent); }
505
+ [data-refresh] svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; pointer-events: none; }
506
+ select { min-width: 0; max-width: 240px; }
507
+ /* Folder controls interleave with file tabs; shared groups keep nested controls contiguous. */
508
+ .directory-tab .chevron { flex: 0 0 auto; width: 9px; height: 9px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.12s ease; }
509
+ .directory-tab[aria-expanded="true"] .chevron { transform: rotate(90deg); }
510
+ /* The selection survives a folder collapse: the nearest collapsed ancestor
511
+ highlights instead, without taking the fill reserved for the open document. */
512
+ .directory-tab.contains-active { color: var(--pi-accent); }
513
+ .directory-tab.contains-active::after { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--pi-accent); }
475
514
  code, pre { border: 1px solid var(--pi-border-muted); border-radius: 6px; background: var(--pi-bg); color: var(--pi-text-secondary); font: 12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
476
515
  code { padding: 2px 5px; }
477
516
  pre { margin: 0; overflow: auto; padding: 8px; white-space: pre-wrap; overflow-wrap: anywhere; }
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: relay
3
+ description: "Carry work across a chain of fresh agent contexts using a shared goal, compact baton, and durable record. Use when a user invokes Relay, discusses the Relay method, prepares a Relay, or continues an active Relay. Do not load for generic multi-step work or ordinary delegation."
4
+ ---
5
+
6
+ # Relay
7
+
8
+ A Relay carries work across fresh agent contexts until the agreed goal is reached or an agent needs human help. Each context owns one useful slice, called a **leg**. There is no standing coordinator or fixed set of agent roles.
9
+
10
+ Follow the [Relay Principle](https://relayprinciple.ai/): give agents a destination and enough continuity to act, rather than recreating a management structure around them.
11
+
12
+ ## Finish line over plan
13
+
14
+ Help the human express what they want built and how they will recognize it is done. Resolve material ambiguity before dispatch. An existing requirements document can supply the goal; reference it rather than rewriting it into a larger specification.
15
+
16
+ Keep the goal stable and the route adaptable. Each runner checks the finish line against the current work and chooses the next useful slice. Changing the goal requires human agreement; changing implementation or sequencing within scope does not.
17
+
18
+ ## Scope over script
19
+
20
+ Record the relay-specific boundaries, limitations, conditions, and clarifications needed to understand the request. Preserve technical requirements and any other details the human explicitly asks to include.
21
+
22
+ Do not invent an implementation roadmap, speculative requirements, or a new software process. Project instructions, skills, and harness conventions remain where they belong; each runner discovers and follows what applies to its work. A Relay does not replace or weaken those rules.
23
+
24
+ ## Handoff over handhold
25
+
26
+ A baton says **where we are**, not **how you must work**. Avoid suggesting or assigning the next slice: even a provisional suggestion can anchor the successor. Record remaining gaps and concrete dependencies instead, and trust the successor to inspect reality and choose its slice.
27
+
28
+ Choose a meaningful increment that fits one context, not the tiniest possible task. Investigation and related work can stay together. Leg boundaries protect context quality, not organizational ownership.
29
+
30
+ Finish ongoing work and preserve the state before starting at most one fresh successor. Handoff is the final operational action; only a user-facing summary follows. Do not watch or steer the successor.
31
+
32
+ ## Record over memory
33
+
34
+ Keep three kinds of durable information:
35
+
36
+ - **Goal:** the agreed finish line and relay-specific scope. Current status cannot override it.
37
+ - **Baton:** current position, completed work, what remains, relevant evidence and decisions, useful pointers, and any blocker.
38
+ - **History:** concise entries recording each leg's result, decisions, artifacts, checks, and handoff or stop.
39
+
40
+ Keep the baton compact. Use history for targeted lookup, not mandatory reconstruction. Inspect the actual work as needed; the record saves rediscovering prior decisions, not reading the project.
41
+
42
+ ## Signal over spin
43
+
44
+ Stop when the finish line is met, with evidence. Completion does not require finding another improvement.
45
+
46
+ Stop visibly when progress needs human input: record the blocker, what was tried, and the specific decision or help needed. If successive legs keep revisiting the same issue without new evidence or meaningful progress, surface that stall instead of spawning another attempt.
47
+
48
+ Optional cleanup, hypothetical risks, and a desire for perfection are not reasons to prolong the chain. Revisit a settled decision when facts change or concrete evidence shows it was wrong, not merely because a fresh agent has arrived.
49
+
50
+ Tools, storage, and session creation belong to the environment-specific runner skill, not the definition of Relay.
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: relay-runner
3
+ description: "Prepare and run Relay legs in Pi: keep the goal, baton, and log durable, then hand off to one fresh session or stop visibly. Use with relay for /relay, /relay-worktree, or a handoff naming relay-runner. Supplies continuity and a bounded fresh-context final review without prescribing the development route."
4
+ ---
5
+
6
+ # Relay runner
7
+
8
+ This skill binds the `relay` method to Pi sessions and a small file packet. It supplies continuity and one completion gate: a fresh-context final review. The development route remains adaptive. Each agent discovers applicable project instructions and skills through the repository and harness; do not copy them into the packet or preselect them for future legs.
9
+
10
+ ## Packet
11
+
12
+ Use `.pi-web/relays/<name>/` in the working checkout unless the user selects another location inside the target workspace. Start with three files:
13
+
14
+ - **`charter.md` — goal.** The agreed outcome and recognizable finish line, relay-specific scope boundaries and clarifications, and any explicit human requirements. Reference an existing specification when useful. Do not add project rules, implementation plans, or generic quality or delivery procedures; include such details only when the human explicitly asks.
15
+ - **`status.md` — baton.** State (`Draft — awaiting approval; not dispatched`, `Active`, `Complete`, or `Needs help`), last completed leg and next leg number, working location, current progress, remaining gaps to the goal, relevant checks, current review state, targeted pointers, and blockers. Include only what is useful now. Avoid suggesting the next slice; record remaining gaps and concrete dependencies instead.
16
+ - **`log.md` — history.** Append a short entry per leg: what changed or was learned, important decisions and why, artifact or commit references, checks and actual results, and the next leg or stop. Record human approval and scope changes here too.
17
+
18
+ Charter = agreement; status = position; decisions = durable reasoning; log = history. Keep revisions in the log, not a separate revisions document; no decision template is required. Status, decisions, and the log cannot silently change the agreement. Keep relay-specific decisions durable without adding documents merely to satisfy a template. The packet is not a second home for project policy or this skill's instructions.
19
+
20
+ Add **`decisions.md` only when useful**: a compact, living record of consequential decisions and their reasons, including rejected approaches or review concerns worth remembering. Keep current conclusions there and record revisions in the log. Link it from status and consult relevant entries rather than duplicating the reasoning in the baton. It is not a plan, task list, or another home for project rules. Human changes to the goal or scope still belong in the charter. Do not create an empty register or impose a decision template.
21
+
22
+ ## Preparation and dispatch
23
+
24
+ The preparation prompt owns discussion and approval. Drafting is allowed before approval; `dispatch_relay` is not. After the human reviews the goal and boundaries, require an explicit **Approve and dispatch** response. If the approved goal, scope, or working target changes materially, obtain fresh approval.
25
+
26
+ Use the current checkout for `/relay` unless the user chooses another. For `/relay-worktree`, create a fresh branch and worktree after approval, following project conventions; use current HEAD as the starting point unless another base is agreed. Ask about a material target ambiguity rather than guessing. Move the draft packet into the target checkout before dispatch, update its location, and remove the stale drafting copy.
27
+
28
+ Record the actual checkout and, in Git, branch and starting commit in status. Keep packet files out of delivery commits using an existing ignore rule or a local Git exclusion. Leave unrelated existing work untouched. Bootstrap the target as needed under project conventions; setup does not automatically require a separate leg.
29
+
30
+ Record approval in status/log, mark status `Active`, and seed leg 1. The first runner chooses its own slice; preparation need not prescribe one. Dispatch with the same handoff mechanics used by later legs.
31
+
32
+ ## Run a leg
33
+
34
+ 1. Read the charter and status, then inspect relevant project guidance and work. Consult only the history or supporting material needed to understand the current state. Repair small record gaps with targeted inspection; ask for help if the goal or ownership is unclear.
35
+ 2. Compare reality with the finish line and completion requirements, including the final review below. If all are satisfied, record completion and stop. Otherwise choose one useful, context-sized slice that closes a remaining gap. Briefly state in the session which slice you chose and how it advances the goal.
36
+ 3. Do the work and the checks appropriate to it under project conventions. Record failed, skipped, or incomplete checks honestly.
37
+ 4. Make the result durable before handoff. In Git, commit the leg's changes when project policy and human instructions permit, without including unrelated changes or the packet. Otherwise record the exact saved work and why it is uncommitted. Finish any helpers before handing off.
38
+ 5. Refresh the compact status and append the log entry. Record progress against the goal, important evidence and decisions, remaining gaps, and any limitations the successor needs to know. Then complete, ask for help, or hand off once.
39
+
40
+ Other reviews, delivery steps, and gates apply only when the human or project requires them. Keep this skill's review procedure here, not copied into the packet.
41
+
42
+ ## Final review
43
+
44
+ When a leg finishes substantive work and believes implementation is done, record that final review is pending and hand off to a fresh leg. A fresh runner finding implementation complete with review pending performs the review instead of passing it on again. Leave substantive corrections to another leg so the review stays independent.
45
+
46
+ Review the whole relay result, not just the last slice, against the charter and applicable project guidance. Approve when no concrete, evidence-backed in-scope blocker remains. Optional improvements, speculative concerns, and unrelated pre-existing shortcomings do not block completion. Record consequential finding dispositions in `decisions.md` when useful.
47
+
48
+ Allow **at most three review attempts total**: the initial review and up to two post-correction reviews, not three mandatory passes. Keep the attempt count, latest result, and reviewed work reference in status; put evidence and findings in the log or link to decisions. Subsequent attempts happen only after concrete corrections and focus on those corrections and changed evidence, carrying supported prior decisions forward rather than restarting an expanding audit.
49
+
50
+ If the third attempt still has blockers, or a required further review would exceed the budget, mark `Needs help`, record what remains, and stop without dispatching another review or correction leg. A valid approval satisfies the gate; a new context or packet-only update does not reopen it. Material changes to the reviewed result require re-review within the same budget.
51
+
52
+ ## Stop or hand off
53
+
54
+ Mark `Complete` and report the result and evidence when no required work remains and final review has passed for the current result. Do not spawn a successor to search for extra work.
55
+
56
+ Mark `Needs help` when a decision, permission, environment problem, or lack of progress prevents responsible continuation. Record the concrete blocker, attempts and evidence, and the smallest question or action needed from the human. Surface it clearly in the user-facing response; use `ask_user` when an answer is needed. Do not hand a human-dependent blocker to another context hoping it will disappear.
57
+
58
+ Before continuing, check that concrete required work remains, including any pending final review; leave slice selection to the successor.
59
+
60
+ For handoff, finish work and all packet writes first. The charter supplies the goal and saved `status.md` is the actual baton: save progress, remaining gaps, decisions, checks and blockers there, with targeted pointers to supporting records as needed. Do not put missing continuity into a separate handover prompt.
61
+
62
+ Call the dedicated `dispatch_relay` tool at most once with the saved directory as `packet`, the next leg identity as `leg`, and the target checkout as `cwd`. A relative `packet` resolves inside that `cwd`; custom packet locations must also stay inside the target workspace. Pass `leg` as a string: the next leg number written as `"2"`, or an explicitly chosen identifier of 1–32 letters, digits, dots, underscores or hyphens, starting with a letter or digit. Non-string values are rejected rather than converted. For example, substitute the actual paths and next leg:
63
+
64
+ ```json
65
+ {
66
+ "packet": ".pi-web/relays/<name>",
67
+ "leg": "2",
68
+ "cwd": "/absolute/path/to/checkout"
69
+ }
70
+ ```
71
+
72
+ The tool validates the saved packet, generates the handover instructions, and records explicit Relay identity and a predictable session name. It accepts no free-form prompt and starts an independent session; do not substitute a generic session tool or tracked subsession. Omit `model` and `thinkingLevel` to inherit them unless the human instructed otherwise; keep any relay-wide instruction in the packet.
73
+
74
+ `dispatch_relay` is the final operational action. After it returns, give only a brief handoff summary: no further tool use, packet writes, work, or downstream supervision. If the tool is unavailable or dispatch fails, report the failure rather than claiming the next leg started.
@@ -0,0 +1,42 @@
1
+ // Generated from pi-packages/workflows/browser/pi-web-plugin.ts. Do not edit directly.
2
+ import { openWorktreeDialog } from "./worktreeDialog.js";
3
+ function canCreateWorktree({ state, backend }) {
4
+ return state.selectedProject !== undefined && backend !== undefined;
5
+ }
6
+ const plugin = {
7
+ apiVersion: 5,
8
+ name: "Workflows",
9
+ activate: ({ lifetimeSignal, selection, translate }) => {
10
+ const t = translate ?? ((_key, fallback) => fallback);
11
+ let closeDialog;
12
+ let unsubscribe;
13
+ const close = () => { closeDialog?.(); closeDialog = undefined; unsubscribe?.(); unsubscribe = undefined; };
14
+ lifetimeSignal.addEventListener("abort", close, { once: true });
15
+ return {
16
+ contributions: {
17
+ actions: [{
18
+ id: "worktree.create",
19
+ title: t("bundled.workflows.create.worktree", "Create Worktree"),
20
+ description: t("bundled.workflows.create.description", "Choose a base branch and purpose, then start a new conversation in the main workspace"),
21
+ group: t("bundled.workflows.group", "Workflows"),
22
+ enabled: canCreateWorktree,
23
+ disabledReason: () => t("bundled.workflows.select.project", "Select a project with the Workflows backend available first."),
24
+ run: (context) => {
25
+ const project = context.state.selectedProject;
26
+ if (!project || !context.backend || lifetimeSignal.aborted)
27
+ return;
28
+ close();
29
+ const peer = context.backend.forScope({ kind: "project", projectId: project.id });
30
+ closeDialog = openWorktreeDialog(context, peer, () => { closeDialog = undefined; unsubscribe?.(); unsubscribe = undefined; }, translate);
31
+ unsubscribe = selection?.subscribe((snapshot) => {
32
+ if (snapshot.selectedProject?.id !== project.id || snapshot.selectedMachine?.id !== context.catalog.machineId)
33
+ close();
34
+ });
35
+ },
36
+ }],
37
+ },
38
+ dispose() { close(); lifetimeSignal.removeEventListener("abort", close); },
39
+ };
40
+ },
41
+ };
42
+ export default plugin;