@openpalm/ui 0.12.16 → 0.12.22

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 (380) hide show
  1. package/build/.openpalm-ui-version +1 -1
  2. package/build/client/_app/immutable/assets/4.DQdAwaDZ.css +1 -0
  3. package/build/client/_app/immutable/assets/4.DQdAwaDZ.css.br +0 -0
  4. package/build/client/_app/immutable/assets/4.DQdAwaDZ.css.gz +0 -0
  5. package/build/client/_app/immutable/chunks/{BWPHbP-a.js → BRX6kifW.js} +1 -1
  6. package/build/client/_app/immutable/chunks/BRX6kifW.js.br +0 -0
  7. package/build/client/_app/immutable/chunks/BRX6kifW.js.gz +0 -0
  8. package/build/client/_app/immutable/chunks/{-xOymq6q.js → BXNfEZOa.js} +2 -2
  9. package/build/client/_app/immutable/chunks/BXNfEZOa.js.br +0 -0
  10. package/build/client/_app/immutable/chunks/BXNfEZOa.js.gz +0 -0
  11. package/build/client/_app/immutable/chunks/{Dcw6L0GF.js → CgDyA2Qw.js} +2 -2
  12. package/build/client/_app/immutable/chunks/CgDyA2Qw.js.br +0 -0
  13. package/build/client/_app/immutable/chunks/CgDyA2Qw.js.gz +0 -0
  14. package/build/client/_app/immutable/chunks/DLcBqErP.js +1 -0
  15. package/build/client/_app/immutable/chunks/DLcBqErP.js.br +2 -0
  16. package/build/client/_app/immutable/chunks/DLcBqErP.js.gz +0 -0
  17. package/build/client/_app/immutable/chunks/{CLgRRUN_.js → DpHEXvQk.js} +1 -1
  18. package/build/client/_app/immutable/chunks/DpHEXvQk.js.br +0 -0
  19. package/build/client/_app/immutable/chunks/DpHEXvQk.js.gz +0 -0
  20. package/build/client/_app/immutable/chunks/Dr8nRIOR.js +1 -0
  21. package/build/client/_app/immutable/chunks/Dr8nRIOR.js.br +0 -0
  22. package/build/client/_app/immutable/chunks/Dr8nRIOR.js.gz +0 -0
  23. package/build/client/_app/immutable/chunks/{rzt4cfw4.js → _60-pFCk.js} +1 -1
  24. package/build/client/_app/immutable/chunks/_60-pFCk.js.br +0 -0
  25. package/build/client/_app/immutable/chunks/_60-pFCk.js.gz +0 -0
  26. package/build/client/_app/immutable/entry/{app.SorM6UkK.js → app.BjL1fvKO.js} +2 -2
  27. package/build/client/_app/immutable/entry/app.BjL1fvKO.js.br +0 -0
  28. package/build/client/_app/immutable/entry/app.BjL1fvKO.js.gz +0 -0
  29. package/build/client/_app/immutable/entry/start.De0IKYiu.js +1 -0
  30. package/build/client/_app/immutable/entry/start.De0IKYiu.js.br +0 -0
  31. package/build/client/_app/immutable/entry/start.De0IKYiu.js.gz +0 -0
  32. package/build/client/_app/immutable/nodes/{0.Bb8qAGW8.js → 0.AZnG4POF.js} +1 -1
  33. package/build/client/_app/immutable/nodes/0.AZnG4POF.js.br +0 -0
  34. package/build/client/_app/immutable/nodes/0.AZnG4POF.js.gz +0 -0
  35. package/build/client/_app/immutable/nodes/{1.DpT4QF0H.js → 1.B7a7Tm6Z.js} +1 -1
  36. package/build/client/_app/immutable/nodes/{1.DpT4QF0H.js.br → 1.B7a7Tm6Z.js.br} +0 -0
  37. package/build/client/_app/immutable/nodes/1.B7a7Tm6Z.js.gz +0 -0
  38. package/build/client/_app/immutable/nodes/4.DI__DjJl.js +126 -0
  39. package/build/client/_app/immutable/nodes/4.DI__DjJl.js.br +0 -0
  40. package/build/client/_app/immutable/nodes/4.DI__DjJl.js.gz +0 -0
  41. package/build/client/_app/immutable/nodes/{5.C8wCnxxh.js → 5.B9AKDWT5.js} +2 -2
  42. package/build/client/_app/immutable/nodes/5.B9AKDWT5.js.br +0 -0
  43. package/build/client/_app/immutable/nodes/5.B9AKDWT5.js.gz +0 -0
  44. package/build/client/_app/immutable/nodes/{6.BOxcLwjM.js → 6.hyWOgJjN.js} +1 -1
  45. package/build/client/_app/immutable/nodes/6.hyWOgJjN.js.br +0 -0
  46. package/build/client/_app/immutable/nodes/6.hyWOgJjN.js.gz +0 -0
  47. package/build/client/_app/immutable/nodes/{7.DxfMsEA7.js → 7.nZLq6rhJ.js} +1 -1
  48. package/build/client/_app/immutable/nodes/7.nZLq6rhJ.js.br +0 -0
  49. package/build/client/_app/immutable/nodes/7.nZLq6rhJ.js.gz +0 -0
  50. package/build/client/_app/immutable/nodes/{8.DYWtGZJY.js → 8.DHYGH125.js} +1 -1
  51. package/build/client/_app/immutable/nodes/8.DHYGH125.js.br +0 -0
  52. package/build/client/_app/immutable/nodes/8.DHYGH125.js.gz +0 -0
  53. package/build/client/_app/version.json +1 -1
  54. package/build/client/_app/version.json.br +1 -1
  55. package/build/client/_app/version.json.gz +0 -0
  56. package/build/server/chunks/{0-DrD9dfbN.js → 0-DL6Jfu7F.js} +3 -3
  57. package/build/server/chunks/{0-DrD9dfbN.js.map → 0-DL6Jfu7F.js.map} +1 -1
  58. package/build/server/chunks/1-DC1YDW9y.js +9 -0
  59. package/build/server/chunks/{1-FxMcltlA.js.map → 1-DC1YDW9y.js.map} +1 -1
  60. package/build/server/chunks/{10-BPBARiSq.js → 10-BnN-v5b4.js} +5 -5
  61. package/build/server/chunks/10-BnN-v5b4.js.map +1 -0
  62. package/build/server/chunks/4-BnTXsRc6.js +9 -0
  63. package/build/server/chunks/{4-B08tqK8Y.js.map → 4-BnTXsRc6.js.map} +1 -1
  64. package/build/server/chunks/{5-BhJQE2sc.js → 5-C26TlGBo.js} +3 -3
  65. package/build/server/chunks/{5-BhJQE2sc.js.map → 5-C26TlGBo.js.map} +1 -1
  66. package/build/server/chunks/6-D1YRT-u9.js +9 -0
  67. package/build/server/chunks/{6-fNyqnDtj.js.map → 6-D1YRT-u9.js.map} +1 -1
  68. package/build/server/chunks/{7-BLA7XoVb.js → 7-DB2WCCTk.js} +3 -3
  69. package/build/server/chunks/{7-BLA7XoVb.js.map → 7-DB2WCCTk.js.map} +1 -1
  70. package/build/server/chunks/{8-BrUUS_pN.js → 8-D9q3TEwk.js} +3 -3
  71. package/build/server/chunks/{8-BrUUS_pN.js.map → 8-D9q3TEwk.js.map} +1 -1
  72. package/build/server/chunks/{IconMic-BM_3hm2T.js → IconMic-DK0ZRKNm.js} +2 -2
  73. package/build/server/chunks/{IconMic-BM_3hm2T.js.map → IconMic-DK0ZRKNm.js.map} +1 -1
  74. package/build/server/chunks/{Navbar-moD488WP.js → Navbar-Bx84i9hX.js} +5 -5
  75. package/build/server/chunks/{Navbar-moD488WP.js.map → Navbar-Bx84i9hX.js.map} +1 -1
  76. package/build/server/chunks/{_layout.svelte-Dd-1jqRZ.js → _layout.svelte-CtPb7AoM.js} +2 -2
  77. package/build/server/chunks/{_layout.svelte-Dd-1jqRZ.js.map → _layout.svelte-CtPb7AoM.js.map} +1 -1
  78. package/build/server/chunks/{_page.svelte-BIVji1xz.js → _page.svelte-1gYVQfSX.js} +7 -7
  79. package/build/server/chunks/{_page.svelte-BIVji1xz.js.map → _page.svelte-1gYVQfSX.js.map} +1 -1
  80. package/build/server/chunks/{_page.svelte-CpJ-tyl5.js → _page.svelte-Ce5yuZKH.js} +7 -7
  81. package/build/server/chunks/{_page.svelte-CpJ-tyl5.js.map → _page.svelte-Ce5yuZKH.js.map} +1 -1
  82. package/build/server/chunks/{_page.svelte-BYQeMT5r.js → _page.svelte-DhqtAyz4.js} +5 -5
  83. package/build/server/chunks/{_page.svelte-BYQeMT5r.js.map → _page.svelte-DhqtAyz4.js.map} +1 -1
  84. package/build/server/chunks/{_page.svelte-B0oAGTVO.js → _page.svelte-Dlch5rzj.js} +3 -3
  85. package/build/server/chunks/{_page.svelte-B0oAGTVO.js.map → _page.svelte-Dlch5rzj.js.map} +1 -1
  86. package/build/server/chunks/{_page.svelte-_CPdonpL.js → _page.svelte-VwZb1o-L.js} +31 -715
  87. package/build/server/chunks/_page.svelte-VwZb1o-L.js.map +1 -0
  88. package/build/server/chunks/{_server.ts-Lsn47WWy.js → _server.ts-29oJfZHd.js} +2 -2
  89. package/build/server/chunks/{_server.ts-Lsn47WWy.js.map → _server.ts-29oJfZHd.js.map} +1 -1
  90. package/build/server/chunks/{_server.ts-C-HdBXhJ.js → _server.ts-54pdKqwY.js} +6 -6
  91. package/build/server/chunks/{_server.ts-C-HdBXhJ.js.map → _server.ts-54pdKqwY.js.map} +1 -1
  92. package/build/server/chunks/{_server.ts-Cytzcych.js → _server.ts-8R-n-zEh.js} +5 -5
  93. package/build/server/chunks/{_server.ts-Cytzcych.js.map → _server.ts-8R-n-zEh.js.map} +1 -1
  94. package/build/server/chunks/_server.ts-8b481A1c.js +89 -0
  95. package/build/server/chunks/_server.ts-8b481A1c.js.map +1 -0
  96. package/build/server/chunks/{_server.ts-weBXoTJ3.js → _server.ts-9AjUEqAT.js} +6 -6
  97. package/build/server/chunks/{_server.ts-weBXoTJ3.js.map → _server.ts-9AjUEqAT.js.map} +1 -1
  98. package/build/server/chunks/{_server.ts-BuIXXEyT.js → _server.ts-9qPwtSPc.js} +5 -5
  99. package/build/server/chunks/{_server.ts-BuIXXEyT.js.map → _server.ts-9qPwtSPc.js.map} +1 -1
  100. package/build/server/chunks/{_server.ts-A2_uhIs4.js → _server.ts-B1qG26BE.js} +5 -5
  101. package/build/server/chunks/_server.ts-B1qG26BE.js.map +1 -0
  102. package/build/server/chunks/{_server.ts-DM49wW_J.js → _server.ts-B5JZoMbG.js} +6 -6
  103. package/build/server/chunks/{_server.ts-DM49wW_J.js.map → _server.ts-B5JZoMbG.js.map} +1 -1
  104. package/build/server/chunks/{_server.ts-BDZyJU9G.js → _server.ts-B8xyYAeq.js} +5 -5
  105. package/build/server/chunks/{_server.ts-BDZyJU9G.js.map → _server.ts-B8xyYAeq.js.map} +1 -1
  106. package/build/server/chunks/{_server.ts-4bt2oMoW.js → _server.ts-B9CQbSjg.js} +4 -4
  107. package/build/server/chunks/{_server.ts-4bt2oMoW.js.map → _server.ts-B9CQbSjg.js.map} +1 -1
  108. package/build/server/chunks/{_server.ts-DOLd5BmL.js → _server.ts-B9ykDkc2.js} +2 -2
  109. package/build/server/chunks/{_server.ts-DOLd5BmL.js.map → _server.ts-B9ykDkc2.js.map} +1 -1
  110. package/build/server/chunks/{_server.ts-tqTqAAWG.js → _server.ts-BPdeRlDI.js} +5 -5
  111. package/build/server/chunks/{_server.ts-tqTqAAWG.js.map → _server.ts-BPdeRlDI.js.map} +1 -1
  112. package/build/server/chunks/{_server.ts-debYCsDy.js → _server.ts-B_0VQmyi.js} +5 -5
  113. package/build/server/chunks/{_server.ts-debYCsDy.js.map → _server.ts-B_0VQmyi.js.map} +1 -1
  114. package/build/server/chunks/{_server.ts-dnBaE4gO.js → _server.ts-B__xH1cU.js} +5 -5
  115. package/build/server/chunks/_server.ts-B__xH1cU.js.map +1 -0
  116. package/build/server/chunks/{_server.ts-BM13agwb.js → _server.ts-Bc4VE_mK.js} +6 -6
  117. package/build/server/chunks/{_server.ts-BM13agwb.js.map → _server.ts-Bc4VE_mK.js.map} +1 -1
  118. package/build/server/chunks/{_server.ts-BIWqZKbr.js → _server.ts-BdDIXPU0.js} +5 -5
  119. package/build/server/chunks/_server.ts-BdDIXPU0.js.map +1 -0
  120. package/build/server/chunks/{_server.ts-L7goMVLO.js → _server.ts-BeSu9n9F.js} +5 -5
  121. package/build/server/chunks/{_server.ts-L7goMVLO.js.map → _server.ts-BeSu9n9F.js.map} +1 -1
  122. package/build/server/chunks/{_server.ts-DtlbWSL9.js → _server.ts-BjAWFnFv.js} +6 -6
  123. package/build/server/chunks/{_server.ts-DtlbWSL9.js.map → _server.ts-BjAWFnFv.js.map} +1 -1
  124. package/build/server/chunks/{_server.ts-DslY4ICX.js → _server.ts-Bk-SzSGo.js} +5 -5
  125. package/build/server/chunks/_server.ts-Bk-SzSGo.js.map +1 -0
  126. package/build/server/chunks/{_server.ts-CpwGGda6.js → _server.ts-BswBNUz0.js} +5 -5
  127. package/build/server/chunks/{_server.ts-CpwGGda6.js.map → _server.ts-BswBNUz0.js.map} +1 -1
  128. package/build/server/chunks/{_server.ts-Db6HJxP0.js → _server.ts-BtlnrMKD.js} +5 -5
  129. package/build/server/chunks/{_server.ts-Db6HJxP0.js.map → _server.ts-BtlnrMKD.js.map} +1 -1
  130. package/build/server/chunks/{_server.ts-CcAj1YY3.js → _server.ts-BxRGCjoH.js} +5 -5
  131. package/build/server/chunks/{_server.ts-CcAj1YY3.js.map → _server.ts-BxRGCjoH.js.map} +1 -1
  132. package/build/server/chunks/{_server.ts-BgNEBjtB.js → _server.ts-By1az2OR.js} +6 -10
  133. package/build/server/chunks/_server.ts-By1az2OR.js.map +1 -0
  134. package/build/server/chunks/{_server.ts-CwROD4Mv.js → _server.ts-C0ch963P.js} +2 -2
  135. package/build/server/chunks/_server.ts-C0ch963P.js.map +1 -0
  136. package/build/server/chunks/{_server.ts-D-xTAWOk.js → _server.ts-C2NuRv8K.js} +5 -5
  137. package/build/server/chunks/{_server.ts-D-xTAWOk.js.map → _server.ts-C2NuRv8K.js.map} +1 -1
  138. package/build/server/chunks/{_server.ts-Dhk0bUib.js → _server.ts-C4I0eH50.js} +5 -5
  139. package/build/server/chunks/_server.ts-C4I0eH50.js.map +1 -0
  140. package/build/server/chunks/{_server.ts-BisPTVeD.js → _server.ts-C6geMqYp.js} +5 -5
  141. package/build/server/chunks/{_server.ts-BisPTVeD.js.map → _server.ts-C6geMqYp.js.map} +1 -1
  142. package/build/server/chunks/{_server.ts-CSVIX9wz.js → _server.ts-C9QeDhXf.js} +5 -5
  143. package/build/server/chunks/{_server.ts-CSVIX9wz.js.map → _server.ts-C9QeDhXf.js.map} +1 -1
  144. package/build/server/chunks/{_server.ts-1QHF99n2.js → _server.ts-C9cnB4KZ.js} +5 -5
  145. package/build/server/chunks/{_server.ts-1QHF99n2.js.map → _server.ts-C9cnB4KZ.js.map} +1 -1
  146. package/build/server/chunks/{_server.ts-vMp1f8Fp.js → _server.ts-CAwWO268.js} +5 -5
  147. package/build/server/chunks/{_server.ts-vMp1f8Fp.js.map → _server.ts-CAwWO268.js.map} +1 -1
  148. package/build/server/chunks/{_server.ts-C1yVAXR1.js → _server.ts-CBIx55nw.js} +5 -5
  149. package/build/server/chunks/{_server.ts-C1yVAXR1.js.map → _server.ts-CBIx55nw.js.map} +1 -1
  150. package/build/server/chunks/{_server.ts-BTcOpIrR.js → _server.ts-CDHXmvId.js} +5 -5
  151. package/build/server/chunks/{_server.ts-BTcOpIrR.js.map → _server.ts-CDHXmvId.js.map} +1 -1
  152. package/build/server/chunks/{_server.ts-DUSnamZ1.js → _server.ts-CHGTPklX.js} +6 -6
  153. package/build/server/chunks/{_server.ts-DUSnamZ1.js.map → _server.ts-CHGTPklX.js.map} +1 -1
  154. package/build/server/chunks/{_server.ts-D8GEl9HB.js → _server.ts-CKblTbUe.js} +5 -5
  155. package/build/server/chunks/_server.ts-CKblTbUe.js.map +1 -0
  156. package/build/server/chunks/{_server.ts-CXmalu7X.js → _server.ts-CN-ITxq_.js} +6 -6
  157. package/build/server/chunks/{_server.ts-CXmalu7X.js.map → _server.ts-CN-ITxq_.js.map} +1 -1
  158. package/build/server/chunks/{_server.ts-DjgSQOmY.js → _server.ts-CNy4jIvv.js} +5 -5
  159. package/build/server/chunks/{_server.ts-DjgSQOmY.js.map → _server.ts-CNy4jIvv.js.map} +1 -1
  160. package/build/server/chunks/{_server.ts-0C3qWiWb.js → _server.ts-CQgWS2hB.js} +6 -6
  161. package/build/server/chunks/{_server.ts-0C3qWiWb.js.map → _server.ts-CQgWS2hB.js.map} +1 -1
  162. package/build/server/chunks/{_server.ts-xm81oRF8.js → _server.ts-CRSZ1H_z.js} +9 -6
  163. package/build/server/chunks/_server.ts-CRSZ1H_z.js.map +1 -0
  164. package/build/server/chunks/{_server.ts-GkvVYhW3.js → _server.ts-CYCJvxkC.js} +5 -5
  165. package/build/server/chunks/{_server.ts-GkvVYhW3.js.map → _server.ts-CYCJvxkC.js.map} +1 -1
  166. package/build/server/chunks/{_server.ts-BQUHe02L.js → _server.ts-CcyDtTCy.js} +5 -5
  167. package/build/server/chunks/{_server.ts-BQUHe02L.js.map → _server.ts-CcyDtTCy.js.map} +1 -1
  168. package/build/server/chunks/{_server.ts-CSMWl6MA.js → _server.ts-CdHxUlD_.js} +5 -5
  169. package/build/server/chunks/{_server.ts-CSMWl6MA.js.map → _server.ts-CdHxUlD_.js.map} +1 -1
  170. package/build/server/chunks/{_server.ts-DgTbTaoR.js → _server.ts-CeGOgSlg.js} +8 -8
  171. package/build/server/chunks/{_server.ts-DgTbTaoR.js.map → _server.ts-CeGOgSlg.js.map} +1 -1
  172. package/build/server/chunks/{_server.ts-B8TzwUdj.js → _server.ts-CejBAnbx.js} +2 -2
  173. package/build/server/chunks/{_server.ts-B8TzwUdj.js.map → _server.ts-CejBAnbx.js.map} +1 -1
  174. package/build/server/chunks/{_server.ts-mKZ-HR25.js → _server.ts-ChJzwk4k.js} +6 -6
  175. package/build/server/chunks/{_server.ts-mKZ-HR25.js.map → _server.ts-ChJzwk4k.js.map} +1 -1
  176. package/build/server/chunks/{_server.ts-C9M1UY2P.js → _server.ts-CibQYGvX.js} +6 -6
  177. package/build/server/chunks/{_server.ts-C9M1UY2P.js.map → _server.ts-CibQYGvX.js.map} +1 -1
  178. package/build/server/chunks/{_server.ts-Dh_nLXqn.js → _server.ts-CloVt7eS.js} +7 -7
  179. package/build/server/chunks/{_server.ts-Dh_nLXqn.js.map → _server.ts-CloVt7eS.js.map} +1 -1
  180. package/build/server/chunks/{_server.ts-GZkGIPm3.js → _server.ts-CmjNZw87.js} +6 -6
  181. package/build/server/chunks/{_server.ts-GZkGIPm3.js.map → _server.ts-CmjNZw87.js.map} +1 -1
  182. package/build/server/chunks/{_server.ts-BM9aPYjQ.js → _server.ts-Cn7LfLF_.js} +7 -7
  183. package/build/server/chunks/_server.ts-Cn7LfLF_.js.map +1 -0
  184. package/build/server/chunks/{_server.ts-CgZrT5KZ.js → _server.ts-Crdovz8j.js} +5 -5
  185. package/build/server/chunks/{_server.ts-CgZrT5KZ.js.map → _server.ts-Crdovz8j.js.map} +1 -1
  186. package/build/server/chunks/{_server.ts-CSlCxLcD.js → _server.ts-CuYIpIzp.js} +5 -5
  187. package/build/server/chunks/{_server.ts-CSlCxLcD.js.map → _server.ts-CuYIpIzp.js.map} +1 -1
  188. package/build/server/chunks/{_server.ts-C5pch8uB.js → _server.ts-CwgY6ghJ.js} +7 -7
  189. package/build/server/chunks/{_server.ts-C5pch8uB.js.map → _server.ts-CwgY6ghJ.js.map} +1 -1
  190. package/build/server/chunks/{_server.ts-CQIKoHi5.js → _server.ts-CxxrQ9Wz.js} +5 -5
  191. package/build/server/chunks/_server.ts-CxxrQ9Wz.js.map +1 -0
  192. package/build/server/chunks/{_server.ts-vKWg-_oN.js → _server.ts-D6BJWhEf.js} +5 -5
  193. package/build/server/chunks/_server.ts-D6BJWhEf.js.map +1 -0
  194. package/build/server/chunks/{_server.ts-q7l7hcSR.js → _server.ts-D6Y4c9rj.js} +2 -2
  195. package/build/server/chunks/{_server.ts-q7l7hcSR.js.map → _server.ts-D6Y4c9rj.js.map} +1 -1
  196. package/build/server/chunks/{_server.ts-BHyvHgkv.js → _server.ts-D8EweJQC.js} +5 -5
  197. package/build/server/chunks/{_server.ts-BHyvHgkv.js.map → _server.ts-D8EweJQC.js.map} +1 -1
  198. package/build/server/chunks/{_server.ts-ByJNC46B.js → _server.ts-D91I-wzU.js} +5 -5
  199. package/build/server/chunks/{_server.ts-ByJNC46B.js.map → _server.ts-D91I-wzU.js.map} +1 -1
  200. package/build/server/chunks/{_server.ts-9pn27rio.js → _server.ts-D9yPVLtB.js} +5 -5
  201. package/build/server/chunks/{_server.ts-9pn27rio.js.map → _server.ts-D9yPVLtB.js.map} +1 -1
  202. package/build/server/chunks/{_server.ts-CD0bayYu.js → _server.ts-DC0rWv53.js} +5 -5
  203. package/build/server/chunks/{_server.ts-CD0bayYu.js.map → _server.ts-DC0rWv53.js.map} +1 -1
  204. package/build/server/chunks/{_server.ts-CieD4Xwp.js → _server.ts-DGHL7uho.js} +5 -5
  205. package/build/server/chunks/{_server.ts-CieD4Xwp.js.map → _server.ts-DGHL7uho.js.map} +1 -1
  206. package/build/server/chunks/{_server.ts-Br5_Sqdd.js → _server.ts-DHBjlBuv.js} +5 -5
  207. package/build/server/chunks/_server.ts-DHBjlBuv.js.map +1 -0
  208. package/build/server/chunks/{_server.ts-u8yfSFfS.js → _server.ts-DIUdkrLE.js} +5 -5
  209. package/build/server/chunks/{_server.ts-u8yfSFfS.js.map → _server.ts-DIUdkrLE.js.map} +1 -1
  210. package/build/server/chunks/{_server.ts-DdziCNPG.js → _server.ts-DNag2rCU.js} +25 -17
  211. package/build/server/chunks/_server.ts-DNag2rCU.js.map +1 -0
  212. package/build/server/chunks/{_server.ts-C0rvqz69.js → _server.ts-DWXKoPC3.js} +5 -5
  213. package/build/server/chunks/_server.ts-DWXKoPC3.js.map +1 -0
  214. package/build/server/chunks/{_server.ts-BwYc2QYD.js → _server.ts-D_Zne8zk.js} +5 -5
  215. package/build/server/chunks/{_server.ts-BwYc2QYD.js.map → _server.ts-D_Zne8zk.js.map} +1 -1
  216. package/build/server/chunks/{_server.ts-I0DzHljB.js → _server.ts-DarGs6EN.js} +5 -5
  217. package/build/server/chunks/_server.ts-DarGs6EN.js.map +1 -0
  218. package/build/server/chunks/{_server.ts-BlR3E9RP.js → _server.ts-DdjZAsqc.js} +5 -5
  219. package/build/server/chunks/{_server.ts-BlR3E9RP.js.map → _server.ts-DdjZAsqc.js.map} +1 -1
  220. package/build/server/chunks/_server.ts-DhgUx_Ar.js +84 -0
  221. package/build/server/chunks/_server.ts-DhgUx_Ar.js.map +1 -0
  222. package/build/server/chunks/{_server.ts-f9fAHuR9.js → _server.ts-Ds26GwEH.js} +5 -5
  223. package/build/server/chunks/{_server.ts-f9fAHuR9.js.map → _server.ts-Ds26GwEH.js.map} +1 -1
  224. package/build/server/chunks/{_server.ts-D8fWZu-e.js → _server.ts-Dx-W9dxd.js} +5 -5
  225. package/build/server/chunks/{_server.ts-D8fWZu-e.js.map → _server.ts-Dx-W9dxd.js.map} +1 -1
  226. package/build/server/chunks/{_server.ts-Rsnq_FsU.js → _server.ts-DyAZoRvd.js} +6 -6
  227. package/build/server/chunks/{_server.ts-Rsnq_FsU.js.map → _server.ts-DyAZoRvd.js.map} +1 -1
  228. package/build/server/chunks/{_server.ts-BDDzVjfd.js → _server.ts-EYK0bXvj.js} +5 -5
  229. package/build/server/chunks/_server.ts-EYK0bXvj.js.map +1 -0
  230. package/build/server/chunks/{_server.ts-U4djFkTB.js → _server.ts-GB9Cj5oM.js} +5 -5
  231. package/build/server/chunks/{_server.ts-U4djFkTB.js.map → _server.ts-GB9Cj5oM.js.map} +1 -1
  232. package/build/server/chunks/{_server.ts-tOj9jDOq.js → _server.ts-KhshtfY7.js} +7 -7
  233. package/build/server/chunks/_server.ts-KhshtfY7.js.map +1 -0
  234. package/build/server/chunks/{_server.ts-oalBPRXH.js → _server.ts-W0CmGtTj.js} +7 -7
  235. package/build/server/chunks/{_server.ts-oalBPRXH.js.map → _server.ts-W0CmGtTj.js.map} +1 -1
  236. package/build/server/chunks/{_server.ts-DT28Vp0_.js → _server.ts-X_5reIBA.js} +17 -8
  237. package/build/server/chunks/_server.ts-X_5reIBA.js.map +1 -0
  238. package/build/server/chunks/{_server.ts-BLeJ6bdD.js → _server.ts-YHTGVduj.js} +5 -5
  239. package/build/server/chunks/{_server.ts-BLeJ6bdD.js.map → _server.ts-YHTGVduj.js.map} +1 -1
  240. package/build/server/chunks/{_server.ts-G2aFJTEm.js → _server.ts-c9nn_lEh.js} +5 -5
  241. package/build/server/chunks/{_server.ts-G2aFJTEm.js.map → _server.ts-c9nn_lEh.js.map} +1 -1
  242. package/build/server/chunks/{_server.ts-CoJZ9LcF.js → _server.ts-cNcqERWY.js} +7 -7
  243. package/build/server/chunks/{_server.ts-CoJZ9LcF.js.map → _server.ts-cNcqERWY.js.map} +1 -1
  244. package/build/server/chunks/{_server.ts-F8iMDzoI.js → _server.ts-e-kt0L13.js} +4 -4
  245. package/build/server/chunks/_server.ts-e-kt0L13.js.map +1 -0
  246. package/build/server/chunks/{_server.ts-DujzH00p.js → _server.ts-fV4HpgOz.js} +5 -5
  247. package/build/server/chunks/{_server.ts-DujzH00p.js.map → _server.ts-fV4HpgOz.js.map} +1 -1
  248. package/build/server/chunks/{_server.ts-DwUq-jUD.js → _server.ts-hqvYcJBt.js} +5 -5
  249. package/build/server/chunks/_server.ts-hqvYcJBt.js.map +1 -0
  250. package/build/server/chunks/{_server.ts-C-zWYGfc.js → _server.ts-iCDhsOOY.js} +6 -6
  251. package/build/server/chunks/_server.ts-iCDhsOOY.js.map +1 -0
  252. package/build/server/chunks/{_server.ts-ZyPhvKQj.js → _server.ts-jyQMP3IC.js} +5 -5
  253. package/build/server/chunks/{_server.ts-ZyPhvKQj.js.map → _server.ts-jyQMP3IC.js.map} +1 -1
  254. package/build/server/chunks/{_server.ts-D4sfYQZC.js → _server.ts-sY8nzvys.js} +5 -5
  255. package/build/server/chunks/_server.ts-sY8nzvys.js.map +1 -0
  256. package/build/server/chunks/{addon-helpers-D5-mKU2T.js → addon-helpers-DmjAK3BO.js} +3 -3
  257. package/build/server/chunks/addon-helpers-DmjAK3BO.js.map +1 -0
  258. package/build/server/chunks/{akm-zl35RDvs.js → akm-B44WQaeD.js} +2 -2
  259. package/build/server/chunks/{akm-zl35RDvs.js.map → akm-B44WQaeD.js.map} +1 -1
  260. package/build/server/chunks/{catalog-wE1aq8JI.js → catalog-C8yZ2uH2.js} +5 -5
  261. package/build/server/chunks/{catalog-wE1aq8JI.js.map → catalog-C8yZ2uH2.js.map} +1 -1
  262. package/build/server/chunks/{client-D6Q_gQHi.js → client-Dv5ruwWL.js} +2 -2
  263. package/build/server/chunks/{client-D6Q_gQHi.js.map → client-Dv5ruwWL.js.map} +1 -1
  264. package/build/server/chunks/{config-CTNrBr1E.js → config-BXCHMmv_.js} +2 -2
  265. package/build/server/chunks/{config-CTNrBr1E.js.map → config-BXCHMmv_.js.map} +1 -1
  266. package/build/server/chunks/{docker-B09j6SgF.js → docker-qBTgU_Qa.js} +2 -2
  267. package/build/server/chunks/{docker-B09j6SgF.js.map → docker-qBTgU_Qa.js.map} +1 -1
  268. package/build/server/chunks/{endpoints-QZ9qlpfp.js → endpoints-BJw6odky.js} +2 -2
  269. package/build/server/chunks/{endpoints-QZ9qlpfp.js.map → endpoints-BJw6odky.js.map} +1 -1
  270. package/build/server/chunks/{error.svelte-DdGb8Q1_.js → error.svelte-Bk8x64a4.js} +4 -4
  271. package/build/server/chunks/{error.svelte-DdGb8Q1_.js.map → error.svelte-Bk8x64a4.js.map} +1 -1
  272. package/build/server/chunks/{helpers-DJjIZ4h3.js → helpers-DB3Oat0M.js} +3 -3
  273. package/build/server/chunks/{helpers-DJjIZ4h3.js.map → helpers-DB3Oat0M.js.map} +1 -1
  274. package/build/server/chunks/{hooks.server-Bb9yBgcZ.js → hooks.server-DoW_3zHD.js} +7 -7
  275. package/build/server/chunks/hooks.server-DoW_3zHD.js.map +1 -0
  276. package/build/server/chunks/{http-SSRI8uwQ.js → http-C4WWfxK-.js} +2 -2
  277. package/build/server/chunks/{http-SSRI8uwQ.js.map → http-C4WWfxK-.js.map} +1 -1
  278. package/build/server/chunks/{internal-B6rXhdY7.js → internal-Bkw-piFD.js} +3 -3
  279. package/build/server/chunks/{internal-B6rXhdY7.js.map → internal-Bkw-piFD.js.map} +1 -1
  280. package/build/server/chunks/{migration-status-DgYbpz6t.js → migration-status-C-gFVWrV.js} +2 -2
  281. package/build/server/chunks/{migration-status-DgYbpz6t.js.map → migration-status-C-gFVWrV.js.map} +1 -1
  282. package/build/server/chunks/{session-cookie-Bv0xhSHu.js → session-cookie-DYlRFqU6.js} +2 -2
  283. package/build/server/chunks/{session-cookie-Bv0xhSHu.js.map → session-cookie-DYlRFqU6.js.map} +1 -1
  284. package/build/server/chunks/{setup-deploy-hrgPodBR.js → setup-deploy-D3XucKIu.js} +2 -2
  285. package/build/server/chunks/{setup-deploy-hrgPodBR.js.map → setup-deploy-D3XucKIu.js.map} +1 -1
  286. package/build/server/chunks/{src-CqA6lZdE.js → src-DPd0Zos1.js} +241 -663
  287. package/build/server/chunks/src-DPd0Zos1.js.map +1 -0
  288. package/build/server/chunks/{state-C-jmnlkM.js → state-CmEW57i2.js} +2 -2
  289. package/build/server/chunks/{state-C-jmnlkM.js.map → state-CmEW57i2.js.map} +1 -1
  290. package/build/server/chunks/{state2-V7tXhf0j.js → state2-zSoANrav.js} +2 -2
  291. package/build/server/chunks/{state2-V7tXhf0j.js.map → state2-zSoANrav.js.map} +1 -1
  292. package/build/server/chunks/{theme-state.svelte-BgBXJ060.js → theme-state.svelte-DshW_ZYI.js} +2 -81
  293. package/build/server/chunks/theme-state.svelte-DshW_ZYI.js.map +1 -0
  294. package/build/server/index.js +32 -2
  295. package/build/server/index.js.map +1 -1
  296. package/build/server/manifest.js +93 -107
  297. package/build/server/manifest.js.map +1 -1
  298. package/package.json +2 -2
  299. package/build/client/_app/immutable/assets/4.BLk6Mqyj.css +0 -1
  300. package/build/client/_app/immutable/assets/4.BLk6Mqyj.css.br +0 -0
  301. package/build/client/_app/immutable/assets/4.BLk6Mqyj.css.gz +0 -0
  302. package/build/client/_app/immutable/chunks/-xOymq6q.js.br +0 -0
  303. package/build/client/_app/immutable/chunks/-xOymq6q.js.gz +0 -0
  304. package/build/client/_app/immutable/chunks/BSYf71k_.js +0 -1
  305. package/build/client/_app/immutable/chunks/BSYf71k_.js.br +0 -2
  306. package/build/client/_app/immutable/chunks/BSYf71k_.js.gz +0 -0
  307. package/build/client/_app/immutable/chunks/BWPHbP-a.js.br +0 -0
  308. package/build/client/_app/immutable/chunks/BWPHbP-a.js.gz +0 -0
  309. package/build/client/_app/immutable/chunks/CLgRRUN_.js.br +0 -0
  310. package/build/client/_app/immutable/chunks/CLgRRUN_.js.gz +0 -0
  311. package/build/client/_app/immutable/chunks/DRHnoVLf.js +0 -1
  312. package/build/client/_app/immutable/chunks/DRHnoVLf.js.br +0 -0
  313. package/build/client/_app/immutable/chunks/DRHnoVLf.js.gz +0 -0
  314. package/build/client/_app/immutable/chunks/Dcw6L0GF.js.br +0 -0
  315. package/build/client/_app/immutable/chunks/Dcw6L0GF.js.gz +0 -0
  316. package/build/client/_app/immutable/chunks/rzt4cfw4.js.br +0 -0
  317. package/build/client/_app/immutable/chunks/rzt4cfw4.js.gz +0 -0
  318. package/build/client/_app/immutable/entry/app.SorM6UkK.js.br +0 -0
  319. package/build/client/_app/immutable/entry/app.SorM6UkK.js.gz +0 -0
  320. package/build/client/_app/immutable/entry/start.WjUMzReT.js +0 -1
  321. package/build/client/_app/immutable/entry/start.WjUMzReT.js.br +0 -0
  322. package/build/client/_app/immutable/entry/start.WjUMzReT.js.gz +0 -0
  323. package/build/client/_app/immutable/nodes/0.Bb8qAGW8.js.br +0 -0
  324. package/build/client/_app/immutable/nodes/0.Bb8qAGW8.js.gz +0 -0
  325. package/build/client/_app/immutable/nodes/1.DpT4QF0H.js.gz +0 -0
  326. package/build/client/_app/immutable/nodes/4.081sb6LL.js +0 -130
  327. package/build/client/_app/immutable/nodes/4.081sb6LL.js.br +0 -0
  328. package/build/client/_app/immutable/nodes/4.081sb6LL.js.gz +0 -0
  329. package/build/client/_app/immutable/nodes/5.C8wCnxxh.js.br +0 -0
  330. package/build/client/_app/immutable/nodes/5.C8wCnxxh.js.gz +0 -0
  331. package/build/client/_app/immutable/nodes/6.BOxcLwjM.js.br +0 -0
  332. package/build/client/_app/immutable/nodes/6.BOxcLwjM.js.gz +0 -0
  333. package/build/client/_app/immutable/nodes/7.DxfMsEA7.js.br +0 -0
  334. package/build/client/_app/immutable/nodes/7.DxfMsEA7.js.gz +0 -0
  335. package/build/client/_app/immutable/nodes/8.DYWtGZJY.js.br +0 -0
  336. package/build/client/_app/immutable/nodes/8.DYWtGZJY.js.gz +0 -0
  337. package/build/server/chunks/1-FxMcltlA.js +0 -9
  338. package/build/server/chunks/10-BPBARiSq.js.map +0 -1
  339. package/build/server/chunks/4-B08tqK8Y.js +0 -9
  340. package/build/server/chunks/6-fNyqnDtj.js +0 -9
  341. package/build/server/chunks/_page.svelte-_CPdonpL.js.map +0 -1
  342. package/build/server/chunks/_server.ts-A2_uhIs4.js.map +0 -1
  343. package/build/server/chunks/_server.ts-BDDzVjfd.js.map +0 -1
  344. package/build/server/chunks/_server.ts-BIWqZKbr.js.map +0 -1
  345. package/build/server/chunks/_server.ts-BM9aPYjQ.js.map +0 -1
  346. package/build/server/chunks/_server.ts-BgNEBjtB.js.map +0 -1
  347. package/build/server/chunks/_server.ts-Br5_Sqdd.js.map +0 -1
  348. package/build/server/chunks/_server.ts-C-WdEDTH.js +0 -88
  349. package/build/server/chunks/_server.ts-C-WdEDTH.js.map +0 -1
  350. package/build/server/chunks/_server.ts-C-zWYGfc.js.map +0 -1
  351. package/build/server/chunks/_server.ts-C0rvqz69.js.map +0 -1
  352. package/build/server/chunks/_server.ts-CQIKoHi5.js.map +0 -1
  353. package/build/server/chunks/_server.ts-CwROD4Mv.js.map +0 -1
  354. package/build/server/chunks/_server.ts-D4sfYQZC.js.map +0 -1
  355. package/build/server/chunks/_server.ts-D8GEl9HB.js.map +0 -1
  356. package/build/server/chunks/_server.ts-DT28Vp0_.js.map +0 -1
  357. package/build/server/chunks/_server.ts-DdziCNPG.js.map +0 -1
  358. package/build/server/chunks/_server.ts-Dhk0bUib.js.map +0 -1
  359. package/build/server/chunks/_server.ts-DslY4ICX.js.map +0 -1
  360. package/build/server/chunks/_server.ts-DwUq-jUD.js.map +0 -1
  361. package/build/server/chunks/_server.ts-F8iMDzoI.js.map +0 -1
  362. package/build/server/chunks/_server.ts-FXl25WAR.js +0 -47
  363. package/build/server/chunks/_server.ts-FXl25WAR.js.map +0 -1
  364. package/build/server/chunks/_server.ts-I0DzHljB.js.map +0 -1
  365. package/build/server/chunks/_server.ts-JJHgPRXV.js +0 -121
  366. package/build/server/chunks/_server.ts-JJHgPRXV.js.map +0 -1
  367. package/build/server/chunks/_server.ts-dnBaE4gO.js.map +0 -1
  368. package/build/server/chunks/_server.ts-r5jXzF9w.js +0 -64
  369. package/build/server/chunks/_server.ts-r5jXzF9w.js.map +0 -1
  370. package/build/server/chunks/_server.ts-tOj9jDOq.js.map +0 -1
  371. package/build/server/chunks/_server.ts-vKWg-_oN.js.map +0 -1
  372. package/build/server/chunks/_server.ts-xm81oRF8.js.map +0 -1
  373. package/build/server/chunks/addon-helpers-D5-mKU2T.js.map +0 -1
  374. package/build/server/chunks/environment-DEXz32e5.js +0 -36
  375. package/build/server/chunks/environment-DEXz32e5.js.map +0 -1
  376. package/build/server/chunks/hooks.server-Bb9yBgcZ.js.map +0 -1
  377. package/build/server/chunks/src-CqA6lZdE.js.map +0 -1
  378. package/build/server/chunks/theme-state.svelte-BgBXJ060.js.map +0 -1
  379. package/build/server/chunks/version-cache-CSnmLqxQ.js +0 -54
  380. package/build/server/chunks/version-cache-CSnmLqxQ.js.map +0 -1
