@agimon-ai/po 0.0.0-alpha.2 → 0.0.0-alpha.21

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 (255) hide show
  1. package/README.md +14 -11
  2. package/dist/antigravity.mjs +1 -2
  3. package/dist/baseCommand.mjs +1 -2
  4. package/dist/bin/cli.cjs +37 -14
  5. package/dist/bin/cli.cjs.map +1 -1
  6. package/dist/bin/cli.mjs +34 -14
  7. package/dist/bin/cli.mjs.map +1 -1
  8. package/dist/bin/{doomRunner.cjs → poRunner.cjs} +5 -5
  9. package/dist/bin/poRunner.cjs.map +1 -0
  10. package/dist/bin/{doomRunner.d.mts → poRunner.d.mts} +2 -2
  11. package/dist/bin/poRunner.d.mts.map +1 -0
  12. package/dist/bin/{doomRunner.mjs → poRunner.mjs} +5 -5
  13. package/dist/bin/poRunner.mjs.map +1 -0
  14. package/dist/builders/cli/extensionAssembler/index.cjs +14 -12
  15. package/dist/builders/cli/extensionAssembler/index.cjs.map +1 -1
  16. package/dist/builders/cli/extensionAssembler/index.d.mts +2 -1
  17. package/dist/builders/cli/extensionAssembler/index.d.mts.map +1 -1
  18. package/dist/builders/cli/extensionAssembler/index.mjs +14 -12
  19. package/dist/builders/cli/extensionAssembler/index.mjs.map +1 -1
  20. package/dist/catalog/index.json +68 -51
  21. package/dist/cliApp.mjs +1 -2
  22. package/dist/codex.mjs +1 -2
  23. package/dist/compatibilityCommand.mjs +1 -2
  24. package/dist/compatibilityContext.mjs +1 -2
  25. package/dist/compatibilityOptions.mjs +1 -2
  26. package/dist/config.cjs +57 -12
  27. package/dist/config.d.mts +3 -3
  28. package/dist/config.mjs +3 -3
  29. package/dist/doctorCommand.mjs +1 -2
  30. package/dist/emitMcpCommand.mjs +1 -2
  31. package/dist/explainCommand.mjs +1 -2
  32. package/dist/extensions/server.cjs +11 -7
  33. package/dist/extensions/server.cjs.map +1 -1
  34. package/dist/extensions/server.d.mts +2 -2
  35. package/dist/extensions/server.d.mts.map +1 -1
  36. package/dist/extensions/server.mjs +12 -8
  37. package/dist/extensions/server.mjs.map +1 -1
  38. package/dist/harnessContext.mjs +1 -2
  39. package/dist/harnessState.cjs +66 -11
  40. package/dist/harnessState.d.mts +2 -2
  41. package/dist/harnessState.mjs +1 -2
  42. package/dist/index.cjs +60 -15
  43. package/dist/index.d.mts +3 -3
  44. package/dist/index.mjs +3 -3
  45. package/dist/initCommand.mjs +1 -2
  46. package/dist/matrixOptions.mjs +1 -2
  47. package/dist/options.mjs +1 -2
  48. package/dist/process.mjs +1 -2
  49. package/dist/projectTrust.cjs +2 -2
  50. package/dist/projectTrust.d.mts +2 -2
  51. package/dist/projectTrust.mjs +1 -2
  52. package/dist/repository.cjs +1 -1
  53. package/dist/repository.d.mts +2 -2
  54. package/dist/repository.mjs +1 -2
  55. package/dist/router.mjs +1 -2
  56. package/dist/shared.mjs +1 -2
  57. package/dist/src/bin/agentDirectory.cjs +18 -12
  58. package/dist/src/bin/agentDirectory.cjs.map +1 -1
  59. package/dist/src/bin/agentDirectory.mjs +15 -12
  60. package/dist/src/bin/agentDirectory.mjs.map +1 -1
  61. package/dist/src/builders/apiContractExport/index.cjs +6 -6
  62. package/dist/src/builders/apiContractExport/index.cjs.map +1 -1
  63. package/dist/src/builders/apiContractExport/index.mjs +9 -9
  64. package/dist/src/builders/apiContractExport/index.mjs.map +1 -1
  65. package/dist/src/builders/cli/entryResolution.cjs +3 -3
  66. package/dist/src/builders/cli/entryResolution.cjs.map +1 -1
  67. package/dist/src/builders/cli/entryResolution.mjs +3 -3
  68. package/dist/src/builders/cli/entryResolution.mjs.map +1 -1
  69. package/dist/src/builders/cli/harnessContext.cjs +5 -5
  70. package/dist/src/builders/cli/harnessContext.cjs.map +1 -1
  71. package/dist/src/builders/cli/harnessContext.mjs +7 -7
  72. package/dist/src/builders/cli/harnessContext.mjs.map +1 -1
  73. package/dist/src/builders/hooks/index.cjs +1 -1
  74. package/dist/src/builders/hooks/index.cjs.map +1 -1
  75. package/dist/src/builders/hooks/index.mjs +2 -2
  76. package/dist/src/builders/hooks/index.mjs.map +1 -1
  77. package/dist/src/builders/server/backgroundSync.cjs +13 -1
  78. package/dist/src/builders/server/backgroundSync.cjs.map +1 -1
  79. package/dist/src/builders/server/backgroundSync.mjs +13 -1
  80. package/dist/src/builders/server/backgroundSync.mjs.map +1 -1
  81. package/dist/src/builders/server/bundlerService.cjs +151 -0
  82. package/dist/src/builders/server/bundlerService.cjs.map +1 -0
  83. package/dist/src/builders/server/bundlerService.mjs +151 -0
  84. package/dist/src/builders/server/bundlerService.mjs.map +1 -0
  85. package/dist/src/builders/server/computerUseBinding.cjs +2 -2
  86. package/dist/src/builders/server/computerUseBinding.cjs.map +1 -1
  87. package/dist/src/builders/server/computerUseBinding.mjs +3 -3
  88. package/dist/src/builders/server/computerUseBinding.mjs.map +1 -1
  89. package/dist/src/builders/server/defaultWorkspace.cjs +1 -1
  90. package/dist/src/builders/server/defaultWorkspace.cjs.map +1 -1
  91. package/dist/src/builders/server/defaultWorkspace.mjs +2 -2
  92. package/dist/src/builders/server/defaultWorkspace.mjs.map +1 -1
  93. package/dist/src/builders/server/idleRestart.cjs +3 -3
  94. package/dist/src/builders/server/idleRestart.cjs.map +1 -1
  95. package/dist/src/builders/server/idleRestart.mjs +3 -3
  96. package/dist/src/builders/server/idleRestart.mjs.map +1 -1
  97. package/dist/src/builders/server/index.cjs +6 -6
  98. package/dist/src/builders/server/index.cjs.map +1 -1
  99. package/dist/src/builders/server/index.mjs +6 -6
  100. package/dist/src/builders/server/index.mjs.map +1 -1
  101. package/dist/src/builders/server/logSink.cjs +3 -3
  102. package/dist/src/builders/server/logSink.cjs.map +1 -1
  103. package/dist/src/builders/server/logSink.mjs +2 -2
  104. package/dist/src/builders/server/logSink.mjs.map +1 -1
  105. package/dist/src/builders/server/mcpBundle.cjs.map +1 -1
  106. package/dist/src/builders/server/mcpBundle.d.mts +2 -2
  107. package/dist/src/builders/server/mcpBundle.mjs.map +1 -1
  108. package/dist/src/builders/server/packageUrl.cjs +25 -18
  109. package/dist/src/builders/server/packageUrl.cjs.map +1 -1
  110. package/dist/src/builders/server/packageUrl.mjs +25 -18
  111. package/dist/src/builders/server/packageUrl.mjs.map +1 -1
  112. package/dist/src/builders/server/runtime.cjs +157 -168
  113. package/dist/src/builders/server/runtime.cjs.map +1 -1
  114. package/dist/src/builders/server/runtime.mjs +161 -171
  115. package/dist/src/builders/server/runtime.mjs.map +1 -1
  116. package/dist/src/builders/server/selectionStatus.cjs +3 -3
  117. package/dist/src/builders/server/selectionStatus.cjs.map +1 -1
  118. package/dist/src/builders/server/selectionStatus.mjs +3 -3
  119. package/dist/src/builders/server/selectionStatus.mjs.map +1 -1
  120. package/dist/src/builders/server/sessionArguments.cjs.map +1 -1
  121. package/dist/src/builders/server/sessionArguments.mjs.map +1 -1
  122. package/dist/src/builders/server/watcherService.cjs +65 -0
  123. package/dist/src/builders/server/watcherService.cjs.map +1 -0
  124. package/dist/src/builders/server/watcherService.mjs +61 -0
  125. package/dist/src/builders/server/watcherService.mjs.map +1 -0
  126. package/dist/src/builders/server/webTemplateDecision.cjs +1 -1
  127. package/dist/src/builders/server/webTemplateDecision.cjs.map +1 -1
  128. package/dist/src/builders/server/webTemplateDecision.mjs +2 -2
  129. package/dist/src/builders/server/webTemplateDecision.mjs.map +1 -1
  130. package/dist/src/builders/web/bundle.cjs.map +1 -1
  131. package/dist/src/builders/web/bundle.d.mts +4 -3
  132. package/dist/src/builders/web/bundle.mjs.map +1 -1
  133. package/dist/src/builders/web/bundleAssetPolicy.d.mts +1 -0
  134. package/dist/src/builders/web/index.cjs +1 -1
  135. package/dist/src/builders/web/index.cjs.map +1 -1
  136. package/dist/src/builders/web/index.d.mts +1 -0
  137. package/dist/src/builders/web/index.mjs +1 -1
  138. package/dist/src/builders/web/index.mjs.map +1 -1
  139. package/dist/src/builders/web/webPluginGenerate.cjs +4 -15
  140. package/dist/src/builders/web/webPluginGenerate.cjs.map +1 -1
  141. package/dist/src/builders/web/webPluginGenerate.d.mts +5 -9
  142. package/dist/src/builders/web/webPluginGenerate.d.mts.map +1 -1
  143. package/dist/src/builders/web/webPluginGenerate.mjs +4 -15
  144. package/dist/src/builders/web/webPluginGenerate.mjs.map +1 -1
  145. package/dist/src/builders/web/webPluginVite.d.mts +1 -0
  146. package/dist/src/cli/cliApp.cjs +1 -1
  147. package/dist/src/cli/cliApp.cjs.map +1 -1
  148. package/dist/src/cli/cliApp.mjs +1 -1
  149. package/dist/src/cli/cliApp.mjs.map +1 -1
  150. package/dist/src/cli/commands/compat/index.cjs +1 -1
  151. package/dist/src/cli/commands/compat/index.cjs.map +1 -1
  152. package/dist/src/cli/commands/compat/index.mjs +1 -1
  153. package/dist/src/cli/commands/compat/index.mjs.map +1 -1
  154. package/dist/src/cli/commands/doctor/index.cjs +2 -2
  155. package/dist/src/cli/commands/doctor/index.cjs.map +1 -1
  156. package/dist/src/cli/commands/doctor/index.d.mts +1 -0
  157. package/dist/src/cli/commands/doctor/index.d.mts.map +1 -1
  158. package/dist/src/cli/commands/doctor/index.mjs +4 -4
  159. package/dist/src/cli/commands/doctor/index.mjs.map +1 -1
  160. package/dist/src/cli/commands/explain/index.cjs +3 -1
  161. package/dist/src/cli/commands/explain/index.cjs.map +1 -1
  162. package/dist/src/cli/commands/explain/index.d.mts.map +1 -1
  163. package/dist/src/cli/commands/explain/index.mjs +4 -2
  164. package/dist/src/cli/commands/explain/index.mjs.map +1 -1
  165. package/dist/src/cli/commands/init/index.cjs +2 -2
  166. package/dist/src/cli/commands/init/index.cjs.map +1 -1
  167. package/dist/src/cli/commands/init/index.mjs +3 -3
  168. package/dist/src/cli/commands/init/index.mjs.map +1 -1
  169. package/dist/src/cli/commands/init/presenter.cjs +1 -1
  170. package/dist/src/cli/commands/init/presenter.cjs.map +1 -1
  171. package/dist/src/cli/commands/init/presenter.mjs +2 -2
  172. package/dist/src/cli/commands/init/presenter.mjs.map +1 -1
  173. package/dist/src/cli/commands/sync/index.cjs +4 -4
  174. package/dist/src/cli/commands/sync/index.cjs.map +1 -1
  175. package/dist/src/cli/commands/sync/index.d.mts +1 -0
  176. package/dist/src/cli/commands/sync/index.mjs +7 -7
  177. package/dist/src/cli/commands/sync/index.mjs.map +1 -1
  178. package/dist/src/cli/commands/sync/presenter.cjs +1 -1
  179. package/dist/src/cli/commands/sync/presenter.cjs.map +1 -1
  180. package/dist/src/cli/commands/sync/presenter.d.mts +1 -1
  181. package/dist/src/cli/commands/sync/presenter.mjs +1 -1
  182. package/dist/src/cli/commands/sync/presenter.mjs.map +1 -1
  183. package/dist/src/cli/commands/web/index.cjs +2 -1
  184. package/dist/src/cli/commands/web/index.cjs.map +1 -1
  185. package/dist/src/cli/commands/web/index.mjs +2 -1
  186. package/dist/src/cli/commands/web/index.mjs.map +1 -1
  187. package/dist/src/cli/harnessOptions.cjs +1 -1
  188. package/dist/src/cli/harnessOptions.cjs.map +1 -1
  189. package/dist/src/cli/harnessOptions.mjs +2 -2
  190. package/dist/src/cli/harnessOptions.mjs.map +1 -1
  191. package/dist/src/cli/help.cjs +2 -0
  192. package/dist/src/cli/help.cjs.map +1 -1
  193. package/dist/src/cli/help.mjs +2 -0
  194. package/dist/src/cli/help.mjs.map +1 -1
  195. package/dist/src/cli/matrixOptions.cjs +1 -1
  196. package/dist/src/cli/matrixOptions.cjs.map +1 -1
  197. package/dist/src/cli/matrixOptions.d.mts +1 -1
  198. package/dist/src/cli/matrixOptions.mjs +1 -1
  199. package/dist/src/cli/matrixOptions.mjs.map +1 -1
  200. package/dist/src/cli/server/run.cjs +1 -1
  201. package/dist/src/cli/server/run.cjs.map +1 -1
  202. package/dist/src/cli/server/run.mjs +2 -2
  203. package/dist/src/cli/server/run.mjs.map +1 -1
  204. package/dist/src/composition/harnessState/index.cjs +66 -11
  205. package/dist/src/composition/harnessState/index.cjs.map +1 -1
  206. package/dist/src/composition/harnessState/index.d.mts +3 -3
  207. package/dist/src/composition/harnessState/index.mjs +2 -2
  208. package/dist/src/composition/harnessState/index.mjs.map +1 -1
  209. package/dist/src/composition/layerPackageInstaller/index.cjs +5 -4
  210. package/dist/src/composition/layerPackageInstaller/index.cjs.map +1 -1
  211. package/dist/src/composition/layerPackageInstaller/index.mjs +6 -5
  212. package/dist/src/composition/layerPackageInstaller/index.mjs.map +1 -1
  213. package/dist/src/composition/poHomeMigration/index.cjs +1 -1
  214. package/dist/src/composition/poHomeMigration/index.cjs.map +1 -1
  215. package/dist/src/composition/poHomeMigration/index.mjs +1 -1
  216. package/dist/src/composition/poHomeMigration/index.mjs.map +1 -1
  217. package/dist/src/composition/projectTrust/index.cjs +6 -6
  218. package/dist/src/composition/projectTrust/index.cjs.map +1 -1
  219. package/dist/src/composition/projectTrust/index.d.mts +7 -7
  220. package/dist/src/composition/projectTrust/index.d.mts.map +1 -1
  221. package/dist/src/composition/projectTrust/index.mjs +6 -6
  222. package/dist/src/composition/projectTrust/index.mjs.map +1 -1
  223. package/dist/src/composition/repository/index.cjs +8 -8
  224. package/dist/src/composition/repository/index.cjs.map +1 -1
  225. package/dist/src/composition/repository/index.d.mts +5 -5
  226. package/dist/src/composition/repository/index.d.mts.map +1 -1
  227. package/dist/src/composition/repository/index.mjs +10 -10
  228. package/dist/src/composition/repository/index.mjs.map +1 -1
  229. package/dist/src/composition/syncService/index.cjs +29 -9
  230. package/dist/src/composition/syncService/index.cjs.map +1 -1
  231. package/dist/src/composition/syncService/index.d.mts.map +1 -1
  232. package/dist/src/composition/syncService/index.mjs +31 -11
  233. package/dist/src/composition/syncService/index.mjs.map +1 -1
  234. package/dist/src/composition/syncService/localBuilds.cjs +7 -2
  235. package/dist/src/composition/syncService/localBuilds.cjs.map +1 -1
  236. package/dist/src/composition/syncService/localBuilds.mjs +7 -2
  237. package/dist/src/composition/syncService/localBuilds.mjs.map +1 -1
  238. package/dist/src/extensions/setupDiagnostics.cjs +3 -3
  239. package/dist/src/extensions/setupDiagnostics.cjs.map +1 -1
  240. package/dist/src/extensions/setupDiagnostics.mjs +3 -3
  241. package/dist/src/extensions/setupDiagnostics.mjs.map +1 -1
  242. package/dist/utils.mjs +1 -2
  243. package/docs/server/api-export.md +3 -3
  244. package/docs/server/api.md +23 -22
  245. package/docs/server/getting-started.md +7 -7
  246. package/docs/server/index.md +4 -4
  247. package/docs/server/ipc.md +7 -11
  248. package/docs/server/lifecycle.md +17 -17
  249. package/docs/server/security.md +8 -8
  250. package/package.json +42 -45
  251. package/src/prompts/po-author-extension/SKILL.md +1 -1
  252. package/src/prompts/po-author-extension/references/extension-contract.md +4 -4
  253. package/dist/bin/doomRunner.cjs.map +0 -1
  254. package/dist/bin/doomRunner.d.mts.map +0 -1
  255. package/dist/bin/doomRunner.mjs.map +0 -1
