aimeat 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (722) hide show
  1. package/dist/.env.example +9 -4
  2. package/dist/locales/en.json +63 -1
  3. package/dist/locales/fi.json +63 -1
  4. package/dist/public/components/LinkPreview.js +101 -0
  5. package/dist/public/components/NotificationBell.js +18 -1
  6. package/dist/public/cortex-bundled/aimeat-charts.js +158 -10
  7. package/dist/public/cortex-bundled/aimeat-charts.yaml +1 -1
  8. package/dist/public/cortex-bundled/aimeat-dag.js +515 -173
  9. package/dist/public/cortex-bundled/aimeat-dag.yaml +1 -1
  10. package/dist/public/cortex-bundled/aimeat-i18n.js +6 -1
  11. package/dist/public/cortex-bundled/aimeat-i18n.yaml +1 -1
  12. package/dist/public/cortex-bundled/aimeat-surface.js +577 -0
  13. package/dist/public/cortex-bundled/aimeat-surface.yaml +107 -0
  14. package/dist/public/cortex-bundled/aimeat-viewport.js +405 -0
  15. package/dist/public/cortex-bundled/aimeat-viewport.yaml +100 -0
  16. package/dist/public/css/theme.css +57 -7
  17. package/dist/public/css/views/admin.css +8 -1
  18. package/dist/public/css/views/app-grant.css +18 -0
  19. package/dist/public/css/views/inbox.css +47 -1
  20. package/dist/public/css/views/portfolio.css +46 -0
  21. package/dist/public/css/views/profile.css +38 -4
  22. package/dist/public/js/services/apps.js +19 -3
  23. package/dist/public/js/services/messages-ai-prompts.js +38 -0
  24. package/dist/public/js/services/messages.js +26 -4
  25. package/dist/public/js/services/notebook.js +76 -0
  26. package/dist/public/js/services/unfurl.js +43 -0
  27. package/dist/public/lib/VENDORED.md +6 -3
  28. package/dist/public/lib/aimeat-daisyui-bridge.css +39 -2
  29. package/dist/public/lib/aimeat-theme.css +538 -0
  30. package/dist/public/lib/fonts/LICENSE.md +11 -4
  31. package/dist/public/lib/fonts/fraunces-var-latin-ext.woff2 +0 -0
  32. package/dist/public/lib/fonts/fraunces-var-latin.woff2 +0 -0
  33. package/dist/public/lib/fonts/inter-var-latin-ext.woff2 +0 -0
  34. package/dist/public/lib/fonts/inter-var-latin.woff2 +0 -0
  35. package/dist/public/lib/fonts/jetbrains-mono-var-latin-ext.woff2 +0 -0
  36. package/dist/public/lib/fonts/jetbrains-mono-var-latin.woff2 +0 -0
  37. package/dist/public/lib/fonts/space-grotesk-var-latin-ext.woff2 +0 -0
  38. package/dist/public/lib/fonts/space-grotesk-var-latin.woff2 +0 -0
  39. package/dist/public/lib/samples/LICENSE.md +11 -0
  40. package/dist/public/lib/samples/bass/A1.mp3 +0 -0
  41. package/dist/public/lib/samples/bass/B2.mp3 +0 -0
  42. package/dist/public/lib/samples/bass/D2.mp3 +0 -0
  43. package/dist/public/lib/samples/bass/E1.mp3 +0 -0
  44. package/dist/public/lib/samples/bass/E3.mp3 +0 -0
  45. package/dist/public/lib/samples/bass/G2.mp3 +0 -0
  46. package/dist/public/lib/samples/epiano/C2.mp3 +0 -0
  47. package/dist/public/lib/samples/epiano/C3.mp3 +0 -0
  48. package/dist/public/lib/samples/epiano/C4.mp3 +0 -0
  49. package/dist/public/lib/samples/epiano/C5.mp3 +0 -0
  50. package/dist/public/lib/samples/epiano/C6.mp3 +0 -0
  51. package/dist/public/lib/samples/epiano/G2.mp3 +0 -0
  52. package/dist/public/lib/samples/epiano/G3.mp3 +0 -0
  53. package/dist/public/lib/samples/epiano/G4.mp3 +0 -0
  54. package/dist/public/lib/samples/epiano/G5.mp3 +0 -0
  55. package/dist/public/lib/samples/guitar-steel/A2.mp3 +0 -0
  56. package/dist/public/lib/samples/guitar-steel/A4.mp3 +0 -0
  57. package/dist/public/lib/samples/guitar-steel/B3.mp3 +0 -0
  58. package/dist/public/lib/samples/guitar-steel/D3.mp3 +0 -0
  59. package/dist/public/lib/samples/guitar-steel/E2.mp3 +0 -0
  60. package/dist/public/lib/samples/guitar-steel/E4.mp3 +0 -0
  61. package/dist/public/lib/samples/guitar-steel/E5.mp3 +0 -0
  62. package/dist/public/lib/samples/guitar-steel/G3.mp3 +0 -0
  63. package/dist/public/lib/samples/organ/C2.mp3 +0 -0
  64. package/dist/public/lib/samples/organ/C3.mp3 +0 -0
  65. package/dist/public/lib/samples/organ/C4.mp3 +0 -0
  66. package/dist/public/lib/samples/organ/C5.mp3 +0 -0
  67. package/dist/public/lib/samples/organ/C6.mp3 +0 -0
  68. package/dist/public/lib/samples/organ/G2.mp3 +0 -0
  69. package/dist/public/lib/samples/organ/G3.mp3 +0 -0
  70. package/dist/public/lib/samples/organ/G4.mp3 +0 -0
  71. package/dist/public/lib/samples/organ/G5.mp3 +0 -0
  72. package/dist/public/lib/samples/strings/C2.mp3 +0 -0
  73. package/dist/public/lib/samples/strings/C3.mp3 +0 -0
  74. package/dist/public/lib/samples/strings/C4.mp3 +0 -0
  75. package/dist/public/lib/samples/strings/C5.mp3 +0 -0
  76. package/dist/public/lib/samples/strings/C6.mp3 +0 -0
  77. package/dist/public/lib/samples/strings/G2.mp3 +0 -0
  78. package/dist/public/lib/samples/strings/G3.mp3 +0 -0
  79. package/dist/public/lib/samples/strings/G4.mp3 +0 -0
  80. package/dist/public/lib/samples/strings/G5.mp3 +0 -0
  81. package/dist/public/lib/samples/theme-check.html +92 -0
  82. package/dist/public/lib/samples/themes-boot.js +20 -0
  83. package/dist/public/lib/samples/themes.html +154 -0
  84. package/dist/public/lib/samples/themes.js +60 -0
  85. package/dist/public/lib/samples/trumpet/A3.mp3 +0 -0
  86. package/dist/public/lib/samples/trumpet/A4.mp3 +0 -0
  87. package/dist/public/lib/samples/trumpet/A5.mp3 +0 -0
  88. package/dist/public/lib/samples/trumpet/C4.mp3 +0 -0
  89. package/dist/public/lib/samples/trumpet/C5.mp3 +0 -0
  90. package/dist/public/lib/samples/trumpet/E3.mp3 +0 -0
  91. package/dist/public/lib/samples/trumpet/E4.mp3 +0 -0
  92. package/dist/public/lib/samples/trumpet/E5.mp3 +0 -0
  93. package/dist/public/spa.html +2 -0
  94. package/dist/public/views/app-grant.js +24 -4
  95. package/dist/public/views/portfolio.js +61 -6
  96. package/dist/public/views/profile/access-tab/connected-apps.js +81 -5
  97. package/dist/public/views/profile/apps-tab.js +18 -1
  98. package/dist/public/views/profile/extensions-tab.maturity.js +4 -1
  99. package/dist/public/views/profile/inbox-tab/ai-actions.js +86 -0
  100. package/dist/public/views/profile/inbox-tab/components.js +141 -10
  101. package/dist/public/views/profile/inbox-tab/helpers.js +26 -0
  102. package/dist/public/views/profile/inbox-tab/panels.js +18 -3
  103. package/dist/public/views/profile/inbox-tab/use-thread-ux.js +47 -3
  104. package/dist/public/views/profile/inbox-tab.js +46 -49
  105. package/dist/public/views/profile/landing-page.cards.js +7 -0
  106. package/dist/public/views/profile/landing-page.js +12 -1
  107. package/dist/public/views/profile/libraries-tab.js +10 -2
  108. package/dist/public/views/profile/skills-tab.js +1 -1
  109. package/dist/public/views/profile/wallet-tab.js +64 -0
  110. package/dist/public/views/public-workspace-viewer.js +1 -1
  111. package/dist/public/views/start.js +2 -1
  112. package/dist/scripts/build-sdk-libs.d.ts +16 -0
  113. package/dist/scripts/build-sdk-libs.d.ts.map +1 -0
  114. package/dist/scripts/build-sdk-libs.js +112 -0
  115. package/dist/scripts/build-sdk-libs.js.map +1 -0
  116. package/dist/scripts/check-openapi.d.ts +2 -0
  117. package/dist/scripts/check-openapi.d.ts.map +1 -0
  118. package/dist/scripts/check-openapi.js +139 -0
  119. package/dist/scripts/check-openapi.js.map +1 -0
  120. package/dist/scripts/embed-viewport.d.ts +23 -0
  121. package/dist/scripts/embed-viewport.d.ts.map +1 -0
  122. package/dist/scripts/embed-viewport.js +116 -0
  123. package/dist/scripts/embed-viewport.js.map +1 -0
  124. package/dist/src/auth/sse-domain-scopes.d.ts +50 -0
  125. package/dist/src/auth/sse-domain-scopes.d.ts.map +1 -0
  126. package/dist/src/auth/sse-domain-scopes.js +111 -0
  127. package/dist/src/auth/sse-domain-scopes.js.map +1 -0
  128. package/dist/src/cli/connect/auth.d.ts +15 -0
  129. package/dist/src/cli/connect/auth.d.ts.map +1 -1
  130. package/dist/src/cli/connect/auth.js +25 -6
  131. package/dist/src/cli/connect/auth.js.map +1 -1
  132. package/dist/src/cli/connect/keychain.d.ts +9 -0
  133. package/dist/src/cli/connect/keychain.d.ts.map +1 -1
  134. package/dist/src/cli/connect/keychain.js +21 -8
  135. package/dist/src/cli/connect/keychain.js.map +1 -1
  136. package/dist/src/cli/connect/mcp/tools/agent-tasks.d.ts.map +1 -1
  137. package/dist/src/cli/connect/mcp/tools/agent-tasks.js +4 -1
  138. package/dist/src/cli/connect/mcp/tools/agent-tasks.js.map +1 -1
  139. package/dist/src/cli/connect/mcp/tools/core.d.ts.map +1 -1
  140. package/dist/src/cli/connect/mcp/tools/core.js +14 -3
  141. package/dist/src/cli/connect/mcp/tools/core.js.map +1 -1
  142. package/dist/src/cli/connect/mcp/tools/exchange.d.ts +18 -0
  143. package/dist/src/cli/connect/mcp/tools/exchange.d.ts.map +1 -0
  144. package/dist/src/cli/connect/mcp/tools/exchange.js +170 -0
  145. package/dist/src/cli/connect/mcp/tools/exchange.js.map +1 -0
  146. package/dist/src/cli/connect/mcp/tools/index.d.ts.map +1 -1
  147. package/dist/src/cli/connect/mcp/tools/index.js +2 -0
  148. package/dist/src/cli/connect/mcp/tools/index.js.map +1 -1
  149. package/dist/src/cli/connect/mcp/tools/workspaces.d.ts +3 -0
  150. package/dist/src/cli/connect/mcp/tools/workspaces.d.ts.map +1 -1
  151. package/dist/src/cli/connect/mcp/tools/workspaces.js +4 -2
  152. package/dist/src/cli/connect/mcp/tools/workspaces.js.map +1 -1
  153. package/dist/src/cli/connect/tool-call-defs-core.d.ts.map +1 -1
  154. package/dist/src/cli/connect/tool-call-defs-core.js +13 -1
  155. package/dist/src/cli/connect/tool-call-defs-core.js.map +1 -1
  156. package/dist/src/cli/connect/tool-call-defs-exchange.d.ts +3 -0
  157. package/dist/src/cli/connect/tool-call-defs-exchange.d.ts.map +1 -0
  158. package/dist/src/cli/connect/tool-call-defs-exchange.js +146 -0
  159. package/dist/src/cli/connect/tool-call-defs-exchange.js.map +1 -0
  160. package/dist/src/cli/connect/tool-call.d.ts.map +1 -1
  161. package/dist/src/cli/connect/tool-call.js +2 -0
  162. package/dist/src/cli/connect/tool-call.js.map +1 -1
  163. package/dist/src/commerce/__tests__/x402-registry.test.d.ts +2 -0
  164. package/dist/src/commerce/__tests__/x402-registry.test.d.ts.map +1 -0
  165. package/dist/src/commerce/__tests__/x402-registry.test.js +105 -0
  166. package/dist/src/commerce/__tests__/x402-registry.test.js.map +1 -0
  167. package/dist/src/commerce/evm-address.d.ts +21 -0
  168. package/dist/src/commerce/evm-address.d.ts.map +1 -0
  169. package/dist/src/commerce/evm-address.js +94 -0
  170. package/dist/src/commerce/evm-address.js.map +1 -0
  171. package/dist/src/commerce/money.d.ts +18 -5
  172. package/dist/src/commerce/money.d.ts.map +1 -1
  173. package/dist/src/commerce/money.js +27 -6
  174. package/dist/src/commerce/money.js.map +1 -1
  175. package/dist/src/commerce/session-service.d.ts +14 -0
  176. package/dist/src/commerce/session-service.d.ts.map +1 -1
  177. package/dist/src/commerce/session-service.js +1 -1
  178. package/dist/src/commerce/session-service.js.map +1 -1
  179. package/dist/src/commerce/x402-facilitator.d.ts +64 -13
  180. package/dist/src/commerce/x402-facilitator.d.ts.map +1 -1
  181. package/dist/src/commerce/x402-facilitator.js +71 -19
  182. package/dist/src/commerce/x402-facilitator.js.map +1 -1
  183. package/dist/src/commerce/x402-handler.d.ts +13 -7
  184. package/dist/src/commerce/x402-handler.d.ts.map +1 -1
  185. package/dist/src/commerce/x402-handler.js +23 -10
  186. package/dist/src/commerce/x402-handler.js.map +1 -1
  187. package/dist/src/commerce/x402.d.ts +11 -6
  188. package/dist/src/commerce/x402.d.ts.map +1 -1
  189. package/dist/src/commerce/x402.js +10 -7
  190. package/dist/src/commerce/x402.js.map +1 -1
  191. package/dist/src/config-types.d.ts +12 -0
  192. package/dist/src/config-types.d.ts.map +1 -1
  193. package/dist/src/config.d.ts.map +1 -1
  194. package/dist/src/config.js +8 -0
  195. package/dist/src/config.js.map +1 -1
  196. package/dist/src/data/app-templates/shells.d.ts +15 -3
  197. package/dist/src/data/app-templates/shells.d.ts.map +1 -1
  198. package/dist/src/data/app-templates/shells.js +97 -12
  199. package/dist/src/data/app-templates/shells.js.map +1 -1
  200. package/dist/src/data/app-templates.js +2 -2
  201. package/dist/src/data/app-templates.js.map +1 -1
  202. package/dist/src/data/appdev-pitfalls.d.ts +2 -0
  203. package/dist/src/data/appdev-pitfalls.d.ts.map +1 -1
  204. package/dist/src/data/appdev-pitfalls.js +24 -1
  205. package/dist/src/data/appdev-pitfalls.js.map +1 -1
  206. package/dist/src/data/library-packs/cortex.d.ts.map +1 -1
  207. package/dist/src/data/library-packs/cortex.js +108 -5
  208. package/dist/src/data/library-packs/cortex.js.map +1 -1
  209. package/dist/src/data/library-packs/sdk.d.ts.map +1 -1
  210. package/dist/src/data/library-packs/sdk.js +32 -8
  211. package/dist/src/data/library-packs/sdk.js.map +1 -1
  212. package/dist/src/data/library-packs/vendored.d.ts.map +1 -1
  213. package/dist/src/data/library-packs/vendored.js +83 -6
  214. package/dist/src/data/library-packs/vendored.js.map +1 -1
  215. package/dist/src/generated/api-types.d.ts +2039 -24
  216. package/dist/src/generated/api-types.d.ts.map +1 -1
  217. package/dist/src/mcp/agent-tasks.d.ts +4 -0
  218. package/dist/src/mcp/agent-tasks.d.ts.map +1 -1
  219. package/dist/src/mcp/agent-tasks.js +20 -2
  220. package/dist/src/mcp/agent-tasks.js.map +1 -1
  221. package/dist/src/mcp/annotations.d.ts.map +1 -1
  222. package/dist/src/mcp/annotations.js +20 -0
  223. package/dist/src/mcp/annotations.js.map +1 -1
  224. package/dist/src/mcp/apps.d.ts.map +1 -1
  225. package/dist/src/mcp/apps.js +8 -4
  226. package/dist/src/mcp/apps.js.map +1 -1
  227. package/dist/src/mcp/capabilities.d.ts +7 -1
  228. package/dist/src/mcp/capabilities.d.ts.map +1 -1
  229. package/dist/src/mcp/capabilities.js +5 -2
  230. package/dist/src/mcp/capabilities.js.map +1 -1
  231. package/dist/src/mcp/catalog/definitions/commerce.d.ts.map +1 -1
  232. package/dist/src/mcp/catalog/definitions/commerce.js +4 -2
  233. package/dist/src/mcp/catalog/definitions/commerce.js.map +1 -1
  234. package/dist/src/mcp/catalog/definitions/discovery-work-boards.d.ts.map +1 -1
  235. package/dist/src/mcp/catalog/definitions/discovery-work-boards.js +4 -3
  236. package/dist/src/mcp/catalog/definitions/discovery-work-boards.js.map +1 -1
  237. package/dist/src/mcp/catalog/definitions/exchange.d.ts +18 -0
  238. package/dist/src/mcp/catalog/definitions/exchange.d.ts.map +1 -0
  239. package/dist/src/mcp/catalog/definitions/exchange.js +182 -0
  240. package/dist/src/mcp/catalog/definitions/exchange.js.map +1 -0
  241. package/dist/src/mcp/catalog/definitions/organisms-workspaces-apps.js +1 -1
  242. package/dist/src/mcp/catalog/definitions/organisms-workspaces-apps.js.map +1 -1
  243. package/dist/src/mcp/catalog/definitions/schedules-tasks-memory.d.ts.map +1 -1
  244. package/dist/src/mcp/catalog/definitions/schedules-tasks-memory.js +3 -2
  245. package/dist/src/mcp/catalog/definitions/schedules-tasks-memory.js.map +1 -1
  246. package/dist/src/mcp/catalog/definitions.d.ts.map +1 -1
  247. package/dist/src/mcp/catalog/definitions.js +2 -0
  248. package/dist/src/mcp/catalog/definitions.js.map +1 -1
  249. package/dist/src/mcp/catalog/output-schemas.d.ts +6 -1
  250. package/dist/src/mcp/catalog/output-schemas.d.ts.map +1 -1
  251. package/dist/src/mcp/catalog/output-schemas.js +6 -1
  252. package/dist/src/mcp/catalog/output-schemas.js.map +1 -1
  253. package/dist/src/mcp/catalog/scopes.d.ts.map +1 -1
  254. package/dist/src/mcp/catalog/scopes.js +22 -0
  255. package/dist/src/mcp/catalog/scopes.js.map +1 -1
  256. package/dist/src/mcp/catalog/surfaces.d.ts.map +1 -1
  257. package/dist/src/mcp/catalog/surfaces.js +14 -0
  258. package/dist/src/mcp/catalog/surfaces.js.map +1 -1
  259. package/dist/src/mcp/commerce.d.ts.map +1 -1
  260. package/dist/src/mcp/commerce.js +15 -3
  261. package/dist/src/mcp/commerce.js.map +1 -1
  262. package/dist/src/mcp/core-storage.d.ts +23 -0
  263. package/dist/src/mcp/core-storage.d.ts.map +1 -0
  264. package/dist/src/mcp/core-storage.js +157 -0
  265. package/dist/src/mcp/core-storage.js.map +1 -0
  266. package/dist/src/mcp/core.d.ts +16 -0
  267. package/dist/src/mcp/core.d.ts.map +1 -1
  268. package/dist/src/mcp/core.js +75 -119
  269. package/dist/src/mcp/core.js.map +1 -1
  270. package/dist/src/mcp/dm-messages.d.ts +4 -0
  271. package/dist/src/mcp/dm-messages.d.ts.map +1 -1
  272. package/dist/src/mcp/dm-messages.js +43 -2
  273. package/dist/src/mcp/dm-messages.js.map +1 -1
  274. package/dist/src/mcp/exchange-run.d.ts +5 -0
  275. package/dist/src/mcp/exchange-run.d.ts.map +1 -0
  276. package/dist/src/mcp/exchange-run.js +226 -0
  277. package/dist/src/mcp/exchange-run.js.map +1 -0
  278. package/dist/src/mcp/exchange.d.ts +5 -0
  279. package/dist/src/mcp/exchange.d.ts.map +1 -0
  280. package/dist/src/mcp/exchange.js +352 -0
  281. package/dist/src/mcp/exchange.js.map +1 -0
  282. package/dist/src/mcp/extensions.d.ts.map +1 -1
  283. package/dist/src/mcp/extensions.js +17 -2
  284. package/dist/src/mcp/extensions.js.map +1 -1
  285. package/dist/src/mcp/index.d.ts +5 -0
  286. package/dist/src/mcp/index.d.ts.map +1 -1
  287. package/dist/src/mcp/index.js +26 -3
  288. package/dist/src/mcp/index.js.map +1 -1
  289. package/dist/src/mcp/memory-namespace-hints.d.ts +33 -0
  290. package/dist/src/mcp/memory-namespace-hints.d.ts.map +1 -0
  291. package/dist/src/mcp/memory-namespace-hints.js +60 -0
  292. package/dist/src/mcp/memory-namespace-hints.js.map +1 -0
  293. package/dist/src/mcp/workspaces.d.ts +5 -0
  294. package/dist/src/mcp/workspaces.d.ts.map +1 -1
  295. package/dist/src/mcp/workspaces.js +5 -3
  296. package/dist/src/mcp/workspaces.js.map +1 -1
  297. package/dist/src/models/agent-task-schemas.d.ts +25 -3
  298. package/dist/src/models/agent-task-schemas.d.ts.map +1 -1
  299. package/dist/src/models/agent-task-schemas.js +16 -0
  300. package/dist/src/models/agent-task-schemas.js.map +1 -1
  301. package/dist/src/models/app-tool-schemas.d.ts +573 -2
  302. package/dist/src/models/app-tool-schemas.d.ts.map +1 -1
  303. package/dist/src/models/app-tool-schemas.js +73 -2
  304. package/dist/src/models/app-tool-schemas.js.map +1 -1
  305. package/dist/src/models/odps-schemas.d.ts +305 -0
  306. package/dist/src/models/odps-schemas.d.ts.map +1 -0
  307. package/dist/src/models/odps-schemas.js +182 -0
  308. package/dist/src/models/odps-schemas.js.map +1 -0
  309. package/dist/src/models/offer-schemas.d.ts +359 -4
  310. package/dist/src/models/offer-schemas.d.ts.map +1 -1
  311. package/dist/src/models/offer-schemas.js +37 -0
  312. package/dist/src/models/offer-schemas.js.map +1 -1
  313. package/dist/src/models/schemas.d.ts +7 -3
  314. package/dist/src/models/schemas.d.ts.map +1 -1
  315. package/dist/src/models/schemas.js +13 -1
  316. package/dist/src/models/schemas.js.map +1 -1
  317. package/dist/src/models/webhook-schemas.d.ts +8 -8
  318. package/dist/src/routes/agent-tasks/create-read.d.ts +4 -0
  319. package/dist/src/routes/agent-tasks/create-read.d.ts.map +1 -1
  320. package/dist/src/routes/agent-tasks/create-read.js +20 -1
  321. package/dist/src/routes/agent-tasks/create-read.js.map +1 -1
  322. package/dist/src/routes/agent-tasks/lifecycle.d.ts.map +1 -1
  323. package/dist/src/routes/agent-tasks/lifecycle.js +10 -0
  324. package/dist/src/routes/agent-tasks/lifecycle.js.map +1 -1
  325. package/dist/src/routes/agents/device-auth.d.ts +4 -0
  326. package/dist/src/routes/agents/device-auth.d.ts.map +1 -1
  327. package/dist/src/routes/agents/device-auth.js +19 -4
  328. package/dist/src/routes/agents/device-auth.js.map +1 -1
  329. package/dist/src/routes/agents/offers.d.ts +2 -0
  330. package/dist/src/routes/agents/offers.d.ts.map +1 -1
  331. package/dist/src/routes/agents/offers.js +0 -0
  332. package/dist/src/routes/agents/offers.js.map +1 -1
  333. package/dist/src/routes/app-grants.d.ts +12 -0
  334. package/dist/src/routes/app-grants.d.ts.map +1 -1
  335. package/dist/src/routes/app-grants.js +90 -27
  336. package/dist/src/routes/app-grants.js.map +1 -1
  337. package/dist/src/routes/apps/drafts.d.ts +3 -0
  338. package/dist/src/routes/apps/drafts.d.ts.map +1 -1
  339. package/dist/src/routes/apps/drafts.js +63 -1
  340. package/dist/src/routes/apps/drafts.js.map +1 -1
  341. package/dist/src/routes/apps/fork-manage.d.ts.map +1 -1
  342. package/dist/src/routes/apps/fork-manage.js +24 -1
  343. package/dist/src/routes/apps/fork-manage.js.map +1 -1
  344. package/dist/src/routes/apps/publish.d.ts +4 -0
  345. package/dist/src/routes/apps/publish.d.ts.map +1 -1
  346. package/dist/src/routes/apps/publish.js +44 -3
  347. package/dist/src/routes/apps/publish.js.map +1 -1
  348. package/dist/src/routes/apps-cost.d.ts +25 -0
  349. package/dist/src/routes/apps-cost.d.ts.map +1 -0
  350. package/dist/src/routes/apps-cost.js +107 -0
  351. package/dist/src/routes/apps-cost.js.map +1 -0
  352. package/dist/src/routes/commerce.d.ts.map +1 -1
  353. package/dist/src/routes/commerce.js +122 -2
  354. package/dist/src/routes/commerce.js.map +1 -1
  355. package/dist/src/routes/exchange-market.d.ts +32 -0
  356. package/dist/src/routes/exchange-market.d.ts.map +1 -0
  357. package/dist/src/routes/exchange-market.js +580 -0
  358. package/dist/src/routes/exchange-market.js.map +1 -0
  359. package/dist/src/routes/exchange.d.ts +33 -0
  360. package/dist/src/routes/exchange.d.ts.map +1 -0
  361. package/dist/src/routes/exchange.js +398 -0
  362. package/dist/src/routes/exchange.js.map +1 -0
  363. package/dist/src/routes/extensions/actions.d.ts.map +1 -1
  364. package/dist/src/routes/extensions/actions.js +18 -0
  365. package/dist/src/routes/extensions/actions.js.map +1 -1
  366. package/dist/src/routes/extensions/crud.d.ts.map +1 -1
  367. package/dist/src/routes/extensions/crud.js +36 -3
  368. package/dist/src/routes/extensions/crud.js.map +1 -1
  369. package/dist/src/routes/extensions/entitlement-gate.d.ts +33 -0
  370. package/dist/src/routes/extensions/entitlement-gate.d.ts.map +1 -0
  371. package/dist/src/routes/extensions/entitlement-gate.js +156 -0
  372. package/dist/src/routes/extensions/entitlement-gate.js.map +1 -0
  373. package/dist/src/routes/extensions/manifest.d.ts +15 -0
  374. package/dist/src/routes/extensions/manifest.d.ts.map +1 -1
  375. package/dist/src/routes/extensions/manifest.js +101 -2
  376. package/dist/src/routes/extensions/manifest.js.map +1 -1
  377. package/dist/src/routes/extensions/pacing.d.ts +31 -0
  378. package/dist/src/routes/extensions/pacing.d.ts.map +1 -0
  379. package/dist/src/routes/extensions/pacing.js +73 -0
  380. package/dist/src/routes/extensions/pacing.js.map +1 -0
  381. package/dist/src/routes/extensions/paywall.d.ts.map +1 -1
  382. package/dist/src/routes/extensions/paywall.js +20 -11
  383. package/dist/src/routes/extensions/paywall.js.map +1 -1
  384. package/dist/src/routes/federation-sync/messaging.d.ts.map +1 -1
  385. package/dist/src/routes/federation-sync/messaging.js +3 -1
  386. package/dist/src/routes/federation-sync/messaging.js.map +1 -1
  387. package/dist/src/routes/ghii/recovery.d.ts +2 -0
  388. package/dist/src/routes/ghii/recovery.d.ts.map +1 -1
  389. package/dist/src/routes/ghii/recovery.js +7 -0
  390. package/dist/src/routes/ghii/recovery.js.map +1 -1
  391. package/dist/src/routes/ghii/register-login.d.ts +4 -0
  392. package/dist/src/routes/ghii/register-login.d.ts.map +1 -1
  393. package/dist/src/routes/ghii/register-login.js +45 -22
  394. package/dist/src/routes/ghii/register-login.js.map +1 -1
  395. package/dist/src/routes/ghii/web-verify.d.ts +5 -0
  396. package/dist/src/routes/ghii/web-verify.d.ts.map +1 -1
  397. package/dist/src/routes/ghii/web-verify.js +24 -3
  398. package/dist/src/routes/ghii/web-verify.js.map +1 -1
  399. package/dist/src/routes/libs/sdk-serve.d.ts +11 -0
  400. package/dist/src/routes/libs/sdk-serve.d.ts.map +1 -0
  401. package/dist/src/routes/libs/sdk-serve.js +53 -0
  402. package/dist/src/routes/libs/sdk-serve.js.map +1 -0
  403. package/dist/src/routes/libs.d.ts +7 -1
  404. package/dist/src/routes/libs.d.ts.map +1 -1
  405. package/dist/src/routes/libs.js +65 -146
  406. package/dist/src/routes/libs.js.map +1 -1
  407. package/dist/src/routes/memory/crud.d.ts.map +1 -1
  408. package/dist/src/routes/memory/crud.js +10 -0
  409. package/dist/src/routes/memory/crud.js.map +1 -1
  410. package/dist/src/routes/messages.d.ts +3 -0
  411. package/dist/src/routes/messages.d.ts.map +1 -1
  412. package/dist/src/routes/messages.js +9 -0
  413. package/dist/src/routes/messages.js.map +1 -1
  414. package/dist/src/routes/notifications.d.ts +6 -3
  415. package/dist/src/routes/notifications.d.ts.map +1 -1
  416. package/dist/src/routes/notifications.js +32 -3
  417. package/dist/src/routes/notifications.js.map +1 -1
  418. package/dist/src/routes/organisms/crud.d.ts +3 -0
  419. package/dist/src/routes/organisms/crud.d.ts.map +1 -1
  420. package/dist/src/routes/organisms/crud.js +5 -2
  421. package/dist/src/routes/organisms/crud.js.map +1 -1
  422. package/dist/src/routes/organisms/workspace-access.d.ts.map +1 -1
  423. package/dist/src/routes/organisms/workspace-access.js +38 -20
  424. package/dist/src/routes/organisms/workspace-access.js.map +1 -1
  425. package/dist/src/routes/organisms/workspace-read.d.ts.map +1 -1
  426. package/dist/src/routes/organisms/workspace-read.js +7 -2
  427. package/dist/src/routes/organisms/workspace-read.js.map +1 -1
  428. package/dist/src/routes/public-stats.d.ts +7 -0
  429. package/dist/src/routes/public-stats.d.ts.map +1 -1
  430. package/dist/src/routes/public-stats.js +28 -7
  431. package/dist/src/routes/public-stats.js.map +1 -1
  432. package/dist/src/routes/sse.d.ts +7 -0
  433. package/dist/src/routes/sse.d.ts.map +1 -1
  434. package/dist/src/routes/sse.js +36 -6
  435. package/dist/src/routes/sse.js.map +1 -1
  436. package/dist/src/routes/storage-files.d.ts +11 -0
  437. package/dist/src/routes/storage-files.d.ts.map +1 -1
  438. package/dist/src/routes/storage-files.js +58 -51
  439. package/dist/src/routes/storage-files.js.map +1 -1
  440. package/dist/src/routes/subdomains.d.ts +4 -0
  441. package/dist/src/routes/subdomains.d.ts.map +1 -1
  442. package/dist/src/routes/subdomains.js +42 -5
  443. package/dist/src/routes/subdomains.js.map +1 -1
  444. package/dist/src/routes/unfurl.d.ts +27 -0
  445. package/dist/src/routes/unfurl.d.ts.map +1 -0
  446. package/dist/src/routes/unfurl.js +180 -0
  447. package/dist/src/routes/unfurl.js.map +1 -0
  448. package/dist/src/routes/upload.d.ts +13 -0
  449. package/dist/src/routes/upload.d.ts.map +1 -1
  450. package/dist/src/routes/upload.js +115 -28
  451. package/dist/src/routes/upload.js.map +1 -1
  452. package/dist/src/routes/webmcp.d.ts +3 -0
  453. package/dist/src/routes/webmcp.d.ts.map +1 -1
  454. package/dist/src/routes/webmcp.js +59 -0
  455. package/dist/src/routes/webmcp.js.map +1 -1
  456. package/dist/src/schemas/knowledge-package.d.ts +1 -1
  457. package/dist/src/server-bootstrap/routes-loader.d.ts +1 -0
  458. package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
  459. package/dist/src/server-bootstrap/routes-loader.js +8 -0
  460. package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
  461. package/dist/src/server-bootstrap/static-files.d.ts +4 -0
  462. package/dist/src/server-bootstrap/static-files.d.ts.map +1 -1
  463. package/dist/src/server-bootstrap/static-files.js +11 -0
  464. package/dist/src/server-bootstrap/static-files.js.map +1 -1
  465. package/dist/src/services/agent-face.d.ts +10 -2
  466. package/dist/src/services/agent-face.d.ts.map +1 -1
  467. package/dist/src/services/agent-face.js +10 -4
  468. package/dist/src/services/agent-face.js.map +1 -1
  469. package/dist/src/services/app-tool-interfaces.d.ts +37 -0
  470. package/dist/src/services/app-tool-interfaces.d.ts.map +1 -0
  471. package/dist/src/services/app-tool-interfaces.js +101 -0
  472. package/dist/src/services/app-tool-interfaces.js.map +1 -0
  473. package/dist/src/services/build-app-prompt.d.ts +22 -0
  474. package/dist/src/services/build-app-prompt.d.ts.map +1 -1
  475. package/dist/src/services/build-app-prompt.js +108 -11
  476. package/dist/src/services/build-app-prompt.js.map +1 -1
  477. package/dist/src/services/call-timing.d.ts +51 -0
  478. package/dist/src/services/call-timing.d.ts.map +1 -0
  479. package/dist/src/services/call-timing.js +91 -0
  480. package/dist/src/services/call-timing.js.map +1 -0
  481. package/dist/src/services/capability-invoke.d.ts +2 -0
  482. package/dist/src/services/capability-invoke.d.ts.map +1 -1
  483. package/dist/src/services/capability-invoke.js +10 -0
  484. package/dist/src/services/capability-invoke.js.map +1 -1
  485. package/dist/src/services/config-schema.d.ts.map +1 -1
  486. package/dist/src/services/config-schema.js +6 -0
  487. package/dist/src/services/config-schema.js.map +1 -1
  488. package/dist/src/services/contacts.d.ts +25 -1
  489. package/dist/src/services/contacts.d.ts.map +1 -1
  490. package/dist/src/services/contacts.js +30 -0
  491. package/dist/src/services/contacts.js.map +1 -1
  492. package/dist/src/services/draft-token.d.ts +22 -2
  493. package/dist/src/services/draft-token.d.ts.map +1 -1
  494. package/dist/src/services/draft-token.js +52 -3
  495. package/dist/src/services/draft-token.js.map +1 -1
  496. package/dist/src/services/entitlement-money.d.ts +55 -0
  497. package/dist/src/services/entitlement-money.d.ts.map +1 -0
  498. package/dist/src/services/entitlement-money.js +68 -0
  499. package/dist/src/services/entitlement-money.js.map +1 -0
  500. package/dist/src/services/exchange-market.d.ts +280 -0
  501. package/dist/src/services/exchange-market.d.ts.map +1 -0
  502. package/dist/src/services/exchange-market.js +276 -0
  503. package/dist/src/services/exchange-market.js.map +1 -0
  504. package/dist/src/services/exchange-odps.d.ts +58 -0
  505. package/dist/src/services/exchange-odps.d.ts.map +1 -0
  506. package/dist/src/services/exchange-odps.js +400 -0
  507. package/dist/src/services/exchange-odps.js.map +1 -0
  508. package/dist/src/services/exchange-projection.d.ts +61 -0
  509. package/dist/src/services/exchange-projection.d.ts.map +1 -0
  510. package/dist/src/services/exchange-projection.js +504 -0
  511. package/dist/src/services/exchange-projection.js.map +1 -0
  512. package/dist/src/services/exchange-proposals.d.ts +47 -0
  513. package/dist/src/services/exchange-proposals.d.ts.map +1 -0
  514. package/dist/src/services/exchange-proposals.js +73 -0
  515. package/dist/src/services/exchange-proposals.js.map +1 -0
  516. package/dist/src/services/exchange-work.d.ts +30 -0
  517. package/dist/src/services/exchange-work.d.ts.map +1 -0
  518. package/dist/src/services/exchange-work.js +43 -0
  519. package/dist/src/services/exchange-work.js.map +1 -0
  520. package/dist/src/services/extension-files.d.ts +64 -0
  521. package/dist/src/services/extension-files.d.ts.map +1 -0
  522. package/dist/src/services/extension-files.js +88 -0
  523. package/dist/src/services/extension-files.js.map +1 -0
  524. package/dist/src/services/extension-runtime.d.ts +33 -0
  525. package/dist/src/services/extension-runtime.d.ts.map +1 -1
  526. package/dist/src/services/extension-runtime.js +52 -0
  527. package/dist/src/services/extension-runtime.js.map +1 -1
  528. package/dist/src/services/file-refs.d.ts +105 -0
  529. package/dist/src/services/file-refs.d.ts.map +1 -0
  530. package/dist/src/services/file-refs.js +106 -0
  531. package/dist/src/services/file-refs.js.map +1 -0
  532. package/dist/src/services/message-send.d.ts.map +1 -1
  533. package/dist/src/services/message-send.js +4 -1
  534. package/dist/src/services/message-send.js.map +1 -1
  535. package/dist/src/services/metered-entitlements.d.ts +210 -0
  536. package/dist/src/services/metered-entitlements.d.ts.map +1 -0
  537. package/dist/src/services/metered-entitlements.js +268 -0
  538. package/dist/src/services/metered-entitlements.js.map +1 -0
  539. package/dist/src/services/notify.d.ts +7 -0
  540. package/dist/src/services/notify.d.ts.map +1 -1
  541. package/dist/src/services/notify.js +35 -0
  542. package/dist/src/services/notify.js.map +1 -1
  543. package/dist/src/services/owner-memory.d.ts +30 -1
  544. package/dist/src/services/owner-memory.d.ts.map +1 -1
  545. package/dist/src/services/owner-memory.js +31 -14
  546. package/dist/src/services/owner-memory.js.map +1 -1
  547. package/dist/src/services/owner-provisioning.d.ts +5 -0
  548. package/dist/src/services/owner-provisioning.d.ts.map +1 -1
  549. package/dist/src/services/owner-provisioning.js +20 -2
  550. package/dist/src/services/owner-provisioning.js.map +1 -1
  551. package/dist/src/services/task-files.d.ts +51 -0
  552. package/dist/src/services/task-files.d.ts.map +1 -0
  553. package/dist/src/services/task-files.js +58 -0
  554. package/dist/src/services/task-files.js.map +1 -0
  555. package/dist/src/services/upload-token.d.ts +29 -0
  556. package/dist/src/services/upload-token.d.ts.map +1 -1
  557. package/dist/src/services/upload-token.js +37 -0
  558. package/dist/src/services/upload-token.js.map +1 -1
  559. package/dist/src/services/upload-zip.d.ts +2 -0
  560. package/dist/src/services/upload-zip.d.ts.map +1 -1
  561. package/dist/src/services/upload-zip.js +5 -1
  562. package/dist/src/services/upload-zip.js.map +1 -1
  563. package/dist/src/services/workspace-meta.d.ts +15 -0
  564. package/dist/src/services/workspace-meta.d.ts.map +1 -1
  565. package/dist/src/services/workspace-meta.js +17 -0
  566. package/dist/src/services/workspace-meta.js.map +1 -1
  567. package/dist/src/services/workspace-provision.d.ts +3 -0
  568. package/dist/src/services/workspace-provision.d.ts.map +1 -1
  569. package/dist/src/services/workspace-provision.js +5 -3
  570. package/dist/src/services/workspace-provision.js.map +1 -1
  571. package/dist/src/storage/providers/postgres-kysely/methods/app-grants.d.ts +1 -0
  572. package/dist/src/storage/providers/postgres-kysely/methods/app-grants.d.ts.map +1 -1
  573. package/dist/src/storage/providers/postgres-kysely/methods/app-grants.js +10 -0
  574. package/dist/src/storage/providers/postgres-kysely/methods/app-grants.js.map +1 -1
  575. package/dist/src/storage/providers/postgres-kysely/methods/apps.d.ts +1 -0
  576. package/dist/src/storage/providers/postgres-kysely/methods/apps.d.ts.map +1 -1
  577. package/dist/src/storage/providers/postgres-kysely/methods/apps.js +2 -0
  578. package/dist/src/storage/providers/postgres-kysely/methods/apps.js.map +1 -1
  579. package/dist/src/storage/providers/postgres-kysely/methods/identity.d.ts +1 -0
  580. package/dist/src/storage/providers/postgres-kysely/methods/identity.d.ts.map +1 -1
  581. package/dist/src/storage/providers/postgres-kysely/methods/identity.js +4 -0
  582. package/dist/src/storage/providers/postgres-kysely/methods/identity.js.map +1 -1
  583. package/dist/src/storage/providers/postgres-kysely/methods/memory.d.ts +2 -0
  584. package/dist/src/storage/providers/postgres-kysely/methods/memory.d.ts.map +1 -1
  585. package/dist/src/storage/providers/postgres-kysely/methods/memory.js +12 -1
  586. package/dist/src/storage/providers/postgres-kysely/methods/memory.js.map +1 -1
  587. package/dist/src/storage/providers/postgres-kysely/methods/organisms.d.ts.map +1 -1
  588. package/dist/src/storage/providers/postgres-kysely/methods/organisms.js +5 -1
  589. package/dist/src/storage/providers/postgres-kysely/methods/organisms.js.map +1 -1
  590. package/dist/src/storage/providers/postgres-kysely/migrations/0011_unique_verified_email.sql +25 -0
  591. package/dist/src/storage/providers/postgres-kysely/migrations/0012_unique_live_app_grant.sql +29 -0
  592. package/dist/src/storage/providers/sqlite/methods/apps.d.ts +4 -0
  593. package/dist/src/storage/providers/sqlite/methods/apps.d.ts.map +1 -1
  594. package/dist/src/storage/providers/sqlite/methods/apps.js +9 -0
  595. package/dist/src/storage/providers/sqlite/methods/apps.js.map +1 -1
  596. package/dist/src/storage/providers/sqlite/methods/governance.d.ts +1 -0
  597. package/dist/src/storage/providers/sqlite/methods/governance.d.ts.map +1 -1
  598. package/dist/src/storage/providers/sqlite/methods/governance.js +4 -1
  599. package/dist/src/storage/providers/sqlite/methods/governance.js.map +1 -1
  600. package/dist/src/storage/providers/sqlite/methods/identity-nodes.d.ts +1 -0
  601. package/dist/src/storage/providers/sqlite/methods/identity-nodes.d.ts.map +1 -1
  602. package/dist/src/storage/providers/sqlite/methods/identity-nodes.js +4 -0
  603. package/dist/src/storage/providers/sqlite/methods/identity-nodes.js.map +1 -1
  604. package/dist/src/storage/providers/sqlite/methods/owner.d.ts +5 -0
  605. package/dist/src/storage/providers/sqlite/methods/owner.d.ts.map +1 -1
  606. package/dist/src/storage/providers/sqlite/methods/owner.js +8 -0
  607. package/dist/src/storage/providers/sqlite/methods/owner.js.map +1 -1
  608. package/dist/src/storage/providers/sqlite/schema.d.ts +3 -0
  609. package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
  610. package/dist/src/storage/providers/sqlite/schema.js +40 -0
  611. package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
  612. package/dist/src/storage/repositories/app-grant.repository.d.ts +9 -1
  613. package/dist/src/storage/repositories/app-grant.repository.d.ts.map +1 -1
  614. package/dist/src/storage/repositories/app.repository.d.ts +0 -0
  615. package/dist/src/storage/repositories/app.repository.d.ts.map +1 -1
  616. package/dist/src/storage/repositories/identity.repository.d.ts +6 -0
  617. package/dist/src/storage/repositories/identity.repository.d.ts.map +1 -1
  618. package/dist/src/storage/repositories/memory.repository.d.ts +14 -0
  619. package/dist/src/storage/repositories/memory.repository.d.ts.map +1 -1
  620. package/dist/src/storage/repositories-impl/memory-repository.d.ts +8 -1
  621. package/dist/src/storage/repositories-impl/memory-repository.d.ts.map +1 -1
  622. package/dist/src/storage/repositories-impl/memory-repository.js +15 -4
  623. package/dist/src/storage/repositories-impl/memory-repository.js.map +1 -1
  624. package/dist/src/storage/types/agents-messaging.d.ts +19 -0
  625. package/dist/src/storage/types/agents-messaging.d.ts.map +1 -1
  626. package/dist/src/storage/types/agents-messaging.js.map +1 -1
  627. package/dist/src/storage/types/apps.d.ts +1 -0
  628. package/dist/src/storage/types/apps.d.ts.map +1 -1
  629. package/dist/src/storage/types/organisms-federation.d.ts +50 -0
  630. package/dist/src/storage/types/organisms-federation.d.ts.map +1 -1
  631. package/dist/src/utils/app-badge.d.ts.map +1 -1
  632. package/dist/src/utils/app-badge.js +7 -3
  633. package/dist/src/utils/app-badge.js.map +1 -1
  634. package/dist/src/utils/app-mobile-lint.d.ts +17 -0
  635. package/dist/src/utils/app-mobile-lint.d.ts.map +1 -0
  636. package/dist/src/utils/app-mobile-lint.js +40 -0
  637. package/dist/src/utils/app-mobile-lint.js.map +1 -0
  638. package/dist/static/app-catalog/_template.html +18 -82
  639. package/dist/static/app-catalog/js/apps-io.js +51 -165
  640. package/dist/static/app-catalog/js/cortex.js +3 -1
  641. package/dist/static/app-catalog/js/cost.js +100 -0
  642. package/dist/static/app-catalog/js/db.js +23 -93
  643. package/dist/static/app-catalog/js/detail.js +568 -59
  644. package/dist/static/app-catalog/js/favorites.js +71 -0
  645. package/dist/static/app-catalog/js/i18n-data.js +369 -19
  646. package/dist/static/app-catalog/js/main.js +50 -139
  647. package/dist/static/app-catalog/js/migrate.js +88 -0
  648. package/dist/static/app-catalog/js/monetize.js +205 -17
  649. package/dist/static/app-catalog/js/odps.js +489 -0
  650. package/dist/static/app-catalog/js/promote.js +70 -0
  651. package/dist/static/app-catalog/js/render.js +29 -139
  652. package/dist/static/app-catalog/js/server-io.js +126 -223
  653. package/dist/static/app-catalog/js/settings.js +11 -204
  654. package/dist/static/app-catalog/js/workcopy.js +198 -0
  655. package/dist/static/app-catalog/styles/app-catalog.css +100 -0
  656. package/dist/static/app-catalog.html +2220 -1029
  657. package/dist/static/sdk-libs/_core/config.js +52 -0
  658. package/dist/static/sdk-libs/_core/http.js +52 -0
  659. package/dist/static/sdk-libs/_core/namespace.js +33 -0
  660. package/dist/static/sdk-libs/_core/sdk-globals.d.ts +50 -0
  661. package/dist/static/sdk-libs/_core/session.js +66 -0
  662. package/dist/static/sdk-libs/agentface/index.js +102 -0
  663. package/dist/static/sdk-libs/agents/index.js +305 -0
  664. package/dist/static/sdk-libs/ai/index.js +153 -0
  665. package/dist/static/sdk-libs/audio/core.js +111 -0
  666. package/dist/static/sdk-libs/audio/index.js +380 -0
  667. package/dist/static/sdk-libs/audio/instruments.js +369 -0
  668. package/dist/static/sdk-libs/auth/cluster.js +97 -0
  669. package/dist/static/sdk-libs/auth/config.js +46 -0
  670. package/dist/static/sdk-libs/auth/crypto.js +166 -0
  671. package/dist/static/sdk-libs/auth/events.js +27 -0
  672. package/dist/static/sdk-libs/auth/i18n.js +64 -0
  673. package/dist/static/sdk-libs/auth/index.js +61 -0
  674. package/dist/static/sdk-libs/auth/locale.js +151 -0
  675. package/dist/static/sdk-libs/auth/modal.js +554 -0
  676. package/dist/static/sdk-libs/auth/palette.js +172 -0
  677. package/dist/static/sdk-libs/auth/pill.js +198 -0
  678. package/dist/static/sdk-libs/auth/session.js +792 -0
  679. package/dist/static/sdk-libs/auth/signup.js +232 -0
  680. package/dist/static/sdk-libs/auth/theme.js +137 -0
  681. package/dist/static/sdk-libs/capabilities/index.js +179 -0
  682. package/dist/static/sdk-libs/commerce/index.js +243 -0
  683. package/dist/static/sdk-libs/data/index.js +250 -0
  684. package/dist/static/sdk-libs/dist/aimeat-agentface.js +91 -0
  685. package/dist/static/sdk-libs/dist/aimeat-agents.js +348 -0
  686. package/dist/static/sdk-libs/dist/aimeat-ai.js +168 -0
  687. package/dist/static/sdk-libs/dist/aimeat-audio.js +979 -0
  688. package/dist/static/sdk-libs/dist/aimeat-auth.js +2232 -0
  689. package/dist/static/sdk-libs/dist/aimeat-capabilities.js +177 -0
  690. package/dist/static/sdk-libs/dist/aimeat-commerce.js +265 -0
  691. package/dist/static/sdk-libs/dist/aimeat-data.js +247 -0
  692. package/dist/static/sdk-libs/dist/aimeat-editor.js +299 -0
  693. package/dist/static/sdk-libs/dist/aimeat-header.js +270 -0
  694. package/dist/static/sdk-libs/dist/aimeat-intake.js +94 -0
  695. package/dist/static/sdk-libs/dist/aimeat-live.js +317 -0
  696. package/dist/static/sdk-libs/dist/aimeat-markdown.js +633 -0
  697. package/dist/static/sdk-libs/dist/aimeat-organism.js +394 -0
  698. package/dist/static/sdk-libs/dist/aimeat-portfolio-standalone.js +90 -0
  699. package/dist/static/sdk-libs/dist/aimeat-social.js +157 -0
  700. package/dist/static/sdk-libs/dist/aimeat-speech.js +300 -0
  701. package/dist/static/sdk-libs/dist/aimeat-storage.js +210 -0
  702. package/dist/static/sdk-libs/dist/aimeat-tunnel.js +383 -0
  703. package/dist/static/sdk-libs/dist/aimeat-wallet.js +118 -0
  704. package/dist/static/sdk-libs/dist/aimeat-webmcp.js +187 -0
  705. package/dist/static/sdk-libs/dist/aimeat-work.js +213 -0
  706. package/dist/static/sdk-libs/dist/aimeat-workflows.js +147 -0
  707. package/dist/static/sdk-libs/editor/index.js +229 -0
  708. package/dist/static/sdk-libs/header/index.js +249 -0
  709. package/dist/static/sdk-libs/intake/index.js +75 -0
  710. package/dist/static/sdk-libs/live/index.js +223 -0
  711. package/dist/static/sdk-libs/markdown/index.js +570 -0
  712. package/dist/static/sdk-libs/organism/index.js +381 -0
  713. package/dist/static/sdk-libs/portfolio-standalone/index.js +78 -0
  714. package/dist/static/sdk-libs/social/index.js +140 -0
  715. package/dist/static/sdk-libs/speech/index.js +321 -0
  716. package/dist/static/sdk-libs/storage/index.js +189 -0
  717. package/dist/static/sdk-libs/tunnel/index.js +428 -0
  718. package/dist/static/sdk-libs/wallet/index.js +115 -0
  719. package/dist/static/sdk-libs/webmcp/index.js +185 -0
  720. package/dist/static/sdk-libs/work/index.js +191 -0
  721. package/dist/static/sdk-libs/workflows/index.js +113 -0
  722. package/package.json +10 -3
