@xopcai/xopc 0.0.145 → 0.0.147

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/README.md +2 -2
  2. package/dist/browser-ext/manifest.json +1 -1
  3. package/dist/extensions/demo-memory/src/index.js +6 -4
  4. package/dist/extensions/demo-memory/src/index.js.map +1 -1
  5. package/dist/extensions/telegram/xopc.extension.json +1 -1
  6. package/dist/gateway/static/root/assets/Combination-14nmIgxH.js +41 -0
  7. package/dist/gateway/static/root/assets/activity-store-DXeSSlw1.js +1 -0
  8. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BEUxdhZx.js → agent-avatar-dicebear-CFdJKSjY.js} +1 -1
  9. package/dist/gateway/static/root/assets/agents-DKjbRpbA.js +2 -0
  10. package/dist/gateway/static/root/assets/api-Bs69B5zA.js +1 -0
  11. package/dist/gateway/static/root/assets/{app-management-settings-panel-CRHSZJWi.js → app-management-settings-panel-ag1ViXT_.js} +1 -1
  12. package/dist/gateway/static/root/assets/{appearance-settings-BunADYJb.js → appearance-settings-C6iMpwOM.js} +1 -1
  13. package/dist/gateway/static/root/assets/apps-page-CpX3lBFF.js +1 -0
  14. package/dist/gateway/static/root/assets/{archive-plugin-B6vTkH2A.js → archive-plugin-Dwi3mIBy.js} +1 -1
  15. package/dist/gateway/static/root/assets/{attachment-load-BjZXzaNv.js → attachment-load-BaCDoq40.js} +1 -1
  16. package/dist/gateway/static/root/assets/{automation-suggestion-card-ZDA-Stg1.js → automation-suggestion-card-CwqtFgnw.js} +1 -1
  17. package/dist/gateway/static/root/assets/automations-page-DlupOxFQ.js +6 -0
  18. package/dist/gateway/static/root/assets/{binary-plugins-DYZfLvPz.js → binary-plugins-DoAYhsxa.js} +1 -1
  19. package/dist/gateway/static/root/assets/{block-editor-C3MUlYC9.js → block-editor-Bw72pO7S.js} +31 -31
  20. package/dist/gateway/static/root/assets/browser-settings-page-BwLoUBcZ.js +8 -0
  21. package/dist/gateway/static/root/assets/capability-presets-api-vdbAR65Q.js +1 -0
  22. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BAsKbJgm.js +2 -0
  23. package/dist/gateway/static/root/assets/{channel-recipient-api-fTlTnWB4.js → channel-recipient-api-rTG26jpV.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-settings-CxFWy0cE.js +1 -0
  25. package/dist/gateway/static/root/assets/channels-status-swr-OKlqTtKJ.js +1 -0
  26. package/dist/gateway/static/root/assets/{connector-logo-BVFNT2zW.js → connector-logo-DIMP4NWY.js} +1 -1
  27. package/dist/gateway/static/root/assets/connectors-page-BjQQwX62.js +2 -0
  28. package/dist/gateway/static/root/assets/{desktop-pet-_jUmoXd3.js → desktop-pet-kQq2e0BN.js} +1 -1
  29. package/dist/gateway/static/root/assets/{desktop-pet-settings-DwGOy4AQ.js → desktop-pet-settings-B6vtozMY.js} +1 -1
  30. package/dist/gateway/static/root/assets/{directory-picker-path-field-akvF0F-u.js → directory-picker-path-field-Dn5-e3v4.js} +1 -1
  31. package/dist/gateway/static/root/assets/dist-C230izr8.js +1 -0
  32. package/dist/gateway/static/root/assets/dist-CxGUk8J-.js +1 -0
  33. package/dist/gateway/static/root/assets/dreaming-settings-BzwIujPG.js +3 -0
  34. package/dist/gateway/static/root/assets/extension-debug-page-D_e_hsEy.js +1 -0
  35. package/dist/gateway/static/root/assets/{extension-page-CwWktRNz.js → extension-page-D15CWHBd.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-settings-page-CuggWOIl.js → extension-settings-page-D4P0n1om.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-config-api-B7sxIbza.js → gateway-config-api-B4qZctjG.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-settings-DIv0eKMf.js → gateway-settings-BvndV7TP.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-startup-retry-DtoLihQE.js → gateway-startup-retry-BpgMunEb.js} +1 -1
  40. package/dist/gateway/static/root/assets/{goal-create-dialog-C4Kw0mfS.js → goal-create-dialog-DrVHKXHq.js} +1 -1
  41. package/dist/gateway/static/root/assets/goal-detail-page-PHlCwv68.js +4 -0
  42. package/dist/gateway/static/root/assets/{goals-config-api-B0jm5JaA.js → goals-config-api-B6YJB_ct.js} +1 -1
  43. package/dist/gateway/static/root/assets/goals-page-Hg9uyO6e.js +2 -0
  44. package/dist/gateway/static/root/assets/{goals-settings-N5_iL7es.js → goals-settings-BROWCIcL.js} +1 -1
  45. package/dist/gateway/static/root/assets/{heartbeat-settings-XzH3lbRR.js → heartbeat-settings-CoCwIOIg.js} +1 -1
  46. package/dist/gateway/static/root/assets/index-CxkNzw3e.js +259 -0
  47. package/dist/gateway/static/root/assets/index-DjCSOyaN.css +1 -0
  48. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-Bm_AIYQ7.js +1 -0
  49. package/dist/gateway/static/root/assets/local-app-workbench-page-BJWFcxwG.js +2 -0
  50. package/dist/gateway/static/root/assets/local-apps-page-BsiZMrEf.js +1 -0
  51. package/dist/gateway/static/root/assets/{locale-store-CiM-D9jA.js → locale-store-Bp8joZck.js} +1 -1
  52. package/dist/gateway/static/root/assets/logs-page-DOmK61ey.js +7 -0
  53. package/dist/gateway/static/root/assets/{markdown-split-5rJx5flj.js → markdown-split-Dy7QpaAz.js} +1 -1
  54. package/dist/gateway/static/root/assets/{media-plugins-DYXccwAd.js → media-plugins-3Lxliy9D.js} +1 -1
  55. package/dist/gateway/static/root/assets/messages-CQGpD-dC.js +5 -0
  56. package/dist/gateway/static/root/assets/models-hub-panel-DGCZom4o.js +2 -0
  57. package/dist/gateway/static/root/assets/{notes-page-BgLyndCO.js → notes-page-BJtT4vSf.js} +1 -1
  58. package/dist/gateway/static/root/assets/notes-workbench-B_bN7cOR.js +4 -0
  59. package/dist/gateway/static/root/assets/{page-tabs-6Al9_sGz.js → page-tabs-DKB6RDre.js} +1 -1
  60. package/dist/gateway/static/root/assets/{preview-open-alternatives-Cm3G72Hv.js → preview-open-alternatives-Br_YhYHp.js} +1 -1
  61. package/dist/gateway/static/root/assets/project-detail-page-Dq8JouJj.js +1 -0
  62. package/dist/gateway/static/root/assets/projects-page-DvfL7fSe.js +1 -0
  63. package/dist/gateway/static/root/assets/remote-access-hub-DqwMXSXP.js +1 -0
  64. package/dist/gateway/static/root/assets/{save-bar-controls-BYtfzu_F.js → save-bar-controls-BgIE9BBh.js} +1 -1
  65. package/dist/gateway/static/root/assets/{schedule-field-CvIRc6yK.js → schedule-field-BXDP-oMz.js} +1 -1
  66. package/dist/gateway/static/root/assets/{schema-form-CQuKx0n7.js → schema-form-Dhv-SmjG.js} +1 -1
  67. package/dist/gateway/static/root/assets/sessions-page-B_mOZkQk.js +1 -0
  68. package/dist/gateway/static/root/assets/settings-advanced-gate-BHGmH6YS.js +1 -0
  69. package/dist/gateway/static/root/assets/{settings-collapsible-section-CF3HHM-t.js → settings-collapsible-section-CUTExnlK.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-form-section-CwWjoRN6.js → settings-form-section-CmnDhsf0.js} +1 -1
  71. package/dist/gateway/static/root/assets/{settings-loading-skeleton-aUFmJa13.js → settings-loading-skeleton-B79dq-XY.js} +1 -1
  72. package/dist/gateway/static/root/assets/{settings-page-B2UUU9TF.js → settings-page-Db8uAv3X.js} +1 -1
  73. package/dist/gateway/static/root/assets/{settings-page-layout-DqpbTWqI.js → settings-page-layout-DaFwstQw.js} +1 -1
  74. package/dist/gateway/static/root/assets/setup-status-panel-BUSEj0KK.js +1 -0
  75. package/dist/gateway/static/root/assets/{share-preview-page-BOhlPsS1.js → share-preview-page-Bi00uXzV.js} +1 -1
  76. package/dist/gateway/static/root/assets/shares-settings-DzsTYfuX.js +1 -0
  77. package/dist/gateway/static/root/assets/skill-reload-api-DSsdU081.js +1 -0
  78. package/dist/gateway/static/root/assets/skills-page-DeB1tQZL.js +2 -0
  79. package/dist/gateway/static/root/assets/{system-settings-panel-CWxSvuwD.js → system-settings-panel-Cxaph7hW.js} +1 -1
  80. package/dist/gateway/static/root/assets/{theme-store-C9Dxcppm.js → theme-store-eCTN1RpG.js} +1 -1
  81. package/dist/gateway/static/root/assets/{typed-models-lib-qROAvqTw.js → typed-models-lib-CcZ_tyFY.js} +1 -1
  82. package/dist/gateway/static/root/assets/{use-channel-catalog-DE9cpn4G.js → use-channel-catalog-C4PWbNoi.js} +1 -1
  83. package/dist/gateway/static/root/assets/user-context-page-QTVMx_hG.js +1 -0
  84. package/dist/gateway/static/root/assets/{user-profile-fields-editor-CWxc0ghP.js → user-profile-fields-editor-CPOO9Jz5.js} +1 -1
  85. package/dist/gateway/static/root/assets/{user-profile-settings-panel-DW-Up6vt.js → user-profile-settings-panel-C8cgtSF7.js} +1 -1
  86. package/dist/gateway/static/root/assets/{utils-D53uRXVr.js → utils-CiZK2KwH.js} +1 -1
  87. package/dist/gateway/static/root/assets/voice-api-key-field-b-YZtvUu.js +1 -0
  88. package/dist/gateway/static/root/assets/work-discovery-page-4zVDOl2G.js +1 -0
  89. package/dist/gateway/static/root/assets/work-item-detail-page-CHe2tfkc.js +1 -0
  90. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-D_x9ELJp.js → workflow-run-setup-panel-8SLCYeXE.js} +2 -2
  91. package/dist/gateway/static/root/assets/workflows-page-DEOFqiWn.js +11 -0
  92. package/dist/gateway/static/root/index.html +10 -9
  93. package/dist/package.js +1 -1
  94. package/dist/src/activity/types.d.ts +1 -1
  95. package/dist/src/agent/agent-instance-gateway.d.ts +1 -1
  96. package/dist/src/agent/agent-manager.d.ts +1 -1
  97. package/dist/src/agent/agent-manager.js +5 -4
  98. package/dist/src/agent/agent-manager.js.map +1 -1
  99. package/dist/src/agent/background-review/coordinator.js +0 -1
  100. package/dist/src/agent/background-review/coordinator.js.map +1 -1
  101. package/dist/src/agent/background-review/settings.d.ts +1 -1
  102. package/dist/src/agent/background-review/settings.js +10 -17
  103. package/dist/src/agent/background-review/settings.js.map +1 -1
  104. package/dist/src/agent/bootstrap/filter-bootstrap-files.d.ts +1 -1
  105. package/dist/src/agent/bootstrap/filter-bootstrap-files.js +1 -1
  106. package/dist/src/agent/bootstrap/filter-bootstrap-files.js.map +1 -1
  107. package/dist/src/agent/bootstrap/load-bootstrap-files.js +2 -3
  108. package/dist/src/agent/bootstrap/load-bootstrap-files.js.map +1 -1
  109. package/dist/src/agent/code-intelligence/binary.js +1 -1
  110. package/dist/src/agent/context/project-context.d.ts +14 -0
  111. package/dist/src/agent/context/project-context.js +23 -1
  112. package/dist/src/agent/context/project-context.js.map +1 -1
  113. package/dist/src/agent/context/workspace-templates/AGENTS.md +1 -1
  114. package/dist/src/agent/context/workspace.d.ts +1 -2
  115. package/dist/src/agent/context/workspace.js +2 -4
  116. package/dist/src/agent/context/workspace.js.map +1 -1
  117. package/dist/src/agent/embedded/run-for-session.js +1 -2
  118. package/dist/src/agent/embedded/run-for-session.js.map +1 -1
  119. package/dist/src/agent/embedded/run-turn.js +6 -1
  120. package/dist/src/agent/embedded/run-turn.js.map +1 -1
  121. package/dist/src/agent/embedded/types.d.ts +17 -0
  122. package/dist/src/agent/memory/builtin-memory-store.d.ts +2 -2
  123. package/dist/src/agent/memory/builtin-memory-store.js +2 -2
  124. package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
  125. package/dist/src/agent/memory/builtin-provider.d.ts +1 -3
  126. package/dist/src/agent/memory/builtin-provider.js +21 -48
  127. package/dist/src/agent/memory/builtin-provider.js.map +1 -1
  128. package/dist/src/agent/memory/context/planner.js +48 -9
  129. package/dist/src/agent/memory/context/planner.js.map +1 -1
  130. package/dist/src/agent/memory/context/types.d.ts +7 -1
  131. package/dist/src/agent/memory/context-fence.js +1 -1
  132. package/dist/src/agent/memory/context-fence.js.map +1 -1
  133. package/dist/src/agent/memory/create-memory-manager.js +2 -9
  134. package/dist/src/agent/memory/create-memory-manager.js.map +1 -1
  135. package/dist/src/agent/memory/dreaming/config.js +5 -10
  136. package/dist/src/agent/memory/dreaming/config.js.map +1 -1
  137. package/dist/src/agent/memory/dreaming/promotion-lifecycle.js +2 -2
  138. package/dist/src/agent/memory/dreaming/promotion-lifecycle.js.map +1 -1
  139. package/dist/src/agent/memory/dreaming/scope.d.ts +2 -3
  140. package/dist/src/agent/memory/dreaming/scope.js +8 -8
  141. package/dist/src/agent/memory/dreaming/scope.js.map +1 -1
  142. package/dist/src/agent/memory/manager.d.ts +1 -5
  143. package/dist/src/agent/memory/manager.js +2 -23
  144. package/dist/src/agent/memory/manager.js.map +1 -1
  145. package/dist/src/agent/memory/memory-config.d.ts +3 -3
  146. package/dist/src/agent/memory/memory-config.js +9 -14
  147. package/dist/src/agent/memory/memory-config.js.map +1 -1
  148. package/dist/src/agent/memory/types.d.ts +9 -5
  149. package/dist/src/agent/memory/understanding/service.js +21 -8
  150. package/dist/src/agent/memory/understanding/service.js.map +1 -1
  151. package/dist/src/agent/memory/understanding/types.d.ts +5 -0
  152. package/dist/src/agent/memory/user-context-coordinator.d.ts +1 -1
  153. package/dist/src/agent/memory/user-context-coordinator.js +6 -2
  154. package/dist/src/agent/memory/user-context-coordinator.js.map +1 -1
  155. package/dist/src/agent/orchestration/agent-orchestrator.js +2 -2
  156. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  157. package/dist/src/agent/prompt/memory/index.d.ts +1 -2
  158. package/dist/src/agent/prompt/memory/index.js +6 -7
  159. package/dist/src/agent/prompt/memory/index.js.map +1 -1
  160. package/dist/src/agent/prompt/sections/tooling.js +1 -1
  161. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  162. package/dist/src/agent/service/direct-turn-helpers.js +13 -2
  163. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  164. package/dist/src/agent/tools/curated-memory-tool.js +4 -4
  165. package/dist/src/agent/tools/curated-memory-tool.js.map +1 -1
  166. package/dist/src/agent/tools/factory.d.ts +1 -1
  167. package/dist/src/agent/tools/factory.js +2 -2
  168. package/dist/src/agent/tools/factory.js.map +1 -1
  169. package/dist/src/agent/tools/memory-tool.js +1 -1
  170. package/dist/src/agent/tools/memory-tool.js.map +1 -1
  171. package/dist/src/agent/workflow/workflow-child-tools.js +2 -3
  172. package/dist/src/agent/workflow/workflow-child-tools.js.map +1 -1
  173. package/dist/src/agent/workspace-runtime/registry.d.ts +5 -5
  174. package/dist/src/agent/workspace-runtime/registry.js +6 -11
  175. package/dist/src/agent/workspace-runtime/registry.js.map +1 -1
  176. package/dist/src/agent-manifest/index.js +2 -2
  177. package/dist/src/agent-manifest/prompt.js +1 -7
  178. package/dist/src/agent-manifest/prompt.js.map +1 -1
  179. package/dist/src/agent-manifest/schema.d.ts +0 -598
  180. package/dist/src/agent-manifest/schema.js +2 -143
  181. package/dist/src/agent-manifest/schema.js.map +1 -1
  182. package/dist/src/agent-manifest/validator.js +0 -12
  183. package/dist/src/agent-manifest/validator.js.map +1 -1
  184. package/dist/src/agent-runtime/index.js +1 -1
  185. package/dist/src/agent-runtime/memory-runtime.d.ts +2 -2
  186. package/dist/src/agent-runtime/memory-runtime.js +8 -7
  187. package/dist/src/agent-runtime/memory-runtime.js.map +1 -1
  188. package/dist/src/agent-runtime/runtime-profile.d.ts +2 -0
  189. package/dist/src/agent-runtime/runtime-profile.js +2 -2
  190. package/dist/src/agent-runtime/runtime-profile.js.map +1 -1
  191. package/dist/src/chat-commands/agent-edit.js +1 -2
  192. package/dist/src/chat-commands/agent-edit.js.map +1 -1
  193. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  194. package/dist/src/cli/commands/init.js +0 -22
  195. package/dist/src/cli/commands/init.js.map +1 -1
  196. package/dist/src/cli/templates.d.ts +1 -1
  197. package/dist/src/cli/templates.js +1 -16
  198. package/dist/src/cli/templates.js.map +1 -1
  199. package/dist/src/commands/agents.config.js +0 -10
  200. package/dist/src/commands/agents.config.js.map +1 -1
  201. package/dist/src/config/agent-profile.js +1 -1
  202. package/dist/src/config/index.js +2 -2
  203. package/dist/src/config/paths.d.ts +0 -1
  204. package/dist/src/config/paths.js +1 -2
  205. package/dist/src/config/paths.js.map +1 -1
  206. package/dist/src/config/schema.d.ts +118 -532
  207. package/dist/src/config/schema.js +32 -26
  208. package/dist/src/config/schema.js.map +1 -1
  209. package/dist/src/extensions/loader.js +2 -1
  210. package/dist/src/extensions/loader.js.map +1 -1
  211. package/dist/src/gateway/agents-admin.d.ts +0 -2
  212. package/dist/src/gateway/agents-admin.js +1 -7
  213. package/dist/src/gateway/agents-admin.js.map +1 -1
  214. package/dist/src/gateway/capability-presets-admin.d.ts +0 -2
  215. package/dist/src/gateway/capability-presets-admin.js.map +1 -1
  216. package/dist/src/gateway/chat-stream/mapper.js +26 -0
  217. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  218. package/dist/src/gateway/chat-stream/protocol.d.ts +16 -1
  219. package/dist/src/gateway/dreaming-automation-reconciler.d.ts +0 -1
  220. package/dist/src/gateway/dreaming-automation-reconciler.js +41 -63
  221. package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -1
  222. package/dist/src/gateway/heartbeat/service.js +1 -1
  223. package/dist/src/gateway/hono/app.js +3 -1
  224. package/dist/src/gateway/hono/app.js.map +1 -1
  225. package/dist/src/gateway/hono/lib/config-payload.d.ts +0 -130
  226. package/dist/src/gateway/hono/lib/config-payload.js +0 -1
  227. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  228. package/dist/src/gateway/hono/routes/agents.js +6 -12
  229. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  230. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +6 -0
  231. package/dist/src/gateway/hono/routes/auth-registry-extensions.js.map +1 -1
  232. package/dist/src/gateway/hono/routes/capability-presets.js +2 -2
  233. package/dist/src/gateway/hono/routes/capability-presets.js.map +1 -1
  234. package/dist/src/gateway/hono/routes/dreaming.js +9 -20
  235. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  236. package/dist/src/gateway/hono/routes/index.js +4 -0
  237. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  238. package/dist/src/gateway/hono/routes/local-apps.d.ts +5 -0
  239. package/dist/src/gateway/hono/routes/local-apps.js +99 -0
  240. package/dist/src/gateway/hono/routes/local-apps.js.map +1 -0
  241. package/dist/src/gateway/hono/routes/memory.js +48 -65
  242. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  243. package/dist/src/gateway/hono/routes/projects.js +2 -2
  244. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  245. package/dist/src/gateway/hono/routes/work-discovery.d.ts +3 -0
  246. package/dist/src/gateway/hono/routes/work-discovery.js +150 -0
  247. package/dist/src/gateway/hono/routes/work-discovery.js.map +1 -0
  248. package/dist/src/gateway/hono/routes/you.d.ts +3 -0
  249. package/dist/src/gateway/hono/routes/you.js +358 -91
  250. package/dist/src/gateway/hono/routes/you.js.map +1 -1
  251. package/dist/src/gateway/service.d.ts +3 -0
  252. package/dist/src/gateway/service.js +12 -0
  253. package/dist/src/gateway/service.js.map +1 -1
  254. package/dist/src/heartbeat/index.js +1 -1
  255. package/dist/src/knowledge/connected-knowledge-pipeline.js +9 -5
  256. package/dist/src/knowledge/connected-knowledge-pipeline.js.map +1 -1
  257. package/dist/src/local-apps/acceptance.d.ts +30 -0
  258. package/dist/src/local-apps/acceptance.js +93 -0
  259. package/dist/src/local-apps/acceptance.js.map +1 -0
  260. package/dist/src/local-apps/index.d.ts +5 -0
  261. package/dist/src/local-apps/index.js +4 -0
  262. package/dist/src/local-apps/preview-runtime-bridge.d.ts +4 -0
  263. package/dist/src/local-apps/preview-runtime-bridge.js +171 -0
  264. package/dist/src/local-apps/preview-runtime-bridge.js.map +1 -0
  265. package/dist/src/local-apps/runtime-entry.d.ts +8 -0
  266. package/dist/src/local-apps/runtime-entry.js +25 -0
  267. package/dist/src/local-apps/runtime-entry.js.map +1 -0
  268. package/dist/src/local-apps/scaffold.d.ts +8 -0
  269. package/dist/src/local-apps/scaffold.js +122 -0
  270. package/dist/src/local-apps/scaffold.js.map +1 -0
  271. package/dist/src/local-apps/service.d.ts +37 -0
  272. package/dist/src/local-apps/service.js +553 -0
  273. package/dist/src/local-apps/service.js.map +1 -0
  274. package/dist/src/local-apps/store.d.ts +44 -0
  275. package/dist/src/local-apps/store.js +195 -0
  276. package/dist/src/local-apps/store.js.map +1 -0
  277. package/dist/src/local-apps/types.d.ts +105 -0
  278. package/dist/src/local-apps/types.js +1 -0
  279. package/dist/src/storage/sqlite/index.d.ts +3 -2
  280. package/dist/src/storage/sqlite/index.js +4 -3
  281. package/dist/src/storage/sqlite/memory-index-repository.d.ts +2 -3
  282. package/dist/src/storage/sqlite/memory-index-repository.js +16 -20
  283. package/dist/src/storage/sqlite/memory-index-repository.js.map +1 -1
  284. package/dist/src/storage/sqlite/memory-records-repository.d.ts +18 -10
  285. package/dist/src/storage/sqlite/memory-records-repository.js +79 -34
  286. package/dist/src/storage/sqlite/memory-records-repository.js.map +1 -1
  287. package/dist/src/storage/sqlite/memory-reference-consent-repository.d.ts +27 -0
  288. package/dist/src/storage/sqlite/memory-reference-consent-repository.js +109 -0
  289. package/dist/src/storage/sqlite/memory-reference-consent-repository.js.map +1 -0
  290. package/dist/src/storage/sqlite/migrations/038_user_owned_memory.sql +68 -0
  291. package/dist/src/storage/sqlite/migrations/039_memory_reference_consents.sql +19 -0
  292. package/dist/src/storage/sqlite/migrations/040_local_apps.sql +32 -0
  293. package/dist/src/storage/sqlite/migrations/041_local_app_release_lifecycle.sql +17 -0
  294. package/dist/src/storage/sqlite/migrations/042_work_discovery.sql +41 -0
  295. package/dist/src/storage/sqlite/migrations/043_local_app_acceptance_runs.sql +16 -0
  296. package/dist/src/storage/sqlite/migrations/044_repair_work_discovery_foreign_keys.sql +75 -0
  297. package/dist/src/storage/sqlite/migrations/045_extension_ui_grants.sql +13 -0
  298. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  299. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  300. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  301. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  302. package/dist/src/storage/sqlite/schema.js +1 -1
  303. package/dist/src/storage/sqlite/schema.sql +20 -0
  304. package/dist/src/user-context/config.d.ts +227 -0
  305. package/dist/src/user-context/config.js +158 -0
  306. package/dist/src/user-context/config.js.map +1 -0
  307. package/dist/src/user-context/import.d.ts +1 -1
  308. package/dist/src/user-context/import.js +6 -1
  309. package/dist/src/user-context/import.js.map +1 -1
  310. package/dist/src/user-context/owner.d.ts +5 -0
  311. package/dist/src/user-context/owner.js +9 -0
  312. package/dist/src/user-context/owner.js.map +1 -0
  313. package/dist/src/user-context/projection.d.ts +11 -9
  314. package/dist/src/user-context/projection.js +74 -47
  315. package/dist/src/user-context/projection.js.map +1 -1
  316. package/dist/src/user-context/runtime.d.ts +13 -0
  317. package/dist/src/user-context/runtime.js +36 -0
  318. package/dist/src/user-context/runtime.js.map +1 -0
  319. package/dist/src/work-discovery/analyzer.d.ts +11 -0
  320. package/dist/src/work-discovery/analyzer.js +171 -0
  321. package/dist/src/work-discovery/analyzer.js.map +1 -0
  322. package/dist/src/work-discovery/index.d.ts +5 -0
  323. package/dist/src/work-discovery/index.js +5 -0
  324. package/dist/src/work-discovery/probe.d.ts +12 -0
  325. package/dist/src/work-discovery/probe.js +335 -0
  326. package/dist/src/work-discovery/probe.js.map +1 -0
  327. package/dist/src/work-discovery/repository.d.ts +11 -0
  328. package/dist/src/work-discovery/repository.js +100 -0
  329. package/dist/src/work-discovery/repository.js.map +1 -0
  330. package/dist/src/work-discovery/service.d.ts +30 -0
  331. package/dist/src/work-discovery/service.js +387 -0
  332. package/dist/src/work-discovery/service.js.map +1 -0
  333. package/dist/src/work-discovery/types.d.ts +114 -0
  334. package/dist/src/work-discovery/types.js +1 -0
  335. package/dist/src/workflows/service/workflow-session-bridge.js +1 -1
  336. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  337. package/package.json +5 -3
  338. package/skills/engineering/build-xopc-local-app/SKILL.md +45 -0
  339. package/skills/engineering/build-xopc-local-app/references/app-contract.md +33 -0
  340. package/skills/engineering/build-xopc-local-app/scripts/validate-local-app.mjs +72 -0
  341. package/dist/gateway/static/root/assets/Combination-DolwnuKi.js +0 -41
  342. package/dist/gateway/static/root/assets/activity-center-store-3l9ahUqb.js +0 -1
  343. package/dist/gateway/static/root/assets/agents-1bpT0xRO.js +0 -2
  344. package/dist/gateway/static/root/assets/apps-page-Cc4JgVUQ.js +0 -1
  345. package/dist/gateway/static/root/assets/automations-page-mb0fdVpq.js +0 -6
  346. package/dist/gateway/static/root/assets/browser-settings-page-Bb0xhaMN.js +0 -8
  347. package/dist/gateway/static/root/assets/capability-presets-api-BV76yN9a.js +0 -1
  348. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CUcGKZqC.js +0 -2
  349. package/dist/gateway/static/root/assets/channels-settings-BlSDMGdy.js +0 -1
  350. package/dist/gateway/static/root/assets/channels-status-swr-CJauF1CW.js +0 -1
  351. package/dist/gateway/static/root/assets/connectors-page-CMgAFGvb.js +0 -2
  352. package/dist/gateway/static/root/assets/dist-C99RGfAH.js +0 -1
  353. package/dist/gateway/static/root/assets/dreaming-settings-BLetQiYY.js +0 -3
  354. package/dist/gateway/static/root/assets/extension-debug-page-Cof2ncxE.js +0 -1
  355. package/dist/gateway/static/root/assets/goal-detail-page-BMmzYpZL.js +0 -4
  356. package/dist/gateway/static/root/assets/goals-page-CGeT77PC.js +0 -2
  357. package/dist/gateway/static/root/assets/index-CSLF84-Q.css +0 -1
  358. package/dist/gateway/static/root/assets/index-I-ZCenVw.js +0 -259
  359. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-x_v0nrIi.js +0 -1
  360. package/dist/gateway/static/root/assets/logs-page-BSh1t8cD.js +0 -7
  361. package/dist/gateway/static/root/assets/messages-Cb1VMeqP.js +0 -5
  362. package/dist/gateway/static/root/assets/models-hub-panel-BNpTenAI.js +0 -2
  363. package/dist/gateway/static/root/assets/notes-workbench-teklkhcE.js +0 -4
  364. package/dist/gateway/static/root/assets/project-detail-page-CCB_dKoh.js +0 -1
  365. package/dist/gateway/static/root/assets/projects-page-VOAFAHYj.js +0 -1
  366. package/dist/gateway/static/root/assets/remote-access-hub-USYu64Ru.js +0 -1
  367. package/dist/gateway/static/root/assets/sessions-page-oGC8O5h_.js +0 -1
  368. package/dist/gateway/static/root/assets/settings-advanced-gate-D4rP66R1.js +0 -1
  369. package/dist/gateway/static/root/assets/setup-status-panel-Ck9keROI.js +0 -1
  370. package/dist/gateway/static/root/assets/shares-settings-BYLsCuqj.js +0 -1
  371. package/dist/gateway/static/root/assets/skill-reload-api-BNHUyVML.js +0 -1
  372. package/dist/gateway/static/root/assets/skills-page-CpXbQH4n.js +0 -2
  373. package/dist/gateway/static/root/assets/user-context-page-DbNEK4Yp.js +0 -1
  374. package/dist/gateway/static/root/assets/voice-api-key-field-Cs7MOrg0.js +0 -1
  375. package/dist/gateway/static/root/assets/work-item-detail-page-D1ziG1Pp.js +0 -1
  376. package/dist/gateway/static/root/assets/workflows-page-DHGV_n6i.js +0 -11
  377. package/dist/src/agent/context/workspace-templates/MEMORY.md +0 -33
  378. package/dist/src/agent/memory/access-policy.d.ts +0 -12
  379. package/dist/src/agent/memory/access-policy.js +0 -44
  380. package/dist/src/agent/memory/access-policy.js.map +0 -1