@@ -738,7 +738,7 @@ var import_main = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
738
738
  module.exports = DotenvModule;
739
739
  })))();
740
740
  var package_default = {
741
- version: "0.12.16"};
741
+ version: "0.12.22"};
742
742
  //#endregion
743
743
  //#region ../lib/src/control-plane/versioning.ts
744
744
  var SEMVER_RE = /^v?\d+\.\d+\.\d+(?:[-+].*)?$/;
@@ -806,15 +806,6 @@ function compareComparableVersions(a, b) {
806
806
  if (aParsed.prerelease !== null && bParsed.prerelease !== null) return comparePrerelease(aParsed.prerelease, bParsed.prerelease);
807
807
  return 0;
808
808
  }
809
- function majorVersionOf(version) {
810
- if (!isComparableSemver(version)) return null;
811
- return parseComparableVersion(version).major;
812
- }
813
- function isSameMajorVersion(a, b) {
814
- const aMajor = majorVersionOf(a);
815
- const bMajor = majorVersionOf(b);
816
- return aMajor !== null && bMajor !== null && aMajor === bMajor;
817
- }
818
809
  /**
819
810
  * npm/display form: strip a single leading `v` and trim. `v0.12.0` → `0.12.0`.
820
811
  * Pass-through for an already-bare version. Empty/whitespace → ''.
@@ -1087,81 +1078,26 @@ function nonSensitiveAddonEnvKeys() {
1087
1078
  return keys;
1088
1079
  }
1089
1080
  //#endregion
1090
- //#region ../lib/src/control-plane/image-tags.ts
1091
- var PLATFORM_IMAGE_TAG_KEYS = [
1092
- "OP_ASSISTANT_IMAGE_TAG",
1093
- "OP_GUARDIAN_IMAGE_TAG",
1094
- "OP_PORTAL_IMAGE_TAG"
1095
- ];
1096
- var PINNABLE_PLATFORM_IMAGE_SET = new Set(["guardian", "portal"]);
1097
- function parsePinnedImages(value) {
1098
- if (!value) return [];
1099
- return [...new Set(value.split(",").map((entry) => entry.trim().toLowerCase()).filter((entry) => PINNABLE_PLATFORM_IMAGE_SET.has(entry)))].sort();
1100
- }
1101
- function platformImageTagKeyFor(image) {
1102
- switch (image) {
1103
- case "guardian": return "OP_GUARDIAN_IMAGE_TAG";
1104
- case "portal": return "OP_PORTAL_IMAGE_TAG";
1105
- }
1106
- }
1107
- function resolveEffectivePlatformImageTag(env, image) {
1108
- const primary = env[platformImageTagKeyFor(image)]?.trim();
1109
- if (primary) return primary;
1110
- if (image === "portal") {
1111
- const legacy = env.OP_CHANNEL_IMAGE_TAG?.trim();
1112
- if (legacy) return legacy;
1113
- }
1114
- return env.OP_IMAGE_TAG?.trim() || "latest";
1115
- }
1116
- function buildPinnedImageTagEnv(env, pinnedImages) {
1117
- const updates = {};
1118
- for (const image of pinnedImages) updates[platformImageTagKeyFor(image)] = resolveEffectivePlatformImageTag(env, image);
1119
- return updates;
1120
- }
1121
- var DEPLOYABLE_UNITS = [
1122
- "assistant",
1123
- "guardian",
1124
- "portals",
1125
- "voice"
1126
- ];
1127
- var DEPLOYABLE_UNIT_IMAGE_NAMES = {
1128
- assistant: "assistant",
1129
- guardian: "guardian",
1130
- portals: "portal",
1131
- voice: "voice"
1132
- };
1133
- var DEPLOYABLE_UNIT_IMAGE_TAG_KEYS = {
1134
- assistant: "OP_ASSISTANT_IMAGE_TAG",
1135
- guardian: "OP_GUARDIAN_IMAGE_TAG",
1136
- portals: "OP_PORTAL_IMAGE_TAG",
1137
- voice: "OP_VOICE_IMAGE_TAG"
1138
- };
1139
- function isDeployableUnit(value) {
1140
- return DEPLOYABLE_UNITS.includes(value);
1141
- }
1142
- function deployableUnitImageName(unit) {
1143
- return DEPLOYABLE_UNIT_IMAGE_NAMES[unit];
1144
- }
1145
- function deployableUnitImageTagKey(unit) {
1146
- return DEPLOYABLE_UNIT_IMAGE_TAG_KEYS[unit];
1147
- }
1081
+ //#region ../lib/src/control-plane/addon-ids.ts
1148
1082
  /**
1149
- * Build the stack.env image-tag entries for a platform release.
1083
+ * Canonical list of built-in addon IDs.
1150
1084
  *
1151
- * `tag` is the platform version-of-record (the assistant tag). Per-image
1152
- * overrides let guardian/portal ride an older published tag when a release
1153
- * shipped only a subset of images (#477). OP_IMAGE_TAG stays as the compose
1154
- * fallback for pre-per-image installs.
1085
+ * Single source of truth imported by both addons.ts and migrations.ts.
1086
+ * Update THIS file (and only this file) when adding or removing a built-in addon.
1087
+ *
1088
+ * Intentionally a pure-constants file with no imports so it can be safely
1089
+ * imported from anywhere without risk of circular dependencies.
1155
1090
  */