@@ -8,8 +8,16 @@
8
8
  * injected once via initDetail(deps) — so there is no import cycle back through the entry module.
9
9
  * @usage import { initDetail, openDetailView, mountLoginPill, ... } from './detail.js'; initDetail({...})
10
10
  * @version-history
11
+ * v1.5.0 — 2026-07-25 — TARGET-048 edit-model clarity: the STATUS card becomes a WORKING COPY →
12
+ * PUBLISHED lifecycle band, saving persists (server draft slot) instead of only touching a
13
+ * transient blob, every save leaves a restorable checkpoint ("Working-copy history"), and the
14
+ * three meanings of "draft" are split into working copy / try-it / published version.
15
+ * v1.4.0 — 2026-07-20 — Server-only cutover: drop the local-only favourite star; the detail view
16
+ * always operates on a server app (materialized in memory on demand for editing).
11
17
  * v1.3.0 — 2026-07-16 — Add openStagingPreview(owner, filename): mint a preview token for an
12
18
  * EXISTING staging draft and open it top-level, driving a library card's "Open staging" button.
19
+ * v1.3.0 — 2026-07-20 — Cost & Contracts section (EXCHANGE G3 / TARGET-045): own published apps get a
20
+ * read-only per-app EXCHANGE entitlement surface (cost.js) after Monetize.
13
21
  * v1.2.0 — 2026-07-14 — Monetize section (TARGET-034 phase B): own published apps get the