@@ -0,0 +1,553 @@
1
+ import { resolveStateDir } from "../config/paths-state.js";
2
+ import { createLogger } from "../utils/logger/index.js";
3
+ import { init_logger } from "../utils/logger.js";
4
+ import { init_paths, resolveExtensionsDir } from "../config/paths.js";
5
+ import { LocalAppStore } from "./store.js";
6
+ import { slugifyProjectName } from "../projects/project-store.js";
7
+ import { readLocalAppAcceptanceConfig } from "./acceptance.js";
8
+ import { LOCAL_APP_RUNTIME_ENTRY, LOCAL_APP_RUNTIME_SOURCE, legacyLocalAppRuntimeSource } from "./runtime-entry.js";
9
+ import { readLocalAppPermissions, scaffoldLocalApp } from "./scaffold.js";
10
+ import { basename, join, relative, resolve, sep } from "node:path";
11
+ import { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync } from "node:fs";
12
+ import { createHash, randomBytes } from "node:crypto";
13
+ //#region src/local-apps/service.ts
14
+ init_paths();
15
+ init_logger();
16
+ const log = createLogger("LocalApps");
17
+ const RELEASE_COPY_EXCLUDED_NAMES = new Set([".git", "node_modules"]);
18
+ const UI_ONLY_PERMISSIONS = new Set([
19
+ "theme",
20
+ "storage",
21
+ "notification"
22
+ ]);
23
+ function requireText(value, label) {
24
+ const trimmed = value.trim();
25
+ if (!trimmed) throw new Error(`${label} is required`);
26
+ return trimmed;
27
+ }
28
+ function extensionConfigRecord(config) {
29
+ return config.extensions && typeof config.extensions === "object" && !Array.isArray(config.extensions) ? { ...config.extensions } : {};
30
+ }
31
+ function stringIds(value) {
32
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
33
+ }
34
+ function setExtensionActivation(config, extensionId, enabled) {
35
+ const extensions = extensionConfigRecord(config);
36
+ const enabledIds = stringIds(extensions.enabled).filter((id) => id !== extensionId);
37
+ const disabledIds = stringIds(extensions.disabled).filter((id) => id !== extensionId);
38
+ if (enabled) enabledIds.push(extensionId);
39
+ else disabledIds.push(extensionId);
40
+ const nextExtensions = {
41
+ ...extensions,
42
+ enabled: enabledIds
43
+ };
44
+ if (disabledIds.length) nextExtensions.disabled = disabledIds;
45
+ else delete nextExtensions.disabled;
46
+ return {
47
+ ...config,
48
+ extensions: nextExtensions
49
+ };
50
+ }
51
+ function removeExtensionActivation(config, extensionId) {
52
+ const extensions = extensionConfigRecord(config);
53
+ return {
54
+ ...config,
55
+ extensions: {
56
+ ...extensions,
57
+ enabled: stringIds(extensions.enabled).filter((id) => id !== extensionId),
58
+ disabled: stringIds(extensions.disabled).filter((id) => id !== extensionId)
59
+ }
60
+ };
61
+ }
62
+ function shouldCopyReleasePath(source) {
63
+ return !RELEASE_COPY_EXCLUDED_NAMES.has(basename(source));
64
+ }
65
+ function hashDirectory(root) {
66
+ const hash = createHash("sha256");
67
+ const visit = (dir) => {
68
+ const entries = readdirSync(dir, { withFileTypes: true }).filter((entry) => !RELEASE_COPY_EXCLUDED_NAMES.has(entry.name)).toSorted((a, b) => a.name.localeCompare(b.name));
69
+ for (const entry of entries) {
70
+ const path = join(dir, entry.name);
71
+ const rel = relative(root, path);
72
+ hash.update(rel);
73
+ if (entry.isDirectory()) visit(path);
74
+ else if (entry.isFile()) hash.update(readFileSync(path));
75
+ else throw new Error(`Unsupported release entry: ${rel}`);
76
+ }
77
+ };
78
+ visit(root);
79
+ return hash.digest("hex");
80
+ }
81
+ function fileHashes(root) {
82
+ const hashes = /* @__PURE__ */ new Map();
83
+ const visit = (dir) => {
84
+ const entries = readdirSync(dir, { withFileTypes: true }).filter((entry) => !RELEASE_COPY_EXCLUDED_NAMES.has(entry.name)).toSorted((a, b) => a.name.localeCompare(b.name));
85
+ for (const entry of entries) {
86
+ const path = join(dir, entry.name);
87
+ const rel = relative(root, path);
88
+ if (entry.isDirectory()) visit(path);
89
+ else if (entry.isFile()) hashes.set(rel, createHash("sha256").update(readFileSync(path)).digest("hex"));
90
+ else throw new Error(`Unsupported release entry: ${rel}`);
91
+ }
92
+ };
93
+ visit(root);
94
+ return hashes;
95
+ }
96
+ function changedFiles(current, active) {
97
+ const paths = new Set([...current.keys(), ...active.keys()]);
98
+ const changes = [];
99
+ for (const path of [...paths].toSorted()) {
100
+ const currentHash = current.get(path);
101
+ const activeHash = active.get(path);
102
+ if (!activeHash) changes.push({
103
+ path,
104
+ status: "added"
105
+ });
106
+ else if (!currentHash) changes.push({
107
+ path,
108
+ status: "deleted"
109
+ });
110
+ else if (currentHash !== activeHash) changes.push({
111
+ path,
112
+ status: "modified"
113
+ });
114
+ }
115
+ return changes;
116
+ }
117
+ function permissionsFromManifestJson(manifestJson) {
118
+ if (!manifestJson) return [];
119
+ try {
120
+ const manifest = JSON.parse(manifestJson);
121
+ return Array.isArray(manifest.ui?.permissions) ? manifest.ui.permissions.filter((value) => typeof value === "string") : [];
122
+ } catch {
123
+ return [];
124
+ }
125
+ }
126
+ function validateLocalAppPackage(root, extensionId) {
127
+ const manifestPath = join(root, "xopc.extension.json");
128
+ if (!existsSync(manifestPath)) throw new Error("Local app manifest is missing");
129
+ const manifestJson = readFileSync(manifestPath, "utf8");
130
+ const manifest = JSON.parse(manifestJson);
131
+ if (manifest.id !== extensionId) throw new Error("Extension id cannot change after the app is created");
132
+ if (!manifest.main || !manifest.ui?.main) throw new Error("Local app manifest must declare main and ui.main");
133
+ const resolvedRoot = resolve(root);
134
+ for (const declaredPath of [manifest.main, manifest.ui.main]) {
135
+ const resolvedPath = resolve(root, declaredPath);
136
+ if (!resolvedPath.startsWith(`${resolvedRoot}${sep}`) || !existsSync(resolvedPath) || !lstatSync(resolvedPath).isFile()) throw new Error(`Declared app file is missing or unsafe: ${declaredPath}`);
137
+ }
138
+ const trustedRuntime = manifest.main === ".xopc/runtime/local-ui.js" ? LOCAL_APP_RUNTIME_SOURCE : manifest.main === "index.js" && typeof manifest.name === "string" ? legacyLocalAppRuntimeSource(extensionId, manifest.name) : null;
139
+ if (trustedRuntime === null || readFileSync(join(root, manifest.main), "utf8") !== trustedRuntime) throw new Error(`Phase 1 local apps must use the xopc-owned runtime entry: ${LOCAL_APP_RUNTIME_ENTRY}`);
140
+ const unsupported = (Array.isArray(manifest.ui.permissions) ? manifest.ui.permissions.filter((value) => typeof value === "string") : []).filter((permission) => !UI_ONLY_PERMISSIONS.has(permission));
141
+ if (unsupported.length) throw new Error(`Phase 1 local apps cannot request: ${unsupported.join(", ")}`);
142
+ const html = readFileSync(join(root, manifest.ui.main), "utf8");
143
+ if (/<script\b(?![^>]*\bsrc=)[^>]*>/i.test(html)) throw new Error("Inline scripts are blocked in local app previews");
144
+ if (/(?:src|href)\s*=\s*["']https?:\/\//i.test(html)) throw new Error("Remote scripts, styles, and frames are blocked in Phase 1 local apps");
145
+ return {
146
+ manifestJson,
147
+ acceptanceScenarios: readLocalAppAcceptanceConfig(root).scenarios.map((scenario) => ({
148
+ id: scenario.id,
149
+ name: scenario.name,
150
+ stepCount: scenario.steps.length
151
+ }))
152
+ };
153
+ }
154
+ var LocalAppService = class {
155
+ constructor(options, store = new LocalAppStore()) {
156
+ this.options = options;
157
+ this.store = store;
158
+ }
159
+ list() {
160
+ return this.store.list();
161
+ }
162
+ get(id) {
163
+ const app = this.store.get(id);
164
+ const token = app ? this.store.getPreviewToken(id) : null;
165
+ if (!app || !token) return null;
166
+ return {
167
+ ...app,
168
+ previewUrl: `/api/local-apps/preview/${token}/ui/index.html`,
169
+ permissions: readLocalAppPermissions(app.workspaceRoot),
170
+ releases: this.store.listReleases(id).map(({ artifactPath: _artifactPath, manifestJson: _manifestJson, ...release }) => release),
171
+ acceptanceRuns: this.store.listAcceptanceRuns(id)
172
+ };
173
+ }
174
+ getUiGrant(extensionId) {
175
+ const app = this.store.findByExtensionId(extensionId);
176
+ const release = app?.activeReleaseId ? this.store.getRelease(app.id, app.activeReleaseId) : null;
177
+ const discovered = !release ? this.options.getExtensionLoader()?.discoverExtensions().find((extension) => extension.id === extensionId) : null;
178
+ if (!release && !discovered) throw new Error("Extension UI manifest not found");
179
+ const manifestJson = release?.manifestJson ?? JSON.stringify(discovered.manifest);
180
+ const manifestDigest = createHash("sha256").update(manifestJson).digest("hex");
181
+ const permissions = release ? permissionsFromManifestJson(manifestJson).toSorted() : [...discovered.manifest.ui?.permissions ?? []].toSorted();
182
+ const grant = this.store.getUiGrant(extensionId, manifestDigest);
183
+ const granted = Boolean(grant && JSON.stringify(grant.permissions.toSorted()) === JSON.stringify(permissions));
184
+ return {
185
+ granted,
186
+ extensionId,
187
+ appId: app?.id,
188
+ manifestDigest,
189
+ permissions,
190
+ grantedAt: granted ? grant?.grantedAt : void 0
191
+ };
192
+ }
193
+ grantUiPermissions(extensionId) {
194
+ const current = this.getUiGrant(extensionId);
195
+ if (!current.manifestDigest) throw new Error("Extension UI manifest not found");
196
+ return this.store.saveUiGrant({
197
+ extensionId,
198
+ appId: current.appId,
199
+ manifestDigest: current.manifestDigest,
200
+ permissions: current.permissions
201
+ });
202
+ }
203
+ create(input) {
204
+ const name = requireText(input.name, "App name");
205
+ const idea = requireText(input.idea, "App idea");
206
+ const suffix = randomBytes(4).toString("hex");
207
+ const extensionId = `local-${slugifyProjectName(name).slice(0, 48)}-${suffix}`;
208
+ const workspaceRoot = join(this.options.workspaceRoot, "local-apps", extensionId);
209
+ const previewToken = randomBytes(24).toString("base64url");
210
+ mkdirSync(workspaceRoot, { recursive: true });
211
+ scaffoldLocalApp({
212
+ workspaceRoot,
213
+ extensionId,
214
+ name,
215
+ idea,
216
+ description: input.description?.trim() || void 0
217
+ });
218
+ const project = this.options.projects.create({
219
+ name,
220
+ slug: extensionId,
221
+ description: input.description?.trim() || `Local app: ${idea}`,
222
+ brief: idea,
223
+ instructions: "Use the $build-xopc-local-app skill. Preserve the extension id and validate the app before each install.",
224
+ defaultAgentId: "coder",
225
+ workspaceRoot,
226
+ projectKind: "coding"
227
+ });
228
+ const app = this.store.create({
229
+ extensionId,
230
+ projectId: project.id,
231
+ name,
232
+ description: input.description?.trim() || void 0,
233
+ idea,
234
+ workspaceRoot: project.workspaceRoot ?? workspaceRoot,
235
+ previewToken
236
+ });
237
+ this.options.emit("local_app.created", {
238
+ appId: app.id,
239
+ projectId: project.id
240
+ });
241
+ return this.get(app.id);
242
+ }
243
+ resolvePreview(previewToken) {
244
+ const app = this.store.findByPreviewToken(previewToken);
245
+ if (!app) return null;
246
+ return {
247
+ app,
248
+ previewToken,
249
+ uiRoot: app.workspaceRoot
250
+ };
251
+ }
252
+ validate(id) {
253
+ const app = this.store.get(id);
254
+ if (!app) throw new Error("Local app not found");
255
+ const issues = [];
256
+ let manifestJson;
257
+ let acceptanceScenarios = [];
258
+ let sourceHash;
259
+ let currentFiles = /* @__PURE__ */ new Map();
260
+ try {
261
+ ({manifestJson, acceptanceScenarios} = validateLocalAppPackage(app.workspaceRoot, app.extensionId));
262
+ currentFiles = fileHashes(app.workspaceRoot);
263
+ sourceHash = hashDirectory(app.workspaceRoot);
264
+ } catch (error) {
265
+ issues.push({
266
+ code: "package_validation_failed",
267
+ severity: "error",
268
+ message: error instanceof Error ? error.message : String(error)
269
+ });
270
+ }
271
+ const activeRelease = app.activeReleaseId ? this.store.getRelease(app.id, app.activeReleaseId) : null;
272
+ let files = [];
273
+ if (activeRelease?.artifactPath && existsSync(activeRelease.artifactPath) && currentFiles.size) try {
274
+ files = changedFiles(currentFiles, fileHashes(activeRelease.artifactPath));
275
+ } catch (error) {
276
+ issues.push({
277
+ code: "release_comparison_failed",
278
+ severity: "warning",
279
+ message: error instanceof Error ? error.message : String(error)
280
+ });
281
+ }
282
+ else if (!activeRelease && currentFiles.size) files = [...currentFiles.keys()].toSorted().map((path) => ({
283
+ path,
284
+ status: "added"
285
+ }));
286
+ const permissions = permissionsFromManifestJson(manifestJson);
287
+ const activePermissions = permissionsFromManifestJson(activeRelease?.manifestJson);
288
+ return {
289
+ status: issues.some((issue) => issue.severity === "error") ? "failed" : "healthy",
290
+ checkedAt: Date.now(),
291
+ sourceHash,
292
+ hasDraftChanges: activeRelease ? sourceHash !== activeRelease.sourceHash : true,
293
+ changedFiles: files.slice(0, 50),
294
+ changedFileCount: files.length,
295
+ permissions,
296
+ permissionDelta: {
297
+ added: permissions.filter((permission) => !activePermissions.includes(permission)),
298
+ removed: activePermissions.filter((permission) => !permissions.includes(permission))
299
+ },
300
+ acceptanceScenarioCount: acceptanceScenarios.length,
301
+ acceptanceScenarios,
302
+ issues
303
+ };
304
+ }
305
+ recordAcceptance(id, input) {
306
+ const app = this.store.get(id);
307
+ if (!app) throw new Error("Local app not found");
308
+ const validation = this.validate(id);
309
+ if (validation.status !== "healthy" || !validation.sourceHash) throw new Error("The current draft must pass static validation before acceptance can be recorded");
310
+ if (input.sourceHash !== validation.sourceHash) throw new Error("Acceptance result is stale because the draft changed");
311
+ if (input.status !== "passed" && input.status !== "failed") throw new Error("Invalid acceptance status");
312
+ if (!Number.isInteger(input.interactiveCount) || input.interactiveCount < 0 || input.interactiveCount > 1e4) throw new Error("Invalid acceptance interactive count");
313
+ const requiredIds = new Set([
314
+ "document",
315
+ "content",
316
+ "interaction"
317
+ ]);
318
+ if (validation.acceptanceScenarioCount > 0) requiredIds.add("criteria");
319
+ const allowedIds = new Set([...requiredIds, "criteria"]);
320
+ const allowedStatuses = new Set([
321
+ "passed",
322
+ "failed",
323
+ "skipped"
324
+ ]);
325
+ if (!Array.isArray(input.checks) || input.checks.length < requiredIds.size || input.checks.length > allowedIds.size) throw new Error("Automatic acceptance must include every required check");
326
+ const seenIds = /* @__PURE__ */ new Set();
327
+ for (const check of input.checks) {
328
+ if (!allowedIds.has(check.id) || seenIds.has(check.id)) throw new Error("Invalid automatic acceptance check");
329
+ if (!allowedStatuses.has(check.status)) throw new Error("Invalid automatic acceptance check status");
330
+ if (typeof check.message !== "string" || !check.message.trim() || check.message.length > 500) throw new Error("Invalid automatic acceptance check message");
331
+ seenIds.add(check.id);
332
+ }
333
+ if ([...requiredIds].some((checkId) => !seenIds.has(checkId))) throw new Error("Automatic acceptance must include every required check");
334
+ if ((input.checks.some((check) => check.status === "failed") ? "failed" : "passed") !== input.status) throw new Error("Acceptance status does not match its checks");
335
+ const run = this.store.recordAcceptance(app.id, input);
336
+ this.options.emit("local_app.acceptance_recorded", {
337
+ appId: app.id,
338
+ sourceHash: run.sourceHash,
339
+ status: run.status
340
+ });
341
+ return run;
342
+ }
343
+ releaseRoot(appId) {
344
+ return join(resolveStateDir(), "local-apps", "releases", appId);
345
+ }
346
+ refreshExtensions(source) {
347
+ this.options.getExtensionLoader()?.invalidateManifestCache();
348
+ this.options.emit("config.reload", {
349
+ section: "extensions",
350
+ source
351
+ });
352
+ }
353
+ assertInstalledRuntime(app, target) {
354
+ const loader = this.options.getExtensionLoader();
355
+ if (!loader) return;
356
+ loader.invalidateManifestCache();
357
+ const installed = loader.discoverExtensions().find((extension) => extension.id === app.extensionId);
358
+ if (!installed || resolve(installed.path) !== resolve(target) || !installed.manifest.ui?.main) throw new Error("Installed local app was not discovered by the extension runtime");
359
+ const extensionRoot = resolve(installed.path);
360
+ const entrypoint = resolve(extensionRoot, installed.manifest.ui.main);
361
+ if (!entrypoint.startsWith(`${extensionRoot}${sep}`) || !existsSync(entrypoint)) throw new Error("Installed local app UI entrypoint is unavailable");
362
+ loader.buildManifestRegistry();
363
+ }
364
+ async activateArtifact(input) {
365
+ const previousConfig = this.options.getConfig();
366
+ const extensionsDir = resolveExtensionsDir();
367
+ mkdirSync(extensionsDir, { recursive: true });
368
+ const transactionRoot = mkdtempSync(join(extensionsDir, ".local-app-activate-"));
369
+ const staged = join(transactionRoot, input.app.extensionId);
370
+ const backup = join(transactionRoot, "previous");
371
+ const target = join(extensionsDir, input.app.extensionId);
372
+ cpSync(input.artifactPath, staged, {
373
+ recursive: true,
374
+ filter: shouldCopyReleasePath
375
+ });
376
+ let hadPrevious = false;
377
+ let configSaved = false;
378
+ try {
379
+ if (existsSync(target)) {
380
+ renameSync(target, backup);
381
+ hadPrevious = true;
382
+ }
383
+ renameSync(staged, target);
384
+ validateLocalAppPackage(target, input.app.extensionId);
385
+ const saved = await this.options.saveConfig(input.nextConfig);
386
+ if (!saved.saved) throw new Error(saved.error ?? "Failed to update local app activation");
387
+ configSaved = true;
388
+ this.refreshExtensions(input.source);
389
+ this.assertInstalledRuntime(input.app, target);
390
+ input.commit();
391
+ } catch (error) {
392
+ if (existsSync(target)) rmSync(target, {
393
+ recursive: true,
394
+ force: true
395
+ });
396
+ if (hadPrevious && existsSync(backup)) renameSync(backup, target);
397
+ if (configSaved) {
398
+ const restored = await this.options.saveConfig(previousConfig);
399
+ if (!restored.saved) log.error({
400
+ appId: input.app.id,
401
+ error: restored.error
402
+ }, "Local app config rollback failed");
403
+ }
404
+ this.refreshExtensions(`${input.source}-rollback`);
405
+ throw error;
406
+ } finally {
407
+ rmSync(transactionRoot, {
408
+ recursive: true,
409
+ force: true
410
+ });
411
+ }
412
+ }
413
+ async install(id) {
414
+ const app = this.store.get(id);
415
+ if (!app) throw new Error("Local app not found");
416
+ const releaseRoot = this.releaseRoot(app.id);
417
+ mkdirSync(releaseRoot, { recursive: true });
418
+ const artifactPath = join(releaseRoot, `v${app.draftVersion}`);
419
+ if (existsSync(artifactPath)) throw new Error(`Release v${app.draftVersion} already exists`);
420
+ const stagingRoot = mkdtempSync(join(releaseRoot, ".draft-"));
421
+ const stagedArtifact = join(stagingRoot, "package");
422
+ let artifactCreated = false;
423
+ try {
424
+ cpSync(app.workspaceRoot, stagedArtifact, {
425
+ recursive: true,
426
+ filter: shouldCopyReleasePath
427
+ });
428
+ const { manifestJson } = validateLocalAppPackage(stagedArtifact, app.extensionId);
429
+ const sourceHash = hashDirectory(stagedArtifact);
430
+ if (this.store.getLatestAcceptanceForSource(app.id, sourceHash)?.status !== "passed") throw new Error("The current draft has not passed automatic acceptance");
431
+ renameSync(stagedArtifact, artifactPath);
432
+ artifactCreated = true;
433
+ await this.activateArtifact({
434
+ app,
435
+ artifactPath,
436
+ nextConfig: setExtensionActivation(this.options.getConfig(), app.extensionId, true),
437
+ source: "local-app-install",
438
+ commit: () => {
439
+ this.store.markInstalled({
440
+ id: app.id,
441
+ version: app.draftVersion,
442
+ sourceHash,
443
+ artifactPath,
444
+ manifestJson
445
+ });
446
+ }
447
+ });
448
+ } catch (error) {
449
+ if (artifactCreated) rmSync(artifactPath, {
450
+ recursive: true,
451
+ force: true
452
+ });
453
+ throw error;
454
+ } finally {
455
+ rmSync(stagingRoot, {
456
+ recursive: true,
457
+ force: true
458
+ });
459
+ }
460
+ const next = this.get(id);
461
+ this.options.emit("local_app.installed", {
462
+ appId: app.id,
463
+ extensionId: app.extensionId,
464
+ version: next.activeVersion
465
+ });
466
+ log.info({
467
+ appId: app.id,
468
+ extensionId: app.extensionId,
469
+ version: next.activeVersion
470
+ }, "Local app installed");
471
+ return next;
472
+ }
473
+ async rollback(id, releaseId) {
474
+ const app = this.store.get(id);
475
+ if (!app) throw new Error("Local app not found");
476
+ const release = this.store.getRelease(id, releaseId);
477
+ if (!release || !release.artifactPath || !existsSync(release.artifactPath)) throw new Error("Local app release artifact is unavailable");
478
+ validateLocalAppPackage(release.artifactPath, app.extensionId);
479
+ await this.activateArtifact({
480
+ app,
481
+ artifactPath: release.artifactPath,
482
+ nextConfig: setExtensionActivation(this.options.getConfig(), app.extensionId, true),
483
+ source: "local-app-rollback",
484
+ commit: () => {
485
+ this.store.activateRelease(id, releaseId);
486
+ }
487
+ });
488
+ this.options.emit("local_app.rolled_back", {
489
+ appId: id,
490
+ releaseId,
491
+ version: release.version
492
+ });
493
+ return this.get(id);
494
+ }
495
+ async setEnabled(id, enabled) {
496
+ const app = this.store.get(id);
497
+ if (!app) throw new Error("Local app not found");
498
+ if (app.installationState !== "installed") throw new Error("Install the local app before changing its enabled state");
499
+ const previousConfig = this.options.getConfig();
500
+ const saved = await this.options.saveConfig(setExtensionActivation(previousConfig, app.extensionId, enabled));
501
+ if (!saved.saved) throw new Error(saved.error ?? "Failed to update local app state");
502
+ try {
503
+ this.store.setEnabled(id, enabled);
504
+ } catch (error) {
505
+ await this.options.saveConfig(previousConfig);
506
+ throw error;
507
+ }
508
+ this.refreshExtensions(enabled ? "local-app-enable" : "local-app-disable");
509
+ this.options.emit(enabled ? "local_app.enabled" : "local_app.disabled", { appId: id });
510
+ return this.get(id);
511
+ }
512
+ async uninstall(id) {
513
+ const app = this.store.get(id);
514
+ if (!app) throw new Error("Local app not found");
515
+ const extensionsDir = resolveExtensionsDir();
516
+ mkdirSync(extensionsDir, { recursive: true });
517
+ const target = join(extensionsDir, app.extensionId);
518
+ const transactionRoot = mkdtempSync(join(extensionsDir, ".local-app-uninstall-"));
519
+ const backup = join(transactionRoot, app.extensionId);
520
+ const previousConfig = this.options.getConfig();
521
+ let moved = false;
522
+ let configSaved = false;
523
+ try {
524
+ if (existsSync(target)) {
525
+ renameSync(target, backup);
526
+ moved = true;
527
+ }
528
+ const saved = await this.options.saveConfig(removeExtensionActivation(previousConfig, app.extensionId));
529
+ if (!saved.saved) throw new Error(saved.error ?? "Failed to uninstall local app");
530
+ configSaved = true;
531
+ this.store.markUninstalled(id);
532
+ this.refreshExtensions("local-app-uninstall");
533
+ } catch (error) {
534
+ if (moved && existsSync(backup)) renameSync(backup, target);
535
+ if (configSaved) await this.options.saveConfig(previousConfig);
536
+ throw error;
537
+ } finally {
538
+ rmSync(transactionRoot, {
539
+ recursive: true,
540
+ force: true
541
+ });
542
+ }
543
+ this.options.emit("local_app.uninstalled", {
544
+ appId: id,
545
+ projectId: app.projectId
546
+ });
547
+ return this.get(id);
548
+ }
549
+ };
550
+ //#endregion
551
+ export { LocalAppService };
552
+
553
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","names":[],"sources":["../../../src/local-apps/service.ts"],"sourcesContent":["import { createHash, randomBytes } from 'node:crypto';\nimport {\n cpSync,\n existsSync,\n mkdirSync,\n mkdtempSync,\n lstatSync,\n readFileSync,\n readdirSync,\n renameSync,\n rmSync,\n} from 'node:fs';\nimport { basename, join, relative, resolve, sep } from 'node:path';\n\nimport { resolveExtensionsDir, resolveStateDir } from '../config/paths.js';\nimport type { Config } from '../config/schema.js';\nimport type { ExtensionLoader } from '../extensions/index.js';\nimport type { ProjectService } from '../projects/index.js';\nimport { slugifyProjectName } from '../projects/project-store.js';\nimport { createLogger } from '../utils/logger.js';\nimport { readLocalAppAcceptanceConfig } from './acceptance.js';\nimport {\n legacyLocalAppRuntimeSource,\n LOCAL_APP_RUNTIME_ENTRY,\n LOCAL_APP_RUNTIME_SOURCE,\n} from './runtime-entry.js';\nimport { readLocalAppPermissions, scaffoldLocalApp } from './scaffold.js';\nimport { LocalAppStore } from './store.js';\nimport type {\n CreateLocalAppInput,\n LocalAppChangedFile,\n LocalApp,\n LocalAppAcceptanceRun,\n LocalAppDetail,\n LocalAppPreviewTarget,\n LocalAppValidationResult,\n LocalAppUiGrant,\n RecordLocalAppAcceptanceInput,\n} from './types.js';\n\nconst log = createLogger('LocalApps');\nconst RELEASE_COPY_EXCLUDED_NAMES = new Set(['.git', 'node_modules']);\nconst UI_ONLY_PERMISSIONS = new Set(['theme', 'storage', 'notification']);\n\nexport interface LocalAppServiceOptions {\n projects: ProjectService;\n workspaceRoot: string;\n getConfig: () => Config;\n saveConfig: (config: Config) => Promise<{ saved: boolean; error?: string }>;\n getExtensionLoader: () => ExtensionLoader | null;\n emit: (type: string, payload: unknown) => void;\n}\n\nfunction requireText(value: string, label: string): string {\n const trimmed = value.trim();\n if (!trimmed) throw new Error(`${label} is required`);\n return trimmed;\n}\n\nfunction extensionConfigRecord(config: Config): Record<string, unknown> {\n return config.extensions && typeof config.extensions === 'object' && !Array.isArray(config.extensions)\n ? { ...(config.extensions as Record<string, unknown>) }\n : {};\n}\n\nfunction stringIds(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string')\n : [];\n}\n\nfunction setExtensionActivation(config: Config, extensionId: string, enabled: boolean): Config {\n const extensions = extensionConfigRecord(config);\n const enabledIds = stringIds(extensions.enabled).filter((id) => id !== extensionId);\n const disabledIds = stringIds(extensions.disabled).filter((id) => id !== extensionId);\n if (enabled) enabledIds.push(extensionId);\n else disabledIds.push(extensionId);\n const nextExtensions: Record<string, unknown> = { ...extensions, enabled: enabledIds };\n if (disabledIds.length) nextExtensions.disabled = disabledIds;\n else delete nextExtensions.disabled;\n return { ...config, extensions: nextExtensions } as Config;\n}\n\nfunction removeExtensionActivation(config: Config, extensionId: string): Config {\n const extensions = extensionConfigRecord(config);\n return {\n ...config,\n extensions: {\n ...extensions,\n enabled: stringIds(extensions.enabled).filter((id) => id !== extensionId),\n disabled: stringIds(extensions.disabled).filter((id) => id !== extensionId),\n },\n } as Config;\n}\n\nfunction shouldCopyReleasePath(source: string): boolean {\n return !RELEASE_COPY_EXCLUDED_NAMES.has(basename(source));\n}\n\nfunction hashDirectory(root: string): string {\n const hash = createHash('sha256');\n const visit = (dir: string): void => {\n const entries = readdirSync(dir, { withFileTypes: true })\n .filter((entry) => !RELEASE_COPY_EXCLUDED_NAMES.has(entry.name))\n .toSorted((a, b) => a.name.localeCompare(b.name));\n for (const entry of entries) {\n const path = join(dir, entry.name);\n const rel = relative(root, path);\n hash.update(rel);\n if (entry.isDirectory()) visit(path);\n else if (entry.isFile()) hash.update(readFileSync(path));\n else throw new Error(`Unsupported release entry: ${rel}`);\n }\n };\n visit(root);\n return hash.digest('hex');\n}\n\nfunction fileHashes(root: string): Map<string, string> {\n const hashes = new Map<string, string>();\n const visit = (dir: string): void => {\n const entries = readdirSync(dir, { withFileTypes: true })\n .filter((entry) => !RELEASE_COPY_EXCLUDED_NAMES.has(entry.name))\n .toSorted((a, b) => a.name.localeCompare(b.name));\n for (const entry of entries) {\n const path = join(dir, entry.name);\n const rel = relative(root, path);\n if (entry.isDirectory()) visit(path);\n else if (entry.isFile()) hashes.set(rel, createHash('sha256').update(readFileSync(path)).digest('hex'));\n else throw new Error(`Unsupported release entry: ${rel}`);\n }\n };\n visit(root);\n return hashes;\n}\n\nfunction changedFiles(current: Map<string, string>, active: Map<string, string>): LocalAppChangedFile[] {\n const paths = new Set([...current.keys(), ...active.keys()]);\n const changes: LocalAppChangedFile[] = [];\n for (const path of [...paths].toSorted()) {\n const currentHash = current.get(path);\n const activeHash = active.get(path);\n if (!activeHash) changes.push({ path, status: 'added' });\n else if (!currentHash) changes.push({ path, status: 'deleted' });\n else if (currentHash !== activeHash) changes.push({ path, status: 'modified' });\n }\n return changes;\n}\n\nfunction permissionsFromManifestJson(manifestJson: string | undefined): string[] {\n if (!manifestJson) return [];\n try {\n const manifest = JSON.parse(manifestJson) as { ui?: { permissions?: unknown } };\n return Array.isArray(manifest.ui?.permissions)\n ? manifest.ui.permissions.filter((value): value is string => typeof value === 'string')\n : [];\n } catch {\n return [];\n }\n}\n\nfunction validateLocalAppPackage(root: string, extensionId: string): {\n manifestJson: string;\n acceptanceScenarios: Array<{ id: string; name: string; stepCount: number }>;\n} {\n const manifestPath = join(root, 'xopc.extension.json');\n if (!existsSync(manifestPath)) throw new Error('Local app manifest is missing');\n const manifestJson = readFileSync(manifestPath, 'utf8');\n const manifest = JSON.parse(manifestJson) as {\n id?: string;\n name?: string;\n main?: string;\n ui?: { main?: string; permissions?: unknown };\n };\n if (manifest.id !== extensionId) throw new Error('Extension id cannot change after the app is created');\n if (!manifest.main || !manifest.ui?.main) throw new Error('Local app manifest must declare main and ui.main');\n const resolvedRoot = resolve(root);\n for (const declaredPath of [manifest.main, manifest.ui.main]) {\n const resolvedPath = resolve(root, declaredPath);\n if (!resolvedPath.startsWith(`${resolvedRoot}${sep}`) || !existsSync(resolvedPath) || !lstatSync(resolvedPath).isFile()) {\n throw new Error(`Declared app file is missing or unsafe: ${declaredPath}`);\n }\n }\n const trustedRuntime = manifest.main === LOCAL_APP_RUNTIME_ENTRY\n ? LOCAL_APP_RUNTIME_SOURCE\n : manifest.main === 'index.js' && typeof manifest.name === 'string'\n ? legacyLocalAppRuntimeSource(extensionId, manifest.name)\n : null;\n if (trustedRuntime === null || readFileSync(join(root, manifest.main), 'utf8') !== trustedRuntime) {\n throw new Error(`Phase 1 local apps must use the xopc-owned runtime entry: ${LOCAL_APP_RUNTIME_ENTRY}`);\n }\n const permissions = Array.isArray(manifest.ui.permissions)\n ? manifest.ui.permissions.filter((value): value is string => typeof value === 'string')\n : [];\n const unsupported = permissions.filter((permission) => !UI_ONLY_PERMISSIONS.has(permission));\n if (unsupported.length) {\n throw new Error(`Phase 1 local apps cannot request: ${unsupported.join(', ')}`);\n }\n const html = readFileSync(join(root, manifest.ui.main), 'utf8');\n if (/<script\\b(?![^>]*\\bsrc=)[^>]*>/i.test(html)) {\n throw new Error('Inline scripts are blocked in local app previews');\n }\n if (/(?:src|href)\\s*=\\s*[\"']https?:\\/\\//i.test(html)) {\n throw new Error('Remote scripts, styles, and frames are blocked in Phase 1 local apps');\n }\n const acceptance = readLocalAppAcceptanceConfig(root);\n return {\n manifestJson,\n acceptanceScenarios: acceptance.scenarios.map((scenario) => ({\n id: scenario.id,\n name: scenario.name,\n stepCount: scenario.steps.length,\n })),\n };\n}\n\nexport class LocalAppService {\n constructor(\n private readonly options: LocalAppServiceOptions,\n private readonly store = new LocalAppStore(),\n ) {}\n\n list(): LocalApp[] {\n return this.store.list();\n }\n\n get(id: string): LocalAppDetail | null {\n const app = this.store.get(id);\n const token = app ? this.store.getPreviewToken(id) : null;\n if (!app || !token) return null;\n return {\n ...app,\n previewUrl: `/api/local-apps/preview/${token}/ui/index.html`,\n permissions: readLocalAppPermissions(app.workspaceRoot),\n releases: this.store.listReleases(id).map(({ artifactPath: _artifactPath, manifestJson: _manifestJson, ...release }) => release),\n acceptanceRuns: this.store.listAcceptanceRuns(id),\n };\n }\n\n getUiGrant(extensionId: string): LocalAppUiGrant {\n const app = this.store.findByExtensionId(extensionId);\n const release = app?.activeReleaseId ? this.store.getRelease(app.id, app.activeReleaseId) : null;\n const discovered = !release\n ? this.options.getExtensionLoader()?.discoverExtensions().find((extension) => extension.id === extensionId)\n : null;\n if (!release && !discovered) throw new Error('Extension UI manifest not found');\n const manifestJson = release?.manifestJson ?? JSON.stringify(discovered!.manifest);\n const manifestDigest = createHash('sha256').update(manifestJson).digest('hex');\n const permissions = release\n ? permissionsFromManifestJson(manifestJson).toSorted()\n : [...(discovered!.manifest.ui?.permissions ?? [])].toSorted();\n const grant = this.store.getUiGrant(extensionId, manifestDigest);\n const granted = Boolean(grant\n && JSON.stringify(grant.permissions.toSorted()) === JSON.stringify(permissions));\n return {\n granted,\n extensionId,\n appId: app?.id,\n manifestDigest,\n permissions,\n grantedAt: granted ? grant?.grantedAt : undefined,\n };\n }\n\n grantUiPermissions(extensionId: string): LocalAppUiGrant {\n const current = this.getUiGrant(extensionId);\n if (!current.manifestDigest) throw new Error('Extension UI manifest not found');\n return this.store.saveUiGrant({\n extensionId,\n appId: current.appId,\n manifestDigest: current.manifestDigest,\n permissions: current.permissions,\n });\n }\n\n create(input: CreateLocalAppInput): LocalAppDetail {\n const name = requireText(input.name, 'App name');\n const idea = requireText(input.idea, 'App idea');\n const suffix = randomBytes(4).toString('hex');\n const slug = slugifyProjectName(name).slice(0, 48);\n const extensionId = `local-${slug}-${suffix}`;\n const workspaceRoot = join(this.options.workspaceRoot, 'local-apps', extensionId);\n const previewToken = randomBytes(24).toString('base64url');\n\n mkdirSync(workspaceRoot, { recursive: true });\n scaffoldLocalApp({\n workspaceRoot,\n extensionId,\n name,\n idea,\n description: input.description?.trim() || undefined,\n });\n const project = this.options.projects.create({\n name,\n slug: extensionId,\n description: input.description?.trim() || `Local app: ${idea}`,\n brief: idea,\n instructions: 'Use the $build-xopc-local-app skill. Preserve the extension id and validate the app before each install.',\n defaultAgentId: 'coder',\n workspaceRoot,\n projectKind: 'coding',\n });\n const app = this.store.create({\n extensionId,\n projectId: project.id,\n name,\n description: input.description?.trim() || undefined,\n idea,\n workspaceRoot: project.workspaceRoot ?? workspaceRoot,\n previewToken,\n });\n this.options.emit('local_app.created', { appId: app.id, projectId: project.id });\n return this.get(app.id)!;\n }\n\n resolvePreview(previewToken: string): LocalAppPreviewTarget | null {\n const app = this.store.findByPreviewToken(previewToken);\n if (!app) return null;\n return { app, previewToken, uiRoot: app.workspaceRoot };\n }\n\n validate(id: string): LocalAppValidationResult {\n const app = this.store.get(id);\n if (!app) throw new Error('Local app not found');\n const issues: LocalAppValidationResult['issues'] = [];\n let manifestJson: string | undefined;\n let acceptanceScenarios: LocalAppValidationResult['acceptanceScenarios'] = [];\n let sourceHash: string | undefined;\n let currentFiles = new Map<string, string>();\n try {\n ({ manifestJson, acceptanceScenarios } = validateLocalAppPackage(app.workspaceRoot, app.extensionId));\n currentFiles = fileHashes(app.workspaceRoot);\n sourceHash = hashDirectory(app.workspaceRoot);\n } catch (error) {\n issues.push({\n code: 'package_validation_failed',\n severity: 'error',\n message: error instanceof Error ? error.message : String(error),\n });\n }\n\n const activeRelease = app.activeReleaseId\n ? this.store.getRelease(app.id, app.activeReleaseId)\n : null;\n let files: LocalAppChangedFile[] = [];\n if (activeRelease?.artifactPath && existsSync(activeRelease.artifactPath) && currentFiles.size) {\n try {\n files = changedFiles(currentFiles, fileHashes(activeRelease.artifactPath));\n } catch (error) {\n issues.push({\n code: 'release_comparison_failed',\n severity: 'warning',\n message: error instanceof Error ? error.message : String(error),\n });\n }\n } else if (!activeRelease && currentFiles.size) {\n files = [...currentFiles.keys()].toSorted().map((path) => ({ path, status: 'added' }));\n }\n\n const permissions = permissionsFromManifestJson(manifestJson);\n const activePermissions = permissionsFromManifestJson(activeRelease?.manifestJson);\n return {\n status: issues.some((issue) => issue.severity === 'error') ? 'failed' : 'healthy',\n checkedAt: Date.now(),\n sourceHash,\n hasDraftChanges: activeRelease ? sourceHash !== activeRelease.sourceHash : true,\n changedFiles: files.slice(0, 50),\n changedFileCount: files.length,\n permissions,\n permissionDelta: {\n added: permissions.filter((permission) => !activePermissions.includes(permission)),\n removed: activePermissions.filter((permission) => !permissions.includes(permission)),\n },\n acceptanceScenarioCount: acceptanceScenarios.length,\n acceptanceScenarios,\n issues,\n };\n }\n\n recordAcceptance(id: string, input: RecordLocalAppAcceptanceInput): LocalAppAcceptanceRun {\n const app = this.store.get(id);\n if (!app) throw new Error('Local app not found');\n const validation = this.validate(id);\n if (validation.status !== 'healthy' || !validation.sourceHash) {\n throw new Error('The current draft must pass static validation before acceptance can be recorded');\n }\n if (input.sourceHash !== validation.sourceHash) {\n throw new Error('Acceptance result is stale because the draft changed');\n }\n if (input.status !== 'passed' && input.status !== 'failed') {\n throw new Error('Invalid acceptance status');\n }\n if (!Number.isInteger(input.interactiveCount) || input.interactiveCount < 0 || input.interactiveCount > 10_000) {\n throw new Error('Invalid acceptance interactive count');\n }\n const requiredIds = new Set(['document', 'content', 'interaction']);\n if (validation.acceptanceScenarioCount > 0) requiredIds.add('criteria');\n const allowedIds = new Set([...requiredIds, 'criteria']);\n const allowedStatuses = new Set(['passed', 'failed', 'skipped']);\n if (!Array.isArray(input.checks)\n || input.checks.length < requiredIds.size\n || input.checks.length > allowedIds.size) {\n throw new Error('Automatic acceptance must include every required check');\n }\n const seenIds = new Set<string>();\n for (const check of input.checks) {\n if (!allowedIds.has(check.id) || seenIds.has(check.id)) throw new Error('Invalid automatic acceptance check');\n if (!allowedStatuses.has(check.status)) throw new Error('Invalid automatic acceptance check status');\n if (typeof check.message !== 'string' || !check.message.trim() || check.message.length > 500) {\n throw new Error('Invalid automatic acceptance check message');\n }\n seenIds.add(check.id);\n }\n if ([...requiredIds].some((checkId) => !seenIds.has(checkId))) {\n throw new Error('Automatic acceptance must include every required check');\n }\n const derivedStatus = input.checks.some((check) => check.status === 'failed') ? 'failed' : 'passed';\n if (derivedStatus !== input.status) throw new Error('Acceptance status does not match its checks');\n const run = this.store.recordAcceptance(app.id, input);\n this.options.emit('local_app.acceptance_recorded', {\n appId: app.id,\n sourceHash: run.sourceHash,\n status: run.status,\n });\n return run;\n }\n\n private releaseRoot(appId: string): string {\n return join(resolveStateDir(), 'local-apps', 'releases', appId);\n }\n\n private refreshExtensions(source: string): void {\n this.options.getExtensionLoader()?.invalidateManifestCache();\n this.options.emit('config.reload', { section: 'extensions', source });\n }\n\n private assertInstalledRuntime(app: LocalApp, target: string): void {\n const loader = this.options.getExtensionLoader();\n if (!loader) return;\n loader.invalidateManifestCache();\n const installed = loader.discoverExtensions().find((extension) => extension.id === app.extensionId);\n if (!installed || resolve(installed.path) !== resolve(target) || !installed.manifest.ui?.main) {\n throw new Error('Installed local app was not discovered by the extension runtime');\n }\n const extensionRoot = resolve(installed.path);\n const entrypoint = resolve(extensionRoot, installed.manifest.ui.main);\n if (!entrypoint.startsWith(`${extensionRoot}${sep}`) || !existsSync(entrypoint)) {\n throw new Error('Installed local app UI entrypoint is unavailable');\n }\n loader.buildManifestRegistry();\n }\n\n private async activateArtifact(input: {\n app: LocalApp;\n artifactPath: string;\n nextConfig: Config;\n source: string;\n commit: () => void;\n }): Promise<void> {\n const previousConfig = this.options.getConfig();\n const extensionsDir = resolveExtensionsDir();\n mkdirSync(extensionsDir, { recursive: true });\n const transactionRoot = mkdtempSync(join(extensionsDir, '.local-app-activate-'));\n const staged = join(transactionRoot, input.app.extensionId);\n const backup = join(transactionRoot, 'previous');\n const target = join(extensionsDir, input.app.extensionId);\n cpSync(input.artifactPath, staged, { recursive: true, filter: shouldCopyReleasePath });\n let hadPrevious = false;\n let configSaved = false;\n try {\n if (existsSync(target)) {\n renameSync(target, backup);\n hadPrevious = true;\n }\n renameSync(staged, target);\n validateLocalAppPackage(target, input.app.extensionId);\n const saved = await this.options.saveConfig(input.nextConfig);\n if (!saved.saved) throw new Error(saved.error ?? 'Failed to update local app activation');\n configSaved = true;\n this.refreshExtensions(input.source);\n this.assertInstalledRuntime(input.app, target);\n input.commit();\n } catch (error) {\n if (existsSync(target)) rmSync(target, { recursive: true, force: true });\n if (hadPrevious && existsSync(backup)) renameSync(backup, target);\n if (configSaved) {\n const restored = await this.options.saveConfig(previousConfig);\n if (!restored.saved) {\n log.error({ appId: input.app.id, error: restored.error }, 'Local app config rollback failed');\n }\n }\n this.refreshExtensions(`${input.source}-rollback`);\n throw error;\n } finally {\n rmSync(transactionRoot, { recursive: true, force: true });\n }\n }\n\n async install(id: string): Promise<LocalAppDetail> {\n const app = this.store.get(id);\n if (!app) throw new Error('Local app not found');\n const releaseRoot = this.releaseRoot(app.id);\n mkdirSync(releaseRoot, { recursive: true });\n const artifactPath = join(releaseRoot, `v${app.draftVersion}`);\n if (existsSync(artifactPath)) throw new Error(`Release v${app.draftVersion} already exists`);\n const stagingRoot = mkdtempSync(join(releaseRoot, '.draft-'));\n const stagedArtifact = join(stagingRoot, 'package');\n let artifactCreated = false;\n try {\n cpSync(app.workspaceRoot, stagedArtifact, { recursive: true, filter: shouldCopyReleasePath });\n const { manifestJson } = validateLocalAppPackage(stagedArtifact, app.extensionId);\n const sourceHash = hashDirectory(stagedArtifact);\n const acceptance = this.store.getLatestAcceptanceForSource(app.id, sourceHash);\n if (acceptance?.status !== 'passed') {\n throw new Error('The current draft has not passed automatic acceptance');\n }\n renameSync(stagedArtifact, artifactPath);\n artifactCreated = true;\n await this.activateArtifact({\n app,\n artifactPath,\n nextConfig: setExtensionActivation(this.options.getConfig(), app.extensionId, true),\n source: 'local-app-install',\n commit: () => {\n this.store.markInstalled({\n id: app.id,\n version: app.draftVersion,\n sourceHash,\n artifactPath,\n manifestJson,\n });\n },\n });\n } catch (error) {\n if (artifactCreated) rmSync(artifactPath, { recursive: true, force: true });\n throw error;\n } finally {\n rmSync(stagingRoot, { recursive: true, force: true });\n }\n\n const next = this.get(id)!;\n this.options.emit('local_app.installed', {\n appId: app.id,\n extensionId: app.extensionId,\n version: next.activeVersion,\n });\n log.info({ appId: app.id, extensionId: app.extensionId, version: next.activeVersion }, 'Local app installed');\n return next;\n }\n\n async rollback(id: string, releaseId: string): Promise<LocalAppDetail> {\n const app = this.store.get(id);\n if (!app) throw new Error('Local app not found');\n const release = this.store.getRelease(id, releaseId);\n if (!release || !release.artifactPath || !existsSync(release.artifactPath)) {\n throw new Error('Local app release artifact is unavailable');\n }\n validateLocalAppPackage(release.artifactPath, app.extensionId);\n await this.activateArtifact({\n app,\n artifactPath: release.artifactPath,\n nextConfig: setExtensionActivation(this.options.getConfig(), app.extensionId, true),\n source: 'local-app-rollback',\n commit: () => { this.store.activateRelease(id, releaseId); },\n });\n this.options.emit('local_app.rolled_back', { appId: id, releaseId, version: release.version });\n return this.get(id)!;\n }\n\n async setEnabled(id: string, enabled: boolean): Promise<LocalAppDetail> {\n const app = this.store.get(id);\n if (!app) throw new Error('Local app not found');\n if (app.installationState !== 'installed') throw new Error('Install the local app before changing its enabled state');\n const previousConfig = this.options.getConfig();\n const saved = await this.options.saveConfig(setExtensionActivation(previousConfig, app.extensionId, enabled));\n if (!saved.saved) throw new Error(saved.error ?? 'Failed to update local app state');\n try {\n this.store.setEnabled(id, enabled);\n } catch (error) {\n await this.options.saveConfig(previousConfig);\n throw error;\n }\n this.refreshExtensions(enabled ? 'local-app-enable' : 'local-app-disable');\n this.options.emit(enabled ? 'local_app.enabled' : 'local_app.disabled', { appId: id });\n return this.get(id)!;\n }\n\n async uninstall(id: string): Promise<LocalAppDetail> {\n const app = this.store.get(id);\n if (!app) throw new Error('Local app not found');\n const extensionsDir = resolveExtensionsDir();\n mkdirSync(extensionsDir, { recursive: true });\n const target = join(extensionsDir, app.extensionId);\n const transactionRoot = mkdtempSync(join(extensionsDir, '.local-app-uninstall-'));\n const backup = join(transactionRoot, app.extensionId);\n const previousConfig = this.options.getConfig();\n let moved = false;\n let configSaved = false;\n try {\n if (existsSync(target)) {\n renameSync(target, backup);\n moved = true;\n }\n const saved = await this.options.saveConfig(removeExtensionActivation(previousConfig, app.extensionId));\n if (!saved.saved) throw new Error(saved.error ?? 'Failed to uninstall local app');\n configSaved = true;\n this.store.markUninstalled(id);\n this.refreshExtensions('local-app-uninstall');\n } catch (error) {\n if (moved && existsSync(backup)) renameSync(backup, target);\n if (configSaved) await this.options.saveConfig(previousConfig);\n throw error;\n } finally {\n rmSync(transactionRoot, { recursive: true, force: true });\n }\n this.options.emit('local_app.uninstalled', { appId: id, projectId: app.projectId });\n return this.get(id)!;\n }\n}\n"],"mappings":";;;;;;;;;;;;;YAc2E;aAKzB;AAqBlD,MAAM,MAAM,aAAa,YAAY;AACrC,MAAM,8BAA8B,IAAI,IAAI,CAAC,QAAQ,eAAe,CAAC;AACrE,MAAM,sBAAsB,IAAI,IAAI;CAAC;CAAS;CAAW;CAAe,CAAC;AAWzE,SAAS,YAAY,OAAe,OAAuB;CACzD,MAAM,UAAU,MAAM,MAAM;AAC5B,KAAI,CAAC,QAAS,OAAM,IAAI,MAAM,GAAG,MAAM,cAAc;AACrD,QAAO;;AAGT,SAAS,sBAAsB,QAAyC;AACtE,QAAO,OAAO,cAAc,OAAO,OAAO,eAAe,YAAY,CAAC,MAAM,QAAQ,OAAO,WAAW,GAClG,EAAE,GAAI,OAAO,YAAwC,GACrD,EAAE;;AAGR,SAAS,UAAU,OAA0B;AAC3C,QAAO,MAAM,QAAQ,MAAM,GACvB,MAAM,QAAQ,SAAyB,OAAO,SAAS,SAAS,GAChE,EAAE;;AAGR,SAAS,uBAAuB,QAAgB,aAAqB,SAA0B;CAC7F,MAAM,aAAa,sBAAsB,OAAO;CAChD,MAAM,aAAa,UAAU,WAAW,QAAQ,CAAC,QAAQ,OAAO,OAAO,YAAY;CACnF,MAAM,cAAc,UAAU,WAAW,SAAS,CAAC,QAAQ,OAAO,OAAO,YAAY;AACrF,KAAI,QAAS,YAAW,KAAK,YAAY;KACpC,aAAY,KAAK,YAAY;CAClC,MAAM,iBAA0C;EAAE,GAAG;EAAY,SAAS;EAAY;AACtF,KAAI,YAAY,OAAQ,gBAAe,WAAW;KAC7C,QAAO,eAAe;AAC3B,QAAO;EAAE,GAAG;EAAQ,YAAY;EAAgB;;AAGlD,SAAS,0BAA0B,QAAgB,aAA6B;CAC9E,MAAM,aAAa,sBAAsB,OAAO;AAChD,QAAO;EACL,GAAG;EACH,YAAY;GACV,GAAG;GACH,SAAS,UAAU,WAAW,QAAQ,CAAC,QAAQ,OAAO,OAAO,YAAY;GACzE,UAAU,UAAU,WAAW,SAAS,CAAC,QAAQ,OAAO,OAAO,YAAY;GAC5E;EACF;;AAGH,SAAS,sBAAsB,QAAyB;AACtD,QAAO,CAAC,4BAA4B,IAAI,SAAS,OAAO,CAAC;;AAG3D,SAAS,cAAc,MAAsB;CAC3C,MAAM,OAAO,WAAW,SAAS;CACjC,MAAM,SAAS,QAAsB;EACnC,MAAM,UAAU,YAAY,KAAK,EAAE,eAAe,MAAM,CAAC,CACtD,QAAQ,UAAU,CAAC,4BAA4B,IAAI,MAAM,KAAK,CAAC,CAC/D,UAAU,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC;AACnD,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,OAAO,KAAK,KAAK,MAAM,KAAK;GAClC,MAAM,MAAM,SAAS,MAAM,KAAK;AAChC,QAAK,OAAO,IAAI;AAChB,OAAI,MAAM,aAAa,CAAE,OAAM,KAAK;YAC3B,MAAM,QAAQ,CAAE,MAAK,OAAO,aAAa,KAAK,CAAC;OACnD,OAAM,IAAI,MAAM,8BAA8B,MAAM;;;AAG7D,OAAM,KAAK;AACX,QAAO,KAAK,OAAO,MAAM;;AAG3B,SAAS,WAAW,MAAmC;CACrD,MAAM,yBAAS,IAAI,KAAqB;CACxC,MAAM,SAAS,QAAsB;EACnC,MAAM,UAAU,YAAY,KAAK,EAAE,eAAe,MAAM,CAAC,CACtD,QAAQ,UAAU,CAAC,4BAA4B,IAAI,MAAM,KAAK,CAAC,CAC/D,UAAU,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC;AACnD,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,OAAO,KAAK,KAAK,MAAM,KAAK;GAClC,MAAM,MAAM,SAAS,MAAM,KAAK;AAChC,OAAI,MAAM,aAAa,CAAE,OAAM,KAAK;YAC3B,MAAM,QAAQ,CAAE,QAAO,IAAI,KAAK,WAAW,SAAS,CAAC,OAAO,aAAa,KAAK,CAAC,CAAC,OAAO,MAAM,CAAC;OAClG,OAAM,IAAI,MAAM,8BAA8B,MAAM;;;AAG7D,OAAM,KAAK;AACX,QAAO;;AAGT,SAAS,aAAa,SAA8B,QAAoD;CACtG,MAAM,QAAQ,IAAI,IAAI,CAAC,GAAG,QAAQ,MAAM,EAAE,GAAG,OAAO,MAAM,CAAC,CAAC;CAC5D,MAAM,UAAiC,EAAE;AACzC,MAAK,MAAM,QAAQ,CAAC,GAAG,MAAM,CAAC,UAAU,EAAE;EACxC,MAAM,cAAc,QAAQ,IAAI,KAAK;EACrC,MAAM,aAAa,OAAO,IAAI,KAAK;AACnC,MAAI,CAAC,WAAY,SAAQ,KAAK;GAAE;GAAM,QAAQ;GAAS,CAAC;WAC/C,CAAC,YAAa,SAAQ,KAAK;GAAE;GAAM,QAAQ;GAAW,CAAC;WACvD,gBAAgB,WAAY,SAAQ,KAAK;GAAE;GAAM,QAAQ;GAAY,CAAC;;AAEjF,QAAO;;AAGT,SAAS,4BAA4B,cAA4C;AAC/E,KAAI,CAAC,aAAc,QAAO,EAAE;AAC5B,KAAI;EACF,MAAM,WAAW,KAAK,MAAM,aAAa;AACzC,SAAO,MAAM,QAAQ,SAAS,IAAI,YAAY,GAC1C,SAAS,GAAG,YAAY,QAAQ,UAA2B,OAAO,UAAU,SAAS,GACrF,EAAE;SACA;AACN,SAAO,EAAE;;;AAIb,SAAS,wBAAwB,MAAc,aAG7C;CACA,MAAM,eAAe,KAAK,MAAM,sBAAsB;AACtD,KAAI,CAAC,WAAW,aAAa,CAAE,OAAM,IAAI,MAAM,gCAAgC;CAC/E,MAAM,eAAe,aAAa,cAAc,OAAO;CACvD,MAAM,WAAW,KAAK,MAAM,aAAa;AAMzC,KAAI,SAAS,OAAO,YAAa,OAAM,IAAI,MAAM,sDAAsD;AACvG,KAAI,CAAC,SAAS,QAAQ,CAAC,SAAS,IAAI,KAAM,OAAM,IAAI,MAAM,mDAAmD;CAC7G,MAAM,eAAe,QAAQ,KAAK;AAClC,MAAK,MAAM,gBAAgB,CAAC,SAAS,MAAM,SAAS,GAAG,KAAK,EAAE;EAC5D,MAAM,eAAe,QAAQ,MAAM,aAAa;AAChD,MAAI,CAAC,aAAa,WAAW,GAAG,eAAe,MAAM,IAAI,CAAC,WAAW,aAAa,IAAI,CAAC,UAAU,aAAa,CAAC,QAAQ,CACrH,OAAM,IAAI,MAAM,2CAA2C,eAAe;;CAG9E,MAAM,iBAAiB,SAAS,SAAA,8BAC5B,2BACA,SAAS,SAAS,cAAc,OAAO,SAAS,SAAS,WACvD,4BAA4B,aAAa,SAAS,KAAK,GACvD;AACN,KAAI,mBAAmB,QAAQ,aAAa,KAAK,MAAM,SAAS,KAAK,EAAE,OAAO,KAAK,eACjF,OAAM,IAAI,MAAM,6DAA6D,0BAA0B;CAKzG,MAAM,eAHc,MAAM,QAAQ,SAAS,GAAG,YAAY,GACtD,SAAS,GAAG,YAAY,QAAQ,UAA2B,OAAO,UAAU,SAAS,GACrF,EAAE,EAC0B,QAAQ,eAAe,CAAC,oBAAoB,IAAI,WAAW,CAAC;AAC5F,KAAI,YAAY,OACd,OAAM,IAAI,MAAM,sCAAsC,YAAY,KAAK,KAAK,GAAG;CAEjF,MAAM,OAAO,aAAa,KAAK,MAAM,SAAS,GAAG,KAAK,EAAE,OAAO;AAC/D,KAAI,kCAAkC,KAAK,KAAK,CAC9C,OAAM,IAAI,MAAM,mDAAmD;AAErE,KAAI,sCAAsC,KAAK,KAAK,CAClD,OAAM,IAAI,MAAM,uEAAuE;AAGzF,QAAO;EACL;EACA,qBAHiB,6BAA6B,KAGf,CAAC,UAAU,KAAK,cAAc;GAC3D,IAAI,SAAS;GACb,MAAM,SAAS;GACf,WAAW,SAAS,MAAM;GAC3B,EAAE;EACJ;;AAGH,IAAa,kBAAb,MAA6B;CAC3B,YACE,SACA,QAAyB,IAAI,eAAe,EAC5C;AAFiB,OAAA,UAAA;AACA,OAAA,QAAA;;CAGnB,OAAmB;AACjB,SAAO,KAAK,MAAM,MAAM;;CAG1B,IAAI,IAAmC;EACrC,MAAM,MAAM,KAAK,MAAM,IAAI,GAAG;EAC9B,MAAM,QAAQ,MAAM,KAAK,MAAM,gBAAgB,GAAG,GAAG;AACrD,MAAI,CAAC,OAAO,CAAC,MAAO,QAAO;AAC3B,SAAO;GACL,GAAG;GACH,YAAY,2BAA2B,MAAM;GAC7C,aAAa,wBAAwB,IAAI,cAAc;GACvD,UAAU,KAAK,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,cAAc,eAAe,cAAc,eAAe,GAAG,cAAc,QAAQ;GAChI,gBAAgB,KAAK,MAAM,mBAAmB,GAAG;GAClD;;CAGH,WAAW,aAAsC;EAC/C,MAAM,MAAM,KAAK,MAAM,kBAAkB,YAAY;EACrD,MAAM,UAAU,KAAK,kBAAkB,KAAK,MAAM,WAAW,IAAI,IAAI,IAAI,gBAAgB,GAAG;EAC5F,MAAM,aAAa,CAAC,UAChB,KAAK,QAAQ,oBAAoB,EAAE,oBAAoB,CAAC,MAAM,cAAc,UAAU,OAAO,YAAY,GACzG;AACJ,MAAI,CAAC,WAAW,CAAC,WAAY,OAAM,IAAI,MAAM,kCAAkC;EAC/E,MAAM,eAAe,SAAS,gBAAgB,KAAK,UAAU,WAAY,SAAS;EAClF,MAAM,iBAAiB,WAAW,SAAS,CAAC,OAAO,aAAa,CAAC,OAAO,MAAM;EAC9E,MAAM,cAAc,UAChB,4BAA4B,aAAa,CAAC,UAAU,GACpD,CAAC,GAAI,WAAY,SAAS,IAAI,eAAe,EAAE,CAAE,CAAC,UAAU;EAChE,MAAM,QAAQ,KAAK,MAAM,WAAW,aAAa,eAAe;EAChE,MAAM,UAAU,QAAQ,SACnB,KAAK,UAAU,MAAM,YAAY,UAAU,CAAC,KAAK,KAAK,UAAU,YAAY,CAAC;AAClF,SAAO;GACL;GACA;GACA,OAAO,KAAK;GACZ;GACA;GACA,WAAW,UAAU,OAAO,YAAY,KAAA;GACzC;;CAGH,mBAAmB,aAAsC;EACvD,MAAM,UAAU,KAAK,WAAW,YAAY;AAC5C,MAAI,CAAC,QAAQ,eAAgB,OAAM,IAAI,MAAM,kCAAkC;AAC/E,SAAO,KAAK,MAAM,YAAY;GAC5B;GACA,OAAO,QAAQ;GACf,gBAAgB,QAAQ;GACxB,aAAa,QAAQ;GACtB,CAAC;;CAGJ,OAAO,OAA4C;EACjD,MAAM,OAAO,YAAY,MAAM,MAAM,WAAW;EAChD,MAAM,OAAO,YAAY,MAAM,MAAM,WAAW;EAChD,MAAM,SAAS,YAAY,EAAE,CAAC,SAAS,MAAM;EAE7C,MAAM,cAAc,SADP,mBAAmB,KAAK,CAAC,MAAM,GAAG,GACd,CAAC,GAAG;EACrC,MAAM,gBAAgB,KAAK,KAAK,QAAQ,eAAe,cAAc,YAAY;EACjF,MAAM,eAAe,YAAY,GAAG,CAAC,SAAS,YAAY;AAE1D,YAAU,eAAe,EAAE,WAAW,MAAM,CAAC;AAC7C,mBAAiB;GACf;GACA;GACA;GACA;GACA,aAAa,MAAM,aAAa,MAAM,IAAI,KAAA;GAC3C,CAAC;EACF,MAAM,UAAU,KAAK,QAAQ,SAAS,OAAO;GAC3C;GACA,MAAM;GACN,aAAa,MAAM,aAAa,MAAM,IAAI,cAAc;GACxD,OAAO;GACP,cAAc;GACd,gBAAgB;GAChB;GACA,aAAa;GACd,CAAC;EACF,MAAM,MAAM,KAAK,MAAM,OAAO;GAC5B;GACA,WAAW,QAAQ;GACnB;GACA,aAAa,MAAM,aAAa,MAAM,IAAI,KAAA;GAC1C;GACA,eAAe,QAAQ,iBAAiB;GACxC;GACD,CAAC;AACF,OAAK,QAAQ,KAAK,qBAAqB;GAAE,OAAO,IAAI;GAAI,WAAW,QAAQ;GAAI,CAAC;AAChF,SAAO,KAAK,IAAI,IAAI,GAAG;;CAGzB,eAAe,cAAoD;EACjE,MAAM,MAAM,KAAK,MAAM,mBAAmB,aAAa;AACvD,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO;GAAE;GAAK;GAAc,QAAQ,IAAI;GAAe;;CAGzD,SAAS,IAAsC;EAC7C,MAAM,MAAM,KAAK,MAAM,IAAI,GAAG;AAC9B,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sBAAsB;EAChD,MAAM,SAA6C,EAAE;EACrD,IAAI;EACJ,IAAI,sBAAuE,EAAE;EAC7E,IAAI;EACJ,IAAI,+BAAe,IAAI,KAAqB;AAC5C,MAAI;AACF,IAAC,CAAE,cAAc,uBAAwB,wBAAwB,IAAI,eAAe,IAAI,YAAY;AACpG,kBAAe,WAAW,IAAI,cAAc;AAC5C,gBAAa,cAAc,IAAI,cAAc;WACtC,OAAO;AACd,UAAO,KAAK;IACV,MAAM;IACN,UAAU;IACV,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAChE,CAAC;;EAGJ,MAAM,gBAAgB,IAAI,kBACtB,KAAK,MAAM,WAAW,IAAI,IAAI,IAAI,gBAAgB,GAClD;EACJ,IAAI,QAA+B,EAAE;AACrC,MAAI,eAAe,gBAAgB,WAAW,cAAc,aAAa,IAAI,aAAa,KACxF,KAAI;AACF,WAAQ,aAAa,cAAc,WAAW,cAAc,aAAa,CAAC;WACnE,OAAO;AACd,UAAO,KAAK;IACV,MAAM;IACN,UAAU;IACV,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAChE,CAAC;;WAEK,CAAC,iBAAiB,aAAa,KACxC,SAAQ,CAAC,GAAG,aAAa,MAAM,CAAC,CAAC,UAAU,CAAC,KAAK,UAAU;GAAE;GAAM,QAAQ;GAAS,EAAE;EAGxF,MAAM,cAAc,4BAA4B,aAAa;EAC7D,MAAM,oBAAoB,4BAA4B,eAAe,aAAa;AAClF,SAAO;GACL,QAAQ,OAAO,MAAM,UAAU,MAAM,aAAa,QAAQ,GAAG,WAAW;GACxE,WAAW,KAAK,KAAK;GACrB;GACA,iBAAiB,gBAAgB,eAAe,cAAc,aAAa;GAC3E,cAAc,MAAM,MAAM,GAAG,GAAG;GAChC,kBAAkB,MAAM;GACxB;GACA,iBAAiB;IACf,OAAO,YAAY,QAAQ,eAAe,CAAC,kBAAkB,SAAS,WAAW,CAAC;IAClF,SAAS,kBAAkB,QAAQ,eAAe,CAAC,YAAY,SAAS,WAAW,CAAC;IACrF;GACD,yBAAyB,oBAAoB;GAC7C;GACA;GACD;;CAGH,iBAAiB,IAAY,OAA6D;EACxF,MAAM,MAAM,KAAK,MAAM,IAAI,GAAG;AAC9B,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sBAAsB;EAChD,MAAM,aAAa,KAAK,SAAS,GAAG;AACpC,MAAI,WAAW,WAAW,aAAa,CAAC,WAAW,WACjD,OAAM,IAAI,MAAM,kFAAkF;AAEpG,MAAI,MAAM,eAAe,WAAW,WAClC,OAAM,IAAI,MAAM,uDAAuD;AAEzE,MAAI,MAAM,WAAW,YAAY,MAAM,WAAW,SAChD,OAAM,IAAI,MAAM,4BAA4B;AAE9C,MAAI,CAAC,OAAO,UAAU,MAAM,iBAAiB,IAAI,MAAM,mBAAmB,KAAK,MAAM,mBAAmB,IACtG,OAAM,IAAI,MAAM,uCAAuC;EAEzD,MAAM,cAAc,IAAI,IAAI;GAAC;GAAY;GAAW;GAAc,CAAC;AACnE,MAAI,WAAW,0BAA0B,EAAG,aAAY,IAAI,WAAW;EACvE,MAAM,aAAa,IAAI,IAAI,CAAC,GAAG,aAAa,WAAW,CAAC;EACxD,MAAM,kBAAkB,IAAI,IAAI;GAAC;GAAU;GAAU;GAAU,CAAC;AAChE,MAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,IAC3B,MAAM,OAAO,SAAS,YAAY,QAClC,MAAM,OAAO,SAAS,WAAW,KACpC,OAAM,IAAI,MAAM,yDAAyD;EAE3E,MAAM,0BAAU,IAAI,KAAa;AACjC,OAAK,MAAM,SAAS,MAAM,QAAQ;AAChC,OAAI,CAAC,WAAW,IAAI,MAAM,GAAG,IAAI,QAAQ,IAAI,MAAM,GAAG,CAAE,OAAM,IAAI,MAAM,qCAAqC;AAC7G,OAAI,CAAC,gBAAgB,IAAI,MAAM,OAAO,CAAE,OAAM,IAAI,MAAM,4CAA4C;AACpG,OAAI,OAAO,MAAM,YAAY,YAAY,CAAC,MAAM,QAAQ,MAAM,IAAI,MAAM,QAAQ,SAAS,IACvF,OAAM,IAAI,MAAM,6CAA6C;AAE/D,WAAQ,IAAI,MAAM,GAAG;;AAEvB,MAAI,CAAC,GAAG,YAAY,CAAC,MAAM,YAAY,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAC3D,OAAM,IAAI,MAAM,yDAAyD;AAG3E,OADsB,MAAM,OAAO,MAAM,UAAU,MAAM,WAAW,SAAS,GAAG,WAAW,cACrE,MAAM,OAAQ,OAAM,IAAI,MAAM,8CAA8C;EAClG,MAAM,MAAM,KAAK,MAAM,iBAAiB,IAAI,IAAI,MAAM;AACtD,OAAK,QAAQ,KAAK,iCAAiC;GACjD,OAAO,IAAI;GACX,YAAY,IAAI;GAChB,QAAQ,IAAI;GACb,CAAC;AACF,SAAO;;CAGT,YAAoB,OAAuB;AACzC,SAAO,KAAK,iBAAiB,EAAE,cAAc,YAAY,MAAM;;CAGjE,kBAA0B,QAAsB;AAC9C,OAAK,QAAQ,oBAAoB,EAAE,yBAAyB;AAC5D,OAAK,QAAQ,KAAK,iBAAiB;GAAE,SAAS;GAAc;GAAQ,CAAC;;CAGvE,uBAA+B,KAAe,QAAsB;EAClE,MAAM,SAAS,KAAK,QAAQ,oBAAoB;AAChD,MAAI,CAAC,OAAQ;AACb,SAAO,yBAAyB;EAChC,MAAM,YAAY,OAAO,oBAAoB,CAAC,MAAM,cAAc,UAAU,OAAO,IAAI,YAAY;AACnG,MAAI,CAAC,aAAa,QAAQ,UAAU,KAAK,KAAK,QAAQ,OAAO,IAAI,CAAC,UAAU,SAAS,IAAI,KACvF,OAAM,IAAI,MAAM,kEAAkE;EAEpF,MAAM,gBAAgB,QAAQ,UAAU,KAAK;EAC7C,MAAM,aAAa,QAAQ,eAAe,UAAU,SAAS,GAAG,KAAK;AACrE,MAAI,CAAC,WAAW,WAAW,GAAG,gBAAgB,MAAM,IAAI,CAAC,WAAW,WAAW,CAC7E,OAAM,IAAI,MAAM,mDAAmD;AAErE,SAAO,uBAAuB;;CAGhC,MAAc,iBAAiB,OAMb;EAChB,MAAM,iBAAiB,KAAK,QAAQ,WAAW;EAC/C,MAAM,gBAAgB,sBAAsB;AAC5C,YAAU,eAAe,EAAE,WAAW,MAAM,CAAC;EAC7C,MAAM,kBAAkB,YAAY,KAAK,eAAe,uBAAuB,CAAC;EAChF,MAAM,SAAS,KAAK,iBAAiB,MAAM,IAAI,YAAY;EAC3D,MAAM,SAAS,KAAK,iBAAiB,WAAW;EAChD,MAAM,SAAS,KAAK,eAAe,MAAM,IAAI,YAAY;AACzD,SAAO,MAAM,cAAc,QAAQ;GAAE,WAAW;GAAM,QAAQ;GAAuB,CAAC;EACtF,IAAI,cAAc;EAClB,IAAI,cAAc;AAClB,MAAI;AACF,OAAI,WAAW,OAAO,EAAE;AACtB,eAAW,QAAQ,OAAO;AAC1B,kBAAc;;AAEhB,cAAW,QAAQ,OAAO;AAC1B,2BAAwB,QAAQ,MAAM,IAAI,YAAY;GACtD,MAAM,QAAQ,MAAM,KAAK,QAAQ,WAAW,MAAM,WAAW;AAC7D,OAAI,CAAC,MAAM,MAAO,OAAM,IAAI,MAAM,MAAM,SAAS,wCAAwC;AACzF,iBAAc;AACd,QAAK,kBAAkB,MAAM,OAAO;AACpC,QAAK,uBAAuB,MAAM,KAAK,OAAO;AAC9C,SAAM,QAAQ;WACP,OAAO;AACd,OAAI,WAAW,OAAO,CAAE,QAAO,QAAQ;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;AACxE,OAAI,eAAe,WAAW,OAAO,CAAE,YAAW,QAAQ,OAAO;AACjE,OAAI,aAAa;IACf,MAAM,WAAW,MAAM,KAAK,QAAQ,WAAW,eAAe;AAC9D,QAAI,CAAC,SAAS,MACZ,KAAI,MAAM;KAAE,OAAO,MAAM,IAAI;KAAI,OAAO,SAAS;KAAO,EAAE,mCAAmC;;AAGjG,QAAK,kBAAkB,GAAG,MAAM,OAAO,WAAW;AAClD,SAAM;YACE;AACR,UAAO,iBAAiB;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;;;CAI7D,MAAM,QAAQ,IAAqC;EACjD,MAAM,MAAM,KAAK,MAAM,IAAI,GAAG;AAC9B,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sBAAsB;EAChD,MAAM,cAAc,KAAK,YAAY,IAAI,GAAG;AAC5C,YAAU,aAAa,EAAE,WAAW,MAAM,CAAC;EAC3C,MAAM,eAAe,KAAK,aAAa,IAAI,IAAI,eAAe;AAC9D,MAAI,WAAW,aAAa,CAAE,OAAM,IAAI,MAAM,YAAY,IAAI,aAAa,iBAAiB;EAC5F,MAAM,cAAc,YAAY,KAAK,aAAa,UAAU,CAAC;EAC7D,MAAM,iBAAiB,KAAK,aAAa,UAAU;EACnD,IAAI,kBAAkB;AACtB,MAAI;AACF,UAAO,IAAI,eAAe,gBAAgB;IAAE,WAAW;IAAM,QAAQ;IAAuB,CAAC;GAC7F,MAAM,EAAE,iBAAiB,wBAAwB,gBAAgB,IAAI,YAAY;GACjF,MAAM,aAAa,cAAc,eAAe;AAEhD,OADmB,KAAK,MAAM,6BAA6B,IAAI,IAAI,WACrD,EAAE,WAAW,SACzB,OAAM,IAAI,MAAM,wDAAwD;AAE1E,cAAW,gBAAgB,aAAa;AACxC,qBAAkB;AAClB,SAAM,KAAK,iBAAiB;IAC1B;IACA;IACA,YAAY,uBAAuB,KAAK,QAAQ,WAAW,EAAE,IAAI,aAAa,KAAK;IACnF,QAAQ;IACR,cAAc;AACZ,UAAK,MAAM,cAAc;MACvB,IAAI,IAAI;MACR,SAAS,IAAI;MACb;MACA;MACA;MACD,CAAC;;IAEL,CAAC;WACK,OAAO;AACd,OAAI,gBAAiB,QAAO,cAAc;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;AAC3E,SAAM;YACE;AACR,UAAO,aAAa;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;;EAGvD,MAAM,OAAO,KAAK,IAAI,GAAG;AACzB,OAAK,QAAQ,KAAK,uBAAuB;GACvC,OAAO,IAAI;GACX,aAAa,IAAI;GACjB,SAAS,KAAK;GACf,CAAC;AACF,MAAI,KAAK;GAAE,OAAO,IAAI;GAAI,aAAa,IAAI;GAAa,SAAS,KAAK;GAAe,EAAE,sBAAsB;AAC7G,SAAO;;CAGT,MAAM,SAAS,IAAY,WAA4C;EACrE,MAAM,MAAM,KAAK,MAAM,IAAI,GAAG;AAC9B,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sBAAsB;EAChD,MAAM,UAAU,KAAK,MAAM,WAAW,IAAI,UAAU;AACpD,MAAI,CAAC,WAAW,CAAC,QAAQ,gBAAgB,CAAC,WAAW,QAAQ,aAAa,CACxE,OAAM,IAAI,MAAM,4CAA4C;AAE9D,0BAAwB,QAAQ,cAAc,IAAI,YAAY;AAC9D,QAAM,KAAK,iBAAiB;GAC1B;GACA,cAAc,QAAQ;GACtB,YAAY,uBAAuB,KAAK,QAAQ,WAAW,EAAE,IAAI,aAAa,KAAK;GACnF,QAAQ;GACR,cAAc;AAAE,SAAK,MAAM,gBAAgB,IAAI,UAAU;;GAC1D,CAAC;AACF,OAAK,QAAQ,KAAK,yBAAyB;GAAE,OAAO;GAAI;GAAW,SAAS,QAAQ;GAAS,CAAC;AAC9F,SAAO,KAAK,IAAI,GAAG;;CAGrB,MAAM,WAAW,IAAY,SAA2C;EACtE,MAAM,MAAM,KAAK,MAAM,IAAI,GAAG;AAC9B,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sBAAsB;AAChD,MAAI,IAAI,sBAAsB,YAAa,OAAM,IAAI,MAAM,0DAA0D;EACrH,MAAM,iBAAiB,KAAK,QAAQ,WAAW;EAC/C,MAAM,QAAQ,MAAM,KAAK,QAAQ,WAAW,uBAAuB,gBAAgB,IAAI,aAAa,QAAQ,CAAC;AAC7G,MAAI,CAAC,MAAM,MAAO,OAAM,IAAI,MAAM,MAAM,SAAS,mCAAmC;AACpF,MAAI;AACF,QAAK,MAAM,WAAW,IAAI,QAAQ;WAC3B,OAAO;AACd,SAAM,KAAK,QAAQ,WAAW,eAAe;AAC7C,SAAM;;AAER,OAAK,kBAAkB,UAAU,qBAAqB,oBAAoB;AAC1E,OAAK,QAAQ,KAAK,UAAU,sBAAsB,sBAAsB,EAAE,OAAO,IAAI,CAAC;AACtF,SAAO,KAAK,IAAI,GAAG;;CAGrB,MAAM,UAAU,IAAqC;EACnD,MAAM,MAAM,KAAK,MAAM,IAAI,GAAG;AAC9B,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sBAAsB;EAChD,MAAM,gBAAgB,sBAAsB;AAC5C,YAAU,eAAe,EAAE,WAAW,MAAM,CAAC;EAC7C,MAAM,SAAS,KAAK,eAAe,IAAI,YAAY;EACnD,MAAM,kBAAkB,YAAY,KAAK,eAAe,wBAAwB,CAAC;EACjF,MAAM,SAAS,KAAK,iBAAiB,IAAI,YAAY;EACrD,MAAM,iBAAiB,KAAK,QAAQ,WAAW;EAC/C,IAAI,QAAQ;EACZ,IAAI,cAAc;AAClB,MAAI;AACF,OAAI,WAAW,OAAO,EAAE;AACtB,eAAW,QAAQ,OAAO;AAC1B,YAAQ;;GAEV,MAAM,QAAQ,MAAM,KAAK,QAAQ,WAAW,0BAA0B,gBAAgB,IAAI,YAAY,CAAC;AACvG,OAAI,CAAC,MAAM,MAAO,OAAM,IAAI,MAAM,MAAM,SAAS,gCAAgC;AACjF,iBAAc;AACd,QAAK,MAAM,gBAAgB,GAAG;AAC9B,QAAK,kBAAkB,sBAAsB;WACtC,OAAO;AACd,OAAI,SAAS,WAAW,OAAO,CAAE,YAAW,QAAQ,OAAO;AAC3D,OAAI,YAAa,OAAM,KAAK,QAAQ,WAAW,eAAe;AAC9D,SAAM;YACE;AACR,UAAO,iBAAiB;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;;AAE3D,OAAK,QAAQ,KAAK,yBAAyB;GAAE,OAAO;GAAI,WAAW,IAAI;GAAW,CAAC;AACnF,SAAO,KAAK,IAAI,GAAG"}