1156
- function buildPlatformImageTagEnv(tag, perImage, pinnedImages = []) {
1157
- const pinned = new Set(pinnedImages);
1158
- return {
1159
- OP_IMAGE_TAG: tag,
1160
- OP_ASSISTANT_IMAGE_TAG: perImage?.OP_ASSISTANT_IMAGE_TAG ?? tag,
1161
- ...pinned.has("guardian") ? {} : { OP_GUARDIAN_IMAGE_TAG: perImage?.OP_GUARDIAN_IMAGE_TAG ?? tag },
1162
- ...pinned.has("portal") ? {} : { OP_PORTAL_IMAGE_TAG: perImage?.OP_PORTAL_IMAGE_TAG ?? perImage?.OP_CHANNEL_IMAGE_TAG ?? tag }
1163
- };
1164
- }
1091
+ var BUILTIN_ADDON_IDS = [
1092
+ "api",
1093
+ "chat",
1094
+ "discord",
1095
+ "gateway",
1096
+ "ollama",
1097
+ "slack",
1098
+ "ssh",
1099
+ "voice"
1100
+ ];
1165
1101
  //#endregion
1166
1102
  //#region ../lib/src/control-plane/migrations.ts
1167
1103
  /**
@@ -1323,7 +1259,7 @@ function readLayoutVersion(ctx) {
1323
1259
  }
1324
1260
  if (existsSync(join(ctx.homeDir, "vault"))) return 0;
1325
1261
  if (existsSync(join(ctx.homeDir, "config", "system.env"))) return 0;
1326
- if (envExists) return 2;
1262
+ if (envExists) return 1;
1327
1263
  if (!hasOpenPalmContent(ctx.homeDir)) return 2;
1328
1264
  throw new UnrecognizedLayoutError(ctx.homeDir);
1329
1265
  }
@@ -1359,9 +1295,6 @@ function stampReleaseVersion(stashDir, version) {
1359
1295
  writeFileSync(envPath, next);
1360
1296
  return true;
1361
1297
  }
1362
- function upsertMany(content, values) {
1363
- return Object.entries(values).reduce((next, [key, value]) => upsertEnvValue(next, key, value), content);
1364
- }
1365
1298
  function ensureDir(ctx, dir) {
1366
1299
  if (ctx.dryRun) {
1367
1300
  ctx.log(`[dry-run] mkdir ${rel(ctx, dir)}`);
@@ -1403,23 +1336,7 @@ function writeFile600(ctx, path, content) {
1403
1336
  chmodSync(path, 384);
1404
1337
  } catch {}
1405
1338
  }
1406
- function seedPerImageTagVars(ctx) {
1407
- const envPath = stackEnvFile(ctx.stashDir);
1408
- if (!existsSync(envPath)) return;
1409
- const current = readFileSync(envPath, "utf-8");
1410
- const imageTag = current.match(/^OP_IMAGE_TAG=(.+)$/m)?.[1]?.trim();
1411
- if (!imageTag) return;
1412
- if (PLATFORM_IMAGE_TAG_KEYS.filter((key) => !new RegExp(`^${key}=`, "m").test(current)).length === 0) return;
1413
- if (ctx.dryRun) {
1414
- ctx.log(`[dry-run] seed per-image tag vars from OP_IMAGE_TAG=${imageTag}`);
1415
- return;
1416
- }
1417
- let next = upsertMany(current, buildPlatformImageTagEnv(imageTag));
1418
- const legacyPortalTag = readStackEnvValue(ctx.stashDir, "OP_CHANNEL_IMAGE_TAG");
1419
- if (legacyPortalTag && !/^OP_PORTAL_IMAGE_TAG=/m.test(next)) next = upsertEnvValue(next, "OP_PORTAL_IMAGE_TAG", legacyPortalTag);
1420
- writeFile600(ctx, envPath, next);
1421
- ctx.log(`seeded per-image tag vars from OP_IMAGE_TAG=${imageTag}`);
1422
- }
1339
+ function seedPerImageTagVars(_ctx) {}
1423
1340
  /**
1424
1341
  * Keys that are sensitive and must stay as compose secret files.
1425
1342
  * Matches the @sensitive annotation in BUILTIN_ADDON_ENV_SCHEMAS.
@@ -1875,20 +1792,11 @@ function selectPendingLayoutMigrations(from, migrations = MIGRATIONS, ceiling =
1875
1792
  return chain;
1876
1793
  }
1877
1794
  /**
1878
- * The hardcoded builtin addon IDs from addons.ts. Inlined here to avoid an
1879
- * import cycle (addons.ts → config-persistence.ts which itself may call
1880
- * migrations). These must stay in sync with BUILTIN_ADDONS in addons.ts.
1795
+ * Set of valid built-in addon IDs for fast membership checks.
1796
+ * Derived from BUILTIN_ADDON_IDS (addon-ids.ts the single source of truth).
1797
+ * To add or remove an addon, update addon-ids.ts only.
1881
1798
  */