14
22
  * apps.{appId}.tools tool editor (monetize.js) between Skills and Manage-on-server.
15
23
  * v1.1.0 — 2026-07-11 — Own-published apps: "Edit Access Code" in serverMgmtInner + "Attach skill"
@@ -18,12 +26,15 @@
18
26
  * v1.0.0 — 2026-07-10 — Initial extraction (TARGET-021 Aalto 3 modularization, phase 7).
19
27
  */
20
28
  import { escapeHtml, jsArg, sourceLabel, sourceLabelText, currentOwnerName } from './util.js';
21
- import { saveApp, deleteApp, getDbMode, setDbMode, closeDbInstance } from './db.js';
29
+ import { saveApp, deleteApp } from './db.js';
22
30
  import { dtlBtn, showConfirm, showNotice } from './ui.js';
23
31
  import { loadConfig } from './config.js';
24
- import { t } from './i18n.js';
25
- import { monetizeSectionInner, monetizeOnOpen } from './monetize.js';
32
+ import { t, getLang } from './i18n.js';
33
+ import { getPromotion, setPromotion, loadPromoted } from './promote.js';
34
+ import { monetizeSectionInner, monetizeOnOpen, odpsSectionInner } from './monetize.js';
35
+ import { costSectionInner, costOnOpen } from './cost.js';
26
36
  import { appManifestAgents } from './app-agents.js';