@@ -2,9 +2,9 @@ import { domainStatus } from "@agimon-ai/po-domain";
2
2
  import { statusText } from "@agimon-ai/po-major-mode";
3
3
  //#region src/builders/server/selectionStatus.ts
4
4
  function publishHeadlessSelectionStatus(setStatus, selection) {
5
- setStatus("doom-major-mode", statusText(selection.majorMode, selection.domains, selection.profile));
6
- setStatus("doom-domain", domainStatus(selection.domains));
7
- setStatus("doom-profile", selection.profile);
5
+ setStatus("po-major-mode", statusText(selection.majorMode, selection.domains, selection.profile));
6
+ setStatus("po-domain", domainStatus(selection.domains));
7
+ setStatus("po-profile", selection.profile);
8
8
  }
9
9
  //#endregion
10
10
  export { publishHeadlessSelectionStatus };
@@ -1 +1 @@
1
- {"version":3,"file":"selectionStatus.mjs","names":[],"sources":["../../../../src/builders/server/selectionStatus.ts"],"sourcesContent":["import type { DoomHeadlessSelection } from '@agimon-ai/po-core/headless';\nimport { domainStatus } from '@agimon-ai/po-domain';\nimport { statusText } from '@agimon-ai/po-major-mode';\nexport function publishHeadlessSelectionStatus(\n setStatus: (source: string, text: string | undefined) => void,\n selection: DoomHeadlessSelection,\n): void {\n setStatus('doom-major-mode', statusText(selection.majorMode, selection.domains, selection.profile));\n setStatus('doom-domain', domainStatus(selection.domains));\n setStatus('doom-profile', selection.profile);\n}\n"],"mappings":";;;AAGA,SAAgB,+BACd,WACA,WACM;CACN,UAAU,mBAAmB,WAAW,UAAU,WAAW,UAAU,SAAS,UAAU,OAAO,CAAC;CAClG,UAAU,eAAe,aAAa,UAAU,OAAO,CAAC;CACxD,UAAU,gBAAgB,UAAU,OAAO;AAC7C"}
1
+ {"version":3,"file":"selectionStatus.mjs","names":[],"sources":["../../../../src/builders/server/selectionStatus.ts"],"sourcesContent":["import type { PoHeadlessSelection } from '@agimon-ai/po-core/headless';\nimport { domainStatus } from '@agimon-ai/po-domain';\nimport { statusText } from '@agimon-ai/po-major-mode';\nexport function publishHeadlessSelectionStatus(\n setStatus: (source: string, text: string | undefined) => void,\n selection: PoHeadlessSelection,\n): void {\n setStatus('po-major-mode', statusText(selection.majorMode, selection.domains, selection.profile));\n setStatus('po-domain', domainStatus(selection.domains));\n setStatus('po-profile', selection.profile);\n}\n"],"mappings":";;;AAGA,SAAgB,+BACd,WACA,WACM;CACN,UAAU,iBAAiB,WAAW,UAAU,WAAW,UAAU,SAAS,UAAU,OAAO,CAAC;CAChG,UAAU,aAAa,aAAa,UAAU,OAAO,CAAC;CACtD,UAAU,cAAc,UAAU,OAAO;AAC3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"sessionArguments.cjs","names":[],"sources":["../../../../src/builders/server/sessionArguments.ts"],"sourcesContent":["import type { DoomHubSessionCreateRequest } from '@agimon-ai/po-core/hubChannel';\n\nconst SESSION_ID_OPTION = '--session-id';\nconst NAME_OPTION = '--name';\nconst PROFILE_OPTION = '--profile';\nconst DOMAINS_OPTION = '--domains';\nconst NO_DOMAINS_OPTION = '--no-domains';\nconst MODEL_OPTION = '--model';\nconst THINKING_OPTION = '--thinking';\nconst APPEND_SYSTEM_PROMPT_OPTION = '--append-system-prompt';\nexport interface SessionIdentity {\n sessionId: string;\n sessionName: string;\n}\n\n/** Settles the direct session identity from explicit arguments or caller defaults. */\nexport function resolveSessionIdentity(\n agentArgs: readonly string[],\n fallback: SessionIdentity,\n): { agentArgs: string[]; identity: SessionIdentity } {\n const args = [...agentArgs];\n const identity = { ...fallback };\n for (const [option, key] of [\n [SESSION_ID_OPTION, 'sessionId'],\n [NAME_OPTION, 'sessionName'],\n ] as const) {\n const index = args.indexOf(option);\n const value = index === -1 ? undefined : args[index + 1];\n if (value !== undefined && !value.startsWith('-')) identity[key] = value;\n else args.push(option, identity[key]);\n }\n if (!/^[a-zA-Z0-9_-]+$/u.test(identity.sessionId)) throw new Error('Invalid session id.');\n return { agentArgs: args, identity };\n}\n\nconst MAJOR_MODE_OPTION = '--major-mode';\n\n/** Selection axes a request pins, which later inherited defaults must not replace. */\nexport type PinnedSelectionAxis = 'majorMode' | 'domains' | 'profile';\n\n/**\n * The harness arguments for a session a package created with explicit settings.\n *\n * Translating to flags keeps one validation path: the same parser that checks\n * a `po --major-mode ... --model ...` launch checks these. Minor modes have\n * no flag; the caller seeds them into the selection state directly.\n */\nexport function sessionSelectionArgs(\n request: Pick<DoomHubSessionCreateRequest, 'selection' | 'model' | 'thinking' | 'appendSystemPrompt'>,\n): {\n args: string[];\n pinned: PinnedSelectionAxis[];\n} {\n const { selection, model, thinking, appendSystemPrompt } = request;\n const args: string[] = [];\n const pinned: PinnedSelectionAxis[] = [];\n if (selection?.majorMode !== undefined) {\n args.push(MAJOR_MODE_OPTION, selection.majorMode);\n pinned.push('majorMode');\n }\n if (selection?.profile !== undefined) {\n args.push(PROFILE_OPTION, selection.profile);\n pinned.push('profile');\n }\n if (selection?.domains !== undefined) {\n if (selection.domains.length === 0) args.push(NO_DOMAINS_OPTION);\n else args.push(DOMAINS_OPTION, selection.domains.join(','));\n pinned.push('domains');\n }\n if (model !== undefined) args.push(MODEL_OPTION, model);\n if (thinking !== undefined) args.push(THINKING_OPTION, thinking);\n // Unknown to the harness parser, so it reaches Pi, which appends it to the system prompt.\n if (appendSystemPrompt !== undefined) args.push(APPEND_SYSTEM_PROMPT_OPTION, appendSystemPrompt);\n return { args, pinned };\n}\n\n/**\n * The agent arguments with the major mode pinned to a relaunch target.\n *\n * Any prior selection is dropped so repeated switches never accumulate flags.\n * The new pair goes last, the position launcher scripts already use, which\n * also keeps a leading script path intact when the agent runs via node.\n */\nexport function relaunchAgentArgs(args: readonly string[], majorMode: string): string[] {\n const kept: string[] = [];\n let skipValue = false;\n for (const argument of args) {\n if (skipValue) {\n skipValue = false;\n continue;\n }\n if (argument === MAJOR_MODE_OPTION) {\n skipValue = true;\n continue;\n }\n kept.push(argument);\n }\n return [...kept, MAJOR_MODE_OPTION, majorMode];\n}\n"],"mappings":";AAEA,MAAM,oBAAoB;AAC1B,MAAM,cAAc;AACpB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,eAAe;AACrB,MAAM,kBAAkB;AACxB,MAAM,8BAA8B;;AAOpC,SAAgB,uBACd,WACA,UACoD;CACpD,MAAM,OAAO,CAAC,GAAG,SAAS;CAC1B,MAAM,WAAW,EAAE,GAAG,SAAS;CAC/B,KAAK,MAAM,CAAC,QAAQ,QAAQ,CAC1B,CAAC,mBAAmB,WAAW,GAC/B,CAAC,aAAa,aAAa,CAC7B,GAAY;EACV,MAAM,QAAQ,KAAK,QAAQ,MAAM;EACjC,MAAM,QAAQ,UAAU,KAAK,KAAA,IAAY,KAAK,QAAQ;EACtD,IAAI,UAAU,KAAA,KAAa,CAAC,MAAM,WAAW,GAAG,GAAG,SAAS,OAAO;OAC9D,KAAK,KAAK,QAAQ,SAAS,IAAI;CACtC;CACA,IAAI,CAAC,oBAAoB,KAAK,SAAS,SAAS,GAAG,MAAM,IAAI,MAAM,qBAAqB;CACxF,OAAO;EAAE,WAAW;EAAM;CAAS;AACrC;AAEA,MAAM,oBAAoB;;;;;;;;AAY1B,SAAgB,qBACd,SAIA;CACA,MAAM,EAAE,WAAW,OAAO,UAAU,uBAAuB;CAC3D,MAAM,OAAiB,CAAC;CACxB,MAAM,SAAgC,CAAC;CACvC,IAAI,WAAW,cAAc,KAAA,GAAW;EACtC,KAAK,KAAK,mBAAmB,UAAU,SAAS;EAChD,OAAO,KAAK,WAAW;CACzB;CACA,IAAI,WAAW,YAAY,KAAA,GAAW;EACpC,KAAK,KAAK,gBAAgB,UAAU,OAAO;EAC3C,OAAO,KAAK,SAAS;CACvB;CACA,IAAI,WAAW,YAAY,KAAA,GAAW;EACpC,IAAI,UAAU,QAAQ,WAAW,GAAG,KAAK,KAAK,iBAAiB;OAC1D,KAAK,KAAK,gBAAgB,UAAU,QAAQ,KAAK,GAAG,CAAC;EAC1D,OAAO,KAAK,SAAS;CACvB;CACA,IAAI,UAAU,KAAA,GAAW,KAAK,KAAK,cAAc,KAAK;CACtD,IAAI,aAAa,KAAA,GAAW,KAAK,KAAK,iBAAiB,QAAQ;CAE/D,IAAI,uBAAuB,KAAA,GAAW,KAAK,KAAK,6BAA6B,kBAAkB;CAC/F,OAAO;EAAE;EAAM;CAAO;AACxB"}
1
+ {"version":3,"file":"sessionArguments.cjs","names":[],"sources":["../../../../src/builders/server/sessionArguments.ts"],"sourcesContent":["import type { PoHubSessionCreateRequest } from '@agimon-ai/po-core/hubChannel';\n\nconst SESSION_ID_OPTION = '--session-id';\nconst NAME_OPTION = '--name';\nconst PROFILE_OPTION = '--profile';\nconst DOMAINS_OPTION = '--domains';\nconst NO_DOMAINS_OPTION = '--no-domains';\nconst MODEL_OPTION = '--model';\nconst THINKING_OPTION = '--thinking';\nconst APPEND_SYSTEM_PROMPT_OPTION = '--append-system-prompt';\nexport interface SessionIdentity {\n sessionId: string;\n sessionName: string;\n}\n\n/** Settles the direct session identity from explicit arguments or caller defaults. */\nexport function resolveSessionIdentity(\n agentArgs: readonly string[],\n fallback: SessionIdentity,\n): { agentArgs: string[]; identity: SessionIdentity } {\n const args = [...agentArgs];\n const identity = { ...fallback };\n for (const [option, key] of [\n [SESSION_ID_OPTION, 'sessionId'],\n [NAME_OPTION, 'sessionName'],\n ] as const) {\n const index = args.indexOf(option);\n const value = index === -1 ? undefined : args[index + 1];\n if (value !== undefined && !value.startsWith('-')) identity[key] = value;\n else args.push(option, identity[key]);\n }\n if (!/^[a-zA-Z0-9_-]+$/u.test(identity.sessionId)) throw new Error('Invalid session id.');\n return { agentArgs: args, identity };\n}\n\nconst MAJOR_MODE_OPTION = '--major-mode';\n\n/** Selection axes a request pins, which later inherited defaults must not replace. */\nexport type PinnedSelectionAxis = 'majorMode' | 'domains' | 'profile';\n\n/**\n * The harness arguments for a session a package created with explicit settings.\n *\n * Translating to flags keeps one validation path: the same parser that checks\n * a `po --major-mode ... --model ...` launch checks these. Minor modes have\n * no flag; the caller seeds them into the selection state directly.\n */\nexport function sessionSelectionArgs(\n request: Pick<PoHubSessionCreateRequest, 'selection' | 'model' | 'thinking' | 'appendSystemPrompt'>,\n): {\n args: string[];\n pinned: PinnedSelectionAxis[];\n} {\n const { selection, model, thinking, appendSystemPrompt } = request;\n const args: string[] = [];\n const pinned: PinnedSelectionAxis[] = [];\n if (selection?.majorMode !== undefined) {\n args.push(MAJOR_MODE_OPTION, selection.majorMode);\n pinned.push('majorMode');\n }\n if (selection?.profile !== undefined) {\n args.push(PROFILE_OPTION, selection.profile);\n pinned.push('profile');\n }\n if (selection?.domains !== undefined) {\n if (selection.domains.length === 0) args.push(NO_DOMAINS_OPTION);\n else args.push(DOMAINS_OPTION, selection.domains.join(','));\n pinned.push('domains');\n }\n if (model !== undefined) args.push(MODEL_OPTION, model);\n if (thinking !== undefined) args.push(THINKING_OPTION, thinking);\n // Unknown to the harness parser, so it reaches Pi, which appends it to the system prompt.\n if (appendSystemPrompt !== undefined) args.push(APPEND_SYSTEM_PROMPT_OPTION, appendSystemPrompt);\n return { args, pinned };\n}\n\n/**\n * The agent arguments with the major mode pinned to a relaunch target.\n *\n * Any prior selection is dropped so repeated switches never accumulate flags.\n * The new pair goes last, the position launcher scripts already use, which\n * also keeps a leading script path intact when the agent runs via node.\n */\nexport function relaunchAgentArgs(args: readonly string[], majorMode: string): string[] {\n const kept: string[] = [];\n let skipValue = false;\n for (const argument of args) {\n if (skipValue) {\n skipValue = false;\n continue;\n }\n if (argument === MAJOR_MODE_OPTION) {\n skipValue = true;\n continue;\n }\n kept.push(argument);\n }\n return [...kept, MAJOR_MODE_OPTION, majorMode];\n}\n"],"mappings":";AAEA,MAAM,oBAAoB;AAC1B,MAAM,cAAc;AACpB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,eAAe;AACrB,MAAM,kBAAkB;AACxB,MAAM,8BAA8B;;AAOpC,SAAgB,uBACd,WACA,UACoD;CACpD,MAAM,OAAO,CAAC,GAAG,SAAS;CAC1B,MAAM,WAAW,EAAE,GAAG,SAAS;CAC/B,KAAK,MAAM,CAAC,QAAQ,QAAQ,CAC1B,CAAC,mBAAmB,WAAW,GAC/B,CAAC,aAAa,aAAa,CAC7B,GAAY;EACV,MAAM,QAAQ,KAAK,QAAQ,MAAM;EACjC,MAAM,QAAQ,UAAU,KAAK,KAAA,IAAY,KAAK,QAAQ;EACtD,IAAI,UAAU,KAAA,KAAa,CAAC,MAAM,WAAW,GAAG,GAAG,SAAS,OAAO;OAC9D,KAAK,KAAK,QAAQ,SAAS,IAAI;CACtC;CACA,IAAI,CAAC,oBAAoB,KAAK,SAAS,SAAS,GAAG,MAAM,IAAI,MAAM,qBAAqB;CACxF,OAAO;EAAE,WAAW;EAAM;CAAS;AACrC;AAEA,MAAM,oBAAoB;;;;;;;;AAY1B,SAAgB,qBACd,SAIA;CACA,MAAM,EAAE,WAAW,OAAO,UAAU,uBAAuB;CAC3D,MAAM,OAAiB,CAAC;CACxB,MAAM,SAAgC,CAAC;CACvC,IAAI,WAAW,cAAc,KAAA,GAAW;EACtC,KAAK,KAAK,mBAAmB,UAAU,SAAS;EAChD,OAAO,KAAK,WAAW;CACzB;CACA,IAAI,WAAW,YAAY,KAAA,GAAW;EACpC,KAAK,KAAK,gBAAgB,UAAU,OAAO;EAC3C,OAAO,KAAK,SAAS;CACvB;CACA,IAAI,WAAW,YAAY,KAAA,GAAW;EACpC,IAAI,UAAU,QAAQ,WAAW,GAAG,KAAK,KAAK,iBAAiB;OAC1D,KAAK,KAAK,gBAAgB,UAAU,QAAQ,KAAK,GAAG,CAAC;EAC1D,OAAO,KAAK,SAAS;CACvB;CACA,IAAI,UAAU,KAAA,GAAW,KAAK,KAAK,cAAc,KAAK;CACtD,IAAI,aAAa,KAAA,GAAW,KAAK,KAAK,iBAAiB,QAAQ;CAE/D,IAAI,uBAAuB,KAAA,GAAW,KAAK,KAAK,6BAA6B,kBAAkB;CAC/F,OAAO;EAAE;EAAM;CAAO;AACxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"sessionArguments.mjs","names":[],"sources":["../../../../src/builders/server/sessionArguments.ts"],"sourcesContent":["import type { DoomHubSessionCreateRequest } from '@agimon-ai/po-core/hubChannel';\n\nconst SESSION_ID_OPTION = '--session-id';\nconst NAME_OPTION = '--name';\nconst PROFILE_OPTION = '--profile';\nconst DOMAINS_OPTION = '--domains';\nconst NO_DOMAINS_OPTION = '--no-domains';\nconst MODEL_OPTION = '--model';\nconst THINKING_OPTION = '--thinking';\nconst APPEND_SYSTEM_PROMPT_OPTION = '--append-system-prompt';\nexport interface SessionIdentity {\n sessionId: string;\n sessionName: string;\n}\n\n/** Settles the direct session identity from explicit arguments or caller defaults. */\nexport function resolveSessionIdentity(\n agentArgs: readonly string[],\n fallback: SessionIdentity,\n): { agentArgs: string[]; identity: SessionIdentity } {\n const args = [...agentArgs];\n const identity = { ...fallback };\n for (const [option, key] of [\n [SESSION_ID_OPTION, 'sessionId'],\n [NAME_OPTION, 'sessionName'],\n ] as const) {\n const index = args.indexOf(option);\n const value = index === -1 ? undefined : args[index + 1];\n if (value !== undefined && !value.startsWith('-')) identity[key] = value;\n else args.push(option, identity[key]);\n }\n if (!/^[a-zA-Z0-9_-]+$/u.test(identity.sessionId)) throw new Error('Invalid session id.');\n return { agentArgs: args, identity };\n}\n\nconst MAJOR_MODE_OPTION = '--major-mode';\n\n/** Selection axes a request pins, which later inherited defaults must not replace. */\nexport type PinnedSelectionAxis = 'majorMode' | 'domains' | 'profile';\n\n/**\n * The harness arguments for a session a package created with explicit settings.\n *\n * Translating to flags keeps one validation path: the same parser that checks\n * a `po --major-mode ... --model ...` launch checks these. Minor modes have\n * no flag; the caller seeds them into the selection state directly.\n */\nexport function sessionSelectionArgs(\n request: Pick<DoomHubSessionCreateRequest, 'selection' | 'model' | 'thinking' | 'appendSystemPrompt'>,\n): {\n args: string[];\n pinned: PinnedSelectionAxis[];\n} {\n const { selection, model, thinking, appendSystemPrompt } = request;\n const args: string[] = [];\n const pinned: PinnedSelectionAxis[] = [];\n if (selection?.majorMode !== undefined) {\n args.push(MAJOR_MODE_OPTION, selection.majorMode);\n pinned.push('majorMode');\n }\n if (selection?.profile !== undefined) {\n args.push(PROFILE_OPTION, selection.profile);\n pinned.push('profile');\n }\n if (selection?.domains !== undefined) {\n if (selection.domains.length === 0) args.push(NO_DOMAINS_OPTION);\n else args.push(DOMAINS_OPTION, selection.domains.join(','));\n pinned.push('domains');\n }\n if (model !== undefined) args.push(MODEL_OPTION, model);\n if (thinking !== undefined) args.push(THINKING_OPTION, thinking);\n // Unknown to the harness parser, so it reaches Pi, which appends it to the system prompt.\n if (appendSystemPrompt !== undefined) args.push(APPEND_SYSTEM_PROMPT_OPTION, appendSystemPrompt);\n return { args, pinned };\n}\n\n/**\n * The agent arguments with the major mode pinned to a relaunch target.\n *\n * Any prior selection is dropped so repeated switches never accumulate flags.\n * The new pair goes last, the position launcher scripts already use, which\n * also keeps a leading script path intact when the agent runs via node.\n */\nexport function relaunchAgentArgs(args: readonly string[], majorMode: string): string[] {\n const kept: string[] = [];\n let skipValue = false;\n for (const argument of args) {\n if (skipValue) {\n skipValue = false;\n continue;\n }\n if (argument === MAJOR_MODE_OPTION) {\n skipValue = true;\n continue;\n }\n kept.push(argument);\n }\n return [...kept, MAJOR_MODE_OPTION, majorMode];\n}\n"],"mappings":";AAEA,MAAM,oBAAoB;AAC1B,MAAM,cAAc;AACpB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,eAAe;AACrB,MAAM,kBAAkB;AACxB,MAAM,8BAA8B;;AAOpC,SAAgB,uBACd,WACA,UACoD;CACpD,MAAM,OAAO,CAAC,GAAG,SAAS;CAC1B,MAAM,WAAW,EAAE,GAAG,SAAS;CAC/B,KAAK,MAAM,CAAC,QAAQ,QAAQ,CAC1B,CAAC,mBAAmB,WAAW,GAC/B,CAAC,aAAa,aAAa,CAC7B,GAAY;EACV,MAAM,QAAQ,KAAK,QAAQ,MAAM;EACjC,MAAM,QAAQ,UAAU,KAAK,KAAA,IAAY,KAAK,QAAQ;EACtD,IAAI,UAAU,KAAA,KAAa,CAAC,MAAM,WAAW,GAAG,GAAG,SAAS,OAAO;OAC9D,KAAK,KAAK,QAAQ,SAAS,IAAI;CACtC;CACA,IAAI,CAAC,oBAAoB,KAAK,SAAS,SAAS,GAAG,MAAM,IAAI,MAAM,qBAAqB;CACxF,OAAO;EAAE,WAAW;EAAM;CAAS;AACrC;AAEA,MAAM,oBAAoB;;;;;;;;AAY1B,SAAgB,qBACd,SAIA;CACA,MAAM,EAAE,WAAW,OAAO,UAAU,uBAAuB;CAC3D,MAAM,OAAiB,CAAC;CACxB,MAAM,SAAgC,CAAC;CACvC,IAAI,WAAW,cAAc,KAAA,GAAW;EACtC,KAAK,KAAK,mBAAmB,UAAU,SAAS;EAChD,OAAO,KAAK,WAAW;CACzB;CACA,IAAI,WAAW,YAAY,KAAA,GAAW;EACpC,KAAK,KAAK,gBAAgB,UAAU,OAAO;EAC3C,OAAO,KAAK,SAAS;CACvB;CACA,IAAI,WAAW,YAAY,KAAA,GAAW;EACpC,IAAI,UAAU,QAAQ,WAAW,GAAG,KAAK,KAAK,iBAAiB;OAC1D,KAAK,KAAK,gBAAgB,UAAU,QAAQ,KAAK,GAAG,CAAC;EAC1D,OAAO,KAAK,SAAS;CACvB;CACA,IAAI,UAAU,KAAA,GAAW,KAAK,KAAK,cAAc,KAAK;CACtD,IAAI,aAAa,KAAA,GAAW,KAAK,KAAK,iBAAiB,QAAQ;CAE/D,IAAI,uBAAuB,KAAA,GAAW,KAAK,KAAK,6BAA6B,kBAAkB;CAC/F,OAAO;EAAE;EAAM;CAAO;AACxB"}
1
+ {"version":3,"file":"sessionArguments.mjs","names":[],"sources":["../../../../src/builders/server/sessionArguments.ts"],"sourcesContent":["import type { PoHubSessionCreateRequest } from '@agimon-ai/po-core/hubChannel';\n\nconst SESSION_ID_OPTION = '--session-id';\nconst NAME_OPTION = '--name';\nconst PROFILE_OPTION = '--profile';\nconst DOMAINS_OPTION = '--domains';\nconst NO_DOMAINS_OPTION = '--no-domains';\nconst MODEL_OPTION = '--model';\nconst THINKING_OPTION = '--thinking';\nconst APPEND_SYSTEM_PROMPT_OPTION = '--append-system-prompt';\nexport interface SessionIdentity {\n sessionId: string;\n sessionName: string;\n}\n\n/** Settles the direct session identity from explicit arguments or caller defaults. */\nexport function resolveSessionIdentity(\n agentArgs: readonly string[],\n fallback: SessionIdentity,\n): { agentArgs: string[]; identity: SessionIdentity } {\n const args = [...agentArgs];\n const identity = { ...fallback };\n for (const [option, key] of [\n [SESSION_ID_OPTION, 'sessionId'],\n [NAME_OPTION, 'sessionName'],\n ] as const) {\n const index = args.indexOf(option);\n const value = index === -1 ? undefined : args[index + 1];\n if (value !== undefined && !value.startsWith('-')) identity[key] = value;\n else args.push(option, identity[key]);\n }\n if (!/^[a-zA-Z0-9_-]+$/u.test(identity.sessionId)) throw new Error('Invalid session id.');\n return { agentArgs: args, identity };\n}\n\nconst MAJOR_MODE_OPTION = '--major-mode';\n\n/** Selection axes a request pins, which later inherited defaults must not replace. */\nexport type PinnedSelectionAxis = 'majorMode' | 'domains' | 'profile';\n\n/**\n * The harness arguments for a session a package created with explicit settings.\n *\n * Translating to flags keeps one validation path: the same parser that checks\n * a `po --major-mode ... --model ...` launch checks these. Minor modes have\n * no flag; the caller seeds them into the selection state directly.\n */\nexport function sessionSelectionArgs(\n request: Pick<PoHubSessionCreateRequest, 'selection' | 'model' | 'thinking' | 'appendSystemPrompt'>,\n): {\n args: string[];\n pinned: PinnedSelectionAxis[];\n} {\n const { selection, model, thinking, appendSystemPrompt } = request;\n const args: string[] = [];\n const pinned: PinnedSelectionAxis[] = [];\n if (selection?.majorMode !== undefined) {\n args.push(MAJOR_MODE_OPTION, selection.majorMode);\n pinned.push('majorMode');\n }\n if (selection?.profile !== undefined) {\n args.push(PROFILE_OPTION, selection.profile);\n pinned.push('profile');\n }\n if (selection?.domains !== undefined) {\n if (selection.domains.length === 0) args.push(NO_DOMAINS_OPTION);\n else args.push(DOMAINS_OPTION, selection.domains.join(','));\n pinned.push('domains');\n }\n if (model !== undefined) args.push(MODEL_OPTION, model);\n if (thinking !== undefined) args.push(THINKING_OPTION, thinking);\n // Unknown to the harness parser, so it reaches Pi, which appends it to the system prompt.\n if (appendSystemPrompt !== undefined) args.push(APPEND_SYSTEM_PROMPT_OPTION, appendSystemPrompt);\n return { args, pinned };\n}\n\n/**\n * The agent arguments with the major mode pinned to a relaunch target.\n *\n * Any prior selection is dropped so repeated switches never accumulate flags.\n * The new pair goes last, the position launcher scripts already use, which\n * also keeps a leading script path intact when the agent runs via node.\n */\nexport function relaunchAgentArgs(args: readonly string[], majorMode: string): string[] {\n const kept: string[] = [];\n let skipValue = false;\n for (const argument of args) {\n if (skipValue) {\n skipValue = false;\n continue;\n }\n if (argument === MAJOR_MODE_OPTION) {\n skipValue = true;\n continue;\n }\n kept.push(argument);\n }\n return [...kept, MAJOR_MODE_OPTION, majorMode];\n}\n"],"mappings":";AAEA,MAAM,oBAAoB;AAC1B,MAAM,cAAc;AACpB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,eAAe;AACrB,MAAM,kBAAkB;AACxB,MAAM,8BAA8B;;AAOpC,SAAgB,uBACd,WACA,UACoD;CACpD,MAAM,OAAO,CAAC,GAAG,SAAS;CAC1B,MAAM,WAAW,EAAE,GAAG,SAAS;CAC/B,KAAK,MAAM,CAAC,QAAQ,QAAQ,CAC1B,CAAC,mBAAmB,WAAW,GAC/B,CAAC,aAAa,aAAa,CAC7B,GAAY;EACV,MAAM,QAAQ,KAAK,QAAQ,MAAM;EACjC,MAAM,QAAQ,UAAU,KAAK,KAAA,IAAY,KAAK,QAAQ;EACtD,IAAI,UAAU,KAAA,KAAa,CAAC,MAAM,WAAW,GAAG,GAAG,SAAS,OAAO;OAC9D,KAAK,KAAK,QAAQ,SAAS,IAAI;CACtC;CACA,IAAI,CAAC,oBAAoB,KAAK,SAAS,SAAS,GAAG,MAAM,IAAI,MAAM,qBAAqB;CACxF,OAAO;EAAE,WAAW;EAAM;CAAS;AACrC;AAEA,MAAM,oBAAoB;;;;;;;;AAY1B,SAAgB,qBACd,SAIA;CACA,MAAM,EAAE,WAAW,OAAO,UAAU,uBAAuB;CAC3D,MAAM,OAAiB,CAAC;CACxB,MAAM,SAAgC,CAAC;CACvC,IAAI,WAAW,cAAc,KAAA,GAAW;EACtC,KAAK,KAAK,mBAAmB,UAAU,SAAS;EAChD,OAAO,KAAK,WAAW;CACzB;CACA,IAAI,WAAW,YAAY,KAAA,GAAW;EACpC,KAAK,KAAK,gBAAgB,UAAU,OAAO;EAC3C,OAAO,KAAK,SAAS;CACvB;CACA,IAAI,WAAW,YAAY,KAAA,GAAW;EACpC,IAAI,UAAU,QAAQ,WAAW,GAAG,KAAK,KAAK,iBAAiB;OAC1D,KAAK,KAAK,gBAAgB,UAAU,QAAQ,KAAK,GAAG,CAAC;EAC1D,OAAO,KAAK,SAAS;CACvB;CACA,IAAI,UAAU,KAAA,GAAW,KAAK,KAAK,cAAc,KAAK;CACtD,IAAI,aAAa,KAAA,GAAW,KAAK,KAAK,iBAAiB,QAAQ;CAE/D,IAAI,uBAAuB,KAAA,GAAW,KAAK,KAAK,6BAA6B,kBAAkB;CAC/F,OAAO;EAAE;EAAM;CAAO;AACxB"}
@@ -0,0 +1,65 @@
1
+ const require_runtime = require("../../../_virtual/_rolldown/runtime.cjs");
2
+ let node_fs = require("node:fs");
3
+ node_fs = require_runtime.__toESM(node_fs, 1);
4
+ let node_path = require("node:path");
5
+ node_path = require_runtime.__toESM(node_path, 1);
6
+ //#region src/builders/server/watcherService.ts
7
+ /** Quiet time after the last event before a change is reported, so a build in progress reports once. */
8
+ const SETTLE_MS = 300;
9
+ /** Safety net for what a watcher misses (dropped events, unwatched installs): report a change this often. */
10
+ const REVALIDATE_MS = 6e4;
11
+ /**
12
+ * Debounced file watching over directories, with a periodic revalidation tick. It knows
13
+ * nothing about what the paths mean; the caller decides what a change invalidates.
14
+ * Watchers are not persistent, so they never keep the process alive.
15
+ */
16
+ function createWatcherService(options) {
17
+ const settleMs = options.settleMs ?? SETTLE_MS;
18
+ const watchers = /* @__PURE__ */ new Map();
19
+ let pending;
20
+ const changed = () => {
21
+ if (pending !== void 0) clearTimeout(pending);
22
+ pending = setTimeout(() => {
23
+ pending = void 0;
24
+ options.onChange();
25
+ }, settleMs);
26
+ pending.unref();
27
+ };
28
+ const tick = setInterval(options.onChange, options.revalidateMs ?? REVALIDATE_MS);
29
+ tick.unref();
30
+ return {
31
+ /** Watches a directory once; adding the same path again is a no-op. */
32
+ add(target) {
33
+ if (watchers.has(target.path) || !node_fs.default.existsSync(target.path)) return;
34
+ try {
35
+ const watcher = node_fs.default.watch(target.path, {
36
+ recursive: target.recursive === true,
37
+ persistent: false
38
+ }, (_, file) => {
39
+ if (file === null || target.include === void 0 || target.include(file)) changed();
40
+ });
41
+ watcher.on("error", (error) => {
42
+ options.onNotice(`Stopped watching ${target.path}: ${error.message}`);
43
+ watcher.close();
44
+ watchers.delete(target.path);
45
+ });
46
+ watchers.set(target.path, watcher);
47
+ } catch (error) {
48
+ options.onNotice(`Could not watch ${target.path}: ${error instanceof Error ? error.message : String(error)}`);
49
+ }
50
+ },
51
+ close() {
52
+ clearInterval(tick);
53
+ if (pending !== void 0) clearTimeout(pending);
54
+ for (const watcher of watchers.values()) watcher.close();
55
+ watchers.clear();
56
+ }
57
+ };
58
+ }
59
+ /** Changes under a package root that matter: anything outside its `node_modules` (snapshots live there). */
60
+ const outsideNodeModules = (relative) => relative.split(node_path.default.sep)[0] !== "node_modules";
61
+ //#endregion
62
+ exports.createWatcherService = createWatcherService;
63
+ exports.outsideNodeModules = outsideNodeModules;
64
+
65
+ //# sourceMappingURL=watcherService.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcherService.cjs","names":["fs","path"],"sources":["../../../../src/builders/server/watcherService.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\n/** Quiet time after the last event before a change is reported, so a build in progress reports once. */\nconst SETTLE_MS = 300;\n/** Safety net for what a watcher misses (dropped events, unwatched installs): report a change this often. */\nconst REVALIDATE_MS = 60_000;\n\nexport interface WatchTarget {\n /** A directory to watch. A missing one is skipped; the revalidation tick covers it. */\n readonly path: string;\n readonly recursive?: boolean;\n /** Which changed paths, relative to `path`, count. Every path counts when omitted. */\n readonly include?: (relative: string) => boolean;\n}\n\nexport interface WatcherServiceOptions {\n /** Called once per settled burst of changes, and on every revalidation tick. */\n readonly onChange: () => void;\n readonly onNotice: (message: string) => void;\n readonly settleMs?: number;\n readonly revalidateMs?: number;\n}\n\n/**\n * Debounced file watching over directories, with a periodic revalidation tick. It knows\n * nothing about what the paths mean; the caller decides what a change invalidates.\n * Watchers are not persistent, so they never keep the process alive.\n */\nexport function createWatcherService(options: WatcherServiceOptions) {\n const settleMs = options.settleMs ?? SETTLE_MS;\n const watchers = new Map<string, fs.FSWatcher>();\n let pending: NodeJS.Timeout | undefined;\n const changed = () => {\n if (pending !== undefined) clearTimeout(pending);\n pending = setTimeout(() => {\n pending = undefined;\n options.onChange();\n }, settleMs);\n pending.unref();\n };\n const tick = setInterval(options.onChange, options.revalidateMs ?? REVALIDATE_MS);\n tick.unref();\n\n return {\n /** Watches a directory once; adding the same path again is a no-op. */\n add(target: WatchTarget): void {\n if (watchers.has(target.path) || !fs.existsSync(target.path)) return;\n try {\n const watcher = fs.watch(\n target.path,\n { recursive: target.recursive === true, persistent: false },\n (_, file) => {\n if (file === null || target.include === undefined || target.include(file)) changed();\n },\n );\n // ponytail: a failed watcher (removed directory, descriptor limit) is dropped and the\n // revalidation tick covers it; re-add on the next composition if that proves too slow.\n watcher.on('error', (error) => {\n options.onNotice(`Stopped watching ${target.path}: ${error.message}`);\n watcher.close();\n watchers.delete(target.path);\n });\n watchers.set(target.path, watcher);\n } catch (error) {\n options.onNotice(`Could not watch ${target.path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n close(): void {\n clearInterval(tick);\n if (pending !== undefined) clearTimeout(pending);\n for (const watcher of watchers.values()) watcher.close();\n watchers.clear();\n },\n };\n}\n\n/** Changes under a package root that matter: anything outside its `node_modules` (snapshots live there). */\nexport const outsideNodeModules = (relative: string): boolean => relative.split(path.sep)[0] !== 'node_modules';\n\nexport type WatcherService = ReturnType<typeof createWatcherService>;\n"],"mappings":";;;;;;;AAIA,MAAM,YAAY;;AAElB,MAAM,gBAAgB;;;;;;AAuBtB,SAAgB,qBAAqB,SAAgC;CACnE,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,2BAAW,IAAI,IAA0B;CAC/C,IAAI;CACJ,MAAM,gBAAgB;EACpB,IAAI,YAAY,KAAA,GAAW,aAAa,OAAO;EAC/C,UAAU,iBAAiB;GACzB,UAAU,KAAA;GACV,QAAQ,SAAS;EACnB,GAAG,QAAQ;EACX,QAAQ,MAAM;CAChB;CACA,MAAM,OAAO,YAAY,QAAQ,UAAU,QAAQ,gBAAgB,aAAa;CAChF,KAAK,MAAM;CAEX,OAAO;;EAEL,IAAI,QAA2B;GAC7B,IAAI,SAAS,IAAI,OAAO,IAAI,KAAK,CAACA,QAAAA,QAAG,WAAW,OAAO,IAAI,GAAG;GAC9D,IAAI;IACF,MAAM,UAAUA,QAAAA,QAAG,MACjB,OAAO,MACP;KAAE,WAAW,OAAO,cAAc;KAAM,YAAY;IAAM,IACzD,GAAG,SAAS;KACX,IAAI,SAAS,QAAQ,OAAO,YAAY,KAAA,KAAa,OAAO,QAAQ,IAAI,GAAG,QAAQ;IACrF,CACF;IAGA,QAAQ,GAAG,UAAU,UAAU;KAC7B,QAAQ,SAAS,oBAAoB,OAAO,KAAK,IAAI,MAAM,SAAS;KACpE,QAAQ,MAAM;KACd,SAAS,OAAO,OAAO,IAAI;IAC7B,CAAC;IACD,SAAS,IAAI,OAAO,MAAM,OAAO;GACnC,SAAS,OAAO;IACd,QAAQ,SAAS,mBAAmB,OAAO,KAAK,IAAI,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG;GAC9G;EACF;EACA,QAAc;GACZ,cAAc,IAAI;GAClB,IAAI,YAAY,KAAA,GAAW,aAAa,OAAO;GAC/C,KAAK,MAAM,WAAW,SAAS,OAAO,GAAG,QAAQ,MAAM;GACvD,SAAS,MAAM;EACjB;CACF;AACF;;AAGA,MAAa,sBAAsB,aAA8B,SAAS,MAAMC,UAAAA,QAAK,GAAG,CAAC,CAAC,OAAO"}
@@ -0,0 +1,61 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ //#region src/builders/server/watcherService.ts
4
+ /** Quiet time after the last event before a change is reported, so a build in progress reports once. */
5
+ const SETTLE_MS = 300;
6
+ /** Safety net for what a watcher misses (dropped events, unwatched installs): report a change this often. */
7
+ const REVALIDATE_MS = 6e4;
8
+ /**
9
+ * Debounced file watching over directories, with a periodic revalidation tick. It knows
10
+ * nothing about what the paths mean; the caller decides what a change invalidates.
11
+ * Watchers are not persistent, so they never keep the process alive.
12
+ */
13
+ function createWatcherService(options) {
14
+ const settleMs = options.settleMs ?? SETTLE_MS;
15
+ const watchers = /* @__PURE__ */ new Map();
16
+ let pending;
17
+ const changed = () => {
18
+ if (pending !== void 0) clearTimeout(pending);
19
+ pending = setTimeout(() => {
20
+ pending = void 0;
21
+ options.onChange();
22
+ }, settleMs);
23
+ pending.unref();
24
+ };
25
+ const tick = setInterval(options.onChange, options.revalidateMs ?? REVALIDATE_MS);
26
+ tick.unref();
27
+ return {
28
+ /** Watches a directory once; adding the same path again is a no-op. */
29
+ add(target) {
30
+ if (watchers.has(target.path) || !fs.existsSync(target.path)) return;
31
+ try {
32
+ const watcher = fs.watch(target.path, {
33
+ recursive: target.recursive === true,
34
+ persistent: false
35
+ }, (_, file) => {
36
+ if (file === null || target.include === void 0 || target.include(file)) changed();
37
+ });
38
+ watcher.on("error", (error) => {
39
+ options.onNotice(`Stopped watching ${target.path}: ${error.message}`);
40
+ watcher.close();
41
+ watchers.delete(target.path);
42
+ });
43
+ watchers.set(target.path, watcher);
44
+ } catch (error) {
45
+ options.onNotice(`Could not watch ${target.path}: ${error instanceof Error ? error.message : String(error)}`);
46
+ }
47
+ },
48
+ close() {
49
+ clearInterval(tick);
50
+ if (pending !== void 0) clearTimeout(pending);
51
+ for (const watcher of watchers.values()) watcher.close();
52
+ watchers.clear();
53
+ }
54
+ };
55
+ }
56
+ /** Changes under a package root that matter: anything outside its `node_modules` (snapshots live there). */
57
+ const outsideNodeModules = (relative) => relative.split(path.sep)[0] !== "node_modules";
58
+ //#endregion
59
+ export { createWatcherService, outsideNodeModules };
60
+
61
+ //# sourceMappingURL=watcherService.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcherService.mjs","names":[],"sources":["../../../../src/builders/server/watcherService.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\n/** Quiet time after the last event before a change is reported, so a build in progress reports once. */\nconst SETTLE_MS = 300;\n/** Safety net for what a watcher misses (dropped events, unwatched installs): report a change this often. */\nconst REVALIDATE_MS = 60_000;\n\nexport interface WatchTarget {\n /** A directory to watch. A missing one is skipped; the revalidation tick covers it. */\n readonly path: string;\n readonly recursive?: boolean;\n /** Which changed paths, relative to `path`, count. Every path counts when omitted. */\n readonly include?: (relative: string) => boolean;\n}\n\nexport interface WatcherServiceOptions {\n /** Called once per settled burst of changes, and on every revalidation tick. */\n readonly onChange: () => void;\n readonly onNotice: (message: string) => void;\n readonly settleMs?: number;\n readonly revalidateMs?: number;\n}\n\n/**\n * Debounced file watching over directories, with a periodic revalidation tick. It knows\n * nothing about what the paths mean; the caller decides what a change invalidates.\n * Watchers are not persistent, so they never keep the process alive.\n */\nexport function createWatcherService(options: WatcherServiceOptions) {\n const settleMs = options.settleMs ?? SETTLE_MS;\n const watchers = new Map<string, fs.FSWatcher>();\n let pending: NodeJS.Timeout | undefined;\n const changed = () => {\n if (pending !== undefined) clearTimeout(pending);\n pending = setTimeout(() => {\n pending = undefined;\n options.onChange();\n }, settleMs);\n pending.unref();\n };\n const tick = setInterval(options.onChange, options.revalidateMs ?? REVALIDATE_MS);\n tick.unref();\n\n return {\n /** Watches a directory once; adding the same path again is a no-op. */\n add(target: WatchTarget): void {\n if (watchers.has(target.path) || !fs.existsSync(target.path)) return;\n try {\n const watcher = fs.watch(\n target.path,\n { recursive: target.recursive === true, persistent: false },\n (_, file) => {\n if (file === null || target.include === undefined || target.include(file)) changed();\n },\n );\n // ponytail: a failed watcher (removed directory, descriptor limit) is dropped and the\n // revalidation tick covers it; re-add on the next composition if that proves too slow.\n watcher.on('error', (error) => {\n options.onNotice(`Stopped watching ${target.path}: ${error.message}`);\n watcher.close();\n watchers.delete(target.path);\n });\n watchers.set(target.path, watcher);\n } catch (error) {\n options.onNotice(`Could not watch ${target.path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n close(): void {\n clearInterval(tick);\n if (pending !== undefined) clearTimeout(pending);\n for (const watcher of watchers.values()) watcher.close();\n watchers.clear();\n },\n };\n}\n\n/** Changes under a package root that matter: anything outside its `node_modules` (snapshots live there). */\nexport const outsideNodeModules = (relative: string): boolean => relative.split(path.sep)[0] !== 'node_modules';\n\nexport type WatcherService = ReturnType<typeof createWatcherService>;\n"],"mappings":";;;;AAIA,MAAM,YAAY;;AAElB,MAAM,gBAAgB;;;;;;AAuBtB,SAAgB,qBAAqB,SAAgC;CACnE,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,2BAAW,IAAI,IAA0B;CAC/C,IAAI;CACJ,MAAM,gBAAgB;EACpB,IAAI,YAAY,KAAA,GAAW,aAAa,OAAO;EAC/C,UAAU,iBAAiB;GACzB,UAAU,KAAA;GACV,QAAQ,SAAS;EACnB,GAAG,QAAQ;EACX,QAAQ,MAAM;CAChB;CACA,MAAM,OAAO,YAAY,QAAQ,UAAU,QAAQ,gBAAgB,aAAa;CAChF,KAAK,MAAM;CAEX,OAAO;;EAEL,IAAI,QAA2B;GAC7B,IAAI,SAAS,IAAI,OAAO,IAAI,KAAK,CAAC,GAAG,WAAW,OAAO,IAAI,GAAG;GAC9D,IAAI;IACF,MAAM,UAAU,GAAG,MACjB,OAAO,MACP;KAAE,WAAW,OAAO,cAAc;KAAM,YAAY;IAAM,IACzD,GAAG,SAAS;KACX,IAAI,SAAS,QAAQ,OAAO,YAAY,KAAA,KAAa,OAAO,QAAQ,IAAI,GAAG,QAAQ;IACrF,CACF;IAGA,QAAQ,GAAG,UAAU,UAAU;KAC7B,QAAQ,SAAS,oBAAoB,OAAO,KAAK,IAAI,MAAM,SAAS;KACpE,QAAQ,MAAM;KACd,SAAS,OAAO,OAAO,IAAI;IAC7B,CAAC;IACD,SAAS,IAAI,OAAO,MAAM,OAAO;GACnC,SAAS,OAAO;IACd,QAAQ,SAAS,mBAAmB,OAAO,KAAK,IAAI,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG;GAC9G;EACF;EACA,QAAc;GACZ,cAAc,IAAI;GAClB,IAAI,YAAY,KAAA,GAAW,aAAa,OAAO;GAC/C,KAAK,MAAM,WAAW,SAAS,OAAO,GAAG,QAAQ,MAAM;GACvD,SAAS,MAAM;EACjB;CACF;AACF;;AAGA,MAAa,sBAAsB,aAA8B,SAAS,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO"}
@@ -18,7 +18,7 @@ function resolveWebTemplateDecision(options) {
18
18
  workspaceId: workspace.id
19
19
  };
20
20
  try {
21
- const id = (0, _agimon_ai_po_config_config.loadDoomConfigLayers)(workspace?.root, options.homeDirectory, options.environment).valueAt([host, "template"]);
21
+ const id = (0, _agimon_ai_po_config_config.loadPoConfigLayers)(workspace?.root, options.homeDirectory, options.environment).valueAt([host, "template"]);
22
22
  return {
23
23
  ...typeof id === "string" ? { id } : {},
24
24
  mount
@@ -1 +1 @@
1
- {"version":3,"file":"webTemplateDecision.cjs","names":["path","loadDoomConfigLayers"],"sources":["../../../../src/builders/server/webTemplateDecision.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { loadDoomConfigLayers } from '@agimon-ai/po-config/config';\n\ninterface WebTemplateDecision {\n id?: string;\n mount: { scope: 'global' } | { scope: 'workspace'; workspaceId: string };\n}\n\n/**\n * Resolve presentation from the server launch, never the selected session or workspace.\n * `host` picks the config key: `web.template` for the cockpit, `native.template` for the phone app.\n */\nexport function resolveWebTemplateDecision(options: {\n cwd: string;\n launchWorkspaceId?: string;\n workspaces: readonly { id: string; root: string }[];\n homeDirectory: string;\n environment: NodeJS.ProcessEnv;\n notice: (message: string) => void;\n host?: 'web' | 'native';\n}): WebTemplateDecision {\n const host = options.host ?? 'web';\n // ponytail: without initial admission, a member checkout outside its canonical workspace\n // root falls back to global config. Resolving it must not admit or sync a new workspace.\n const workspace =\n options.workspaces.find((candidate) => candidate.id === options.launchWorkspaceId) ??\n options.workspaces\n .filter((candidate) => {\n const relative = path.relative(candidate.root, options.cwd);\n return relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);\n })\n .sort((left, right) => right.root.length - left.root.length)[0];\n const mount: WebTemplateDecision['mount'] =\n workspace === undefined ? { scope: 'global' } : { scope: 'workspace', workspaceId: workspace.id };\n try {\n const id = loadDoomConfigLayers(workspace?.root, options.homeDirectory, options.environment).valueAt([\n host,\n 'template',\n ]);\n return { ...(typeof id === 'string' ? { id } : {}), mount };\n } catch (error) {\n options.notice(\n `${host === 'web' ? 'Web' : 'Native'} template configuration unavailable: ${error instanceof Error ? error.message : String(error)}`,\n );\n return { mount };\n }\n}\n"],"mappings":";;;;;;;;;AAaA,SAAgB,2BAA2B,SAQnB;CACtB,MAAM,OAAO,QAAQ,QAAQ;CAG7B,MAAM,YACJ,QAAQ,WAAW,MAAM,cAAc,UAAU,OAAO,QAAQ,iBAAiB,KACjF,QAAQ,WACL,QAAQ,cAAc;EACrB,MAAM,WAAWA,UAAAA,QAAK,SAAS,UAAU,MAAM,QAAQ,GAAG;EAC1D,OAAO,aAAa,QAAQ,CAAC,SAAS,WAAW,KAAKA,UAAAA,QAAK,KAAK,KAAK,CAACA,UAAAA,QAAK,WAAW,QAAQ;CAChG,CAAC,CAAC,CACD,MAAM,MAAM,UAAU,MAAM,KAAK,SAAS,KAAK,KAAK,MAAM,CAAC,CAAC;CACjE,MAAM,QACJ,cAAc,KAAA,IAAY,EAAE,OAAO,SAAS,IAAI;EAAE,OAAO;EAAa,aAAa,UAAU;CAAG;CAClG,IAAI;EACF,MAAM,MAAA,GAAKC,4BAAAA,qBAAAA,CAAqB,WAAW,MAAM,QAAQ,eAAe,QAAQ,WAAW,CAAC,CAAC,QAAQ,CACnG,MACA,UACF,CAAC;EACD,OAAO;GAAE,GAAI,OAAO,OAAO,WAAW,EAAE,GAAG,IAAI,CAAC;GAAI;EAAM;CAC5D,SAAS,OAAO;EACd,QAAQ,OACN,GAAG,SAAS,QAAQ,QAAQ,SAAS,uCAAuC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GACnI;EACA,OAAO,EAAE,MAAM;CACjB;AACF"}
1
+ {"version":3,"file":"webTemplateDecision.cjs","names":["path","loadPoConfigLayers"],"sources":["../../../../src/builders/server/webTemplateDecision.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { loadPoConfigLayers } from '@agimon-ai/po-config/config';\n\ninterface WebTemplateDecision {\n id?: string;\n mount: { scope: 'global' } | { scope: 'workspace'; workspaceId: string };\n}\n\n/**\n * Resolve presentation from the server launch, never the selected session or workspace.\n * `host` picks the config key: `web.template` for the cockpit, `native.template` for the phone app.\n */\nexport function resolveWebTemplateDecision(options: {\n cwd: string;\n launchWorkspaceId?: string;\n workspaces: readonly { id: string; root: string }[];\n homeDirectory: string;\n environment: NodeJS.ProcessEnv;\n notice: (message: string) => void;\n host?: 'web' | 'native';\n}): WebTemplateDecision {\n const host = options.host ?? 'web';\n // ponytail: without initial admission, a member checkout outside its canonical workspace\n // root falls back to global config. Resolving it must not admit or sync a new workspace.\n const workspace =\n options.workspaces.find((candidate) => candidate.id === options.launchWorkspaceId) ??\n options.workspaces\n .filter((candidate) => {\n const relative = path.relative(candidate.root, options.cwd);\n return relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);\n })\n .sort((left, right) => right.root.length - left.root.length)[0];\n const mount: WebTemplateDecision['mount'] =\n workspace === undefined ? { scope: 'global' } : { scope: 'workspace', workspaceId: workspace.id };\n try {\n const id = loadPoConfigLayers(workspace?.root, options.homeDirectory, options.environment).valueAt([\n host,\n 'template',\n ]);\n return { ...(typeof id === 'string' ? { id } : {}), mount };\n } catch (error) {\n options.notice(\n `${host === 'web' ? 'Web' : 'Native'} template configuration unavailable: ${error instanceof Error ? error.message : String(error)}`,\n );\n return { mount };\n }\n}\n"],"mappings":";;;;;;;;;AAaA,SAAgB,2BAA2B,SAQnB;CACtB,MAAM,OAAO,QAAQ,QAAQ;CAG7B,MAAM,YACJ,QAAQ,WAAW,MAAM,cAAc,UAAU,OAAO,QAAQ,iBAAiB,KACjF,QAAQ,WACL,QAAQ,cAAc;EACrB,MAAM,WAAWA,UAAAA,QAAK,SAAS,UAAU,MAAM,QAAQ,GAAG;EAC1D,OAAO,aAAa,QAAQ,CAAC,SAAS,WAAW,KAAKA,UAAAA,QAAK,KAAK,KAAK,CAACA,UAAAA,QAAK,WAAW,QAAQ;CAChG,CAAC,CAAC,CACD,MAAM,MAAM,UAAU,MAAM,KAAK,SAAS,KAAK,KAAK,MAAM,CAAC,CAAC;CACjE,MAAM,QACJ,cAAc,KAAA,IAAY,EAAE,OAAO,SAAS,IAAI;EAAE,OAAO;EAAa,aAAa,UAAU;CAAG;CAClG,IAAI;EACF,MAAM,MAAA,GAAKC,4BAAAA,mBAAAA,CAAmB,WAAW,MAAM,QAAQ,eAAe,QAAQ,WAAW,CAAC,CAAC,QAAQ,CACjG,MACA,UACF,CAAC;EACD,OAAO;GAAE,GAAI,OAAO,OAAO,WAAW,EAAE,GAAG,IAAI,CAAC;GAAI;EAAM;CAC5D,SAAS,OAAO;EACd,QAAQ,OACN,GAAG,SAAS,QAAQ,QAAQ,SAAS,uCAAuC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GACnI;EACA,OAAO,EAAE,MAAM;CACjB;AACF"}
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import { loadDoomConfigLayers } from "@agimon-ai/po-config/config";
2
+ import { loadPoConfigLayers } from "@agimon-ai/po-config/config";
3
3
  //#region src/builders/server/webTemplateDecision.ts
4
4
  /**
5
5
  * Resolve presentation from the server launch, never the selected session or workspace.
@@ -16,7 +16,7 @@ function resolveWebTemplateDecision(options) {
16
16
  workspaceId: workspace.id
17
17
  };
18
18
  try {
19
- const id = loadDoomConfigLayers(workspace?.root, options.homeDirectory, options.environment).valueAt([host, "template"]);
19
+ const id = loadPoConfigLayers(workspace?.root, options.homeDirectory, options.environment).valueAt([host, "template"]);
20
20
  return {
21
21
  ...typeof id === "string" ? { id } : {},
22
22
  mount
@@ -1 +1 @@
1
- {"version":3,"file":"webTemplateDecision.mjs","names":[],"sources":["../../../../src/builders/server/webTemplateDecision.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { loadDoomConfigLayers } from '@agimon-ai/po-config/config';\n\ninterface WebTemplateDecision {\n id?: string;\n mount: { scope: 'global' } | { scope: 'workspace'; workspaceId: string };\n}\n\n/**\n * Resolve presentation from the server launch, never the selected session or workspace.\n * `host` picks the config key: `web.template` for the cockpit, `native.template` for the phone app.\n */\nexport function resolveWebTemplateDecision(options: {\n cwd: string;\n launchWorkspaceId?: string;\n workspaces: readonly { id: string; root: string }[];\n homeDirectory: string;\n environment: NodeJS.ProcessEnv;\n notice: (message: string) => void;\n host?: 'web' | 'native';\n}): WebTemplateDecision {\n const host = options.host ?? 'web';\n // ponytail: without initial admission, a member checkout outside its canonical workspace\n // root falls back to global config. Resolving it must not admit or sync a new workspace.\n const workspace =\n options.workspaces.find((candidate) => candidate.id === options.launchWorkspaceId) ??\n options.workspaces\n .filter((candidate) => {\n const relative = path.relative(candidate.root, options.cwd);\n return relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);\n })\n .sort((left, right) => right.root.length - left.root.length)[0];\n const mount: WebTemplateDecision['mount'] =\n workspace === undefined ? { scope: 'global' } : { scope: 'workspace', workspaceId: workspace.id };\n try {\n const id = loadDoomConfigLayers(workspace?.root, options.homeDirectory, options.environment).valueAt([\n host,\n 'template',\n ]);\n return { ...(typeof id === 'string' ? { id } : {}), mount };\n } catch (error) {\n options.notice(\n `${host === 'web' ? 'Web' : 'Native'} template configuration unavailable: ${error instanceof Error ? error.message : String(error)}`,\n );\n return { mount };\n }\n}\n"],"mappings":";;;;;;;AAaA,SAAgB,2BAA2B,SAQnB;CACtB,MAAM,OAAO,QAAQ,QAAQ;CAG7B,MAAM,YACJ,QAAQ,WAAW,MAAM,cAAc,UAAU,OAAO,QAAQ,iBAAiB,KACjF,QAAQ,WACL,QAAQ,cAAc;EACrB,MAAM,WAAW,KAAK,SAAS,UAAU,MAAM,QAAQ,GAAG;EAC1D,OAAO,aAAa,QAAQ,CAAC,SAAS,WAAW,KAAK,KAAK,KAAK,KAAK,CAAC,KAAK,WAAW,QAAQ;CAChG,CAAC,CAAC,CACD,MAAM,MAAM,UAAU,MAAM,KAAK,SAAS,KAAK,KAAK,MAAM,CAAC,CAAC;CACjE,MAAM,QACJ,cAAc,KAAA,IAAY,EAAE,OAAO,SAAS,IAAI;EAAE,OAAO;EAAa,aAAa,UAAU;CAAG;CAClG,IAAI;EACF,MAAM,KAAK,qBAAqB,WAAW,MAAM,QAAQ,eAAe,QAAQ,WAAW,CAAC,CAAC,QAAQ,CACnG,MACA,UACF,CAAC;EACD,OAAO;GAAE,GAAI,OAAO,OAAO,WAAW,EAAE,GAAG,IAAI,CAAC;GAAI;EAAM;CAC5D,SAAS,OAAO;EACd,QAAQ,OACN,GAAG,SAAS,QAAQ,QAAQ,SAAS,uCAAuC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GACnI;EACA,OAAO,EAAE,MAAM;CACjB;AACF"}
1
+ {"version":3,"file":"webTemplateDecision.mjs","names":[],"sources":["../../../../src/builders/server/webTemplateDecision.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { loadPoConfigLayers } from '@agimon-ai/po-config/config';\n\ninterface WebTemplateDecision {\n id?: string;\n mount: { scope: 'global' } | { scope: 'workspace'; workspaceId: string };\n}\n\n/**\n * Resolve presentation from the server launch, never the selected session or workspace.\n * `host` picks the config key: `web.template` for the cockpit, `native.template` for the phone app.\n */\nexport function resolveWebTemplateDecision(options: {\n cwd: string;\n launchWorkspaceId?: string;\n workspaces: readonly { id: string; root: string }[];\n homeDirectory: string;\n environment: NodeJS.ProcessEnv;\n notice: (message: string) => void;\n host?: 'web' | 'native';\n}): WebTemplateDecision {\n const host = options.host ?? 'web';\n // ponytail: without initial admission, a member checkout outside its canonical workspace\n // root falls back to global config. Resolving it must not admit or sync a new workspace.\n const workspace =\n options.workspaces.find((candidate) => candidate.id === options.launchWorkspaceId) ??\n options.workspaces\n .filter((candidate) => {\n const relative = path.relative(candidate.root, options.cwd);\n return relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);\n })\n .sort((left, right) => right.root.length - left.root.length)[0];\n const mount: WebTemplateDecision['mount'] =\n workspace === undefined ? { scope: 'global' } : { scope: 'workspace', workspaceId: workspace.id };\n try {\n const id = loadPoConfigLayers(workspace?.root, options.homeDirectory, options.environment).valueAt([\n host,\n 'template',\n ]);\n return { ...(typeof id === 'string' ? { id } : {}), mount };\n } catch (error) {\n options.notice(\n `${host === 'web' ? 'Web' : 'Native'} template configuration unavailable: ${error instanceof Error ? error.message : String(error)}`,\n );\n return { mount };\n }\n}\n"],"mappings":";;;;;;;AAaA,SAAgB,2BAA2B,SAQnB;CACtB,MAAM,OAAO,QAAQ,QAAQ;CAG7B,MAAM,YACJ,QAAQ,WAAW,MAAM,cAAc,UAAU,OAAO,QAAQ,iBAAiB,KACjF,QAAQ,WACL,QAAQ,cAAc;EACrB,MAAM,WAAW,KAAK,SAAS,UAAU,MAAM,QAAQ,GAAG;EAC1D,OAAO,aAAa,QAAQ,CAAC,SAAS,WAAW,KAAK,KAAK,KAAK,KAAK,CAAC,KAAK,WAAW,QAAQ;CAChG,CAAC,CAAC,CACD,MAAM,MAAM,UAAU,MAAM,KAAK,SAAS,KAAK,KAAK,MAAM,CAAC,CAAC;CACjE,MAAM,QACJ,cAAc,KAAA,IAAY,EAAE,OAAO,SAAS,IAAI;EAAE,OAAO;EAAa,aAAa,UAAU;CAAG;CAClG,IAAI;EACF,MAAM,KAAK,mBAAmB,WAAW,MAAM,QAAQ,eAAe,QAAQ,WAAW,CAAC,CAAC,QAAQ,CACjG,MACA,UACF,CAAC;EACD,OAAO;GAAE,GAAI,OAAO,OAAO,WAAW,EAAE,GAAG,IAAI,CAAC;GAAI;EAAM;CAC5D,SAAS,OAAO;EACd,QAAQ,OACN,GAAG,SAAS,QAAQ,QAAQ,SAAS,uCAAuC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GACnI;EACA,OAAO,EAAE,MAAM;CACjB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.cjs","names":["scanWebPlugins","path","writeSyncWebPluginModules","PLUGIN_ROOTS_FILE","webPluginOverridePlugin","bundleAssetPolicyPlugin","webPluginRuntimeAliases","webPluginCssAlias","webPluginRuntimeFacadePlugin","isWebPluginFacade","WEB_PLUGIN_FACADE_CHUNK","fs","writeWebPluginStyleEntries","BASE_STYLE_ENTRY","pluginStyleEntryName"],"sources":["../../../../src/builders/web/bundle.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { bundleAssetPolicyPlugin } from './bundleAssetPolicy';\nimport { PLUGIN_ROOTS_FILE } from './webDevRoots';\nimport {\n BASE_STYLE_ENTRY,\n pluginStyleEntryName,\n writeSyncWebPluginModules,\n writeWebPluginStyleEntries,\n} from './webPluginGenerate';\nimport { scanWebPlugins } from './webPluginScan';\nimport {\n isWebPluginFacade,\n WEB_PLUGIN_FACADE_CHUNK,\n webPluginCssAlias,\n webPluginOverridePlugin,\n webPluginRuntimeAliases,\n webPluginRuntimeFacadePlugin,\n} from './webPluginVite';\n\n/** Shared runtime packages every plugin's client code must resolve to the host copies. */\nconst DEDUPED_RUNTIMES = [\n 'react',\n 'react-dom',\n '@tanstack/store',\n '@tanstack/react-store',\n '@tanstack/react-router',\n '@agimon-ai/po-core',\n '@agimon-ai/po-web-dashboard',\n '@agimon-ai/po-web-components',\n // The sealed transport is a module singleton whose nonce counters every\n // plugin shares; a second copy would start counting at zero.\n '@agimon-ai/po-web-security',\n // CodeMirror's state and view are singletons in all but name: a document\n // built against one copy is rejected by an editor from the other, and a\n // grammar chunk resolved separately from the editor is exactly how a second\n // copy appears.\n '@codemirror/state',\n '@codemirror/view',\n];\n\nexport interface BundleCockpitWebOptions {\n hostRoot: string;\n /** Package roots to scan for poWeb manifests, usually the installed composition. */\n pluginRoots: readonly string[];\n /** Output directory; receives web/, plugins/, generated/, and pluginRoots.json. */\n outDir: string;\n onNotice?: (message: string) => void;\n}\n\nexport interface BundleCockpitWebResult {\n /** The cockpit shell with the host's own plugins; every other plugin ships in pluginsDir. */\n assetsDir: string;\n /** Standalone session plugin composition artifacts. */\n pluginsDir: string;\n pluginIds: string[];\n /** Every declared plugin copy with its slot and the files its slot entry reaches. */\n plugins: WebPluginBuildRecord[];\n /** One content-hashed stylesheet per slot below pluginsDir; host plugins share the base. */\n pluginStyles: Record<string, string>;\n /** The shell-only stylesheet below pluginsDir. */\n baseStyle: string;\n}\n\n/** One plugin copy in a build: its slot entry and the emitted files that entry can load. */\nexport interface WebPluginBuildRecord {\n pluginId: string;\n slot: string;\n packageDir: string;\n isHost: boolean;\n /** The slot entry module below pluginsDir. */\n entry: string;\n /** Every file the entry reaches through static and dynamic imports, plus the slot stylesheet and its assets. */\n files: string[];\n /** The stylesheets of the entry's static import closure, which a mount loads up front. */\n css: string[];\n}\n\ninterface ManifestChunk {\n file: string;\n imports?: string[];\n dynamicImports?: string[];\n css?: string[];\n assets?: string[];\n}\n\n/**\n * The files one manifest entry reaches: `files` follows static and dynamic imports and holds\n * every chunk, asset, and stylesheet on the way; `css` follows static imports only.\n */\nexport function manifestClosure(\n manifest: Readonly<Record<string, ManifestChunk>>,\n entryKey: string,\n): { entry: string; files: string[]; css: string[] } {\n const chunkOf = (key: string): ManifestChunk => {\n const chunk = manifest[key];\n if (chunk === undefined) throw new Error(`The composition manifest has no chunk '${key}'.`);\n return chunk;\n };\n const files = new Set<string>();\n const visited = new Set<string>();\n const walk = (key: string): void => {\n if (visited.has(key)) return;\n visited.add(key);\n const chunk = chunkOf(key);\n files.add(chunk.file);\n for (const file of [...(chunk.css ?? []), ...(chunk.assets ?? [])]) files.add(file);\n for (const next of [...(chunk.imports ?? []), ...(chunk.dynamicImports ?? [])]) walk(next);\n };\n walk(entryKey);\n const css = new Set<string>();\n const staticVisited = new Set<string>();\n const walkStatic = (key: string): void => {\n if (staticVisited.has(key)) return;\n staticVisited.add(key);\n const chunk = chunkOf(key);\n for (const file of chunk.css ?? []) css.add(file);\n for (const next of chunk.imports ?? []) walkStatic(next);\n };\n walkStatic(entryKey);\n return { entry: chunkOf(entryKey).file, files: [...files], css: [...css] };\n}\n\n/**\n * Builds the cockpit SPA against the installed plugin set.\n *\n * This is what `po sync` calls: manifests come from the given package\n * roots (no hardcoded plugin dependencies anywhere), the generated entry\n * modules are aliased over the committed builtin registry, and Vite compiles\n * the host shell and, separately, each plugin's shipped web source into one\n * ES-module composition with an entry per slot, so each plugin and its assets ship once.\n * The roots file beside\n * the bundle lets the dev server serve the same composition with hot reload.\n */\nexport async function bundleCockpitWeb(options: BundleCockpitWebOptions): Promise<BundleCockpitWebResult> {\n const notice = options.onNotice ?? ((): void => {});\n const hostRoot = options.hostRoot;\n const plugins = scanWebPlugins(hostRoot, options.pluginRoots, notice);\n notice(\n `bundling the cockpit with ${String(plugins.length)} web plugin(s): ${plugins.map((p) => p.pluginId).join(', ')}`,\n );\n\n const generatedDir = path.join(options.outDir, 'generated');\n const assetsDir = path.join(options.outDir, 'web');\n const pluginsDir = path.join(options.outDir, 'plugins');\n const generated = writeSyncWebPluginModules(plugins, generatedDir, hostRoot);\n const roots = [...new Set(options.pluginRoots.map((root) => path.resolve(root)))];\n fs.writeFileSync(path.join(options.outDir, PLUGIN_ROOTS_FILE), `${JSON.stringify(roots, null, 2)}\\n`);\n\n // Vite and its plugins are regular dependencies so this works from an\n // installed package, not only the workspace.\n const { build } = await import('vite');\n const { default: react } = await import('@vitejs/plugin-react');\n const { default: tailwindcss } = await import('@tailwindcss/vite');\n\n const clientRoot = path.join(hostRoot, 'src', 'web');\n\n // The shell carries only the host's own plugins; the rest load from the composition below.\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n root: clientRoot,\n plugins: [webPluginOverridePlugin(clientRoot, generated.shell), react(), tailwindcss(), bundleAssetPolicyPlugin()],\n resolve: {\n dedupe: [...DEDUPED_RUNTIMES],\n alias: [...webPluginRuntimeAliases(clientRoot), webPluginCssAlias(generated.shell)],\n },\n build: {\n outDir: assetsDir,\n emptyOutDir: true,\n sourcemap: false,\n },\n });\n\n // One ES-module composition: an entry per slot exporting its webPlugin, shared chunks\n // between them, and the shared runtime modules read from the page through facades.\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n base: './',\n plugins: [webPluginRuntimeFacadePlugin(hostRoot), react(), tailwindcss()],\n resolve: {\n dedupe: [...DEDUPED_RUNTIMES],\n alias: [webPluginCssAlias(generated)],\n },\n build: {\n cssCodeSplit: true,\n modulePreload: false,\n outDir: pluginsDir,\n emptyOutDir: true,\n sourcemap: false,\n assetsInlineLimit: 0,\n manifest: 'manifest.json',\n rollupOptions: {\n input: generated.slotEntryPaths,\n // Each slot entry is loaded for its webPlugin export, so it must keep it.\n preserveEntrySignatures: 'exports-only',\n output: {\n format: 'es',\n entryFileNames: 'slots/[name]-[hash].js',\n chunkFileNames: 'chunks/[name]-[hash].js',\n assetFileNames: 'assets/[name]-[hash][extname]',\n manualChunks: (id) => (isWebPluginFacade(id) ? WEB_PLUGIN_FACADE_CHUNK : undefined),\n },\n },\n },\n });\n const manifest = JSON.parse(fs.readFileSync(path.join(pluginsDir, 'manifest.json'), 'utf8')) as Record<\n string,\n ManifestChunk\n >;\n // Manifest keys are the entry sources relative to the build root, which is the working directory.\n const manifestRoot = fs.realpathSync(process.cwd());\n const closures = new Map(\n plugins.map((plugin) => {\n const entryPath = fs.realpathSync(generated.slotEntryPaths[plugin.slot]);\n return [plugin.slot, manifestClosure(manifest, path.relative(manifestRoot, entryPath).split(path.sep).join('/'))];\n }),\n );\n\n // One content-hashed stylesheet per plugin, compiled from its own sources over the shell's.\n const styles = writeWebPluginStyleEntries(plugins, generatedDir, hostRoot);\n const stylesRoot = path.dirname(styles.baseEntryPath);\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n root: stylesRoot,\n base: './',\n plugins: [tailwindcss()],\n resolve: {\n alias: [{ find: /^\\.\\/webPluginSources\\.generated\\.css$/, replacement: styles.baseSourcesPath }],\n },\n build: {\n cssCodeSplit: true,\n outDir: pluginsDir,\n emptyOutDir: false,\n sourcemap: false,\n assetsInlineLimit: 0,\n manifest: 'styles.manifest.json',\n rollupOptions: {\n input: Object.fromEntries([\n [BASE_STYLE_ENTRY, styles.baseEntryPath],\n ...[...styles.pluginEntryPaths].map(([slot, entry]) => [pluginStyleEntryName(slot), entry]),\n ]),\n output: { assetFileNames: 'assets/[name]-[hash][extname]' },\n },\n },\n });\n const styleManifest = JSON.parse(fs.readFileSync(path.join(pluginsDir, 'styles.manifest.json'), 'utf8')) as Record<\n string,\n { file?: string; css?: string[]; assets?: string[] }\n >;\n fs.rmSync(path.join(pluginsDir, 'styles.manifest.json'));\n const emitted = (entry: string): { file: string; assets: string[] } => {\n const record = styleManifest[path.relative(stylesRoot, entry).split(path.sep).join('/')];\n const file = record?.file?.endsWith('.css') ? record.file : record?.css?.[0];\n if (file === undefined) throw new Error(`The stylesheet entry '${entry}' emitted no CSS file.`);\n return { file, assets: record?.assets ?? [] };\n };\n const base = emitted(styles.baseEntryPath);\n const slotStyles = new Map(\n plugins.map((plugin) => {\n const entry = styles.pluginEntryPaths.get(plugin.slot);\n return [plugin.slot, entry === undefined ? base : emitted(entry)];\n }),\n );\n const pluginStyles = Object.fromEntries([...slotStyles].map(([slot, style]) => [slot, style.file]));\n fs.writeFileSync(path.join(pluginsDir, 'index.html'), '<!doctype html>\\n<title>Po plugin composition</title>\\n');\n\n return {\n assetsDir,\n pluginsDir,\n pluginIds: plugins.map((plugin) => plugin.pluginId),\n plugins: plugins.map((plugin) => {\n const closure = closures.get(plugin.slot);\n const style = slotStyles.get(plugin.slot);\n if (closure === undefined || style === undefined) throw new Error(`The slot '${plugin.slot}' emitted no entry.`);\n return {\n pluginId: plugin.pluginId,\n slot: plugin.slot,\n packageDir: plugin.packageDir,\n isHost: plugin.isHost,\n entry: closure.entry,\n // The slot's own stylesheet and the fonts it references load with it.\n files: [...new Set([...closure.files, style.file, ...style.assets])],\n css: closure.css,\n };\n }),\n pluginStyles,\n baseStyle: base.file,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bundle.cjs","names":["scanWebPlugins","path","writeSyncWebPluginModules","PLUGIN_ROOTS_FILE","webPluginOverridePlugin","bundleAssetPolicyPlugin","webPluginRuntimeAliases","webPluginCssAlias","webPluginRuntimeFacadePlugin","isWebPluginFacade","WEB_PLUGIN_FACADE_CHUNK","fs","writeWebPluginStyleEntries","BASE_STYLE_ENTRY","pluginStyleEntryName"],"sources":["../../../../src/builders/web/bundle.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { bundleAssetPolicyPlugin } from './bundleAssetPolicy';\nimport { PLUGIN_ROOTS_FILE } from './webDevRoots';\nimport {\n BASE_STYLE_ENTRY,\n pluginStyleEntryName,\n writeSyncWebPluginModules,\n writeWebPluginStyleEntries,\n} from './webPluginGenerate';\nimport { scanWebPlugins } from './webPluginScan';\nimport {\n isWebPluginFacade,\n WEB_PLUGIN_FACADE_CHUNK,\n webPluginCssAlias,\n webPluginOverridePlugin,\n webPluginRuntimeAliases,\n webPluginRuntimeFacadePlugin,\n} from './webPluginVite';\n\n/** Shared runtime packages every plugin's client code must resolve to the host copies. */\nconst DEDUPED_RUNTIMES = [\n 'react',\n 'react-dom',\n '@tanstack/store',\n '@tanstack/react-store',\n '@tanstack/react-router',\n '@agimon-ai/po-core',\n '@agimon-ai/po-web-dashboard',\n '@agimon-ai/po-web-components',\n // The sealed transport is a module singleton whose nonce counters every\n // plugin shares; a second copy would start counting at zero.\n '@agimon-ai/po-web-security',\n // CodeMirror's state and view are singletons in all but name: a document\n // built against one copy is rejected by an editor from the other, and a\n // grammar chunk resolved separately from the editor is exactly how a second\n // copy appears.\n '@codemirror/state',\n '@codemirror/view',\n];\n\nexport interface BundleCockpitWebOptions {\n hostRoot: string;\n /** Package roots to scan for poWeb manifests, usually the installed composition. */\n pluginRoots: readonly string[];\n /** Output directory; receives web/, plugins/, generated/, and pluginRoots.json. */\n outDir: string;\n onNotice?: (message: string) => void;\n}\n\nexport interface BundleCockpitWebResult {\n /** The cockpit shell with the host's own plugins; every other plugin ships in pluginsDir. */\n assetsDir: string;\n /** Standalone session plugin composition artifacts. */\n pluginsDir: string;\n pluginIds: string[];\n /** Every declared plugin copy with its slot and the files its slot entry reaches. */\n plugins: WebPluginBuildRecord[];\n /** The shared content-hashed Tailwind stylesheet below pluginsDir, keyed by slot. */\n pluginStyles: Record<string, string>;\n /** The same shared stylesheet, also loaded by mounts without plugins. */\n baseStyle: string;\n}\n\n/** One plugin copy in a build: its slot entry and the emitted files that entry can load. */\nexport interface WebPluginBuildRecord {\n pluginId: string;\n slot: string;\n packageDir: string;\n isHost: boolean;\n /** The slot entry module below pluginsDir. */\n entry: string;\n /** Every file the entry reaches through imports, plus the shared stylesheet and its assets. */\n files: string[];\n /** The stylesheets of the entry's static import closure, which a mount loads up front. */\n css: string[];\n}\n\ninterface ManifestChunk {\n file: string;\n imports?: string[];\n dynamicImports?: string[];\n css?: string[];\n assets?: string[];\n}\n\n/**\n * The files one manifest entry reaches: `files` follows static and dynamic imports and holds\n * every chunk, asset, and stylesheet on the way; `css` follows static imports only.\n */\nexport function manifestClosure(\n manifest: Readonly<Record<string, ManifestChunk>>,\n entryKey: string,\n): { entry: string; files: string[]; css: string[] } {\n const chunkOf = (key: string): ManifestChunk => {\n const chunk = manifest[key];\n if (chunk === undefined) throw new Error(`The composition manifest has no chunk '${key}'.`);\n return chunk;\n };\n const files = new Set<string>();\n const visited = new Set<string>();\n const walk = (key: string): void => {\n if (visited.has(key)) return;\n visited.add(key);\n const chunk = chunkOf(key);\n files.add(chunk.file);\n for (const file of [...(chunk.css ?? []), ...(chunk.assets ?? [])]) files.add(file);\n for (const next of [...(chunk.imports ?? []), ...(chunk.dynamicImports ?? [])]) walk(next);\n };\n walk(entryKey);\n const css = new Set<string>();\n const staticVisited = new Set<string>();\n const walkStatic = (key: string): void => {\n if (staticVisited.has(key)) return;\n staticVisited.add(key);\n const chunk = chunkOf(key);\n for (const file of chunk.css ?? []) css.add(file);\n for (const next of chunk.imports ?? []) walkStatic(next);\n };\n walkStatic(entryKey);\n return { entry: chunkOf(entryKey).file, files: [...files], css: [...css] };\n}\n\n/**\n * Builds the cockpit SPA against the installed plugin set.\n *\n * This is what `po sync` calls: manifests come from the given package\n * roots (no hardcoded plugin dependencies anywhere), the generated entry\n * modules are aliased over the committed builtin registry, and Vite compiles\n * the host shell and, separately, each plugin's shipped web source into one\n * ES-module composition with an entry per slot, so each plugin and its assets ship once.\n * The roots file beside\n * the bundle lets the dev server serve the same composition with hot reload.\n */\nexport async function bundleCockpitWeb(options: BundleCockpitWebOptions): Promise<BundleCockpitWebResult> {\n const notice = options.onNotice ?? ((): void => {});\n const hostRoot = options.hostRoot;\n const plugins = scanWebPlugins(hostRoot, options.pluginRoots, notice);\n notice(\n `bundling the cockpit with ${String(plugins.length)} web plugin(s): ${plugins.map((p) => p.pluginId).join(', ')}`,\n );\n\n const generatedDir = path.join(options.outDir, 'generated');\n const assetsDir = path.join(options.outDir, 'web');\n const pluginsDir = path.join(options.outDir, 'plugins');\n const generated = writeSyncWebPluginModules(plugins, generatedDir, hostRoot);\n const roots = [...new Set(options.pluginRoots.map((root) => path.resolve(root)))];\n fs.writeFileSync(path.join(options.outDir, PLUGIN_ROOTS_FILE), `${JSON.stringify(roots, null, 2)}\\n`);\n\n // Vite and its plugins are regular dependencies so this works from an\n // installed package, not only the workspace.\n const { build } = await import('vite');\n const { default: react } = await import('@vitejs/plugin-react');\n const { default: tailwindcss } = await import('@tailwindcss/vite');\n\n const clientRoot = path.join(hostRoot, 'src', 'web');\n\n // The shell carries only the host's own plugins; the rest load from the composition below.\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n root: clientRoot,\n plugins: [webPluginOverridePlugin(clientRoot, generated.shell), react(), tailwindcss(), bundleAssetPolicyPlugin()],\n resolve: {\n dedupe: [...DEDUPED_RUNTIMES],\n alias: [...webPluginRuntimeAliases(clientRoot), webPluginCssAlias(generated.shell)],\n },\n build: {\n outDir: assetsDir,\n emptyOutDir: true,\n sourcemap: false,\n },\n });\n\n // One ES-module composition: an entry per slot exporting its webPlugin, shared chunks\n // between them, and the shared runtime modules read from the page through facades.\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n base: './',\n plugins: [webPluginRuntimeFacadePlugin(hostRoot), react(), tailwindcss()],\n resolve: {\n dedupe: [...DEDUPED_RUNTIMES],\n alias: [webPluginCssAlias(generated)],\n },\n build: {\n cssCodeSplit: true,\n modulePreload: false,\n outDir: pluginsDir,\n emptyOutDir: true,\n sourcemap: false,\n assetsInlineLimit: 0,\n manifest: 'manifest.json',\n rollupOptions: {\n input: generated.slotEntryPaths,\n // Each slot entry is loaded for its webPlugin export, so it must keep it.\n preserveEntrySignatures: 'exports-only',\n output: {\n format: 'es',\n entryFileNames: 'slots/[name]-[hash].js',\n chunkFileNames: 'chunks/[name]-[hash].js',\n assetFileNames: 'assets/[name]-[hash][extname]',\n manualChunks: (id) => (isWebPluginFacade(id) ? WEB_PLUGIN_FACADE_CHUNK : undefined),\n },\n },\n },\n });\n const manifest = JSON.parse(fs.readFileSync(path.join(pluginsDir, 'manifest.json'), 'utf8')) as Record<\n string,\n ManifestChunk\n >;\n // Manifest keys are the entry sources relative to the build root, which is the working directory.\n const manifestRoot = fs.realpathSync(process.cwd());\n const closures = new Map(\n plugins.map((plugin) => {\n const entryPath = fs.realpathSync(generated.slotEntryPaths[plugin.slot]);\n return [plugin.slot, manifestClosure(manifest, path.relative(manifestRoot, entryPath).split(path.sep).join('/'))];\n }),\n );\n\n // One content-hashed Tailwind stylesheet for the shell, fallback template, and all plugins.\n const styles = writeWebPluginStyleEntries(plugins, generatedDir, hostRoot);\n const stylesRoot = path.dirname(styles.baseEntryPath);\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n root: stylesRoot,\n base: './',\n plugins: [tailwindcss()],\n resolve: {\n alias: [{ find: /^\\.\\/webPluginSources\\.generated\\.css$/, replacement: styles.baseSourcesPath }],\n },\n build: {\n cssCodeSplit: true,\n outDir: pluginsDir,\n emptyOutDir: false,\n sourcemap: false,\n assetsInlineLimit: 0,\n manifest: 'styles.manifest.json',\n rollupOptions: {\n input: Object.fromEntries([\n [BASE_STYLE_ENTRY, styles.baseEntryPath],\n ...[...styles.pluginEntryPaths].map(([slot, entry]) => [pluginStyleEntryName(slot), entry]),\n ]),\n output: { assetFileNames: 'assets/[name]-[hash][extname]' },\n },\n },\n });\n const styleManifest = JSON.parse(fs.readFileSync(path.join(pluginsDir, 'styles.manifest.json'), 'utf8')) as Record<\n string,\n { file?: string; css?: string[]; assets?: string[] }\n >;\n fs.rmSync(path.join(pluginsDir, 'styles.manifest.json'));\n const emitted = (entry: string): { file: string; assets: string[] } => {\n const record = styleManifest[path.relative(stylesRoot, entry).split(path.sep).join('/')];\n const file = record?.file?.endsWith('.css') ? record.file : record?.css?.[0];\n if (file === undefined) throw new Error(`The stylesheet entry '${entry}' emitted no CSS file.`);\n return { file, assets: record?.assets ?? [] };\n };\n const base = emitted(styles.baseEntryPath);\n const slotStyles = new Map(\n plugins.map((plugin) => {\n const entry = styles.pluginEntryPaths.get(plugin.slot);\n return [plugin.slot, entry === undefined ? base : emitted(entry)];\n }),\n );\n const pluginStyles = Object.fromEntries([...slotStyles].map(([slot, style]) => [slot, style.file]));\n fs.writeFileSync(path.join(pluginsDir, 'index.html'), '<!doctype html>\\n<title>Po plugin composition</title>\\n');\n\n return {\n assetsDir,\n pluginsDir,\n pluginIds: plugins.map((plugin) => plugin.pluginId),\n plugins: plugins.map((plugin) => {\n const closure = closures.get(plugin.slot);\n const style = slotStyles.get(plugin.slot);\n if (closure === undefined || style === undefined) throw new Error(`The slot '${plugin.slot}' emitted no entry.`);\n return {\n pluginId: plugin.pluginId,\n slot: plugin.slot,\n packageDir: plugin.packageDir,\n isHost: plugin.isHost,\n entry: closure.entry,\n // The shared stylesheet and its fonts must be verified for every slot.\n files: [...new Set([...closure.files, style.file, ...style.assets])],\n css: closure.css,\n };\n }),\n pluginStyles,\n baseStyle: base.file,\n };\n}\n"],"mappings":"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"}
@@ -15,9 +15,9 @@ export interface BundleCockpitWebResult {
15
15
  pluginIds: string[];
16
16
  /** Every declared plugin copy with its slot and the files its slot entry reaches. */
17
17
  plugins: WebPluginBuildRecord[];
18
- /** One content-hashed stylesheet per slot below pluginsDir; host plugins share the base. */
18
+ /** The shared content-hashed Tailwind stylesheet below pluginsDir, keyed by slot. */
19
19
  pluginStyles: Record<string, string>;
20
- /** The shell-only stylesheet below pluginsDir. */
20
+ /** The same shared stylesheet, also loaded by mounts without plugins. */
21
21
  baseStyle: string;
22
22
  }
23
23
  /** One plugin copy in a build: its slot entry and the emitted files that entry can load. */
@@ -28,7 +28,7 @@ export interface WebPluginBuildRecord {
28
28
  isHost: boolean;
29
29
  /** The slot entry module below pluginsDir. */
30
30
  entry: string;
31
- /** Every file the entry reaches through static and dynamic imports, plus the slot stylesheet and its assets. */
31
+ /** Every file the entry reaches through imports, plus the shared stylesheet and its assets. */
32
32
  files: string[];
33
33
  /** The stylesheets of the entry's static import closure, which a mount loads up front. */
34
34
  css: string[];
@@ -62,4 +62,5 @@ export declare function manifestClosure(manifest: Readonly<Record<string, Manife
62
62
  */
63
63
  export declare function bundleCockpitWeb(options: BundleCockpitWebOptions): Promise<BundleCockpitWebResult>;
64
64
  //#endregion
65
+ export {};
65
66
  //# sourceMappingURL=bundle.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.mjs","names":[],"sources":["../../../../src/builders/web/bundle.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { bundleAssetPolicyPlugin } from './bundleAssetPolicy';\nimport { PLUGIN_ROOTS_FILE } from './webDevRoots';\nimport {\n BASE_STYLE_ENTRY,\n pluginStyleEntryName,\n writeSyncWebPluginModules,\n writeWebPluginStyleEntries,\n} from './webPluginGenerate';\nimport { scanWebPlugins } from './webPluginScan';\nimport {\n isWebPluginFacade,\n WEB_PLUGIN_FACADE_CHUNK,\n webPluginCssAlias,\n webPluginOverridePlugin,\n webPluginRuntimeAliases,\n webPluginRuntimeFacadePlugin,\n} from './webPluginVite';\n\n/** Shared runtime packages every plugin's client code must resolve to the host copies. */\nconst DEDUPED_RUNTIMES = [\n 'react',\n 'react-dom',\n '@tanstack/store',\n '@tanstack/react-store',\n '@tanstack/react-router',\n '@agimon-ai/po-core',\n '@agimon-ai/po-web-dashboard',\n '@agimon-ai/po-web-components',\n // The sealed transport is a module singleton whose nonce counters every\n // plugin shares; a second copy would start counting at zero.\n '@agimon-ai/po-web-security',\n // CodeMirror's state and view are singletons in all but name: a document\n // built against one copy is rejected by an editor from the other, and a\n // grammar chunk resolved separately from the editor is exactly how a second\n // copy appears.\n '@codemirror/state',\n '@codemirror/view',\n];\n\nexport interface BundleCockpitWebOptions {\n hostRoot: string;\n /** Package roots to scan for poWeb manifests, usually the installed composition. */\n pluginRoots: readonly string[];\n /** Output directory; receives web/, plugins/, generated/, and pluginRoots.json. */\n outDir: string;\n onNotice?: (message: string) => void;\n}\n\nexport interface BundleCockpitWebResult {\n /** The cockpit shell with the host's own plugins; every other plugin ships in pluginsDir. */\n assetsDir: string;\n /** Standalone session plugin composition artifacts. */\n pluginsDir: string;\n pluginIds: string[];\n /** Every declared plugin copy with its slot and the files its slot entry reaches. */\n plugins: WebPluginBuildRecord[];\n /** One content-hashed stylesheet per slot below pluginsDir; host plugins share the base. */\n pluginStyles: Record<string, string>;\n /** The shell-only stylesheet below pluginsDir. */\n baseStyle: string;\n}\n\n/** One plugin copy in a build: its slot entry and the emitted files that entry can load. */\nexport interface WebPluginBuildRecord {\n pluginId: string;\n slot: string;\n packageDir: string;\n isHost: boolean;\n /** The slot entry module below pluginsDir. */\n entry: string;\n /** Every file the entry reaches through static and dynamic imports, plus the slot stylesheet and its assets. */\n files: string[];\n /** The stylesheets of the entry's static import closure, which a mount loads up front. */\n css: string[];\n}\n\ninterface ManifestChunk {\n file: string;\n imports?: string[];\n dynamicImports?: string[];\n css?: string[];\n assets?: string[];\n}\n\n/**\n * The files one manifest entry reaches: `files` follows static and dynamic imports and holds\n * every chunk, asset, and stylesheet on the way; `css` follows static imports only.\n */\nexport function manifestClosure(\n manifest: Readonly<Record<string, ManifestChunk>>,\n entryKey: string,\n): { entry: string; files: string[]; css: string[] } {\n const chunkOf = (key: string): ManifestChunk => {\n const chunk = manifest[key];\n if (chunk === undefined) throw new Error(`The composition manifest has no chunk '${key}'.`);\n return chunk;\n };\n const files = new Set<string>();\n const visited = new Set<string>();\n const walk = (key: string): void => {\n if (visited.has(key)) return;\n visited.add(key);\n const chunk = chunkOf(key);\n files.add(chunk.file);\n for (const file of [...(chunk.css ?? []), ...(chunk.assets ?? [])]) files.add(file);\n for (const next of [...(chunk.imports ?? []), ...(chunk.dynamicImports ?? [])]) walk(next);\n };\n walk(entryKey);\n const css = new Set<string>();\n const staticVisited = new Set<string>();\n const walkStatic = (key: string): void => {\n if (staticVisited.has(key)) return;\n staticVisited.add(key);\n const chunk = chunkOf(key);\n for (const file of chunk.css ?? []) css.add(file);\n for (const next of chunk.imports ?? []) walkStatic(next);\n };\n walkStatic(entryKey);\n return { entry: chunkOf(entryKey).file, files: [...files], css: [...css] };\n}\n\n/**\n * Builds the cockpit SPA against the installed plugin set.\n *\n * This is what `po sync` calls: manifests come from the given package\n * roots (no hardcoded plugin dependencies anywhere), the generated entry\n * modules are aliased over the committed builtin registry, and Vite compiles\n * the host shell and, separately, each plugin's shipped web source into one\n * ES-module composition with an entry per slot, so each plugin and its assets ship once.\n * The roots file beside\n * the bundle lets the dev server serve the same composition with hot reload.\n */\nexport async function bundleCockpitWeb(options: BundleCockpitWebOptions): Promise<BundleCockpitWebResult> {\n const notice = options.onNotice ?? ((): void => {});\n const hostRoot = options.hostRoot;\n const plugins = scanWebPlugins(hostRoot, options.pluginRoots, notice);\n notice(\n `bundling the cockpit with ${String(plugins.length)} web plugin(s): ${plugins.map((p) => p.pluginId).join(', ')}`,\n );\n\n const generatedDir = path.join(options.outDir, 'generated');\n const assetsDir = path.join(options.outDir, 'web');\n const pluginsDir = path.join(options.outDir, 'plugins');\n const generated = writeSyncWebPluginModules(plugins, generatedDir, hostRoot);\n const roots = [...new Set(options.pluginRoots.map((root) => path.resolve(root)))];\n fs.writeFileSync(path.join(options.outDir, PLUGIN_ROOTS_FILE), `${JSON.stringify(roots, null, 2)}\\n`);\n\n // Vite and its plugins are regular dependencies so this works from an\n // installed package, not only the workspace.\n const { build } = await import('vite');\n const { default: react } = await import('@vitejs/plugin-react');\n const { default: tailwindcss } = await import('@tailwindcss/vite');\n\n const clientRoot = path.join(hostRoot, 'src', 'web');\n\n // The shell carries only the host's own plugins; the rest load from the composition below.\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n root: clientRoot,\n plugins: [webPluginOverridePlugin(clientRoot, generated.shell), react(), tailwindcss(), bundleAssetPolicyPlugin()],\n resolve: {\n dedupe: [...DEDUPED_RUNTIMES],\n alias: [...webPluginRuntimeAliases(clientRoot), webPluginCssAlias(generated.shell)],\n },\n build: {\n outDir: assetsDir,\n emptyOutDir: true,\n sourcemap: false,\n },\n });\n\n // One ES-module composition: an entry per slot exporting its webPlugin, shared chunks\n // between them, and the shared runtime modules read from the page through facades.\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n base: './',\n plugins: [webPluginRuntimeFacadePlugin(hostRoot), react(), tailwindcss()],\n resolve: {\n dedupe: [...DEDUPED_RUNTIMES],\n alias: [webPluginCssAlias(generated)],\n },\n build: {\n cssCodeSplit: true,\n modulePreload: false,\n outDir: pluginsDir,\n emptyOutDir: true,\n sourcemap: false,\n assetsInlineLimit: 0,\n manifest: 'manifest.json',\n rollupOptions: {\n input: generated.slotEntryPaths,\n // Each slot entry is loaded for its webPlugin export, so it must keep it.\n preserveEntrySignatures: 'exports-only',\n output: {\n format: 'es',\n entryFileNames: 'slots/[name]-[hash].js',\n chunkFileNames: 'chunks/[name]-[hash].js',\n assetFileNames: 'assets/[name]-[hash][extname]',\n manualChunks: (id) => (isWebPluginFacade(id) ? WEB_PLUGIN_FACADE_CHUNK : undefined),\n },\n },\n },\n });\n const manifest = JSON.parse(fs.readFileSync(path.join(pluginsDir, 'manifest.json'), 'utf8')) as Record<\n string,\n ManifestChunk\n >;\n // Manifest keys are the entry sources relative to the build root, which is the working directory.\n const manifestRoot = fs.realpathSync(process.cwd());\n const closures = new Map(\n plugins.map((plugin) => {\n const entryPath = fs.realpathSync(generated.slotEntryPaths[plugin.slot]);\n return [plugin.slot, manifestClosure(manifest, path.relative(manifestRoot, entryPath).split(path.sep).join('/'))];\n }),\n );\n\n // One content-hashed stylesheet per plugin, compiled from its own sources over the shell's.\n const styles = writeWebPluginStyleEntries(plugins, generatedDir, hostRoot);\n const stylesRoot = path.dirname(styles.baseEntryPath);\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n root: stylesRoot,\n base: './',\n plugins: [tailwindcss()],\n resolve: {\n alias: [{ find: /^\\.\\/webPluginSources\\.generated\\.css$/, replacement: styles.baseSourcesPath }],\n },\n build: {\n cssCodeSplit: true,\n outDir: pluginsDir,\n emptyOutDir: false,\n sourcemap: false,\n assetsInlineLimit: 0,\n manifest: 'styles.manifest.json',\n rollupOptions: {\n input: Object.fromEntries([\n [BASE_STYLE_ENTRY, styles.baseEntryPath],\n ...[...styles.pluginEntryPaths].map(([slot, entry]) => [pluginStyleEntryName(slot), entry]),\n ]),\n output: { assetFileNames: 'assets/[name]-[hash][extname]' },\n },\n },\n });\n const styleManifest = JSON.parse(fs.readFileSync(path.join(pluginsDir, 'styles.manifest.json'), 'utf8')) as Record<\n string,\n { file?: string; css?: string[]; assets?: string[] }\n >;\n fs.rmSync(path.join(pluginsDir, 'styles.manifest.json'));\n const emitted = (entry: string): { file: string; assets: string[] } => {\n const record = styleManifest[path.relative(stylesRoot, entry).split(path.sep).join('/')];\n const file = record?.file?.endsWith('.css') ? record.file : record?.css?.[0];\n if (file === undefined) throw new Error(`The stylesheet entry '${entry}' emitted no CSS file.`);\n return { file, assets: record?.assets ?? [] };\n };\n const base = emitted(styles.baseEntryPath);\n const slotStyles = new Map(\n plugins.map((plugin) => {\n const entry = styles.pluginEntryPaths.get(plugin.slot);\n return [plugin.slot, entry === undefined ? base : emitted(entry)];\n }),\n );\n const pluginStyles = Object.fromEntries([...slotStyles].map(([slot, style]) => [slot, style.file]));\n fs.writeFileSync(path.join(pluginsDir, 'index.html'), '<!doctype html>\\n<title>Po plugin composition</title>\\n');\n\n return {\n assetsDir,\n pluginsDir,\n pluginIds: plugins.map((plugin) => plugin.pluginId),\n plugins: plugins.map((plugin) => {\n const closure = closures.get(plugin.slot);\n const style = slotStyles.get(plugin.slot);\n if (closure === undefined || style === undefined) throw new Error(`The slot '${plugin.slot}' emitted no entry.`);\n return {\n pluginId: plugin.pluginId,\n slot: plugin.slot,\n packageDir: plugin.packageDir,\n isHost: plugin.isHost,\n entry: closure.entry,\n // The slot's own stylesheet and the fonts it references load with it.\n files: [...new Set([...closure.files, style.file, ...style.assets])],\n css: closure.css,\n };\n }),\n pluginStyles,\n baseStyle: base.file,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bundle.mjs","names":[],"sources":["../../../../src/builders/web/bundle.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { bundleAssetPolicyPlugin } from './bundleAssetPolicy';\nimport { PLUGIN_ROOTS_FILE } from './webDevRoots';\nimport {\n BASE_STYLE_ENTRY,\n pluginStyleEntryName,\n writeSyncWebPluginModules,\n writeWebPluginStyleEntries,\n} from './webPluginGenerate';\nimport { scanWebPlugins } from './webPluginScan';\nimport {\n isWebPluginFacade,\n WEB_PLUGIN_FACADE_CHUNK,\n webPluginCssAlias,\n webPluginOverridePlugin,\n webPluginRuntimeAliases,\n webPluginRuntimeFacadePlugin,\n} from './webPluginVite';\n\n/** Shared runtime packages every plugin's client code must resolve to the host copies. */\nconst DEDUPED_RUNTIMES = [\n 'react',\n 'react-dom',\n '@tanstack/store',\n '@tanstack/react-store',\n '@tanstack/react-router',\n '@agimon-ai/po-core',\n '@agimon-ai/po-web-dashboard',\n '@agimon-ai/po-web-components',\n // The sealed transport is a module singleton whose nonce counters every\n // plugin shares; a second copy would start counting at zero.\n '@agimon-ai/po-web-security',\n // CodeMirror's state and view are singletons in all but name: a document\n // built against one copy is rejected by an editor from the other, and a\n // grammar chunk resolved separately from the editor is exactly how a second\n // copy appears.\n '@codemirror/state',\n '@codemirror/view',\n];\n\nexport interface BundleCockpitWebOptions {\n hostRoot: string;\n /** Package roots to scan for poWeb manifests, usually the installed composition. */\n pluginRoots: readonly string[];\n /** Output directory; receives web/, plugins/, generated/, and pluginRoots.json. */\n outDir: string;\n onNotice?: (message: string) => void;\n}\n\nexport interface BundleCockpitWebResult {\n /** The cockpit shell with the host's own plugins; every other plugin ships in pluginsDir. */\n assetsDir: string;\n /** Standalone session plugin composition artifacts. */\n pluginsDir: string;\n pluginIds: string[];\n /** Every declared plugin copy with its slot and the files its slot entry reaches. */\n plugins: WebPluginBuildRecord[];\n /** The shared content-hashed Tailwind stylesheet below pluginsDir, keyed by slot. */\n pluginStyles: Record<string, string>;\n /** The same shared stylesheet, also loaded by mounts without plugins. */\n baseStyle: string;\n}\n\n/** One plugin copy in a build: its slot entry and the emitted files that entry can load. */\nexport interface WebPluginBuildRecord {\n pluginId: string;\n slot: string;\n packageDir: string;\n isHost: boolean;\n /** The slot entry module below pluginsDir. */\n entry: string;\n /** Every file the entry reaches through imports, plus the shared stylesheet and its assets. */\n files: string[];\n /** The stylesheets of the entry's static import closure, which a mount loads up front. */\n css: string[];\n}\n\ninterface ManifestChunk {\n file: string;\n imports?: string[];\n dynamicImports?: string[];\n css?: string[];\n assets?: string[];\n}\n\n/**\n * The files one manifest entry reaches: `files` follows static and dynamic imports and holds\n * every chunk, asset, and stylesheet on the way; `css` follows static imports only.\n */\nexport function manifestClosure(\n manifest: Readonly<Record<string, ManifestChunk>>,\n entryKey: string,\n): { entry: string; files: string[]; css: string[] } {\n const chunkOf = (key: string): ManifestChunk => {\n const chunk = manifest[key];\n if (chunk === undefined) throw new Error(`The composition manifest has no chunk '${key}'.`);\n return chunk;\n };\n const files = new Set<string>();\n const visited = new Set<string>();\n const walk = (key: string): void => {\n if (visited.has(key)) return;\n visited.add(key);\n const chunk = chunkOf(key);\n files.add(chunk.file);\n for (const file of [...(chunk.css ?? []), ...(chunk.assets ?? [])]) files.add(file);\n for (const next of [...(chunk.imports ?? []), ...(chunk.dynamicImports ?? [])]) walk(next);\n };\n walk(entryKey);\n const css = new Set<string>();\n const staticVisited = new Set<string>();\n const walkStatic = (key: string): void => {\n if (staticVisited.has(key)) return;\n staticVisited.add(key);\n const chunk = chunkOf(key);\n for (const file of chunk.css ?? []) css.add(file);\n for (const next of chunk.imports ?? []) walkStatic(next);\n };\n walkStatic(entryKey);\n return { entry: chunkOf(entryKey).file, files: [...files], css: [...css] };\n}\n\n/**\n * Builds the cockpit SPA against the installed plugin set.\n *\n * This is what `po sync` calls: manifests come from the given package\n * roots (no hardcoded plugin dependencies anywhere), the generated entry\n * modules are aliased over the committed builtin registry, and Vite compiles\n * the host shell and, separately, each plugin's shipped web source into one\n * ES-module composition with an entry per slot, so each plugin and its assets ship once.\n * The roots file beside\n * the bundle lets the dev server serve the same composition with hot reload.\n */\nexport async function bundleCockpitWeb(options: BundleCockpitWebOptions): Promise<BundleCockpitWebResult> {\n const notice = options.onNotice ?? ((): void => {});\n const hostRoot = options.hostRoot;\n const plugins = scanWebPlugins(hostRoot, options.pluginRoots, notice);\n notice(\n `bundling the cockpit with ${String(plugins.length)} web plugin(s): ${plugins.map((p) => p.pluginId).join(', ')}`,\n );\n\n const generatedDir = path.join(options.outDir, 'generated');\n const assetsDir = path.join(options.outDir, 'web');\n const pluginsDir = path.join(options.outDir, 'plugins');\n const generated = writeSyncWebPluginModules(plugins, generatedDir, hostRoot);\n const roots = [...new Set(options.pluginRoots.map((root) => path.resolve(root)))];\n fs.writeFileSync(path.join(options.outDir, PLUGIN_ROOTS_FILE), `${JSON.stringify(roots, null, 2)}\\n`);\n\n // Vite and its plugins are regular dependencies so this works from an\n // installed package, not only the workspace.\n const { build } = await import('vite');\n const { default: react } = await import('@vitejs/plugin-react');\n const { default: tailwindcss } = await import('@tailwindcss/vite');\n\n const clientRoot = path.join(hostRoot, 'src', 'web');\n\n // The shell carries only the host's own plugins; the rest load from the composition below.\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n root: clientRoot,\n plugins: [webPluginOverridePlugin(clientRoot, generated.shell), react(), tailwindcss(), bundleAssetPolicyPlugin()],\n resolve: {\n dedupe: [...DEDUPED_RUNTIMES],\n alias: [...webPluginRuntimeAliases(clientRoot), webPluginCssAlias(generated.shell)],\n },\n build: {\n outDir: assetsDir,\n emptyOutDir: true,\n sourcemap: false,\n },\n });\n\n // One ES-module composition: an entry per slot exporting its webPlugin, shared chunks\n // between them, and the shared runtime modules read from the page through facades.\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n base: './',\n plugins: [webPluginRuntimeFacadePlugin(hostRoot), react(), tailwindcss()],\n resolve: {\n dedupe: [...DEDUPED_RUNTIMES],\n alias: [webPluginCssAlias(generated)],\n },\n build: {\n cssCodeSplit: true,\n modulePreload: false,\n outDir: pluginsDir,\n emptyOutDir: true,\n sourcemap: false,\n assetsInlineLimit: 0,\n manifest: 'manifest.json',\n rollupOptions: {\n input: generated.slotEntryPaths,\n // Each slot entry is loaded for its webPlugin export, so it must keep it.\n preserveEntrySignatures: 'exports-only',\n output: {\n format: 'es',\n entryFileNames: 'slots/[name]-[hash].js',\n chunkFileNames: 'chunks/[name]-[hash].js',\n assetFileNames: 'assets/[name]-[hash][extname]',\n manualChunks: (id) => (isWebPluginFacade(id) ? WEB_PLUGIN_FACADE_CHUNK : undefined),\n },\n },\n },\n });\n const manifest = JSON.parse(fs.readFileSync(path.join(pluginsDir, 'manifest.json'), 'utf8')) as Record<\n string,\n ManifestChunk\n >;\n // Manifest keys are the entry sources relative to the build root, which is the working directory.\n const manifestRoot = fs.realpathSync(process.cwd());\n const closures = new Map(\n plugins.map((plugin) => {\n const entryPath = fs.realpathSync(generated.slotEntryPaths[plugin.slot]);\n return [plugin.slot, manifestClosure(manifest, path.relative(manifestRoot, entryPath).split(path.sep).join('/'))];\n }),\n );\n\n // One content-hashed Tailwind stylesheet for the shell, fallback template, and all plugins.\n const styles = writeWebPluginStyleEntries(plugins, generatedDir, hostRoot);\n const stylesRoot = path.dirname(styles.baseEntryPath);\n await build({\n configFile: false,\n envDir: false,\n logLevel: 'warn',\n root: stylesRoot,\n base: './',\n plugins: [tailwindcss()],\n resolve: {\n alias: [{ find: /^\\.\\/webPluginSources\\.generated\\.css$/, replacement: styles.baseSourcesPath }],\n },\n build: {\n cssCodeSplit: true,\n outDir: pluginsDir,\n emptyOutDir: false,\n sourcemap: false,\n assetsInlineLimit: 0,\n manifest: 'styles.manifest.json',\n rollupOptions: {\n input: Object.fromEntries([\n [BASE_STYLE_ENTRY, styles.baseEntryPath],\n ...[...styles.pluginEntryPaths].map(([slot, entry]) => [pluginStyleEntryName(slot), entry]),\n ]),\n output: { assetFileNames: 'assets/[name]-[hash][extname]' },\n },\n },\n });\n const styleManifest = JSON.parse(fs.readFileSync(path.join(pluginsDir, 'styles.manifest.json'), 'utf8')) as Record<\n string,\n { file?: string; css?: string[]; assets?: string[] }\n >;\n fs.rmSync(path.join(pluginsDir, 'styles.manifest.json'));\n const emitted = (entry: string): { file: string; assets: string[] } => {\n const record = styleManifest[path.relative(stylesRoot, entry).split(path.sep).join('/')];\n const file = record?.file?.endsWith('.css') ? record.file : record?.css?.[0];\n if (file === undefined) throw new Error(`The stylesheet entry '${entry}' emitted no CSS file.`);\n return { file, assets: record?.assets ?? [] };\n };\n const base = emitted(styles.baseEntryPath);\n const slotStyles = new Map(\n plugins.map((plugin) => {\n const entry = styles.pluginEntryPaths.get(plugin.slot);\n return [plugin.slot, entry === undefined ? base : emitted(entry)];\n }),\n );\n const pluginStyles = Object.fromEntries([...slotStyles].map(([slot, style]) => [slot, style.file]));\n fs.writeFileSync(path.join(pluginsDir, 'index.html'), '<!doctype html>\\n<title>Po plugin composition</title>\\n');\n\n return {\n assetsDir,\n pluginsDir,\n pluginIds: plugins.map((plugin) => plugin.pluginId),\n plugins: plugins.map((plugin) => {\n const closure = closures.get(plugin.slot);\n const style = slotStyles.get(plugin.slot);\n if (closure === undefined || style === undefined) throw new Error(`The slot '${plugin.slot}' emitted no entry.`);\n return {\n pluginId: plugin.pluginId,\n slot: plugin.slot,\n packageDir: plugin.packageDir,\n isHost: plugin.isHost,\n entry: closure.entry,\n // The shared stylesheet and its fonts must be verified for every slot.\n files: [...new Set([...closure.files, style.file, ...style.assets])],\n css: closure.css,\n };\n }),\n pluginStyles,\n baseStyle: base.file,\n };\n}\n"],"mappings":"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"}
@@ -19,4 +19,5 @@ export declare function classifyOptionalBundleAssets(bundle: Readonly<Record<str
19
19
  /** Emits an authenticated v1 policy derived from Rollup's module and resource graph. */
20
20
  export declare function bundleAssetPolicyPlugin(): Plugin;
21
21
  //#endregion
22
+ export {};
22
23
  //# sourceMappingURL=bundleAssetPolicy.d.mts.map
@@ -52,7 +52,7 @@ function webHostVersion(poHome, environment = process.env) {
52
52
  }
53
53
  }
54
54
  /** Bumped whenever the build's output layout changes, so an old layout is never reused. */
55
- const GLOBAL_BUILD_FORMAT = "global-web-4";
55
+ const GLOBAL_BUILD_FORMAT = "global-web-5";
56
56
  /** The record every keyed global build writes last, so a key directory holding it is complete. */
57
57
  const BUILD_RECORD = "build.json";
58
58
  const BUILD_CHILD_SCRIPT = `