1882
- var KNOWN_ADDON_IDS = new Set([
1883
- "api",
1884
- "chat",
1885
- "discord",
1886
- "gateway",
1887
- "ollama",
1888
- "slack",
1889
- "ssh",
1890
- "voice"
1891
- ]);
1799
+ var KNOWN_ADDON_IDS = new Set(BUILTIN_ADDON_IDS);
1892
1800
  /**
1893
1801
  * Strip any addon IDs from OP_ENABLED_ADDONS that are not in the current
1894
1802
  * builtin addon set. Stale IDs accumulate when an addon is removed from the
@@ -1929,11 +1837,7 @@ function patchPortalsComposeForThinHost(ctx) {
1929
1837
  const content = readFileSync(path, "utf-8");
1930
1838
  if (content.includes("OP_GUARDIAN_VERSION:")) return;
1931
1839
  const ANCHOR = " OP_ASSISTANT_URL: http://assistant:4096";
1932
- if (!content.includes(ANCHOR)) {
1933
- ctx.log("WARN: portals.compose.yml does not contain expected anchor line; skipping thin-host env patch — apply manually");
1934
- ctx.notes.push("portals.compose.yml could not be auto-patched for the guardian thin-host. Add OP_GUARDIAN_VERSION and PLATFORM_VERSION to the guardian service environment manually (see packages/skeleton/config/stack/portals.compose.yml for the reference values).");
1935
- return;
1936
- }
1840
+ if (!content.includes(ANCHOR)) throw new Error(`Migration patchPortalsComposeForThinHost: anchor line not found in ${path}. The guardian thin-host env vars cannot be injected. Manual fix: add OP_GUARDIAN_VERSION and PLATFORM_VERSION env vars to the guardian service in portals.compose.yml.`);
1937
1841
  const INSERTION = [
1938
1842
  " # Thin-host entrypoint uses these to install @openpalm/guardian and",
1939
1843
  " # @openpalm/skeleton at the correct versions on first boot.",
@@ -1950,19 +1854,73 @@ function patchPortalsComposeForThinHost(ctx) {
1950
1854
  writeFileSync(path, patched);
1951
1855
  ctx.log("patched portals.compose.yml: added OP_GUARDIAN_VERSION and PLATFORM_VERSION to guardian service env");
1952
1856
  }
1857
+ /**
1858
+ * Legacy image-tag keys removed by the version-system redesign. The single
1859
+ * whole-stack OP_IMAGE_TAG and the per-unit OP_*_IMAGE_TAG escape-hatch keys are
1860
+ * replaced by one explicit OP_*_VERSION var per image (no compose cascade).
1861
+ */
1862
+ var LEGACY_IMAGE_TAG_KEYS = [
1863
+ "OP_IMAGE_TAG",
1864
+ "OP_ASSISTANT_IMAGE_TAG",
1865
+ "OP_GUARDIAN_IMAGE_TAG",
1866
+ "OP_PORTAL_IMAGE_TAG",
1867
+ "OP_CHANNEL_IMAGE_TAG"
1868
+ ];
1869
+ /**
1870
+ * Map an existing install's legacy image-tag vars onto the new per-image
1871
+ * OP_*_VERSION vars, then strip the legacy keys.
1872
+ *
1873
+ * Each new var is seeded from the most specific legacy source: the per-unit
1874
+ * OP_<UNIT>_IMAGE_TAG when set, else the whole-stack OP_IMAGE_TAG, else "latest"
1875
+ * (the moving default). Voice never had a managed tag var, so it defaults to
1876
+ * "latest". The legacy keys are then removed (they are SYSTEM-managed compose
1877
+ * config, not user data — and the layout migration path takes a full-home backup
1878
+ * first; here ensureReleaseMigrated takes a targeted stack.env backup).
1879
+ *
1880
+ * Idempotent: once the legacy keys are gone and the new vars are present, a
1881
+ * second run is a no-op (mapped values already exist; nothing to strip).
1882
+ */
1883
+ function migrateImageTagsToVersionVars(ctx) {
1884
+ const envPath = stackEnvFile(ctx.stashDir);
1885
+ if (!existsSync(envPath)) return;
1886
+ let content = readFileSync(envPath, "utf-8");
1887
+ const read = (key) => {
1888
+ const m = content.match(new RegExp(`^${key}=(.*)$`, "m"));
1889
+ return m ? m[1].trim() : void 0;
1890
+ };
1891
+ const has = (key) => new RegExp(`^${key}=`, "m").test(content);
1892
+ const imageTag = read("OP_IMAGE_TAG");
1893
+ const fallback = imageTag && imageTag.length > 0 ? imageTag : "latest";
1894
+ const mapped = {
1895
+ OP_ASSISTANT_VERSION: read("OP_ASSISTANT_IMAGE_TAG") ?? fallback,
1896
+ OP_GUARDIAN_VERSION: read("OP_GUARDIAN_IMAGE_TAG") ?? fallback,
1897
+ OP_PORTAL_VERSION: read("OP_PORTAL_IMAGE_TAG") ?? fallback,
1898
+ OP_VOICE_VERSION: "latest"
1899
+ };
1900
+ const hasLegacy = LEGACY_IMAGE_TAG_KEYS.some(has);
1901
+ const missingNew = Object.keys(mapped).some((k) => !has(k));
1902
+ if (!hasLegacy && !missingNew) return;
1903
+ if (ctx.dryRun) {
1904
+ ctx.log(`[dry-run] would set ${Object.entries(mapped).map(([k, v]) => `${k}=${v}`).join(", ")}`);
1905
+ if (hasLegacy) ctx.log(`[dry-run] would remove legacy image-tag keys: ${LEGACY_IMAGE_TAG_KEYS.filter(has).join(", ")}`);
1906
+ return;
1907
+ }
1908
+ for (const [key, value] of Object.entries(mapped)) if (!has(key)) {
1909
+ content = upsertEnvValue(content, key, value);
1910
+ ctx.log(`set ${key}=${value}`);
1911
+ }
1912
+ for (const key of LEGACY_IMAGE_TAG_KEYS) if (has(key)) {
1913
+ content = removeEnvKey(content, key);
1914
+ ctx.log(`removed legacy image-tag key: ${key}`);
1915
+ }
1916
+ writeFile600(ctx, envPath, content);
1917
+ }
1953
1918
  var RELEASE_MIGRATIONS = [
1954
1919
  {
1955
1920
  version: "v0.11.5-rc.1",
1956
- describe: "seed per-image platform tags from OP_IMAGE_TAG",
1921
+ describe: "seed per-image platform tags from OP_IMAGE_TAG (no-op: compose now resolves every service from OP_IMAGE_TAG)",
1957
1922
  apply: seedPerImageTagVars,
1958
- verify(ctx) {
1959
- if (ctx.dryRun) return;
1960
- const envPath = stackEnvFile(ctx.stashDir);
1961
- if (!existsSync(envPath)) return;
1962
- const content = readFileSync(envPath, "utf-8");
1963
- if (!/^OP_IMAGE_TAG=/m.test(content)) return;
1964
- for (const key of PLATFORM_IMAGE_TAG_KEYS) if (!new RegExp(`^${key}=`, "m").test(content)) throw new Error(`post-migration check failed: ${key} is missing`);
1965
- }
1923
+ verify() {}
1966
1924
  },
1967
1925
  {
1968
1926
  version: "v0.12.0-rc.1",
@@ -2004,7 +1962,27 @@ var RELEASE_MIGRATIONS = [
2004
1962
  if (ctx.dryRun) return;
2005
1963
  const path = join(ctx.stackDir, "portals.compose.yml");
2006
1964
  if (!existsSync(path)) return;
2007
- if (!readFileSync(path, "utf-8").includes("OP_GUARDIAN_VERSION:")) throw new Error("post-migration check failed: OP_GUARDIAN_VERSION still missing from portals.compose.yml");
1965
+ const content = readFileSync(path, "utf-8");
1966
+ if (!content.includes("OP_GUARDIAN_VERSION:")) throw new Error("post-migration check failed: OP_GUARDIAN_VERSION still missing from portals.compose.yml");
1967
+ if (!content.includes(" OP_ASSISTANT_URL: http://assistant:4096")) throw new Error("post-migration check failed: portals.compose.yml is missing the expected anchor line (OP_ASSISTANT_URL: http://assistant:4096). The file may be structurally corrupt.");
1968
+ }
1969
+ },
1970
+ {
1971
+ version: "v0.12.19-rc.1",
1972
+ describe: "map OP_IMAGE_TAG / OP_*_IMAGE_TAG -> OP_*_VERSION and remove legacy image-tag keys",
1973
+ apply: migrateImageTagsToVersionVars,
1974
+ verify(ctx) {
1975
+ if (ctx.dryRun) return;
1976
+ const envPath = stackEnvFile(ctx.stashDir);
1977
+ if (!existsSync(envPath)) return;
1978
+ const content = readFileSync(envPath, "utf-8");
1979
+ for (const key of LEGACY_IMAGE_TAG_KEYS) if (new RegExp(`^${key}=`, "m").test(content)) throw new Error(`post-migration check failed: legacy image-tag key '${key}' still present in stack.env`);
1980
+ for (const key of [
1981
+ "OP_ASSISTANT_VERSION",
1982
+ "OP_GUARDIAN_VERSION",
1983
+ "OP_PORTAL_VERSION",
1984
+ "OP_VOICE_VERSION"
1985
+ ]) if (!new RegExp(`^${key}=`, "m").test(content)) throw new Error(`post-migration check failed: ${key} missing from stack.env after version migration`);
2008
1986
  }
2009
1987
  }
2010
1988
  ];