37
+ import { saveWorkingCopy, loadCheckpoints, getCheckpoints, readCheckpoint, deleteCheckpoint, discardWorkingCopy, getDraft } from './workcopy.js';
27
38
 
28
39
  // Injected once at bootstrap by main.js. Functions are main-local; the get* return main's LIVE
29
40
  // state (so reads + in-place mutations propagate across the reassignments main does each render).
@@ -50,6 +61,19 @@ var detailSkillPickerOpen = false; // true while the "attach a skill" picker i
50
61
  var detailMySkills = null; // cached list of the user's own UNBOUND skills (attach options)
51
62
  var detailBoundSkills = []; // refs of the skills currently bound to this app (filters the options)
52
63
  var detailSkillBusy = false; // guards the Attach button while a bind/unbind republish is in flight
64
+ // ── Working copy (TARGET-048) ──
65
+ // The working copy is the app's SERVER DRAFT SLOT, not a browser blob: saving persists it, so it
66
+ // survives a reload and can be tested on a real origin before it ever becomes a published version.
67
+ var detailWorkSavedAt = null; // ISO time this session last persisted the working copy (null = not yet here)
68
+ var detailHasWorkCopy = false; // a saved (unpublished) working copy exists on the server for this app
69
+ var detailCheckpointsHtml = null; // cached rendered checkpoint list, survives re-renders
70
+ var detailCheckpointBusy = false; // guards restore/delete while a memory round-trip is in flight
71
+ var detailLastChangeNote = ''; // the change request behind the pending AI proposal — labels the checkpoint it replaces
72
+ // Bumped whenever the working-copy state changes underneath in-flight async loads (open a different
73
+ // app, publish, discard). A late-resolving loader compares the epoch it captured and bails instead
74
+ // of writing stale state back — otherwise a draft fetch started before a publish lands after it and
75
+ // resurrects "working copy saved" for an app that no longer has one.
76
+ var detailEpoch = 0;
53
77
 
54
78
  function detailGetApp() {
55
79
  for (var i = 0; i < getMainApps().length; i++) {
@@ -158,11 +182,20 @@ function openDetailView(appId) {
158
182
  detailSkillPickerOpen = false;
159
183
  detailMySkills = null;
160
184
  detailBoundSkills = [];
185
+ detailWorkSavedAt = null;
186
+ detailCheckpointsHtml = null;
187
+ detailCheckpointBusy = false;
188
+ detailEpoch++;
161
189
  var app = detailGetApp();
162
190
  if (!app) return;
191
+ // A working copy saved in an EARLIER session shows up in the server listing as has_draft.
192
+ var wcState = (app.publishedFilename && getServerState()[app.publishedFilename]) || null;
193
+ detailHasWorkCopy = !!(wcState && wcState.hasDraft);
163
194
  // Monetize (TARGET-034): reset + async-load the apps.{appId}.tools manifest for OWN published
164
195
  // apps before the first render so the section shell picks up the loading state.
165
196
  monetizeOnOpen(detailServerOwner(app), app.publishedFilename || '', detailIsOwnPublished(app));
197
+ // Cost & contracts (EXCHANGE G3): async-load this app's EXCHANGE entitlements for OWN published apps.
198
+ costOnOpen(detailServerOwner(app), app.publishedFilename || '', detailIsOwnPublished(app));
166
199
  document.getElementById('detail-view').hidden = false;
167
200
  renderDetailView();
168
201
  // AI availability + published versions load asynchronously and re-render in place.
@@ -171,6 +204,11 @@ function openDetailView(appId) {
171
204
  if (app.published && app.publishedFilename && owner) {
172
205
  detailLoadVersions(owner, app.publishedFilename);
173
206
  detailLoadSkills(detailServerOwner(app) || owner, app.publishedFilename);
207
+ detailLoadCheckpoints(detailServerOwner(app) || owner, app.publishedFilename);
208
+ // A working copy saved earlier lives on the server, but the in-memory blob was materialized
209
+ // from the PUBLISHED bytes. Pull the real working copy in, so the source editor and the AI
210
+ // loop operate on YOUR work — not on the live app wearing its name.
211
+ if (detailHasWorkCopy) detailLoadWorkingCopy(app, detailServerOwner(app) || owner);
174
212
  }
175
213
  // Opened via a pencil ("edit the name") → jump straight into the About editor.
176
214
  if (detailEditAboutOnOpen) {
@@ -235,15 +273,8 @@ function loadScriptOnce(src) {
235
273
  }
236
274
 
237
275
  function onAuthChanged() {
238
- // Personal mode is per-account: if the user signed OUT while in it, fall back to Global — it
239
- // would otherwise silently show the shared Global DB.
240
- if (getDbMode() === 'personal' && !currentOwnerName()) {
241
- setDbMode('global');
242
- }
243
- // The per-account IndexedDB changes with the signed-in owner, so re-open it and re-render the
244
- // LOCAL grid + tags too — not just the server sections (the stale-grid-after-login bug).
245
- closeDbInstance();
246
- updateModeToggle();
276
+ // Server-only catalog: the grid is rebuilt from the server on every auth change, so a sign-in /
277
+ // sign-out just re-fetches the owner's apps (their parked/listed apps appear or drop away).
247
278
  try { refreshAll(); } catch (e) { try { loadPublishedApps(); } catch (e2) {} }
248
279
  var sub = document.getElementById('publish-submit-btn');
249
280
  var st = document.getElementById('publish-status');
@@ -296,13 +327,30 @@ function renderDetailView() {
296
327
  '<span style="font-size:1.3rem">' + escapeHtml(icon) + '</span> ' + escapeHtml(app.name || 'App') +
297
328
  ((canEditAbout && !detailEditingAbout) ? ' <button class="rename-pencil" style="font-size:1rem" title="' + escapeHtml(t('detail.editDetails')) + '" onclick="window._launcher.detailAboutEdit()">✏️</button>' : '');
298
329
 
299
- // ── STATUS ──
330
+ // ── LIFECYCLE (TARGET-048) ──
331
+ // Replaces the old two-number STATUS card. One band answers the question the old card never did:
332
+ // WHERE is my work right now — in an unsaved proposal, in a saved (private) working copy, or
333
+ // published for everyone? Each stop says what it means in plain words; one sentence says what to
334
+ // do next. "Draft" is deliberately absent: it used to mean three different things here.
300
335
  var localBytes = app.blob ? Math.round(app.blob.length * 0.75) : 0; // base64 → bytes approx
301
- var publishedV = app.publishedVersionNumber ? ('v' + app.publishedVersionNumber) : (app.published ? 'v?' : t('detail.notPublished'));
302
- var syncClass, syncText;
303
- if (!app.published) { syncClass = 'none'; syncText = t('detail.notPublished'); }
304
- else if (detailDraftBlob) { syncClass = 'diff'; syncText = t('detail.localNewer'); }
305
- else { syncClass = 'ok'; syncText = t('detail.inSync'); }
336
+ var publishedV = app.publishedVersionNumber ? ('v' + app.publishedVersionNumber) : '';
337
+ // Three mutually exclusive working-copy states, in the order the user moves through them.
338
+ var wcState = detailDraftBlob ? 'pending' : (detailHasWorkCopy ? 'saved' : 'clean');
339
+ var wcValue, wcExplain;
340
+ if (wcState === 'pending') {
341
+ wcValue = t('wc.pending');
342
+ wcExplain = t('wc.explainPending');
343
+ } else if (wcState === 'saved') {
344
+ wcValue = detailWorkSavedAt
345
+ ? t('wc.savedAt').replace('{t}', new Date(detailWorkSavedAt).toLocaleTimeString())
346
+ : t('wc.savedEarlier');
347
+ wcExplain = app.published
348
+ ? t('wc.explainSaved').replace('{v}', String((app.publishedVersionNumber || 0) + 1))
349
+ : t('wc.explainSavedUnpublished');
350
+ } else {
351
+ wcValue = app.published ? t('wc.sameAsPublished') : t('wc.nothingYet');
352
+ wcExplain = app.published ? t('wc.explainClean') : t('wc.explainUnpublished');
353
+ }
306
354
 
307
355
  // App thumbnail (right side of the Status card). Built from the published path; hides itself if
308
356
  // the app has no screenshot yet. Cache-busted so a freshly (re)captured shot isn't shown stale.
@@ -318,17 +366,34 @@ function renderDetailView() {
318
366
 
319
367
  var statusHtml =
320
368
  '<div class="dtl-section">' +
321
- '<h3>' + t('detail.status') + '</h3>' +
322
- '<div style="display:flex;gap:16px;align-items:flex-start;flex-wrap:wrap">' +
323
- '<div style="flex:1;min-width:200px">' +
324
- '<div class="dtl-status-row">' +
325
- '<div class="dtl-stat"><span class="dtl-stat-label">' + t('detail.statusLocal') + '</span><span class="dtl-stat-val">' + (app.blob ? fmtSize(localBytes) : (isUrlApp ? 'URL' : '—')) + '</span></div>' +
326
- '<div class="dtl-stat"><span class="dtl-stat-label">' + t('detail.statusPublished') + '</span><span class="dtl-stat-val">' + escapeHtml(publishedV) + '</span></div>' +
369
+ '<h3>' + t('wc.lifecycle') + '</h3>' +
370
+ '<div class="wc-row">' +
371
+ '<div class="wc-band">' +
372
+ '<div class="wc-stop ' + (wcState === 'clean' ? 'is-idle' : 'is-active') + '">' +
373
+ '<span class="wc-stop-label">' + t('wc.title') + '</span>' +
374
+ '<span class="wc-stop-val">' + escapeHtml(wcValue) + '</span>' +
375
+ '<span class="wc-stop-note">' + t('wc.privateNote') + '</span>' +
376
+ '</div>' +
377
+ '<span class="wc-arrow" aria-hidden="true">→</span>' +
378
+ '<div class="wc-stop ' + (app.published ? 'is-live' : 'is-idle') + '">' +
379
+ '<span class="wc-stop-label">' + t('wc.published') + '</span>' +
380
+ '<span class="wc-stop-val">' + escapeHtml(app.published ? (publishedV || 'v?') : t('wc.notPublishedYet')) + '</span>' +
381
+ '<span class="wc-stop-note">' + (app.published ? t('wc.visibleToOthers') : t('wc.notVisibleYet')) + '</span>' +
327
382
  '</div>' +
328
- '<span class="dtl-sync ' + syncClass + '">' + escapeHtml(syncText) + '</span>' +
329
383
  '</div>' +
330
384
  shotImg +
331
385
  '</div>' +
386
+ '<p class="wc-explain">' + escapeHtml(wcExplain) + '</p>' +
387
+ // A saved working copy must never be a dead end: the same three verbs are available right
388
+ // here, so you can try it, publish it, or throw it away without hunting through other menus.
389
+ (wcState === 'saved' && app.published && !isUrlApp
390
+ ? '<div class="dtl-btn-row">' +
391
+ dtlBtn(t('wc.try'), 'window._launcher.detailWorkTry()') +
392
+ dtlBtn(t('wc.publishAs').replace('{v}', String((app.publishedVersionNumber || 0) + 1)), 'window._launcher.detailWorkPublish()', {variant:'success'}) +
393
+ dtlBtn(t('wc.discardWork'), 'window._launcher.detailWorkDiscard()') +
394
+ '</div>'
395
+ : '') +
396
+ (app.blob && !isUrlApp ? '<p class="wc-size">' + escapeHtml(t('detail.size') + ': ' + fmtSize(localBytes)) + '</p>' : '') +
332
397
  '</div>';
333
398
 
334
399
  // ── ABOUT ──
@@ -339,10 +404,9 @@ function renderDetailView() {
339
404
  var tags = (app.tags && app.tags.length) ? app.tags.join(', ') : '—';
340
405
  var cortex = (app.usesCortex && app.usesCortex.length) ? app.usesCortex.join(', ') : '—';
341
406
  var created = app.addedAt ? new Date(app.addedAt).toLocaleString() : '—';
342
- var favBtn = app.blob
343
- ? '<button class="dtl-fav-btn" title="' + escapeHtml(t(app.favorite ? 'detail.unfavorite' : 'detail.favorite')) + '"'
344
- + ' onclick="window._launcher.detailToggleFavorite()">' + (app.favorite ? '' : '☆') + '</button>'
345
- : '';
407
+ // Favourites are a Phase-2 (server-backed) feature; the old local-only star was dropped with the
408
+ // server-only cutover so it isn't shown here anymore.
409
+ var favBtn = '';
346
410
  var aboutHeader =
347
411
  '<h3 style="display:flex;align-items:center;justify-content:space-between;gap:8px">' +
348
412
  '<span>' + t('detail.about') + '</span>' +
@@ -351,13 +415,26 @@ function renderDetailView() {
351
415
  ((canEditAbout && !detailEditingAbout) ? dtlBtn(t('detail.editDetails'), 'window._launcher.detailAboutEdit()') : '') +
352
416
  '</span>' +
353
417
  '</h3>';
418
+ // Per-locale descriptions: EN + FI (extensible). Seed from the manifest's descriptions map,
419
+ // falling back to the canonical description for the default language so an app that only ever had
420
+ // a single description pre-fills English.
421
+ var descs = app.descriptions || {};
422
+ var descEnVal = descs.en || (app.description || '');
423
+ var descFiVal = descs.fi || '';
354
424
  var aboutBody;
355
425
  if (detailEditingAbout) {
356
426
  aboutBody =
357
427
  '<label class="dtl-stat-label" for="detail-name-input">' + t('detail.nameLabel') + '</label>' +
358
428
  '<input id="detail-name-input" class="modal-input" maxlength="120" value="' + escapeHtml(app.name || '') + '" style="margin:4px 0 10px" />' +
359
- '<label class="dtl-stat-label" for="detail-desc-input">' + t('detail.descLabel') + '</label>' +
360
- '<textarea id="detail-desc-input" class="modal-input" rows="3" maxlength="2000" style="margin:4px 0 8px;resize:vertical">' + escapeHtml(app.description || '') + '</textarea>' +
429
+ '<label class="dtl-stat-label" for="detail-desc-en">' + t('detail.descEn') + '</label>' +
430
+ '<textarea id="detail-desc-en" class="modal-input" rows="3" maxlength="2000" style="margin:4px 0 6px;resize:vertical">' + escapeHtml(descEnVal) + '</textarea>' +
431
+ '<label class="dtl-stat-label" for="detail-desc-fi">' + t('detail.descFi') + '</label>' +
432
+ '<textarea id="detail-desc-fi" class="modal-input" rows="3" maxlength="2000" style="margin:4px 0 6px;resize:vertical">' + escapeHtml(descFiVal) + '</textarea>' +
433
+ '<div class="dtl-btn-row" style="margin:0 0 4px">' +
434
+ dtlBtn('🌐 ' + t('detail.translateEnFi'), 'window._launcher.detailTranslateDesc(\'en\',\'fi\')', {id:'detail-tr-enfi'}) +
435
+ dtlBtn('🌐 ' + t('detail.translateFiEn'), 'window._launcher.detailTranslateDesc(\'fi\',\'en\')', {id:'detail-tr-fien'}) +
436
+ '</div>' +
437
+ '<div class="dtl-ai-status" id="detail-tr-status" style="margin:0 0 8px"></div>' +
361
438
  '<label class="dtl-stat-label" for="detail-icon-input">' + t('detail.iconLabel') + '</label>' +
362
439
  '<input id="detail-icon-input" class="modal-input" maxlength="4" value="' + escapeHtml(app.icon || '') + '" style="margin:4px 0 10px;text-align:center;font-size:1.2rem" />' +
363
440
  '<label class="dtl-stat-label" for="detail-tags-input">' + t('detail.tagsLabel') + '</label>' +
@@ -368,8 +445,10 @@ function renderDetailView() {
368
445
  dtlBtn(t('detail.cancelEdit'), 'window._launcher.detailAboutCancel()') +
369
446
  '</div>';
370
447
  } else {
448
+ // Show the description in the current UI language, falling back to the canonical one.
449
+ var shownDesc = (app.descriptions && app.descriptions[getLang()]) || app.description || '';
371
450
  aboutBody =
372
- (app.description ? '<p class="dtl-desc">' + escapeHtml(app.description) + '</p>' : '') +
451
+ (shownDesc ? '<p class="dtl-desc">' + escapeHtml(shownDesc) + '</p>' : '') +
373
452
  '<div class="dtl-meta-grid">' +
374
453
  metaItem(t('detail.category'), app.category || 'utility') +
375
454
  metaItem(t('detail.tags'), tags) +
@@ -401,26 +480,44 @@ function renderDetailView() {
401
480
  '</div>' +
402
481
  '<div class="dtl-ai-status" id="detail-ai-status">' + (detailAiAvailable ? '' : escapeHtml(detailAiUnavailableMsg())) + '</div>' +
403
482
  '<div class="dtl-ai-draft" id="detail-ai-draft"' + (detailDraftBlob ? '' : ' hidden') + '>' +
404
- '<div class="dtl-ai-status" style="margin:0 0 8px">' + t('detail.draftReady') + '</div>' +
483
+ '<div class="dtl-ai-status wc-proposal-head">' + t('detail.draftReady') + '</div>' +
484
+ // The SAME three verbs the source editor uses, in the order you actually move through them:
485
+ // save (private, reversible) → try (real origin, live untouched) → publish (others see it).
405
486
  '<div class="dtl-btn-row">' +
406
- // PUBLISHED app → the real-origin staging path (mic/camera work); the old opaque-
407
- // sandbox "Test" is dropped here to avoid two near-identical "Test" buttons. An
408
- // UNPUBLISHED app has no server draft slot yet, so it keeps the quick sandbox preview.
487
+ dtlBtn(t('wc.save'), 'window._launcher.detailAiKeep()', {variant:'primary'}) +
409
488
  (app.published
410
- ? dtlBtn(t('detail.testLive'), 'window._launcher.detailTestDraftLive()', {variant:'primary'}) +
411
- dtlBtn(t('detail.publishTested'), 'window._launcher.detailPublishTestedDraft()', {variant:'success'})
412
- : dtlBtn(t('detail.test'), 'window._launcher.detailAiTest()', {variant:'primary'})) +
413
- dtlBtn(t('detail.keep'), 'window._launcher.detailAiKeep()') +
414
- dtlBtn(t('detail.discard'), 'window._launcher.detailAiDiscard()') +
489
+ ? dtlBtn(t('wc.try'), 'window._launcher.detailTestDraftLive()') +
490
+ dtlBtn(t('wc.publishAs').replace('{v}', String((app.publishedVersionNumber || 0) + 1)), 'window._launcher.detailPublishTestedDraft()', {variant:'success'})
491
+ // No published app yet → no server slot to stage into; keep the quick sandbox preview.
492
+ : dtlBtn(t('wc.tryLocal'), 'window._launcher.detailAiTest()')) +
493
+ dtlBtn(t('wc.discardProposal'), 'window._launcher.detailAiDiscard()') +
415
494
  '</div>' +
495
+ '<p class="wc-verbs-hint">' + t('wc.verbsHint') + '</p>' +
416
496
  '</div>';
417
497
  }
418
498
  aiHtml += '</div>';
419
499
 
500
+ // ── WORKING-COPY HISTORY (checkpoints, TARGET-048) ──
501
+ // Every save leaves the bytes it replaced here, so iterating can never lose earlier work. Kept
502
+ // visually and verbally separate from the published versions below — that pair of look-alike
503
+ // lists was itself a source of the confusion, so each one states who can see it.
504
+ var historyHtml = '';
505
+ if (!isUrlApp && app.published) {
506
+ historyHtml =
507
+ '<div class="dtl-section">' +
508
+ '<h3>' + t('wc.history') + '</h3>' +
509
+ '<p class="dtl-desc">' + t('wc.historyHint') + '</p>' +
510
+ '<div id="detail-checkpoints">' +
511
+ (detailCheckpointsHtml !== null ? detailCheckpointsHtml : '<span class="wc-muted">…</span>') +
512
+ '</div>' +
513
+ '</div>';
514
+ }
515
+
420
516
  // ── VERSIONS ──
421
517
  var versionsHtml =
422
518
  '<div class="dtl-section">' +
423
519
  '<h3>' + t('detail.versions') + '</h3>' +
520
+ '<p class="dtl-desc">' + t('versions.publishedHint') + '</p>' +
424
521
  '<div id="detail-versions-list">' +
425
522
  (detailVersionsHtml !== null ? detailVersionsHtml :
426
523
  (!hasServer ? '<span class="dtl-sync none">' + t('detail.needServerVersions') + '</span>'
@@ -473,12 +570,30 @@ function renderDetailView() {
473
570
  '</div>';
474
571
  }
475
572
 
573
+ // ── EXCHANGE & ODPS — is this app on the marketplace, and the ODPS defaults every tool inherits.
574
+ // Sits above Monetize because it frames it: the app-level answer to "is this product for sale".
575
+ // Stable container: monetize.js re-renders #detail-odps in place alongside #detail-monetize.
576
+ var odpsHtml = (app.published && detailIsOwnPublished(app))
577
+ ? '<div class="dtl-section" id="detail-odps">' + odpsSectionInner() + '</div>'
578
+ : '';
579
+
476
580
  // ── MONETIZE (TARGET-034) — sell tool calls on this app (own published apps only) ──
477
581
  // Stable container: monetize.js re-renders #detail-monetize in place after loads/saves.
478
582
  var monetizeHtml = (app.published && detailIsOwnPublished(app))
479
583
  ? '<div class="dtl-section" id="detail-monetize">' + monetizeSectionInner() + '</div>'
480
584
  : '';
481
585
 
586
+ // ── COST & CONTRACTS (EXCHANGE G3 / TARGET-045) — what this app SOURCES (own published apps only) ──
587
+ // Stable container: cost.js re-renders #detail-cost in place after the async load.
588
+ var costHtml = (app.published && detailIsOwnPublished(app))
589
+ ? '<div class="dtl-section" id="detail-cost">' + costSectionInner() + '</div>'
590
+ : '';
591
+
592
+ // ── PROMOTE (Phase 2c) — showcase this app on your public profile with EN/FI pitch copy.
593
+ // Own published apps only; persists to the PUBLIC app-catalog.promoted memory doc.
594
+ var promoteHtml = (app.published && detailIsOwnPublished(app))
595
+ ? buildPromoteSection(app) : '';
596
+
482
597
  // ── BUNDLED AGENTS (Agent-Bundled Apps) — crew-defs this app ships. The section lists the
483
598
  // agent names and opens the shared Bundled-agents modal (inspector + hosted instances with
484
599
  // prices + deploy-your-own). Manifest read from the server-manifest cache.
@@ -502,7 +617,180 @@ function renderDetailView() {
502
617
  }
503
618
 
504
619
  document.getElementById('detail-body').innerHTML =
505
- statusHtml + aboutHtml + aiHtml + versionsHtml + skillsHtml + agentsHtml + monetizeHtml + mgmtHtml + actionsHtml;
620
+ statusHtml + aboutHtml + aiHtml + historyHtml + versionsHtml + skillsHtml + agentsHtml + odpsHtml + monetizeHtml + costHtml + promoteHtml + mgmtHtml + actionsHtml;
621
+ }
622
+
623
+ // ── Working-copy history (checkpoints) ────────────────────────────────────────
624
+ // Rendered from the cached index (workcopy.js); each row can be previewed in the sandbox or
625
+ // restored. Restoring is itself a save, so the state you restore FROM is checkpointed too — there
626
+ // is no way to lose work by clicking around in here.
627
+
628
+ function detailCheckpointRows(app) {
629
+ var owner = detailServerOwner(app);
630
+ var list = getCheckpoints(owner, app.publishedFilename || '');
631
+ if (!list.length) return '<span class="wc-muted">' + t('wc.none') + '</span>';
632
+ var out = '';
633
+ for (var i = 0; i < list.length; i++) {
634
+ var c = list[i];
635
+ var when = c.at ? new Date(c.at).toLocaleString() : '';
636
+ var kb = c.size ? (Math.round(c.size / 102.4) / 10) + ' KB' : '';
637
+ var note = c.note ? t('wc.before').replace('{note}', c.note) : t('wc.beforeUnnamed');
638
+ out +=
639
+ '<div class="dtl-version-row">' +
640
+ '<div class="version-meta">' +
641
+ '<span class="wc-ckpt-when">' + escapeHtml(when) + '</span>' +
642
+ '<span class="wc-ckpt-note">' + escapeHtml(note) + (kb ? ' · ' + kb : '') + '</span>' +
643
+ '</div>' +
644
+ '<div class="dtl-btn-row">' +
645
+ dtlBtn(t('wc.preview'), 'window._launcher.detailCheckpointPreview(\'' + jsArg(c.id) + '\')') +
646
+ dtlBtn(t('wc.restore'), 'window._launcher.detailCheckpointRestore(\'' + jsArg(c.id) + '\')', {variant:'primary', disabled: detailCheckpointBusy}) +
647
+ dtlBtn(t('wc.delete'), 'window._launcher.detailCheckpointDelete(\'' + jsArg(c.id) + '\')', {disabled: detailCheckpointBusy}) +
648
+ '</div>' +
649
+ '</div>';
650
+ }
651
+ return out;
652
+ }
653
+
654
+ // Re-render ONLY the checkpoint list in place (keeps scroll + the rest of the detail intact).
655
+ function refreshCheckpoints() {
656
+ var app = detailGetApp();
657
+ if (!app) return;
658
+ detailCheckpointsHtml = detailCheckpointRows(app);
659
+ var el = document.getElementById('detail-checkpoints');
660
+ if (el) el.innerHTML = detailCheckpointsHtml;
661
+ }
662
+
663
+ // Load the saved working copy over the materialized published bytes (see the call site). Silent on
664
+ // failure: the band still says "saved earlier", and the worst case is the previous behaviour.
665
+ function detailLoadWorkingCopy(app, owner) {
666
+ var epoch = detailEpoch;
667
+ getDraft(owner, app.publishedFilename).then(function (d) {
668
+ // Bail if a publish/discard/app-switch happened while this was in flight (see detailEpoch).
669
+ if (!d || !d.content || detailAppId !== app.id || epoch !== detailEpoch) return;
670
+ app.blob = d.content;
671
+ if (d.updated_at) detailWorkSavedAt = d.updated_at;
672
+ saveApp(app).then(function () { if (detailAppId === app.id) renderDetailView(); });
673
+ });
674
+ }
675
+
676
+ function detailLoadCheckpoints(owner, filename) {
677
+ loadCheckpoints(owner, filename)
678
+ .then(function () { if (detailAppId) refreshCheckpoints(); })
679
+ .catch(function () { if (detailAppId) refreshCheckpoints(); });
680
+ }
681
+
682
+ // Open a stored checkpoint in the sandbox overlay WITHOUT touching the working copy.
683
+ function detailCheckpointPreview(id) {
684
+ var app = detailGetApp();
685
+ if (!app) return;
686
+ readCheckpoint(detailServerOwner(app), app.publishedFilename || '', id).then(function (b64) {
687
+ if (!b64) { showNotice(t('wc.gone')); return; }
688
+ var view = document.getElementById('iframe-view');
689
+ var iframe = document.getElementById('app-iframe');
690
+ document.getElementById('iframe-title').textContent = (app.name || 'App') + ' — ' + t('wc.previewTitle');
691
+ iframe.removeAttribute('src');
692
+ iframe.srcdoc = blobToHtml(b64);
693
+ setIframeUrl('');
694
+ delete iframe.dataset.appId;
695
+ view.hidden = false;
696
+ });
697
+ }
698
+
699
+ // Restore = save the checkpoint's bytes AS the working copy (which checkpoints the current bytes
700
+ // first). The published app is untouched until you publish.
701
+ async function detailCheckpointRestore(id) {
702
+ var app = detailGetApp();
703
+ if (!app || detailCheckpointBusy) return;
704
+ if (!getCortexOwnerToken()) { showNotice(t('wc.loginNeeded')); return; }
705
+ if (!(await showConfirm(t('wc.confirmRestore')))) return;
706
+ var owner = detailServerOwner(app);
707
+ var filename = app.publishedFilename || '';
708
+ detailCheckpointBusy = true;
709
+ refreshCheckpoints();
710
+ readCheckpoint(owner, filename, id)
711
+ .then(function (b64) {
712
+ if (!b64) throw new Error(t('wc.gone'));
713
+ return saveWorkingCopy({
714
+ owner: owner, filename: filename,
715
+ previousB64: app.blob, nextB64: b64, note: t('wc.noteRestore'),
716
+ }).then(function () { return b64; });
717
+ })
718
+ .then(function (b64) {
719
+ app.blob = b64;
720
+ detailCheckpointBusy = false;
721
+ detailHasWorkCopy = true;
722
+ detailWorkSavedAt = new Date().toISOString();
723
+ return saveApp(app).then(function () {
724
+ renderDetailView();
725
+ refreshCheckpoints();
726
+ showNotice(t('wc.restored'));
727
+ });
728
+ })
729
+ .catch(function (err) {
730
+ detailCheckpointBusy = false;
731
+ refreshCheckpoints();
732
+ showNotice((err && err.message) || t('wc.saveFailed'));
733
+ });
734
+ }
735
+
736
+ async function detailCheckpointDelete(id) {
737
+ var app = detailGetApp();
738
+ if (!app || detailCheckpointBusy) return;
739
+ if (!(await showConfirm(t('wc.confirmDelete')))) return;
740
+ detailCheckpointBusy = true;
741
+ refreshCheckpoints();
742
+ deleteCheckpoint(detailServerOwner(app), app.publishedFilename || '', id)
743
+ .catch(function () { /* index already updated locally */ })
744
+ .then(function () { detailCheckpointBusy = false; refreshCheckpoints(); });
745
+ }
746
+
747
+ // The Promote section: a short EN/FI pitch that surfaces this app on the owner's public profile.
748
+ // Saving writes the PUBLIC app-catalog.promoted doc; clearing both fields un-promotes the app.
749
+ function promoteRef(app) { return detailServerOwner(app) + '/' + (app.publishedFilename || ''); }
750
+ function buildPromoteSection(app) {
751
+ var ref = promoteRef(app);
752
+ var cur = getPromotion(ref) || {};
753
+ var on = !!(cur.en || cur.fi);
754
+ return '<div class="dtl-section" id="detail-promote">' +
755
+ '<h3 style="display:flex;align-items:center;gap:8px">📣 ' + t('promote.title') +
756
+ (on ? ' <span class="dtl-badge-on">' + t('promote.on') + '</span>' : '') + '</h3>' +
757
+ '<p class="dtl-desc">' + t('promote.hint') + '</p>' +
758
+ '<label class="dtl-stat-label" for="detail-promo-en">' + t('promote.en') + '</label>' +
759
+ '<textarea id="detail-promo-en" class="modal-input" rows="2" maxlength="500" style="margin:4px 0 6px;resize:vertical">' + escapeHtml(cur.en || '') + '</textarea>' +
760
+ '<label class="dtl-stat-label" for="detail-promo-fi">' + t('promote.fi') + '</label>' +
761
+ '<textarea id="detail-promo-fi" class="modal-input" rows="2" maxlength="500" style="margin:4px 0 6px;resize:vertical">' + escapeHtml(cur.fi || '') + '</textarea>' +
762
+ '<div class="dtl-btn-row" style="margin:0 0 4px">' +
763
+ dtlBtn('🌐 ' + t('detail.translateEnFi'), 'window._launcher.detailTranslateDesc(\'en\',\'fi\',\'detail-promo-\',\'detail-promo-tr-status\')') +
764
+ dtlBtn('🌐 ' + t('detail.translateFiEn'), 'window._launcher.detailTranslateDesc(\'fi\',\'en\',\'detail-promo-\',\'detail-promo-tr-status\')') +
765
+ '</div>' +
766
+ '<div class="dtl-ai-status" id="detail-promo-tr-status" style="margin:0 0 8px"></div>' +
767
+ '<div class="dtl-btn-row">' +
768
+ dtlBtn(t('promote.save'), 'window._launcher.detailPromoteSave()', {variant:'primary'}) +
769
+ (on ? dtlBtn(t('promote.remove'), 'window._launcher.detailPromoteClear()') : '') +
770
+ '</div>' +
771
+ '<div class="dtl-ai-status" id="detail-promo-status"></div>' +
772
+ '</div>';
773
+ }
774
+
775
+ function detailPromoteSave() {
776
+ var app = detailGetApp();
777
+ if (!app || !detailIsOwnPublished(app)) return;
778
+ var en = (document.getElementById('detail-promo-en') || {}).value || '';
779
+ var fi = (document.getElementById('detail-promo-fi') || {}).value || '';
780
+ var statusEl = document.getElementById('detail-promo-status');
781
+ if (statusEl) { statusEl.style.color = 'var(--text-muted)'; statusEl.textContent = t('promote.saving'); }
782
+ setPromotion(promoteRef(app), { en: en, fi: fi }).then(function (nowOn) {
783
+ renderApps();
784
+ renderDetailView();
785
+ var s2 = document.getElementById('detail-promo-status');
786
+ if (s2) { s2.style.color = '#34d399'; s2.textContent = nowOn ? '✔ ' + t('promote.saved') : '✔ ' + t('promote.removed'); }
787
+ });
788
+ }
789
+
790
+ function detailPromoteClear() {
791
+ var en = document.getElementById('detail-promo-en'); if (en) en.value = '';
792
+ var fi = document.getElementById('detail-promo-fi'); if (fi) fi.value = '';
793
+ detailPromoteSave();
506
794
  }
507
795
 
508
796
  // Bound skills (skills registry): skills whose frontmatter metadata.binding names this app.
@@ -808,22 +1096,31 @@ function detailAboutSave() {
808
1096
  var app = detailGetApp();
809
1097
  if (!app) return;
810
1098
  var nameEl = document.getElementById('detail-name-input');
811
- var descEl = document.getElementById('detail-desc-input');
1099
+ var enEl = document.getElementById('detail-desc-en');
1100
+ var fiEl = document.getElementById('detail-desc-fi');
812
1101
  var iconEl = document.getElementById('detail-icon-input');
813
1102
  var tagsEl = document.getElementById('detail-tags-input');
814
1103
  var newName = nameEl ? nameEl.value.trim() : '';
815
- var newDesc = descEl ? descEl.value.trim() : '';
1104
+ var enDesc = enEl ? enEl.value.trim() : '';
1105
+ var fiDesc = fiEl ? fiEl.value.trim() : '';
1106
+ // Per-locale map (drop blanks); the canonical description is the English one, or Finnish when
1107
+ // English is blank, so an app always has a non-empty fallback description.
1108
+ var newDescriptions = {};
1109
+ if (enDesc) newDescriptions.en = enDesc;
1110
+ if (fiDesc) newDescriptions.fi = fiDesc;
1111
+ var newDesc = enDesc || fiDesc || '';
816
1112
  // icon + tags are LOCAL metadata (same as the context-menu Edit modal) — no server round-trip.
817
1113
  var newIcon = iconEl ? iconEl.value.trim() : (app.icon || '');
818
1114
  var newTags = tagsEl
819
1115
  ? tagsEl.value.split(',').map(function (s) { return s.trim(); }).filter(Boolean)
820
1116
  : (app.tags || []);
821
1117
  if (!newName) { showNotice(t('detail.nameRequired') || 'Name cannot be empty.'); if (nameEl) nameEl.focus(); return; }
822
- if (app.published && !newDesc) { showNotice(t('detail.descRequired') || 'Description cannot be empty.'); if (descEl) descEl.focus(); return; }
1118
+ if (app.published && !newDesc) { showNotice(t('detail.descRequired') || 'Description cannot be empty.'); if (enEl) enEl.focus(); return; }
823
1119
 
824
1120
  function finishLocal() {
825
1121
  app.name = newName;
826
1122
  app.description = newDesc;
1123
+ app.descriptions = newDescriptions;
827
1124
  app.icon = newIcon;
828
1125
  app.tags = newTags;
829
1126
  saveApp(app).then(function() {
@@ -846,16 +1143,17 @@ function detailAboutSave() {
846
1143
  fetch(aimeatUrl + '/v1/apps/' + encodeURIComponent(filename), {
847
1144
  method: 'PATCH',
848
1145
  headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
849
- body: JSON.stringify({ name: newName, description: newDesc })
1146
+ body: JSON.stringify({ name: newName, description: newDesc, descriptions: newDescriptions })
850
1147
  })
851
1148
  .then(function(resp) { return resp.json().then(function(j) { return { ok: resp.ok, j: j }; }); })
852
1149
  .then(function(res) {
853
1150
  if (res.ok && res.j && res.j.ok !== false) {
854
- // Keep the cached server manifest in sync so a re-render shows the new name.
1151
+ // Keep the cached server manifest in sync so a re-render shows the new name + descriptions.
855
1152
  var key = owner + '\n' + filename;
856
1153
  getServerManifests()[key] = getServerManifests()[key] || {};
857
1154
  getServerManifests()[key].name = newName;
858
1155
  getServerManifests()[key].description = newDesc;
1156
+ getServerManifests()[key].descriptions = newDescriptions;
859
1157
  finishLocal();
860
1158
  } else {
861
1159
  showNotice('Failed: ' + ((res.j && res.j.error && res.j.error.message) || 'Unknown error'));
@@ -864,6 +1162,50 @@ function detailAboutSave() {
864
1162
  .catch(function(err) { showNotice('Error: ' + (err.message || err)); });
865
1163
  }
866
1164
 
1165
+ // Translate one language field to another via the owner's OpenRouter key (/v1/ai/complete).
1166
+ // srcLang/dstLang are 'en'|'fi'; fills the destination textarea in place. `prefix` picks the field
1167
+ // pair ('detail-desc-' for the description editor, 'detail-promo-' for the promotion editor);
1168
+ // `statusId` picks the status line. Reused by both the description and promotion editors.
1169
+ function detailTranslateDesc(srcLang, dstLang, prefix, statusId) {
1170
+ prefix = prefix || 'detail-desc-';
1171
+ var srcEl = document.getElementById(prefix + srcLang);
1172
+ var dstEl = document.getElementById(prefix + dstLang);
1173
+ var statusEl = document.getElementById(statusId || 'detail-tr-status');
1174
+ if (!srcEl || !dstEl) return;
1175
+ var text = (srcEl.value || '').trim();
1176
+ if (!text) { if (statusEl) statusEl.textContent = t('detail.trNeedSource'); return; }
1177
+ var token = getCortexOwnerToken();
1178
+ if (!token) { if (statusEl) statusEl.textContent = t('detail.aiLoginNeeded'); return; }
1179
+ var config = loadConfig();
1180
+ var aimeatUrl = (config.aimeatUrl || '').replace(/\/+$/, '');
1181
+ if (!aimeatUrl) { if (statusEl) statusEl.textContent = t('detail.aiUnavailable'); return; }
1182
+ var langName = { en: 'English', fi: 'Finnish' };
1183
+ if (statusEl) { statusEl.style.color = 'var(--text-muted)'; statusEl.textContent = t('detail.translating'); }
1184
+ var systemPrompt = 'You are a professional translator for short app-store copy. '
1185
+ + 'Translate the text from ' + (langName[srcLang] || srcLang) + ' to ' + (langName[dstLang] || dstLang) + '. '
1186
+ + 'Return ONLY the translated text — no quotes, no notes, no explanation. Keep it concise and natural.';
1187
+ fetch(aimeatUrl + '/v1/ai/complete', {
1188
+ method: 'POST',
1189
+ headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
1190
+ body: JSON.stringify({ prompt: text, systemPrompt: systemPrompt, app_id: 'app-catalog' })
1191
+ })
1192
+ .then(function(resp) { return resp.json(); })
1193
+ .then(function(json) {
1194
+ if (!json || !json.ok) {
1195
+ var msg = (json && json.error && json.error.message) || 'Translation failed';
1196
+ if (statusEl) { statusEl.style.color = 'var(--accent)'; statusEl.textContent = '✘ ' + msg; }
1197
+ return;
1198
+ }
1199
+ var out = (json.data && json.data.content ? json.data.content : '').trim();
1200
+ if (!out) { if (statusEl) { statusEl.style.color = 'var(--accent)'; statusEl.textContent = '✘ ' + t('detail.trEmpty'); } return; }
1201
+ dstEl.value = out;
1202
+ if (statusEl) { statusEl.style.color = '#34d399'; statusEl.textContent = '✔ ' + t('detail.trDone'); }
1203
+ })
1204
+ .catch(function(err) {
1205
+ if (statusEl) { statusEl.style.color = 'var(--accent)'; statusEl.textContent = '✘ ' + (err.message || 'Translation failed'); }
1206
+ });
1207
+ }
1208
+
867
1209
  // Manual override: upload a custom image as this published app's thumbnail. (Bulk auto-capture is
868
1210
  // the server-side `aimeat screenshot-worker`; the browser can't grab the cross-origin sandboxed app
869
1211
  // itself, so this is a file picker, not an in-page capture.)
@@ -1089,6 +1431,7 @@ function detailAiRun() {
1089
1431
  return;
1090
1432
  }
1091
1433
  detailDraftBlob = htmlToBlob(newHtml);
1434
+ detailLastChangeNote = change;
1092
1435
  statusEl.style.color = '#34d399';
1093
1436
  var usage = json.data && json.data.budget && typeof json.data.budget.spent_today_usd !== 'undefined'
1094
1437
  ? (' · ' + t('detail.aiUsage') + ': $' + Number(json.data.budget.spent_today_usd).toFixed(3)) : '';
@@ -1120,19 +1463,58 @@ function detailAiTest() {
1120
1463
  view.hidden = false;
1121
1464
  }
1122
1465
 
1466
+ // Accept the AI proposal INTO the working copy. This used to only overwrite the in-memory blob —
1467
+ // which a reload silently threw away. Now it checkpoints the bytes being replaced and persists the
1468
+ // new ones to the server draft slot, so "saved" actually means saved. The live app is untouched.
1123
1469
  function detailAiKeep() {
1124
1470
  var app = detailGetApp();
1125
1471
  if (!app || !detailDraftBlob) return;
1126
- app.blob = detailDraftBlob;
1127
- app.source = app.source === 'url' ? 'paste' : (app.source || 'paste');
1128
- app.url = app.url || null;
1129
- detailDraftBlob = null;
1130
- saveApp(app).then(function() {
1131
- renderApps();
1132
- renderDetailView();
1133
- var s2 = document.getElementById('detail-ai-status');
1134
- if (s2) { s2.style.color = '#34d399'; s2.textContent = '✔ ' + t('detail.kept'); }
1135
- });
1472
+ var next = detailDraftBlob;
1473
+ var prev = app.blob;
1474
+ var statusEl = document.getElementById('detail-ai-status');
1475
+
1476
+ function finishLocal() {
1477
+ app.blob = next;
1478
+ app.source = app.source === 'url' ? 'paste' : (app.source || 'paste');
1479
+ app.url = app.url || null;
1480
+ detailDraftBlob = null;
1481
+ return saveApp(app).then(function () {
1482
+ renderApps();
1483
+ renderDetailView();
1484
+ });
1485
+ }
1486
+
1487
+ // No published app (no server slot) or signed out → in-memory only, and say so plainly.
1488
+ if (!app.published || !app.publishedFilename || !getCortexOwnerToken()) {
1489
+ finishLocal().then(function () {
1490
+ var s2 = document.getElementById('detail-ai-status');
1491
+ if (s2) { s2.style.color = 'var(--text-muted)'; s2.textContent = t('wc.keptLocalOnly'); }
1492
+ });
1493
+ return;
1494
+ }
1495
+
1496
+ if (statusEl) { statusEl.style.color = 'var(--text-muted)'; statusEl.textContent = t('wc.saving'); }
1497
+ saveWorkingCopy({
1498
+ owner: detailServerOwner(app),
1499
+ filename: app.publishedFilename,
1500
+ previousB64: prev,
1501
+ nextB64: next,
1502
+ note: detailLastChangeNote,
1503
+ })
1504
+ .then(function () {
1505
+ detailHasWorkCopy = true;
1506
+ detailWorkSavedAt = new Date().toISOString();
1507
+ return finishLocal();
1508
+ })
1509
+ .then(function () {
1510
+ refreshCheckpoints();
1511
+ var s2 = document.getElementById('detail-ai-status');
1512
+ if (s2) { s2.style.color = '#34d399'; s2.textContent = '✔ ' + t('wc.saved'); }
1513
+ })
1514
+ .catch(function (err) {
1515
+ var s2 = document.getElementById('detail-ai-status');
1516
+ if (s2) { s2.style.color = 'var(--accent)'; s2.textContent = '✘ ' + ((err && err.message) || t('wc.saveFailed')); }
1517
+ });
1136
1518
  }
1137
1519
 
1138
1520
  function detailAiDiscard() {
@@ -1236,6 +1618,63 @@ function publishDraftBytes(app, contentB64, statusEl, onDone) {
1236
1618
  });
1237
1619
  }
1238
1620
 
1621
+ // ── Saved working copy: try / publish / discard ───────────────────────────────
1622
+ // These act on the SERVER draft slot, which is authoritative. Publishing must NOT re-upload
1623
+ // app.blob: after a reload the in-memory blob is materialized from the PUBLISHED bytes, so
1624
+ // PUT-then-publish would silently overwrite the saved working copy with the live version. The
1625
+ // AI-proposal path is the only one that stages bytes first (they are not on the server yet).
1626
+
1627
+ function detailWorkTry() {
1628
+ var app = detailGetApp();
1629
+ if (!app || !app.publishedFilename) return;
1630
+ openStagingPreview(detailServerOwner(app), app.publishedFilename);
1631
+ }
1632
+
1633
+ async function detailWorkPublish() {
1634
+ var app = detailGetApp();
1635
+ if (!app || !app.publishedFilename) return;
1636
+ if (!getCortexOwnerToken()) { showNotice(t('wc.loginNeeded')); return; }
1637
+ if (!(await showConfirm(t('detail.draftPublishConfirm')))) return;
1638
+ var owner = detailServerOwner(app);
1639
+ draftApi('POST', owner, app.publishedFilename, 'publish-draft')
1640
+ .then(function (data) {
1641
+ detailEpoch++;
1642
+ detailHasWorkCopy = false;
1643
+ detailWorkSavedAt = null;
1644
+ app.publishedVersionNumber = data.version_number || app.publishedVersionNumber;
1645
+ showNotice(t('detail.draftPublished').replace('{v}', data.version_number));
1646
+ // Render BEFORE refreshAll: it empties the working set synchronously, after which
1647
+ // detailGetApp() is null and renderDetailView() bails, leaving the pre-publish DOM on screen.
1648
+ renderDetailView();
1649
+ detailLoadVersions(owner, app.publishedFilename);
1650
+ refreshAll();
1651
+ })
1652
+ .catch(function (err) { showNotice('✘ ' + ((err && err.message) || 'Publish failed')); });
1653
+ }
1654
+
1655
+ // Throw the working copy away and pull the live bytes back in, so what you see afterwards really
1656
+ // IS the published app (rather than a stale in-memory copy of what you just discarded).
1657
+ async function detailWorkDiscard() {
1658
+ var app = detailGetApp();
1659
+ if (!app || !app.publishedFilename) return;
1660
+ if (!(await showConfirm(t('wc.confirmDiscardWork')))) return;
1661
+ var owner = detailServerOwner(app);
1662
+ var cfg = loadConfig();
1663
+ var aimeatUrl = (cfg.aimeatUrl || '').replace(/\/+$/, '');
1664
+ discardWorkingCopy(owner, app.publishedFilename)
1665
+ .then(function () { return fetchAppContentBase64(aimeatUrl, owner, app.publishedFilename); })
1666
+ .then(function (b64) { app.blob = b64; return saveApp(app); })
1667
+ .catch(function () { /* keep whatever we have if the re-fetch fails */ })
1668
+ .then(function () {
1669
+ detailEpoch++;
1670
+ detailHasWorkCopy = false;
1671
+ detailWorkSavedAt = null;
1672
+ renderDetailView(); // before refreshAll — see detailWorkPublish
1673
+ refreshAll();
1674
+ showNotice(t('wc.discardedWork'));
1675
+ });
1676
+ }
1677
+
1239
1678
  // ── AI-loop wrappers (stage the pending AI candidate `detailDraftBlob`) ──
1240
1679
  function detailTestDraftLive() {
1241
1680
  var app = detailGetApp();
@@ -1245,10 +1684,17 @@ function detailTestDraftLive() {
1245
1684
  function detailPublishTestedDraft() {
1246
1685
  var app = detailGetApp();
1247
1686
  if (!app || !detailDraftBlob) return;
1248
- publishDraftBytes(app, detailDraftBlob, document.getElementById('detail-ai-status'), function () {
1687
+ publishDraftBytes(app, detailDraftBlob, document.getElementById('detail-ai-status'), function (data) {
1688
+ // Published: the slot is cleared server-side, so the working copy is level with the live app.
1689
+ detailEpoch++;
1690
+ app.blob = detailDraftBlob;
1249
1691
  detailDraftBlob = null;
1692
+ detailHasWorkCopy = false;
1693
+ detailWorkSavedAt = null;
1694
+ if (data && data.version_number) app.publishedVersionNumber = data.version_number;
1695
+ saveApp(app);
1696
+ renderDetailView(); // before refreshAll — see detailWorkPublish
1250
1697
  refreshAll();
1251
- renderDetailView();
1252
1698
  });
1253
1699
  }
1254
1700
 
@@ -1268,6 +1714,57 @@ function sourceCurrentB64() {
1268
1714
  if (!ta) return null;
1269
1715
  try { return btoa(unescape(encodeURIComponent(ta.value))); } catch (e) { return null; }
1270
1716
  }
1717
+ // "Save working copy" in the source editor — the SAME contract as the AI loop's save: checkpoint
1718
+ // the bytes being replaced, then persist to the server draft slot. Previously this button only
1719
+ // reassigned a transient in-memory blob, so the edit was gone on the next reload. Returns a promise
1720
+ // so main.js can drive the button's label/disabled state.
1721
+ function saveSourceAsWorkingCopy() {
1722
+ var app = sourceOverlayApp();
1723
+ var b64 = sourceCurrentB64();
1724
+ if (!app || b64 == null) return Promise.reject(new Error('No app'));
1725
+ var statusEl = document.getElementById('source-draft-status');
1726
+ var prev = app.blob;
1727
+ var isOpenInDetail = (detailAppId === app.id);
1728
+
1729
+ function localOnly() {
1730
+ app.blob = b64;
1731
+ return saveApp(app).then(function () { renderApps(); });
1732
+ }
1733
+
1734
+ // Unpublished app or signed out → no server slot exists; keep the old in-memory behaviour but
1735
+ // say plainly that it will not survive a reload.
1736
+ if (!app.published || !app.publishedFilename || !getCortexOwnerToken()) {
1737
+ return localOnly().then(function () {
1738
+ if (statusEl) { statusEl.style.color = 'var(--text-muted)'; statusEl.textContent = t('wc.keptLocalOnly'); }
1739
+ return { persisted: false };
1740
+ });
1741
+ }
1742
+
1743
+ if (statusEl) { statusEl.style.color = 'var(--text-muted)'; statusEl.textContent = t('wc.saving'); }
1744
+ return saveWorkingCopy({
1745
+ owner: detailServerOwner(app),
1746
+ filename: app.publishedFilename,
1747
+ previousB64: prev,
1748
+ nextB64: b64,
1749
+ note: t('wc.noteManual'),
1750
+ })
1751
+ .then(function () { return localOnly(); })
1752
+ .then(function () {
1753
+ if (isOpenInDetail) {
1754
+ detailHasWorkCopy = true;
1755
+ detailWorkSavedAt = new Date().toISOString();
1756
+ renderDetailView();
1757
+ refreshCheckpoints();
1758
+ }
1759
+ if (statusEl) { statusEl.style.color = '#34d399'; statusEl.textContent = '✔ ' + t('wc.saved'); }
1760
+ return { persisted: true };
1761
+ })
1762
+ .catch(function (err) {
1763
+ if (statusEl) { statusEl.style.color = 'var(--accent)'; statusEl.textContent = '✘ ' + ((err && err.message) || t('wc.saveFailed')); }
1764
+ throw err;
1765
+ });
1766
+ }
1767
+
1271
1768
  function sourceTestDraftLive() {
1272
1769
  var app = sourceOverlayApp();
1273
1770
  var c = sourceCurrentB64();
@@ -1326,6 +1823,7 @@ function openPublishedDetail(owner, filename, localId, versionNumber) {
1326
1823
  id: generateId(),
1327
1824
  name: meta.name || filename.replace(/\.html?$/i, ''),
1328
1825
  description: meta.description || '',
1826
+ descriptions: meta.descriptions || null,
1329
1827
  category: meta.category || 'utility',
1330
1828
  tags: meta.tags || [],
1331
1829
  usesCortex: meta.usesCortex || [],
@@ -1560,6 +2058,7 @@ async function restoreVersion(owner, filename, version) {
1560
2058
  mime_type: 'text/html',
1561
2059
  name: meta.name || filename.replace(/\.html?$/i, ''),
1562
2060
  description: meta.description || '',
2061
+ descriptions: meta.descriptions || null,
1563
2062
  category: meta.category || 'utility',
1564
2063
  tags: meta.tags || [],
1565
2064
  uses_cortex: meta.usesCortex || []
@@ -1647,6 +2146,9 @@ export {
1647
2146
  detailAboutEdit,
1648
2147
  detailAboutCancel,
1649
2148
  detailAboutSave,
2149
+ detailTranslateDesc,
2150
+ detailPromoteSave,
2151
+ detailPromoteClear,
1650
2152
  detailToggleFavorite,
1651
2153
  detailAccessCodeEdit,
1652
2154
  detailAccessCodeCancel,
@@ -1662,6 +2164,13 @@ export {
1662
2164
  detailAiDiscard,
1663
2165
  detailTestDraftLive,
1664
2166
  detailPublishTestedDraft,
2167
+ detailWorkTry,
2168
+ detailWorkPublish,
2169
+ detailWorkDiscard,
2170
+ detailCheckpointPreview,
2171
+ detailCheckpointRestore,
2172
+ detailCheckpointDelete,
2173
+ saveSourceAsWorkingCopy,
1665
2174
  openStagingPreview,
1666
2175
  sourceTestDraftLive,
1667
2176
  sourcePublishTested,