@@ -5550,7 +5528,7 @@ function resolveLocalOpenpalmDir() {
5550
5528
  * aware — unlike `releases/latest`, which silently excludes prereleases),
5551
5529
  * immutable versions, and a sha512 integrity we verify fail-closed.
5552
5530
  */
5553
- var NPM_REGISTRY$1 = "https://registry.npmjs.org";
5531
+ var NPM_REGISTRY = "https://registry.npmjs.org";
5554
5532
  var UI_PACKAGE = "@openpalm/ui";
5555
5533
  /**
5556
5534
  * Resolve the npm manifest for `@openpalm/ui` by exact version OR dist-tag.
@@ -5558,7 +5536,7 @@ var UI_PACKAGE = "@openpalm/ui";
5558
5536
  * manifest (version + dist.tarball + dist.integrity). Throws on non-OK.
5559
5537
  */
5560
5538
  async function fetchNpmUiManifest(versionOrTag) {
5561
- const res = await fetchWithRetry(`${NPM_REGISTRY$1}/${UI_PACKAGE}/${versionOrTag}`);
5539
+ const res = await fetchWithRetry(`${NPM_REGISTRY}/${UI_PACKAGE}/${versionOrTag}`);
5562
5540
  if (!res.ok) throw new Error(`npm registry returned HTTP ${res.status} for ${UI_PACKAGE}@${versionOrTag}`);
5563
5541
  const m = await res.json();
5564
5542
  if (!m.version || !m.dist?.tarball) throw new Error(`npm manifest for ${UI_PACKAGE}@${versionOrTag} is missing version/dist.tarball`);
@@ -6055,6 +6033,88 @@ var STACK_DEFAULTS = {
6055
6033
  assistant: 3800,
6056
6034
  hostUi: 3880}};
6057
6035
  //#endregion
6036
+ //#region ../lib/src/control-plane/versions.ts
6037
+ /**
6038
+ * Version variable management for the OpenPalm control plane.
6039
+ *
6040
+ * The stack carries two kinds of version pins in knowledge/env/stack.env:
6041
+ *
6042
+ * - SERVICE versions (`OP_*_VERSION`) are Docker image tags. They take an exact
6043
+ * tag ("v0.12.18"), the moving "latest" / "next" refs, or empty (compose
6044
+ * falls back to "latest"). They are NEVER semver ranges — Docker image tags
6045
+ * are concrete refs, not range expressions.
6046
+ * - NPM versions (`OP_*_NPM_VERSION` / `OP_TOOL_*_VERSION`) pin npm packages
6047
+ * installed at container boot (guardian thin-host, assistant CLI tools). These
6048
+ * accept semver ranges ("^1.17.0", "~0.8.14") because npm resolves them.
6049
+ *
6050
+ * Compose reads every SERVICE_VERSION_KEY directly via
6051
+ * `${OP_*_VERSION:-latest}` — there is no cascade fallback to a single platform
6052
+ * tag anymore. Each image rides its own var.
6053
+ */
6054
+ /** Docker image tag pins — one per deployable image. Exact tag / "latest" / "next". */
6055
+ var SERVICE_VERSION_KEYS = [
6056
+ "OP_ASSISTANT_VERSION",
6057
+ "OP_GUARDIAN_VERSION",
6058
+ "OP_PORTAL_VERSION",
6059
+ "OP_VOICE_VERSION"
6060
+ ];
6061
+ /** npm package pins installed at container boot. Semver ranges allowed. */
6062
+ var NPM_VERSION_KEYS = [
6063
+ "OP_GUARDIAN_NPM_VERSION",
6064
+ "OP_TOOL_OPENCODE_VERSION",
6065
+ "OP_TOOL_AKM_VERSION",
6066
+ "OP_TOOL_CLAUDE_CODE_VERSION",
6067
+ "OP_TOOL_CODEX_VERSION"
6068
+ ];
6069
+ /** Every version key the control plane reads/writes in stack.env. */
6070
+ var ALL_VERSION_KEYS = [...SERVICE_VERSION_KEYS, ...NPM_VERSION_KEYS];
6071
+ var VERSION_KEY_SET = new Set(ALL_VERSION_KEYS);
6072
+ /** Default values seeded into a fresh stack.env (and returned for unset keys). */
6073
+ var VERSION_DEFAULTS = {
6074
+ OP_ASSISTANT_VERSION: "latest",
6075
+ OP_GUARDIAN_VERSION: "latest",
6076
+ OP_PORTAL_VERSION: "latest",
6077
+ OP_VOICE_VERSION: "latest",
6078
+ OP_GUARDIAN_NPM_VERSION: "",
6079
+ OP_TOOL_OPENCODE_VERSION: "^1.17.0",
6080
+ OP_TOOL_AKM_VERSION: "^0.8.14",
6081
+ OP_TOOL_CLAUDE_CODE_VERSION: "^1.5.0",
6082
+ OP_TOOL_CODEX_VERSION: "^0.1.0"
6083
+ };
6084
+ function isVersionKey(key) {
6085
+ return VERSION_KEY_SET.has(key);
6086
+ }
6087
+ function stackEnvPath$1(state) {
6088
+ return `${state.stashDir}/env/stack.env`;
6089
+ }
6090
+ /**
6091
+ * Read every version key from stack.env. Keys that are absent fall back to their
6092
+ * documented default (so callers always get the full ALL_VERSION_KEYS set).
6093
+ */
6094
+ function readVersions(state) {
6095
+ const path = stackEnvPath$1(state);
6096
+ const parsed = existsSync(path) ? parseEnvFile(path) : {};
6097
+ const out = {};
6098
+ for (const key of ALL_VERSION_KEYS) out[key] = parsed[key] ?? VERSION_DEFAULTS[key];
6099
+ return out;
6100
+ }
6101
+ /**
6102
+ * Write validated version keys into stack.env. Only keys in the
6103
+ * ALL_VERSION_KEYS allowlist are written; anything else is rejected so a typo or
6104
+ * a hostile caller can't smuggle arbitrary env into the stack config. Uses
6105
+ * mergeEnvContent so existing non-version keys (and comments) are preserved.
6106
+ */
6107
+ function writeVersions(state, updates) {
6108
+ const accepted = {};
6109
+ for (const [key, value] of Object.entries(updates)) {
6110
+ if (!isVersionKey(key)) throw new Error(`Refusing to write unknown version key: ${key}`);
6111
+ accepted[key] = (value ?? "").trim();
6112
+ }
6113
+ if (Object.keys(accepted).length === 0) return;
6114
+ const path = stackEnvPath$1(state);
6115
+ writeFileSync(path, mergeEnvContent(existsSync(path) ? readFileSync(path, "utf-8") : "", accepted), { mode: 384 });
6116
+ }
6117
+ //#endregion
6058
6118
  //#region ../lib/src/control-plane/config-persistence.ts
6059
6119
  /**
6060
6120
  * Runtime file resolution and persistence for the OpenPalm control plane.
@@ -6063,7 +6123,6 @@ var STACK_DEFAULTS = {
6063
6123
  * Files are validated in-place before writing; rollback is handled by
6064
6124
  * the rollback module (snapshot to OP_HOME/data/rollback/).
6065
6125
  */
6066
- var DEFAULT_IMAGE_TAG = "latest";
6067
6126
  var logger$8 = createLogger("config-persistence");
6068
6127
  /**
6069
6128
  * Return the env files used for docker compose --env-file args.
@@ -6191,7 +6250,12 @@ function generateFallbackSystemEnv(state) {
6191
6250
  "",
6192
6251
  "# ── Images ──────────────────────────────────────────────────────────",
6193
6252
  `OP_IMAGE_NAMESPACE=${process.env.OP_IMAGE_NAMESPACE ?? "openpalm"}`,
6194
- ...Object.entries(buildPlatformImageTagEnv(DEFAULT_IMAGE_TAG)).map(([key, value]) => `${key}=${value}`),
6253
+ "# Docker image tags (exact tag, \"latest\", or \"next\" — no semver ranges).",
6254
+ ...SERVICE_VERSION_KEYS.map((key) => `${key}=${VERSION_DEFAULTS[key]}`),
6255
+ "",
6256
+ "# ── npm package versions (semver ranges supported) ──────────────────",
6257
+ "# OP_GUARDIAN_NPM_VERSION empty ⇒ use the GUARDIAN_VERSION baked into the image.",
6258
+ ...NPM_VERSION_KEYS.map((key) => `${key}=${VERSION_DEFAULTS[key]}`),
6195
6259
  "",
6196
6260
  "# ── Layout (on-disk schema version; managed by the migration harness) ──",
6197
6261
  `OP_LAYOUT_VERSION=2`,
@@ -6380,13 +6444,6 @@ function canonicalAddonProfileSelection(addon, profile) {
6380
6444
  */
6381
6445
  var VALID_NAME_RE = /^[a-z0-9][a-z0-9-]{0,62}$/;
6382
6446
  var logger$7 = createLogger("registry");
6383
- var BUILTIN_ADDONS = [
6384
- "api",
6385
- "discord",
6386
- "ollama",
6387
- "slack",
6388
- "voice"
6389
- ];
6390
6447
  function getRegistryAutomation(name) {
6391
6448
  if (!VALID_NAME_RE.test(name)) return null;
6392
6449
  const localOpenpalmDir = resolveLocalOpenpalmDir();
@@ -6403,7 +6460,7 @@ function getRegistryAddonConfig(name) {
6403
6460
  };
6404
6461
  }
6405
6462
  function listAvailableAddonIds() {
6406
- return [...BUILTIN_ADDONS].sort();
6463
+ return [...BUILTIN_ADDON_IDS].sort();
6407
6464
  }
6408
6465
  function listEnabledAddonIds(homeDir) {
6409
6466
  const env = readStackEnv(join(homeDir, "config", "stack"));
@@ -6485,17 +6542,18 @@ function execFileNoThrow(cmd, args, timeoutMs) {
6485
6542
  /**
6486
6543
  * Compute the openpalm/voice image ref for a given GPU variant, matching
6487
6544
  * the substitution chain in the addon compose file:
6488
- * ${OP_IMAGE_NAMESPACE:-openpalm}/voice:${OP_VOICE_IMAGE_TAG:-latest-<variant>}
6545
+ * ${OP_IMAGE_NAMESPACE:-openpalm}/voice:${OP_VOICE_VERSION:-latest-<variant>}
6489
6546
  *
6490
6547
  * Voice images are published OUT OF BAND (publish-voice.yml), decoupled from the
6491
- * platform OP_IMAGE_TAG — they are heavy and rarely change. So the default is
6492
- * the moving `latest-<variant>` voice tag; operators pin a specific build by
6493
- * setting OP_VOICE_IMAGE_TAG (e.g. `v1.0.0-cpu`).
6548
+ * other service images — they are heavy and rarely change. So the default is the
6549
+ * moving `latest-<variant>` voice tag; operators pin a specific build by setting
6550
+ * OP_VOICE_VERSION (e.g. `v1.0.0-cpu`). A bare `latest` (the seeded default) is
6551
+ * treated as "unset" so the GPU-variant default still applies.
6494
6552
  */
6495
6553
  function voiceImageRef(variant) {
6496
6554
  const namespace = process.env.OP_IMAGE_NAMESPACE?.trim() || "openpalm";
6497
- const explicit = process.env.OP_VOICE_IMAGE_TAG?.trim();
6498
- if (explicit) return `${namespace}/voice:${explicit}`;
6555
+ const explicit = process.env.OP_VOICE_VERSION?.trim();
6556
+ if (explicit && explicit !== "latest") return `${namespace}/voice:${explicit}`;
6499
6557
  return `${namespace}/voice:latest-${variant}`;
6500
6558
  }
6501
6559
  /**
@@ -7608,13 +7666,6 @@ function hasArmedSnapshot() {
7608
7666
  //#region ../lib/src/control-plane/lifecycle.ts
7609
7667
  /** Lifecycle helpers — state factory, apply transitions, compose file list. */
7610
7668
  var IMAGE_NAMESPACE_RE = /^[a-z0-9]+(?:[._-][a-z0-9]+)*$/;
7611
- var SEMVER_TAG_RE = /^v\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
7612
- var PLATFORM_IMAGE_NAMES = [
7613
- "assistant",
7614
- "guardian",
7615
- "portal"
7616
- ];
7617
- var AUTH_TRANSITION_BOUNDARY_TAG = "v0.12.0";
7618
7669
  function createState() {
7619
7670
  const homeDir = resolveOpenPalmHome();
7620
7671
  const configDir = resolveConfigDir();
@@ -7709,317 +7760,11 @@ async function applyUninstall(state, opts) {
7709
7760
  releaseLifecycleLock(lock, opts);
7710
7761
  }
7711
7762
  }
7712
- var DOCKER_REGISTRY_TIMEOUT_MS = 1e4;
7713
- /**
7714
- * Resolve the best Docker image tag from a registry tags payload.
7715
- *
7716
- * Constraints (all optional):
7717
- * - `sameMajorAs` — only consider tags whose major component matches this tag.
7718
- * - `atOrBelow` — only consider tags whose version is <= this tag.
7719
- * - `skipPrerelease` — ignore prerelease tags (`-rc`, `-beta`, …). Used so a
7720
- * STABLE base never auto-jumps onto a prerelease (#494),
7721
- * mirroring the UI card's channel gate.
7722
- *
7723
- * With no constraints: returns the first semver tag found, or the first
7724
- * non-"latest" tag as a fallback (mirrors the original resolveNewestDockerTag).
7725
- * With constraints: returns the highest semver tag satisfying all constraints.
7726
- */
7727
- function resolveNewestDockerTag(payload, constraints = {}) {
7728
- const results = payload?.results;
7729
- if (!Array.isArray(results)) return null;
7730
- const { sameMajorAs, atOrBelow, skipPrerelease } = constraints;
7731
- if (!(sameMajorAs !== void 0 || atOrBelow !== void 0 || skipPrerelease === true)) {
7732
- let fallback = null;
7733
- for (const entry of results) {
7734
- const name = typeof entry?.name === "string" ? entry.name.trim() : "";
7735
- if (!name || name === "latest") continue;
7736
- if (SEMVER_TAG_RE.test(name)) return name;
7737
- if (!fallback) fallback = name;
7738
- }
7739
- return fallback;
7740
- }
7741
- let best = null;
7742
- for (const entry of results) {
7743
- const name = typeof entry?.name === "string" ? entry.name.trim() : "";
7744
- if (!isComparableSemver(name)) continue;
7745
- if (skipPrerelease && isPrerelease(name)) continue;
7746
- if (sameMajorAs !== void 0 && !isSameMajorVersion(name, sameMajorAs)) continue;
7747
- if (atOrBelow !== void 0 && compareComparableVersions(name, atOrBelow) > 0) continue;
7748
- if (!best || compareComparableVersions(name, best) > 0) best = name;
7749
- }
7750
- return best;
7751
- }
7752
- function resolvePlatformVersionPolicyBaseTag(state) {
7753
- const configured = parseEnvFile(`${state.stashDir}/env/stack.env`).OP_IMAGE_TAG?.trim();
7754
- if (isComparableSemver(configured)) return configured;
7755
- return PLATFORM_VERSION;
7756
- }
7757
- /**
7758
- * Host-vs-target guard (#492), keyed on the RUNNING control-plane version.
7759
- *
7760
- * The migrations a release needs live inside the @openpalm/lib that is actually
7761
- * executing — i.e. PLATFORM_VERSION (the version of the running data/ui build, or
7762
- * the compiled-in CLI lib). If a user points the stack at a tag NEWER than the
7763
- * control plane they're running, `ensureReleaseMigrated` runs an OLD migration
7764
- * array that doesn't contain that release's migrations → the new images come up
7765
- * against half-migrated files. There is no safe recovery, so this is a HARD block
7766
- * (not a warning): nothing is written before it throws.
7767
- *
7768
- * The thin-harness design (§6.5) makes this satisfiable: the supervisor self-
7769
- * updates data/ui to the current platform BEFORE the UI serves the upgrade
7770
- * request, so "target ≤ running platform" only fails when the user genuinely
7771
- * picks a tag the running control plane cannot migrate to — at which point the
7772
- * fix is to update the app / control plane first, not to proceed.
7773
- *
7774
- * Non-semver targets (a moving `latest`/`dev` tag) are not comparable and are
7775
- * left to the resolver paths that turn them into a concrete release first.
7776
- */
7777
- /**
7778
- * Downgrade-needs-confirmation signal (#501).
7779
- *
7780
- * Release migrations are forward-only (copy-only, additive); they do NOT run
7781
- * backward. Pointing the stack at an OLDER tag than the one currently running is
7782
- * therefore a data-safety event, not a routine version change: the older images
7783
- * may not understand files the newer release already migrated. We don't block it
7784
- * (a user may legitimately need to roll back), but we require an explicit
7785
- * confirmation so it can't happen by a stray dropdown selection. The UI catches
7786
- * this by `code` and shows a plain warning + confirm; the CLI surfaces the
7787
- * message and a `--confirm`/`--yes` path.
7788
- */
7789
- var DowngradeConfirmationRequired = class extends Error {
7790
- code = "downgrade_confirmation_required";
7791
- currentVersion;
7792
- targetVersion;
7793
- constructor(currentVersion, targetVersion) {
7794
- super(`Version ${formatForDisplay(targetVersion)} is older than the version you're running (${formatForDisplay(currentVersion)}). This is a downgrade. Release migrations don't run backward; your data may not be compatible — restore from backup if needed. Re-run with confirmation to proceed. Nothing was changed.`);
7795
- this.name = "DowngradeConfirmationRequired";
7796
- this.currentVersion = currentVersion;
7797
- this.targetVersion = targetVersion;
7798
- }
7799
- };
7800
- /**
7801
- * Throw {@link DowngradeConfirmationRequired} when `targetTag` is strictly older
7802
- * than the version currently configured in stack.env, unless the caller passed
7803
- * an explicit confirmation. Non-semver tags (a moving `latest`/`dev` ref, or a
7804
- * first install with no current tag) are not comparable and pass through — the
7805
- * resolver paths turn `latest` into a concrete release before this runs.
7806
- */
7807
- function assertNotUnconfirmedDowngrade(state, targetTag, confirmDowngrade) {
7808
- if (confirmDowngrade) return;
7809
- const currentTag = resolvePlatformVersionPolicyBaseTag(state);
7810
- if (!isComparableSemver(targetTag) || !isComparableSemver(currentTag)) return;
7811
- if (compareComparableVersions(targetTag, currentTag) >= 0) return;
7812
- throw new DowngradeConfirmationRequired(currentTag, targetTag);
7813
- }
7814
- /**
7815
- * Convert a release git tag to a Docker image tag.
7816
- *
7817
- * The new per-unit release scheme uses prefixed git tags (platform-X.Y.Z,
7818
- * portals-X.Y.Z, etc.) while Docker images always use the v-prefixed form
7819
- * (v0.12.5). This function strips the unit prefix so applyTagChange can
7820
- * resolve the correct Docker image tag from a GitHub release tag.
7821
- */
7822
- function extractDockerTagFromReleaseTag(tag) {
7823
- const unitPrefixMatch = tag.match(/^(?:platform|portals|assistant|guardian)-(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]*)?)$/);
7824
- if (unitPrefixMatch) return formatForDocker(unitPrefixMatch[1]);
7825
- return formatForDocker(tag);
7826
- }
7827
7763
  function resolveImageNamespace(state) {
7828
7764
  const namespace = (parseEnvFile(`${state.stashDir}/env/stack.env`).OP_IMAGE_NAMESPACE ?? process.env.OP_IMAGE_NAMESPACE ?? "openpalm").trim().toLowerCase();
7829
7765
  if (!IMAGE_NAMESPACE_RE.test(namespace)) throw new Error(`Invalid image namespace in system.env: ${namespace}`);
7830
7766
  return namespace;
7831
7767
  }
7832
- function resolveRequiredPlatformImages(state) {
7833
- const required = new Set(["assistant"]);
7834
- if (hasEnabledPortal(listEnabledAddonIds(state.homeDir))) {
7835
- required.add("guardian");
7836
- required.add("portal");
7837
- }
7838
- return PLATFORM_IMAGE_NAMES.filter((name) => required.has(name));
7839
- }
7840
- async function isDockerImageTagPublished(namespace, imageName, tag) {
7841
- let response;
7842
- try {
7843
- response = await fetch(`https://registry.hub.docker.com/v2/repositories/${namespace}/${imageName}/tags/${tag}`, {
7844
- headers: { Accept: "application/json" },
7845
- signal: AbortSignal.timeout(DOCKER_REGISTRY_TIMEOUT_MS)
7846
- });
7847
- } catch (e) {
7848
- throw new Error(`Failed to verify Docker image tag ${namespace}/${imageName}:${tag}: ${e instanceof Error ? e.message : String(e)}`);
7849
- }
7850
- if (response.status === 404) return false;
7851
- if (!response.ok) throw new Error(`Docker tag verification failed for ${namespace}/${imageName}:${tag} (${response.status})`);
7852
- return true;
7853
- }
7854
- async function fetchDockerTagsPayload(namespace, imageName) {
7855
- let response;
7856
- try {
7857
- response = await fetch(`https://registry.hub.docker.com/v2/repositories/${namespace}/${imageName}/tags?page_size=25&ordering=last_updated`, {
7858
- headers: { Accept: "application/json" },
7859
- signal: AbortSignal.timeout(DOCKER_REGISTRY_TIMEOUT_MS)
7860
- });
7861
- } catch (e) {
7862
- throw new Error(`Failed to query Docker tags: ${e instanceof Error ? e.message : String(e)}`);
7863
- }
7864
- if (!response.ok) throw new Error(`Docker tag lookup failed (${response.status})`);
7865
- return response.json();
7866
- }
7867
- /**
7868
- * Resolve the per-image tag env for a target platform tag (#477).
7869
- *
7870
- * `assistant` is the version-of-record image and must be published at the
7871
- * platform tag. Guardian/portal may lag: a release that ships only a subset
7872
- * of images leaves them at an older tag, so each falls back to its newest
7873
- * published tag <= the platform tag in the same major. Fail closed only when
7874
- * a required image (guardian/portal with a portal addon enabled) has no
7875
- * usable tag at all.
7876
- */
7877
- async function resolvePlatformImageTags(state, namespace, platformTag, pinnedImages) {
7878
- if (namespace !== "openpalm") return buildPlatformImageTagEnv(platformTag, void 0, pinnedImages);
7879
- if (!await isDockerImageTagPublished(namespace, "assistant", platformTag)) throw new Error(`Refusing to update to ${namespace}/assistant:${platformTag}: tag is not published. stack.env was left unchanged.`);
7880
- const required = new Set(resolveRequiredPlatformImages(state));
7881
- const perImage = {};
7882
- for (const imageName of ["guardian", "portal"]) {
7883
- if (pinnedImages.includes(imageName)) continue;
7884
- if (await isDockerImageTagPublished(namespace, imageName, platformTag)) continue;
7885
- const fallbackTag = resolveNewestDockerTag(await fetchDockerTagsPayload(namespace, imageName), {
7886
- sameMajorAs: platformTag,
7887
- atOrBelow: platformTag
7888
- });
7889
- if (fallbackTag) {
7890
- perImage[`OP_${imageName.toUpperCase()}_IMAGE_TAG`] = fallbackTag;
7891
- continue;
7892
- }
7893
- if (required.has(imageName)) throw new Error(`Refusing to update to ${namespace}/*:${platformTag}: no published tag found for ${imageName} at or below ${platformTag}. This release is incomplete for the enabled services; stack.env was left unchanged.`);
7894
- }
7895
- return buildPlatformImageTagEnv(platformTag, perImage, pinnedImages);
7896
- }
7897
- function collectPinnedImageWarnings(currentEnv, pinnedImages, platformTag) {
7898
- if (!isComparableSemver(platformTag) || compareComparableVersions(platformTag, AUTH_TRANSITION_BOUNDARY_TAG) < 0) return [];
7899
- const warnings = [];
7900
- for (const image of pinnedImages) {
7901
- const pinnedTag = resolveEffectivePlatformImageTag(currentEnv, image);
7902
- if (!isComparableSemver(pinnedTag) || compareComparableVersions(pinnedTag, AUTH_TRANSITION_BOUNDARY_TAG) >= 0) continue;
7903
- warnings.push(JSON.stringify({
7904
- event: "unsupported-cross-boundary-pin",
7905
- service: image,
7906
- pinnedTag,
7907
- platformTag,
7908
- message: `Pinned ${image} image ${pinnedTag} is older than ${AUTH_TRANSITION_BOUNDARY_TAG} while the platform tag is ${platformTag}. Mixed-auth pinning across the 0.12 boundary is unsupported.`
7909
- }));
7910
- }
7911
- return warnings;
7912
- }
7913
- /**
7914
- * Resolve the newest published tag for a SPECIFIC image on Docker Hub.
7915
- *
7916
- * `assistant` is the version-of-record image, but with independently versioned
7917
- * units each image (guardian, portal, voice) has its own release line. This
7918
- * resolves the newest semver tag for the given image name so a per-unit update
7919
- * check compares against the unit's own latest, not the assistant's.
7920
- *
7921
- * Used both to auto-detect during "Update now" and to resolve a requested
7922
- * `latest` selection into a concrete release tag before fetching stack assets
7923
- * (GitHub has no asset tree at a `latest` ref).
7924
- */
7925
- async function resolveLatestImageTag(namespace, imageName) {
7926
- const latestTag = resolveNewestDockerTag(await fetchDockerTagsPayload(namespace, imageName), {});
7927
- if (!latestTag) throw new Error(`No usable Docker image tag found for ${namespace}/${imageName}`);
7928
- return latestTag;
7929
- }
7930
- /**
7931
- * Resolve the newest published tag for a SPECIFIC image, scoped to the current
7932
- * major version of `currentTag`. Mirrors {@link resolveLatestImageTag} with the
7933
- * same major-scoping + prerelease policy as the platform resolver.
7934
- */
7935
- async function resolveLatestImageTagForCurrentMajor(namespace, imageName, currentTag, opts = {}) {
7936
- const skipPrerelease = !opts.allowPrerelease && !isPrerelease(currentTag);
7937
- const latestTag = resolveNewestDockerTag(await fetchDockerTagsPayload(namespace, imageName), {
7938
- sameMajorAs: currentTag,
7939
- skipPrerelease
7940
- });
7941
- if (!latestTag) throw new Error(`No usable Docker image tag found for ${namespace}/${imageName} in major ${majorVersionOf(currentTag) ?? currentTag}`);
7942
- return latestTag;
7943
- }
7944
- /**
7945
- * List published Docker image tags for a SPECIFIC image, filtered + sorted.
7946
- *
7947
- * Mirrors {@link resolveLatestImageTag} / {@link resolveLatestImageTagForCurrentMajor}
7948
- * but returns ALL matching tags (not just the newest), sorted newest (highest
7949
- * semver) first. Used by the admin UI's per-unit version picker dropdowns so the
7950
- * user can pin/rollback to any published tag — Docker Hub is the authoritative
7951
- * source for what's available to deploy, per unit.
7952
- *
7953
- * Constraints (all optional):
7954
- * - `sameMajorAs` — only tags whose major component matches this tag.
7955
- * - `skipPrerelease` — ignore prerelease tags (`-rc`, `-beta`, …). Default false
7956
- * so the picker shows every tag on the line, including rcs.
7957
- * - `max` — cap the returned list (default 20).
7958
- *
7959
- * Tags are returned in Docker-canonical form (`v`-prefixed, as Docker Hub returns
7960
- * them). The UI strips the `v` for display via `formatForDisplay`.
7961
- */
7962
- async function listDockerImageTags(namespace, imageName, opts = {}) {
7963
- const { sameMajorAs, skipPrerelease = false, max = 20 } = opts;
7964
- const results = (await fetchDockerTagsPayload(namespace, imageName))?.results;
7965
- if (!Array.isArray(results)) return [];
7966
- const tags = [];
7967
- for (const entry of results) {
7968
- const name = typeof entry?.name === "string" ? entry.name.trim() : "";
7969
- if (!name || name === "latest") continue;
7970
- if (!isComparableSemver(name)) continue;
7971
- if (skipPrerelease && isPrerelease(name)) continue;
7972
- if (sameMajorAs !== void 0 && !isSameMajorVersion(name, sameMajorAs)) continue;
7973
- tags.push(name);
7974
- }
7975
- tags.sort((a, b) => compareComparableVersions(b, a));
7976
- return tags.slice(0, max);
7977
- }
7978
- /**
7979
- * Resolve the newest published platform tag from the Docker registry.
7980
- *
7981
- * `assistant` is the version-of-record image: its newest tag is the canonical
7982
- * platform version. Guardian/portal may lag behind it when a release shipped
7983
- * only a subset of images — see resolvePlatformImageTags.
7984
- *
7985
- * Used both to auto-detect during "Update now" and to resolve a requested
7986
- * `latest` selection into a concrete release tag before fetching stack assets
7987
- * (GitHub has no asset tree at a `latest` ref).
7988
- */
7989
- async function resolveLatestPlatformTag(namespace) {
7990
- return resolveLatestImageTag(namespace, "assistant");
7991
- }
7992
- /**
7993
- * Resolve the default target version for `openpalm migrate --dry-run`: the
7994
- * newest published platform tag in the current major. Mirrors the resolver the
7995
- * upgrade path uses (same namespace, same base tag, same prerelease policy) so a
7996
- * dry-run preview reflects the exact version `openpalm update` would move to.
7997
- */
7998
- async function resolveDefaultMigrateTarget(state, opts = {}) {
7999
- return resolveLatestPlatformTagForCurrentMajor(resolveImageNamespace(state), resolvePlatformVersionPolicyBaseTag(state), { allowPrerelease: opts.allowPrerelease });
8000
- }
8001
- async function resolveLatestPlatformTagForCurrentMajor(namespace, currentTag, opts = {}) {
8002
- return resolveLatestImageTagForCurrentMajor(namespace, "assistant", currentTag, opts);
8003
- }
8004
- async function updateStackEnvToLatestImageTag(state, resolvedTag) {
8005
- const systemEnvPath = `${state.stashDir}/env/stack.env`;
8006
- const currentEnv = parseEnvFile(systemEnvPath);
8007
- const pinnedImages = parsePinnedImages(currentEnv.OP_PINNED_IMAGES);
8008
- const namespace = resolveImageNamespace(state);
8009
- const latestTag = resolvedTag ?? await resolveLatestPlatformTagForCurrentMajor(namespace, resolvePlatformVersionPolicyBaseTag(state));
8010
- const imageTagEnv = await resolvePlatformImageTags(state, namespace, latestTag, pinnedImages);
8011
- const pinnedImageEnv = buildPinnedImageTagEnv(currentEnv, pinnedImages);
8012
- const warnings = collectPinnedImageWarnings(currentEnv, pinnedImages, latestTag);
8013
- writeFileSync(systemEnvPath, mergeEnvContent(existsSync(systemEnvPath) ? readFileSync(systemEnvPath, "utf-8") : "", {
8014
- ...pinnedImageEnv,
8015
- ...imageTagEnv
8016
- }));
8017
- return {
8018
- namespace,
8019
- tag: latestTag,
8020
- warnings
8021
- };
8022
- }
8023
7768
  async function applyUpgrade(state, version, opts) {
8024
7769
  const lock = resolveLifecycleLock(state, opts);
8025
7770
  if (!lock) throw new Error("Another install is already in progress");
@@ -8037,10 +7782,20 @@ async function applyUpgrade(state, version, opts) {
8037
7782
  }
8038
7783
  async function withStackEnvRollback(state, run) {
8039
7784
  const stackEnvPath = `${state.stashDir}/env/stack.env`;
7785
+ const portalsComposePath = `${state.stackDir}/portals.compose.yml`;
7786
+ const customComposePath = `${state.stackDir}/custom.compose.yml`;
8040
7787
  let originalStackEnv = null;
7788
+ let originalPortalsCompose = null;
7789
+ let originalCustomCompose = null;
8041
7790
  try {
8042
7791
  originalStackEnv = readFileSync(stackEnvPath, "utf-8");
8043
7792
  } catch {}
7793
+ try {
7794
+ originalPortalsCompose = readFileSync(portalsComposePath, "utf-8");
7795
+ } catch {}
7796
+ try {
7797
+ originalCustomCompose = readFileSync(customComposePath, "utf-8");
7798
+ } catch {}
8044
7799
  snapshotCurrentState(state, { arm: true });
8045
7800
  try {
8046
7801
  return await run();
@@ -8048,26 +7803,35 @@ async function withStackEnvRollback(state, run) {
8048
7803
  if (originalStackEnv !== null) try {
8049
7804
  writeFileSync(stackEnvPath, originalStackEnv);
8050
7805
  } catch {}
7806
+ if (originalPortalsCompose !== null) try {
7807
+ writeFileSync(portalsComposePath, originalPortalsCompose);
7808
+ } catch {}
7809
+ if (originalCustomCompose !== null) try {
7810
+ writeFileSync(customComposePath, originalCustomCompose);
7811
+ } catch {}
8051
7812
  throw e;
8052
7813
  }
8053
7814
  }
8054
7815
  /**
8055
- * Full upgrade: resolve latest image tag, refresh assets, pull images,
8056
- * and recreate containers. Used by both the admin endpoint and CLI.
7816
+ * Update the stack to the running control-plane version: run forward release
7817
+ * migrations, refresh core stack assets (compose/config) for PLATFORM_VERSION,
7818
+ * then pull images and recreate containers honoring the per-image OP_*_VERSION
7819
+ * pins already written in stack.env.
8057
7820
  *
8058
- * Callers handle their own audit logging and admin self-recreation.
7821
+ * There are NO Docker Hub calls: image versions are user-managed in stack.env
7822
+ * (PATCH /admin/versions), and the platform asset version is the running lib's
7823
+ * PLATFORM_VERSION — never resolved from a remote registry.
8059
7824
  */
8060
- async function performUpgrade(state, opts = {}) {
7825
+ async function performUpgrade(state, _opts = {}) {
8061
7826
  return withStackEnvRollback(state, async () => {
8062
7827
  const composeOpts = buildComposeOptions(state);
8063
7828
  const namespace = resolveImageNamespace(state);
8064
- const imageTag = await resolveLatestPlatformTagForCurrentMajor(namespace, resolvePlatformVersionPolicyBaseTag(state), { allowPrerelease: opts.allowPrerelease });
7829
+ const releaseTag = "platform-" + normalizeVersion(PLATFORM_VERSION);
8065
7830
  ensureReleaseMigrated({
8066
7831
  homeDir: state.homeDir,
8067
- targetVersion: imageTag
7832
+ targetVersion: PLATFORM_VERSION
8068
7833
  });
8069
- const { tag: confirmedImageTag, warnings } = await updateStackEnvToLatestImageTag(state, imageTag);
8070
- const upgradeResult = await applyUpgrade(state, "platform-" + normalizeVersion(confirmedImageTag));
7834
+ const upgradeResult = await applyUpgrade(state, releaseTag);
8071
7835
  const pullResult = await composePull(composeOpts);
8072
7836
  if (!pullResult.ok) throw new Error(`Failed to pull images: ${pullResult.stderr}`);
8073
7837
  const services = await buildManagedServices(state);
@@ -8079,134 +7843,11 @@ async function performUpgrade(state, opts = {}) {
8079
7843
  });
8080
7844
  if (!upResult.ok) throw new Error(`Images pulled but failed to recreate containers: ${upResult.stderr}`);
8081
7845
  return {
8082
- imageTag: confirmedImageTag,
7846
+ imageTag: PLATFORM_VERSION,
8083
7847
  namespace,
8084
7848
  backupDir: upgradeResult.backupDir,
8085
7849
  assetsUpdated: upgradeResult.updated,
8086
7850
  restarted: upgradeResult.restarted,
8087
- warnings
8088
- };
8089
- });
8090
- }
8091
- /**
8092
- * Set a specific image tag in stack.env then pull images and restart containers.
8093
- * Used by the admin "set version" action — skips the auto-detect step in performUpgrade.
8094
- */
8095
- async function applyTagChange(state, tag, opts = {}) {
8096
- return withStackEnvRollback(state, async () => {
8097
- const namespace = resolveImageNamespace(state);
8098
- const requested = tag.trim();
8099
- let resolvedTag = requested;
8100
- if (requested === "" || requested.toLowerCase() === "latest") try {
8101
- resolvedTag = await resolveLatestPlatformTag(namespace);
8102
- } catch (e) {
8103
- const msg = e instanceof Error ? e.message : String(e);
8104
- throw new Error(`Cannot resolve "latest" to a concrete release: ${msg}. Check your network connection or select a specific version.`);
8105
- }
8106
- assertNotUnconfirmedDowngrade(state, resolvedTag, opts.confirmDowngrade ?? false);
8107
- const dockerTag = extractDockerTagFromReleaseTag(resolvedTag);
8108
- const stackEnvPath = `${state.stashDir}/env/stack.env`;
8109
- const currentEnv = parseEnvFile(stackEnvPath);
8110
- const pinnedImages = parsePinnedImages(currentEnv.OP_PINNED_IMAGES);
8111
- const imageTagEnv = await resolvePlatformImageTags(state, namespace, dockerTag, pinnedImages);
8112
- const pinnedImageEnv = buildPinnedImageTagEnv(currentEnv, pinnedImages);
8113
- const warnings = collectPinnedImageWarnings(currentEnv, pinnedImages, dockerTag);
8114
- ensureReleaseMigrated({
8115
- homeDir: state.homeDir,
8116
- targetVersion: resolvedTag
8117
- });
8118
- writeFileSync(stackEnvPath, mergeEnvContent(existsSync(stackEnvPath) ? readFileSync(stackEnvPath, "utf-8") : "", {
8119
- ...pinnedImageEnv,
8120
- ...imageTagEnv
8121
- }));
8122
- const upgradeResult = await applyUpgrade(state, resolvedTag);
8123
- return {
8124
- imageTag: dockerTag,
8125
- namespace,
8126
- backupDir: upgradeResult.backupDir,
8127
- assetsUpdated: upgradeResult.updated,
8128
- restarted: upgradeResult.restarted,
8129
- warnings
8130
- };
8131
- });
8132
- }
8133
- /**
8134
- * Read the currently-configured image tag for a single deployable unit from
8135
- * stack.env. Falls back to OP_IMAGE_TAG (the compose substitution fallback) and
8136
- * finally PLATFORM_VERSION, mirroring the compose `${OP_*_IMAGE_TAG:-…}` chain.
8137
- */
8138
- function resolveUnitCurrentTag(state, unit) {
8139
- const envVars = parseEnvFile(`${state.stashDir}/env/stack.env`);
8140
- const tag = envVars[deployableUnitImageTagKey(unit)]?.trim() || envVars.OP_IMAGE_TAG?.trim();
8141
- if (isComparableSemver(tag)) return tag;
8142
- return PLATFORM_VERSION;
8143
- }
8144
- /**
8145
- * Per-unit downgrade gate (#501). A target OLDER than the unit's CURRENT tag is
8146
- * a downgrade — forward-only release migrations don't run backward, so require
8147
- * explicit confirmation. Compared against the unit's own tag (not the platform
8148
- * OP_IMAGE_TAG) so pinning guardian back a patch doesn't trip on the assistant
8149
- * version.
8150
- */
8151
- function assertNotUnconfirmedUnitDowngrade(state, unit, targetTag, confirmDowngrade) {
8152
- if (confirmDowngrade) return;
8153
- const currentTag = resolveUnitCurrentTag(state, unit);
8154
- if (!isComparableSemver(targetTag) || !isComparableSemver(currentTag)) return;
8155
- if (compareComparableVersions(targetTag, currentTag) >= 0) return;
8156
- throw new DowngradeConfirmationRequired(currentTag, targetTag);
8157
- }
8158
- /**
8159
- * Pin a SINGLE deployable unit's image tag in stack.env, then pull + recreate.
8160
- *
8161
- * Unlike {@link applyTagChange} (a full platform upgrade), this writes only the
8162
- * one `OP_*_IMAGE_TAG` env var for the named unit and does NOT run release
8163
- * migrations or refresh stack compose assets — those are platform-level and run
8164
- * on `performUpgrade` / `applyTagChange`. Per-unit pinning is for rolling one
8165
- * image back to a known-good release or pinning it to a tested build without
8166
- * moving the rest of the stack.
8167
- *
8168
- * Non-destructive: the write uses `mergeEnvContent` so existing user keys
8169
- * (including commented-out ones) are preserved.
8170
- */
8171
- async function applyUnitImageTagChange(state, unit, tag, opts = {}) {
8172
- if (!isDeployableUnit(unit)) throw new Error(`Unknown deployable unit: ${unit}`);
8173
- const typedUnit = unit;
8174
- return withStackEnvRollback(state, async () => {
8175
- const namespace = resolveImageNamespace(state);
8176
- const imageName = deployableUnitImageName(typedUnit);
8177
- const envKey = deployableUnitImageTagKey(typedUnit);
8178
- const requested = tag.trim();
8179
- let resolvedTag = requested;
8180
- if (requested === "" || requested.toLowerCase() === "latest") try {
8181
- resolvedTag = await resolveLatestImageTag(namespace, imageName);
8182
- } catch (e) {
8183
- const msg = e instanceof Error ? e.message : String(e);
8184
- throw new Error(`Cannot resolve "latest" to a concrete release for ${typedUnit}: ${msg}. Check your network connection or select a specific version.`);
8185
- }
8186
- assertNotUnconfirmedUnitDowngrade(state, typedUnit, resolvedTag, opts.confirmDowngrade ?? false);
8187
- const dockerTag = extractDockerTagFromReleaseTag(resolvedTag);
8188
- if (namespace === "openpalm") {
8189
- if (!await isDockerImageTagPublished(namespace, imageName, dockerTag)) throw new Error(`Refusing to pin ${namespace}/${imageName}:${dockerTag}: tag is not published. stack.env was left unchanged.`);
8190
- }
8191
- const stackEnvPath = `${state.stashDir}/env/stack.env`;
8192
- writeFileSync(stackEnvPath, mergeEnvContent(existsSync(stackEnvPath) ? readFileSync(stackEnvPath, "utf-8") : "", { [envKey]: dockerTag }));
8193
- const composeOpts = buildComposeOptions(state);
8194
- const pullResult = await composePull(composeOpts);
8195
- if (!pullResult.ok) throw new Error(`Failed to pull images: ${pullResult.stderr}`);
8196
- const services = await buildManagedServices(state);
8197
- const upResult = await composeUp({
8198
- ...composeOpts,
8199
- services,
8200
- forceRecreate: true,
8201
- removeOrphans: true
8202
- });
8203
- if (!upResult.ok) throw new Error(`Images pulled but failed to recreate containers: ${upResult.stderr}`);
8204
- return {
8205
- imageTag: dockerTag,
8206
- namespace,
8207
- backupDir: null,
8208
- assetsUpdated: [],
8209
- restarted: services,
8210
7851
  warnings: []
8211
7852
  };
8212
7853
  });
@@ -8517,7 +8158,8 @@ function parseComposePsOutput(stdout) {
8517
8158
  return results;
8518
8159
  }
8519
8160
  function resolveImageTag(state) {
8520
- return parseEnvFile(`${state.stashDir}/env/stack.env`).OP_IMAGE_TAG ?? "";
8161
+ const env = parseEnvFile(`${state.stashDir}/env/stack.env`);
8162
+ return env.OP_ASSISTANT_VERSION ?? env.OP_IMAGE_TAG ?? "";
8521
8163
  }
8522
8164
  async function missingServiceImages(composeOpts, services) {
8523
8165
  if (services.length === 0) return [];
@@ -9393,71 +9035,6 @@ async function validateProposedState(state) {
9393
9035
  };
9394
9036
  }
9395
9037
  //#endregion
9396
- //#region ../lib/src/control-plane/npm-registry.ts
9397
- /**
9398
- * npm registry lookups — latest version + version list for any npm package.
9399
- *
9400
- * The admin UI's "Admin interface" picker (@openpalm/ui) and the platform
9401
- * latest-version check (@openpalm/lib) both read from the npm registry. Keeping
9402
- * these helpers in lib (not duplicated in the UI) follows the shared control-
9403
- * plane library rule: both CLI and admin import portable lookups from
9404
- * `@openpalm/lib`.
9405
- *
9406
- * Uses the Web Platform `fetch` built-in — no third-party deps.
9407
- */
9408
- var NPM_REGISTRY = "https://registry.npmjs.org";
9409
- var NPM_TIMEOUT_MS = 8e3;
9410
- async function fetchNpmPackument(packageName) {
9411
- let response;
9412
- try {
9413
- response = await fetch(`${NPM_REGISTRY}/${packageName}`, {
9414
- headers: {
9415
- "User-Agent": "openpalm-admin/1.0",
9416
- Accept: "application/json"
9417
- },
9418
- signal: AbortSignal.timeout(NPM_TIMEOUT_MS)
9419
- });
9420
- } catch (e) {
9421
- throw new Error(`Failed to query npm registry: ${e instanceof Error ? e.message : String(e)}`);
9422
- }
9423
- if (response.status === 404) return {};
9424
- if (!response.ok) throw new Error(`npm registry lookup failed (${response.status})`);
9425
- return await response.json();
9426
- }
9427
- /**
9428
- * Resolve the latest published version of an npm package from its dist-tags.
9429
- *
9430
- * `distTag` defaults to `'latest'`; pass `{ allowPrerelease: true }` (or
9431
- * `{ distTag: 'next' }`) to read the prerelease channel. Returns `null` when the
9432
- * package exists but the requested dist-tag is absent.
9433
- */
9434
- async function resolveLatestNpmVersion(packageName, opts = {}) {
9435
- const distTag = opts.distTag ?? (opts.allowPrerelease ? "next" : "latest");
9436
- const version = ((await fetchNpmPackument(packageName))["dist-tags"] ?? {})[distTag];
9437
- return typeof version === "string" ? version : null;
9438
- }
9439
- /**
9440
- * List published npm versions for a package, newest-first by publish time.
9441
- *
9442
- * Mirrors the shape the admin UI's `@openpalm/ui` picker expects. Returns at
9443
- * most `max` entries (default 20). A 404 (package not yet published) yields an
9444
- * empty list.
9445
- */
9446
- async function listNpmVersions(packageName, opts = {}) {
9447
- const { max = 20 } = opts;
9448
- const packument = await fetchNpmPackument(packageName);
9449
- const distTags = packument["dist-tags"] ?? {};
9450
- const versionToTag = /* @__PURE__ */ new Map();
9451
- for (const [tag, version] of Object.entries(distTags)) versionToTag.set(version, tag);
9452
- const time = packument.time ?? {};
9453
- return Object.keys(packument.versions ?? {}).map((version) => ({
9454
- version,
9455
- prerelease: version.includes("-"),
9456
- publishedAt: time[version] ?? null,
9457
- distTag: versionToTag.get(version) ?? null
9458
- })).sort((a, b) => (b.publishedAt ?? "").localeCompare(a.publishedAt ?? "")).slice(0, max);
9459
- }
9460
- //#endregion
9461
9038
  //#region ../lib/src/control-plane/markdown-task.ts
9462
9039
  /**
9463
9040
  * AKM task parser.
@@ -10436,7 +10013,8 @@ async function performSetup(input, opts) {
10436
10013
  try {
10437
10014
  const systemEnvForAkm = existsSync(`${state.stashDir}/env/stack.env`) ? readFileSync(`${state.stashDir}/env/stack.env`, "utf-8") : "";
10438
10015
  const akmUpdates = {};
10439
- Object.assign(akmUpdates, buildPlatformImageTagEnv(imageTag && imageTag.trim() ? imageTag.trim() : DEFAULT_IMAGE_TAG));
10016
+ const requestedTag = imageTag && imageTag.trim() ? imageTag.trim() : "latest";
10017
+ for (const key of SERVICE_VERSION_KEYS) akmUpdates[key] = requestedTag;
10440
10018
  if (Object.keys(akmUpdates).length > 0) writeFileAtomic(`${state.stashDir}/env/stack.env`, mergeEnvContent(systemEnvForAkm, akmUpdates), 384);
10441
10019
  if (llm || embedding) {
10442
10020
  const akmConfigDir = join(state.configDir, "akm");
@@ -10892,5 +10470,5 @@ function collectBindAddressWarnings(env) {
10892
10470
  return warnings;
10893
10471
  }
10894
10472
 
10895
- export { ensureOpenCodeSystemConfig as $, AKM_USER_ENV_REF as A, BackupSpaceError as B, CORE_SERVICES as C, DowngradeConfirmationRequired as D, composeStats as E, composeStop as F, composeUp as G, createLogger as H, INSTALL_LOCK_STALE_AFTER_MS as I, createOpenCodeClient as J, createState as K, deleteUserEnvKey as L, MigrationError as M, deriveLaunchStatus as N, deriveLocalStackState as O, PLATFORM_VERSION as P, detectGpu as Q, detectHostOpenCode as R, detectLocalProviders as S, detectRuntime as T, disableHostAkmSharing as U, dismissSecretStripNotice as V, enableHostAkmSharing as W, ensureAkmUserEnv as X, ensureHomeDirs as Y, ensureMigrated as Z, ensureOpenCodeConfig as _, addonProfileId as a, runDeploy as a$, ensureReleaseMigrated as a0, ensureSecrets as a1, executeAutomation as a2, fetchProviderModels as a3, formatForDisplay as a4, getAddonProfileAvailability as a5, getAddonProfileSelection as a6, getAddonProfiles as a7, getAddonServiceNames as a8, getAkmStats as a9, performSetup as aA, performUpgrade as aB, pruneBackupDirs as aC, readAutomationLogs as aD, readDeployJournal as aE, readSecret as aF, readSecretFile as aG, readSecretStripNotice as aH, readStackEnv as aI, readStackRuntimeEnv as aJ, readStackSecretEnv as aK, readTaskFile as aL, readUserEnvFile as aM, recommendSetup as aN, removeSecretFile as aO, removeTaskFile as aP, resolveComposeProjectName as aQ, resolveDataDir as aR, resolveDefaultMigrateTarget as aS, resolveDeployJournalPath as aT, resolveEffectivePlatformImageTag as aU, resolveLatestImageTag as aV, resolveLatestImageTagForCurrentMajor as aW, resolveLatestNpmVersion as aX, resolveRuntimeFiles as aY, resolveStackDir as aZ, runAssistantAkmCommand as a_, getDockerEvents as aa, getHostAkmSharingStatus as ab, getRegistryAddonConfig as ac, hostAkmStashPath as ad, importHostOpenCode as ae, initializeStateSecrets as af, inspectInstallLock as ag, isAllowedService as ah, isComparableSemver as ai, isDeployableUnit as aj, isHostAkmAvailable as ak, isPrerelease as al, isSetupComplete as am, listAssistantCliTools as an, listAvailableAddonIds as ao, listBackupDirs as ap, listDockerImageTags as aq, listEnabledAddonIds as ar, listNpmVersions as as, listSecretFiles as at, loadAutomations as au, mapDockerError as av, markSetupComplete as aw, parseComposeStderr as ax, parseEnvFile as ay, patchSecretsEnvFile as az, annotateAddonProfileAvailability as b, seedUiBuild as b0, setAddonEnabled as b1, setAddonProfileSelection as b2, summarizeBackups as b3, summarizeComposeStderr as b4, unlockInstallLock as b5, useExistingProviderForAssistantCli as b6, validateProposedState as b7, writeFileAtomic as b8, writeRuntimeFiles as b9, writeSecretFile as ba, writeStackSecretEnv as bb, writeTaskFile as bc, writeUserEnvKey as bd, writeVoiceVars as be, applyInstall as c, applyTagChange as d, applyUninstall as e, applyUnitImageTagChange as f, applyUpdate as g, assertSafeSecretFilename as h, assertSafeTaskFilename as i, authJsonPath as j, backupSetupInputs as k, buildAkmEndpoint as l, buildAkmEnv as m, buildComposeOptions as n, buildManagedServices as o, checkDocker as p, checkDockerCompose as q, classifyLocalInstall as r, collectBindAddressWarnings as s, composeDown as t, composeLogs as u, composePreflight as v, composePs as w, composePull as x, composeRestart as y, composeStart as z };
10896
- //# sourceMappingURL=src-CqA6lZdE.js.map
10473
+ export { ensureSecrets as $, AKM_USER_ENV_REF as A, BackupSpaceError as B, CORE_SERVICES as C, composeStop as D, composeUp as E, createLogger as F, createOpenCodeClient as G, createState as H, INSTALL_LOCK_STALE_AFTER_MS as I, deleteUserEnvKey as J, deriveLaunchStatus as K, deriveLocalStackState as L, MigrationError as M, detectGpu as N, detectHostOpenCode as O, PLATFORM_VERSION as P, detectLocalProviders as Q, detectRuntime as R, disableHostAkmSharing as S, dismissSecretStripNotice as T, enableHostAkmSharing as U, ensureAkmUserEnv as V, ensureHomeDirs as W, ensureMigrated as X, ensureOpenCodeConfig as Y, ensureOpenCodeSystemConfig as Z, ensureReleaseMigrated as _, ALL_VERSION_KEYS as a, writeSecretFile as a$, executeAutomation as a0, fetchProviderModels as a1, formatForDisplay as a2, getAddonProfileAvailability as a3, getAddonProfileSelection as a4, getAddonProfiles as a5, getAddonServiceNames as a6, getAkmStats as a7, getDockerEvents as a8, getHostAkmSharingStatus as a9, readSecretStripNotice as aA, readStackEnv as aB, readStackRuntimeEnv as aC, readStackSecretEnv as aD, readTaskFile as aE, readUserEnvFile as aF, readVersions as aG, recommendSetup as aH, removeSecretFile as aI, removeTaskFile as aJ, resolveComposeProjectName as aK, resolveDataDir as aL, resolveDeployJournalPath as aM, resolveRuntimeFiles as aN, resolveStackDir as aO, runAssistantAkmCommand as aP, runDeploy as aQ, seedUiBuild as aR, setAddonEnabled as aS, setAddonProfileSelection as aT, summarizeBackups as aU, summarizeComposeStderr as aV, unlockInstallLock as aW, useExistingProviderForAssistantCli as aX, validateProposedState as aY, writeFileAtomic as aZ, writeRuntimeFiles as a_, getRegistryAddonConfig as aa, hostAkmStashPath as ab, importHostOpenCode as ac, initializeStateSecrets as ad, inspectInstallLock as ae, isAllowedService as af, isHostAkmAvailable as ag, isPrerelease as ah, isSetupComplete as ai, listAssistantCliTools as aj, listAvailableAddonIds as ak, listBackupDirs as al, listEnabledAddonIds as am, listSecretFiles as an, loadAutomations as ao, mapDockerError as ap, markSetupComplete as aq, parseComposeStderr as ar, patchSecretsEnvFile as as, performSetup as at, performUpgrade as au, pruneBackupDirs as av, readAutomationLogs as aw, readDeployJournal as ax, readSecret as ay, readSecretFile as az, addonProfileId as b, writeStackSecretEnv as b0, writeTaskFile as b1, writeUserEnvKey as b2, writeVersions as b3, writeVoiceVars as b4, annotateAddonProfileAvailability as c, applyInstall as d, applyUninstall as e, applyUpdate as f, assertSafeSecretFilename as g, assertSafeTaskFilename as h, authJsonPath as i, backupSetupInputs as j, buildAkmEndpoint as k, buildAkmEnv as l, buildComposeOptions as m, buildManagedServices as n, checkDocker as o, checkDockerCompose as p, classifyLocalInstall as q, collectBindAddressWarnings as r, composeDown as s, composeLogs as t, composePreflight as u, composePs as v, composePull as w, composeRestart as x, composeStart as y, composeStats as z };
10474
+ //# sourceMappingURL=src-DPd0Zos1.js.map