aimeat 2.0.0 → 2.1.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 (412) hide show
  1. package/dist/locales/en.json +35 -1
  2. package/dist/locales/fi.json +35 -1
  3. package/dist/public/components/LinkPreview.js +101 -0
  4. package/dist/public/components/NotificationBell.js +18 -1
  5. package/dist/public/css/theme.css +57 -7
  6. package/dist/public/css/views/admin.css +8 -1
  7. package/dist/public/css/views/app-grant.css +18 -0
  8. package/dist/public/css/views/inbox.css +46 -0
  9. package/dist/public/css/views/portfolio.css +46 -0
  10. package/dist/public/css/views/profile.css +29 -4
  11. package/dist/public/js/services/apps.js +19 -3
  12. package/dist/public/js/services/messages-ai-prompts.js +38 -0
  13. package/dist/public/js/services/messages.js +26 -4
  14. package/dist/public/js/services/notebook.js +76 -0
  15. package/dist/public/js/services/unfurl.js +43 -0
  16. package/dist/public/lib/samples/LICENSE.md +11 -0
  17. package/dist/public/lib/samples/bass/A1.mp3 +0 -0
  18. package/dist/public/lib/samples/bass/B2.mp3 +0 -0
  19. package/dist/public/lib/samples/bass/D2.mp3 +0 -0
  20. package/dist/public/lib/samples/bass/E1.mp3 +0 -0
  21. package/dist/public/lib/samples/bass/E3.mp3 +0 -0
  22. package/dist/public/lib/samples/bass/G2.mp3 +0 -0
  23. package/dist/public/lib/samples/epiano/C2.mp3 +0 -0
  24. package/dist/public/lib/samples/epiano/C3.mp3 +0 -0
  25. package/dist/public/lib/samples/epiano/C4.mp3 +0 -0
  26. package/dist/public/lib/samples/epiano/C5.mp3 +0 -0
  27. package/dist/public/lib/samples/epiano/C6.mp3 +0 -0
  28. package/dist/public/lib/samples/epiano/G2.mp3 +0 -0
  29. package/dist/public/lib/samples/epiano/G3.mp3 +0 -0
  30. package/dist/public/lib/samples/epiano/G4.mp3 +0 -0
  31. package/dist/public/lib/samples/epiano/G5.mp3 +0 -0
  32. package/dist/public/lib/samples/guitar-steel/A2.mp3 +0 -0
  33. package/dist/public/lib/samples/guitar-steel/A4.mp3 +0 -0
  34. package/dist/public/lib/samples/guitar-steel/B3.mp3 +0 -0
  35. package/dist/public/lib/samples/guitar-steel/D3.mp3 +0 -0
  36. package/dist/public/lib/samples/guitar-steel/E2.mp3 +0 -0
  37. package/dist/public/lib/samples/guitar-steel/E4.mp3 +0 -0
  38. package/dist/public/lib/samples/guitar-steel/E5.mp3 +0 -0
  39. package/dist/public/lib/samples/guitar-steel/G3.mp3 +0 -0
  40. package/dist/public/lib/samples/organ/C2.mp3 +0 -0
  41. package/dist/public/lib/samples/organ/C3.mp3 +0 -0
  42. package/dist/public/lib/samples/organ/C4.mp3 +0 -0
  43. package/dist/public/lib/samples/organ/C5.mp3 +0 -0
  44. package/dist/public/lib/samples/organ/C6.mp3 +0 -0
  45. package/dist/public/lib/samples/organ/G2.mp3 +0 -0
  46. package/dist/public/lib/samples/organ/G3.mp3 +0 -0
  47. package/dist/public/lib/samples/organ/G4.mp3 +0 -0
  48. package/dist/public/lib/samples/organ/G5.mp3 +0 -0
  49. package/dist/public/lib/samples/strings/C2.mp3 +0 -0
  50. package/dist/public/lib/samples/strings/C3.mp3 +0 -0
  51. package/dist/public/lib/samples/strings/C4.mp3 +0 -0
  52. package/dist/public/lib/samples/strings/C5.mp3 +0 -0
  53. package/dist/public/lib/samples/strings/C6.mp3 +0 -0
  54. package/dist/public/lib/samples/strings/G2.mp3 +0 -0
  55. package/dist/public/lib/samples/strings/G3.mp3 +0 -0
  56. package/dist/public/lib/samples/strings/G4.mp3 +0 -0
  57. package/dist/public/lib/samples/strings/G5.mp3 +0 -0
  58. package/dist/public/lib/samples/trumpet/A3.mp3 +0 -0
  59. package/dist/public/lib/samples/trumpet/A4.mp3 +0 -0
  60. package/dist/public/lib/samples/trumpet/A5.mp3 +0 -0
  61. package/dist/public/lib/samples/trumpet/C4.mp3 +0 -0
  62. package/dist/public/lib/samples/trumpet/C5.mp3 +0 -0
  63. package/dist/public/lib/samples/trumpet/E3.mp3 +0 -0
  64. package/dist/public/lib/samples/trumpet/E4.mp3 +0 -0
  65. package/dist/public/lib/samples/trumpet/E5.mp3 +0 -0
  66. package/dist/public/spa.html +2 -0
  67. package/dist/public/views/app-grant.js +24 -4
  68. package/dist/public/views/portfolio.js +61 -6
  69. package/dist/public/views/profile/apps-tab.js +18 -1
  70. package/dist/public/views/profile/inbox-tab/ai-actions.js +86 -0
  71. package/dist/public/views/profile/inbox-tab/components.js +124 -9
  72. package/dist/public/views/profile/inbox-tab/helpers.js +26 -0
  73. package/dist/public/views/profile/inbox-tab/panels.js +18 -3
  74. package/dist/public/views/profile/inbox-tab/use-thread-ux.js +18 -1
  75. package/dist/public/views/profile/inbox-tab.js +46 -49
  76. package/dist/public/views/profile/landing-page.cards.js +7 -0
  77. package/dist/public/views/profile/landing-page.js +12 -1
  78. package/dist/public/views/profile/skills-tab.js +1 -1
  79. package/dist/public/views/public-workspace-viewer.js +1 -1
  80. package/dist/public/views/start.js +2 -1
  81. package/dist/scripts/build-sdk-libs.d.ts +16 -0
  82. package/dist/scripts/build-sdk-libs.d.ts.map +1 -0
  83. package/dist/scripts/build-sdk-libs.js +112 -0
  84. package/dist/scripts/build-sdk-libs.js.map +1 -0
  85. package/dist/src/cli/connect/auth.d.ts +15 -0
  86. package/dist/src/cli/connect/auth.d.ts.map +1 -1
  87. package/dist/src/cli/connect/auth.js +25 -6
  88. package/dist/src/cli/connect/auth.js.map +1 -1
  89. package/dist/src/cli/connect/keychain.d.ts +9 -0
  90. package/dist/src/cli/connect/keychain.d.ts.map +1 -1
  91. package/dist/src/cli/connect/keychain.js +21 -8
  92. package/dist/src/cli/connect/keychain.js.map +1 -1
  93. package/dist/src/cli/connect/mcp/tools/exchange.d.ts +18 -0
  94. package/dist/src/cli/connect/mcp/tools/exchange.d.ts.map +1 -0
  95. package/dist/src/cli/connect/mcp/tools/exchange.js +170 -0
  96. package/dist/src/cli/connect/mcp/tools/exchange.js.map +1 -0
  97. package/dist/src/cli/connect/mcp/tools/index.d.ts.map +1 -1
  98. package/dist/src/cli/connect/mcp/tools/index.js +2 -0
  99. package/dist/src/cli/connect/mcp/tools/index.js.map +1 -1
  100. package/dist/src/cli/connect/tool-call-defs-exchange.d.ts +3 -0
  101. package/dist/src/cli/connect/tool-call-defs-exchange.d.ts.map +1 -0
  102. package/dist/src/cli/connect/tool-call-defs-exchange.js +146 -0
  103. package/dist/src/cli/connect/tool-call-defs-exchange.js.map +1 -0
  104. package/dist/src/cli/connect/tool-call.d.ts.map +1 -1
  105. package/dist/src/cli/connect/tool-call.js +2 -0
  106. package/dist/src/cli/connect/tool-call.js.map +1 -1
  107. package/dist/src/commerce/session-service.d.ts +14 -0
  108. package/dist/src/commerce/session-service.d.ts.map +1 -1
  109. package/dist/src/commerce/session-service.js +1 -1
  110. package/dist/src/commerce/session-service.js.map +1 -1
  111. package/dist/src/data/app-templates/shells.d.ts +7 -3
  112. package/dist/src/data/app-templates/shells.d.ts.map +1 -1
  113. package/dist/src/data/app-templates/shells.js +10 -6
  114. package/dist/src/data/app-templates/shells.js.map +1 -1
  115. package/dist/src/data/appdev-pitfalls.d.ts +2 -0
  116. package/dist/src/data/appdev-pitfalls.d.ts.map +1 -1
  117. package/dist/src/data/appdev-pitfalls.js +24 -1
  118. package/dist/src/data/appdev-pitfalls.js.map +1 -1
  119. package/dist/src/generated/api-types.d.ts +1565 -9
  120. package/dist/src/generated/api-types.d.ts.map +1 -1
  121. package/dist/src/mcp/annotations.d.ts.map +1 -1
  122. package/dist/src/mcp/annotations.js +20 -0
  123. package/dist/src/mcp/annotations.js.map +1 -1
  124. package/dist/src/mcp/apps.d.ts.map +1 -1
  125. package/dist/src/mcp/apps.js +8 -4
  126. package/dist/src/mcp/apps.js.map +1 -1
  127. package/dist/src/mcp/catalog/definitions/exchange.d.ts +18 -0
  128. package/dist/src/mcp/catalog/definitions/exchange.d.ts.map +1 -0
  129. package/dist/src/mcp/catalog/definitions/exchange.js +182 -0
  130. package/dist/src/mcp/catalog/definitions/exchange.js.map +1 -0
  131. package/dist/src/mcp/catalog/definitions.d.ts.map +1 -1
  132. package/dist/src/mcp/catalog/definitions.js +2 -0
  133. package/dist/src/mcp/catalog/definitions.js.map +1 -1
  134. package/dist/src/mcp/catalog/scopes.d.ts.map +1 -1
  135. package/dist/src/mcp/catalog/scopes.js +22 -0
  136. package/dist/src/mcp/catalog/scopes.js.map +1 -1
  137. package/dist/src/mcp/catalog/surfaces.d.ts.map +1 -1
  138. package/dist/src/mcp/catalog/surfaces.js +14 -0
  139. package/dist/src/mcp/catalog/surfaces.js.map +1 -1
  140. package/dist/src/mcp/exchange-run.d.ts +5 -0
  141. package/dist/src/mcp/exchange-run.d.ts.map +1 -0
  142. package/dist/src/mcp/exchange-run.js +226 -0
  143. package/dist/src/mcp/exchange-run.js.map +1 -0
  144. package/dist/src/mcp/exchange.d.ts +5 -0
  145. package/dist/src/mcp/exchange.d.ts.map +1 -0
  146. package/dist/src/mcp/exchange.js +351 -0
  147. package/dist/src/mcp/exchange.js.map +1 -0
  148. package/dist/src/mcp/extensions.d.ts.map +1 -1
  149. package/dist/src/mcp/extensions.js +11 -0
  150. package/dist/src/mcp/extensions.js.map +1 -1
  151. package/dist/src/mcp/index.d.ts.map +1 -1
  152. package/dist/src/mcp/index.js +6 -2
  153. package/dist/src/mcp/index.js.map +1 -1
  154. package/dist/src/models/app-tool-schemas.d.ts +55 -1
  155. package/dist/src/models/app-tool-schemas.d.ts.map +1 -1
  156. package/dist/src/models/app-tool-schemas.js +20 -1
  157. package/dist/src/models/app-tool-schemas.js.map +1 -1
  158. package/dist/src/models/offer-schemas.d.ts +2 -2
  159. package/dist/src/models/schemas.d.ts +1 -0
  160. package/dist/src/models/schemas.d.ts.map +1 -1
  161. package/dist/src/models/schemas.js +3 -0
  162. package/dist/src/models/schemas.js.map +1 -1
  163. package/dist/src/routes/agents/device-auth.d.ts +4 -0
  164. package/dist/src/routes/agents/device-auth.d.ts.map +1 -1
  165. package/dist/src/routes/agents/device-auth.js +19 -4
  166. package/dist/src/routes/agents/device-auth.js.map +1 -1
  167. package/dist/src/routes/app-grants.d.ts +6 -0
  168. package/dist/src/routes/app-grants.d.ts.map +1 -1
  169. package/dist/src/routes/app-grants.js +35 -2
  170. package/dist/src/routes/app-grants.js.map +1 -1
  171. package/dist/src/routes/apps/fork-manage.d.ts.map +1 -1
  172. package/dist/src/routes/apps/fork-manage.js +24 -1
  173. package/dist/src/routes/apps/fork-manage.js.map +1 -1
  174. package/dist/src/routes/apps/publish.d.ts +2 -0
  175. package/dist/src/routes/apps/publish.d.ts.map +1 -1
  176. package/dist/src/routes/apps/publish.js +27 -1
  177. package/dist/src/routes/apps/publish.js.map +1 -1
  178. package/dist/src/routes/apps-cost.d.ts +25 -0
  179. package/dist/src/routes/apps-cost.d.ts.map +1 -0
  180. package/dist/src/routes/apps-cost.js +107 -0
  181. package/dist/src/routes/apps-cost.js.map +1 -0
  182. package/dist/src/routes/exchange-market.d.ts +28 -0
  183. package/dist/src/routes/exchange-market.d.ts.map +1 -0
  184. package/dist/src/routes/exchange-market.js +454 -0
  185. package/dist/src/routes/exchange-market.js.map +1 -0
  186. package/dist/src/routes/exchange.d.ts +33 -0
  187. package/dist/src/routes/exchange.d.ts.map +1 -0
  188. package/dist/src/routes/exchange.js +395 -0
  189. package/dist/src/routes/exchange.js.map +1 -0
  190. package/dist/src/routes/extensions/entitlement-gate.d.ts +33 -0
  191. package/dist/src/routes/extensions/entitlement-gate.d.ts.map +1 -0
  192. package/dist/src/routes/extensions/entitlement-gate.js +143 -0
  193. package/dist/src/routes/extensions/entitlement-gate.js.map +1 -0
  194. package/dist/src/routes/extensions/manifest.d.ts +9 -0
  195. package/dist/src/routes/extensions/manifest.d.ts.map +1 -1
  196. package/dist/src/routes/extensions/manifest.js +33 -1
  197. package/dist/src/routes/extensions/manifest.js.map +1 -1
  198. package/dist/src/routes/extensions/paywall.d.ts.map +1 -1
  199. package/dist/src/routes/extensions/paywall.js +9 -0
  200. package/dist/src/routes/extensions/paywall.js.map +1 -1
  201. package/dist/src/routes/federation-sync/messaging.d.ts.map +1 -1
  202. package/dist/src/routes/federation-sync/messaging.js +3 -1
  203. package/dist/src/routes/federation-sync/messaging.js.map +1 -1
  204. package/dist/src/routes/ghii/recovery.d.ts +2 -0
  205. package/dist/src/routes/ghii/recovery.d.ts.map +1 -1
  206. package/dist/src/routes/ghii/recovery.js +7 -0
  207. package/dist/src/routes/ghii/recovery.js.map +1 -1
  208. package/dist/src/routes/ghii/register-login.d.ts +4 -0
  209. package/dist/src/routes/ghii/register-login.d.ts.map +1 -1
  210. package/dist/src/routes/ghii/register-login.js +45 -22
  211. package/dist/src/routes/ghii/register-login.js.map +1 -1
  212. package/dist/src/routes/ghii/web-verify.d.ts +5 -0
  213. package/dist/src/routes/ghii/web-verify.d.ts.map +1 -1
  214. package/dist/src/routes/ghii/web-verify.js +24 -3
  215. package/dist/src/routes/ghii/web-verify.js.map +1 -1
  216. package/dist/src/routes/libs/sdk-serve.d.ts +11 -0
  217. package/dist/src/routes/libs/sdk-serve.d.ts.map +1 -0
  218. package/dist/src/routes/libs/sdk-serve.js +53 -0
  219. package/dist/src/routes/libs/sdk-serve.js.map +1 -0
  220. package/dist/src/routes/libs.d.ts +7 -1
  221. package/dist/src/routes/libs.d.ts.map +1 -1
  222. package/dist/src/routes/libs.js +65 -146
  223. package/dist/src/routes/libs.js.map +1 -1
  224. package/dist/src/routes/messages.d.ts +3 -0
  225. package/dist/src/routes/messages.d.ts.map +1 -1
  226. package/dist/src/routes/messages.js +9 -0
  227. package/dist/src/routes/messages.js.map +1 -1
  228. package/dist/src/routes/notifications.d.ts +6 -3
  229. package/dist/src/routes/notifications.d.ts.map +1 -1
  230. package/dist/src/routes/notifications.js +32 -3
  231. package/dist/src/routes/notifications.js.map +1 -1
  232. package/dist/src/routes/organisms/workspace-access.d.ts.map +1 -1
  233. package/dist/src/routes/organisms/workspace-access.js +38 -20
  234. package/dist/src/routes/organisms/workspace-access.js.map +1 -1
  235. package/dist/src/routes/unfurl.d.ts +27 -0
  236. package/dist/src/routes/unfurl.d.ts.map +1 -0
  237. package/dist/src/routes/unfurl.js +180 -0
  238. package/dist/src/routes/unfurl.js.map +1 -0
  239. package/dist/src/routes/upload.d.ts +2 -0
  240. package/dist/src/routes/upload.d.ts.map +1 -1
  241. package/dist/src/routes/upload.js +7 -0
  242. package/dist/src/routes/upload.js.map +1 -1
  243. package/dist/src/routes/webmcp.d.ts +3 -0
  244. package/dist/src/routes/webmcp.d.ts.map +1 -1
  245. package/dist/src/routes/webmcp.js +55 -0
  246. package/dist/src/routes/webmcp.js.map +1 -1
  247. package/dist/src/server-bootstrap/routes-loader.d.ts +1 -0
  248. package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
  249. package/dist/src/server-bootstrap/routes-loader.js +8 -0
  250. package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
  251. package/dist/src/services/agent-face.d.ts +10 -2
  252. package/dist/src/services/agent-face.d.ts.map +1 -1
  253. package/dist/src/services/agent-face.js +10 -4
  254. package/dist/src/services/agent-face.js.map +1 -1
  255. package/dist/src/services/app-tool-interfaces.d.ts +37 -0
  256. package/dist/src/services/app-tool-interfaces.d.ts.map +1 -0
  257. package/dist/src/services/app-tool-interfaces.js +101 -0
  258. package/dist/src/services/app-tool-interfaces.js.map +1 -0
  259. package/dist/src/services/build-app-prompt.d.ts +3 -0
  260. package/dist/src/services/build-app-prompt.d.ts.map +1 -1
  261. package/dist/src/services/build-app-prompt.js +12 -1
  262. package/dist/src/services/build-app-prompt.js.map +1 -1
  263. package/dist/src/services/contacts.d.ts +25 -1
  264. package/dist/src/services/contacts.d.ts.map +1 -1
  265. package/dist/src/services/contacts.js +30 -0
  266. package/dist/src/services/contacts.js.map +1 -1
  267. package/dist/src/services/entitlement-money.d.ts +55 -0
  268. package/dist/src/services/entitlement-money.d.ts.map +1 -0
  269. package/dist/src/services/entitlement-money.js +68 -0
  270. package/dist/src/services/entitlement-money.js.map +1 -0
  271. package/dist/src/services/exchange-market.d.ts +247 -0
  272. package/dist/src/services/exchange-market.d.ts.map +1 -0
  273. package/dist/src/services/exchange-market.js +254 -0
  274. package/dist/src/services/exchange-market.js.map +1 -0
  275. package/dist/src/services/exchange-proposals.d.ts +47 -0
  276. package/dist/src/services/exchange-proposals.d.ts.map +1 -0
  277. package/dist/src/services/exchange-proposals.js +71 -0
  278. package/dist/src/services/exchange-proposals.js.map +1 -0
  279. package/dist/src/services/exchange-work.d.ts +30 -0
  280. package/dist/src/services/exchange-work.d.ts.map +1 -0
  281. package/dist/src/services/exchange-work.js +43 -0
  282. package/dist/src/services/exchange-work.js.map +1 -0
  283. package/dist/src/services/message-send.d.ts.map +1 -1
  284. package/dist/src/services/message-send.js +4 -1
  285. package/dist/src/services/message-send.js.map +1 -1
  286. package/dist/src/services/metered-entitlements.d.ts +203 -0
  287. package/dist/src/services/metered-entitlements.d.ts.map +1 -0
  288. package/dist/src/services/metered-entitlements.js +264 -0
  289. package/dist/src/services/metered-entitlements.js.map +1 -0
  290. package/dist/src/services/notify.d.ts +7 -0
  291. package/dist/src/services/notify.d.ts.map +1 -1
  292. package/dist/src/services/notify.js +35 -0
  293. package/dist/src/services/notify.js.map +1 -1
  294. package/dist/src/services/owner-memory.d.ts +16 -0
  295. package/dist/src/services/owner-memory.d.ts.map +1 -1
  296. package/dist/src/services/owner-memory.js +23 -0
  297. package/dist/src/services/owner-memory.js.map +1 -1
  298. package/dist/src/services/owner-provisioning.d.ts +5 -0
  299. package/dist/src/services/owner-provisioning.d.ts.map +1 -1
  300. package/dist/src/services/owner-provisioning.js +20 -2
  301. package/dist/src/services/owner-provisioning.js.map +1 -1
  302. package/dist/src/storage/providers/postgres-kysely/methods/apps.d.ts +1 -0
  303. package/dist/src/storage/providers/postgres-kysely/methods/apps.d.ts.map +1 -1
  304. package/dist/src/storage/providers/postgres-kysely/methods/apps.js +2 -0
  305. package/dist/src/storage/providers/postgres-kysely/methods/apps.js.map +1 -1
  306. package/dist/src/storage/providers/postgres-kysely/methods/identity.d.ts +1 -0
  307. package/dist/src/storage/providers/postgres-kysely/methods/identity.d.ts.map +1 -1
  308. package/dist/src/storage/providers/postgres-kysely/methods/identity.js +4 -0
  309. package/dist/src/storage/providers/postgres-kysely/methods/identity.js.map +1 -1
  310. package/dist/src/storage/providers/postgres-kysely/migrations/0011_unique_verified_email.sql +25 -0
  311. package/dist/src/storage/providers/sqlite/methods/apps.d.ts +1 -0
  312. package/dist/src/storage/providers/sqlite/methods/apps.d.ts.map +1 -1
  313. package/dist/src/storage/providers/sqlite/methods/apps.js +2 -0
  314. package/dist/src/storage/providers/sqlite/methods/apps.js.map +1 -1
  315. package/dist/src/storage/providers/sqlite/methods/identity-nodes.d.ts +1 -0
  316. package/dist/src/storage/providers/sqlite/methods/identity-nodes.d.ts.map +1 -1
  317. package/dist/src/storage/providers/sqlite/methods/identity-nodes.js +4 -0
  318. package/dist/src/storage/providers/sqlite/methods/identity-nodes.js.map +1 -1
  319. package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
  320. package/dist/src/storage/providers/sqlite/schema.js +20 -0
  321. package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
  322. package/dist/src/storage/repositories/app.repository.d.ts +0 -0
  323. package/dist/src/storage/repositories/app.repository.d.ts.map +1 -1
  324. package/dist/src/storage/repositories/identity.repository.d.ts +6 -0
  325. package/dist/src/storage/repositories/identity.repository.d.ts.map +1 -1
  326. package/dist/src/storage/types/apps.d.ts +1 -0
  327. package/dist/src/storage/types/apps.d.ts.map +1 -1
  328. package/dist/src/storage/types/organisms-federation.d.ts +21 -0
  329. package/dist/src/storage/types/organisms-federation.d.ts.map +1 -1
  330. package/dist/src/utils/app-mobile-lint.d.ts +17 -0
  331. package/dist/src/utils/app-mobile-lint.d.ts.map +1 -0
  332. package/dist/src/utils/app-mobile-lint.js +40 -0
  333. package/dist/src/utils/app-mobile-lint.js.map +1 -0
  334. package/dist/static/app-catalog/_template.html +12 -77
  335. package/dist/static/app-catalog/js/apps-io.js +51 -165
  336. package/dist/static/app-catalog/js/cost.js +100 -0
  337. package/dist/static/app-catalog/js/db.js +23 -93
  338. package/dist/static/app-catalog/js/detail.js +158 -24
  339. package/dist/static/app-catalog/js/favorites.js +71 -0
  340. package/dist/static/app-catalog/js/i18n-data.js +90 -16
  341. package/dist/static/app-catalog/js/main.js +23 -103
  342. package/dist/static/app-catalog/js/migrate.js +88 -0
  343. package/dist/static/app-catalog/js/monetize.js +1 -1
  344. package/dist/static/app-catalog/js/promote.js +70 -0
  345. package/dist/static/app-catalog/js/render.js +26 -139
  346. package/dist/static/app-catalog/js/server-io.js +126 -223
  347. package/dist/static/app-catalog/js/settings.js +11 -204
  348. package/dist/static/app-catalog/styles/app-catalog.css +40 -0
  349. package/dist/static/app-catalog.html +790 -912
  350. package/dist/static/sdk-libs/_core/config.js +52 -0
  351. package/dist/static/sdk-libs/_core/http.js +52 -0
  352. package/dist/static/sdk-libs/_core/namespace.js +33 -0
  353. package/dist/static/sdk-libs/_core/sdk-globals.d.ts +50 -0
  354. package/dist/static/sdk-libs/_core/session.js +66 -0
  355. package/dist/static/sdk-libs/agentface/index.js +102 -0
  356. package/dist/static/sdk-libs/agents/index.js +267 -0
  357. package/dist/static/sdk-libs/ai/index.js +153 -0
  358. package/dist/static/sdk-libs/audio/core.js +111 -0
  359. package/dist/static/sdk-libs/audio/index.js +380 -0
  360. package/dist/static/sdk-libs/audio/instruments.js +369 -0
  361. package/dist/static/sdk-libs/auth/config.js +46 -0
  362. package/dist/static/sdk-libs/auth/crypto.js +166 -0
  363. package/dist/static/sdk-libs/auth/events.js +27 -0
  364. package/dist/static/sdk-libs/auth/i18n.js +64 -0
  365. package/dist/static/sdk-libs/auth/index.js +37 -0
  366. package/dist/static/sdk-libs/auth/modal.js +545 -0
  367. package/dist/static/sdk-libs/auth/pill.js +167 -0
  368. package/dist/static/sdk-libs/auth/session.js +792 -0
  369. package/dist/static/sdk-libs/auth/signup.js +232 -0
  370. package/dist/static/sdk-libs/auth/theme.js +96 -0
  371. package/dist/static/sdk-libs/capabilities/index.js +179 -0
  372. package/dist/static/sdk-libs/commerce/index.js +243 -0
  373. package/dist/static/sdk-libs/data/index.js +188 -0
  374. package/dist/static/sdk-libs/dist/aimeat-agentface.js +91 -0
  375. package/dist/static/sdk-libs/dist/aimeat-agents.js +315 -0
  376. package/dist/static/sdk-libs/dist/aimeat-ai.js +168 -0
  377. package/dist/static/sdk-libs/dist/aimeat-audio.js +979 -0
  378. package/dist/static/sdk-libs/dist/aimeat-auth.js +1831 -0
  379. package/dist/static/sdk-libs/dist/aimeat-capabilities.js +177 -0
  380. package/dist/static/sdk-libs/dist/aimeat-commerce.js +265 -0
  381. package/dist/static/sdk-libs/dist/aimeat-data.js +205 -0
  382. package/dist/static/sdk-libs/dist/aimeat-editor.js +299 -0
  383. package/dist/static/sdk-libs/dist/aimeat-header.js +270 -0
  384. package/dist/static/sdk-libs/dist/aimeat-intake.js +94 -0
  385. package/dist/static/sdk-libs/dist/aimeat-live.js +265 -0
  386. package/dist/static/sdk-libs/dist/aimeat-markdown.js +602 -0
  387. package/dist/static/sdk-libs/dist/aimeat-organism.js +394 -0
  388. package/dist/static/sdk-libs/dist/aimeat-portfolio-standalone.js +90 -0
  389. package/dist/static/sdk-libs/dist/aimeat-social.js +157 -0
  390. package/dist/static/sdk-libs/dist/aimeat-speech.js +300 -0
  391. package/dist/static/sdk-libs/dist/aimeat-storage.js +210 -0
  392. package/dist/static/sdk-libs/dist/aimeat-tunnel.js +383 -0
  393. package/dist/static/sdk-libs/dist/aimeat-wallet.js +118 -0
  394. package/dist/static/sdk-libs/dist/aimeat-webmcp.js +187 -0
  395. package/dist/static/sdk-libs/dist/aimeat-work.js +213 -0
  396. package/dist/static/sdk-libs/dist/aimeat-workflows.js +147 -0
  397. package/dist/static/sdk-libs/editor/index.js +229 -0
  398. package/dist/static/sdk-libs/header/index.js +249 -0
  399. package/dist/static/sdk-libs/intake/index.js +75 -0
  400. package/dist/static/sdk-libs/live/index.js +156 -0
  401. package/dist/static/sdk-libs/markdown/index.js +522 -0
  402. package/dist/static/sdk-libs/organism/index.js +381 -0
  403. package/dist/static/sdk-libs/portfolio-standalone/index.js +78 -0
  404. package/dist/static/sdk-libs/social/index.js +140 -0
  405. package/dist/static/sdk-libs/speech/index.js +321 -0
  406. package/dist/static/sdk-libs/storage/index.js +189 -0
  407. package/dist/static/sdk-libs/tunnel/index.js +428 -0
  408. package/dist/static/sdk-libs/wallet/index.js +115 -0
  409. package/dist/static/sdk-libs/webmcp/index.js +185 -0
  410. package/dist/static/sdk-libs/work/index.js +191 -0
  411. package/dist/static/sdk-libs/workflows/index.js +113 -0
  412. package/package.json +5 -2
@@ -0,0 +1,321 @@
1
+ /**
2
+ * @file speech/index.js
3
+ * @description Pilot migration of the aimeat-speech library (SDK-libs migration Phase 0). Exposes
4
+ * `AIMEAT.speech` — text-to-speech, speech-to-text, voice-command matching, and a pluggable
5
+ * provider architecture for cloud TTS/STT (ElevenLabs, Whisper, …). This is the real, JSDoc-typed
6
+ * ESM source that esbuild bundles to the classic IIFE served, unchanged, at /v1/libs/aimeat-speech.js.
7
+ * Behavior is identical to the former `aimeatSpeechLib()` string generator — the only differences
8
+ * are: (1) the non-deterministic `Generated:` timestamp comment is gone, and (2) the global attach
9
+ * goes through the shared `_core/namespace` helper instead of an inline `global.AIMEAT` block.
10
+ * @structure emit() · capability detection · TTS (native + cloud) · STT (native + cloud) · voice
11
+ * command matching · the `speech` public API · attach('speech', …).
12
+ * @usage <script src="/v1/libs/aimeat-speech.js"></script>
13
+ * AIMEAT.speech.say('Hello'); await AIMEAT.speech.listen();
14
+ * @version-history
15
+ * v1.0.0 — 2026-07-19 — Migrated verbatim from src/routes/lib-speech.ts (SDK-libs migration Phase 0).
16
+ */
17
+ import { attach } from '../_core/namespace.js';
18
+
19
+ // ══════════════════════════════════════════════════════
20
+ // Event system
21
+ // ══════════════════════════════════════════════════════
22
+
23
+ /** @type {Record<string, Array<(data: any) => void>>} */
24
+ const _listeners = {};
25
+ function emit(event, data) { (_listeners[event] || []).forEach(function (fn) { fn(data); }); }
26
+
27
+ // ══════════════════════════════════════════════════════
28
+ // Capability detection
29
+ // ══════════════════════════════════════════════════════
30
+
31
+ const _supported = {
32
+ get tts() { return typeof window !== 'undefined' && 'speechSynthesis' in window; },
33
+ get stt() { return typeof window !== 'undefined' && ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window); },
34
+ };
35
+
36
+ // ══════════════════════════════════════════════════════
37
+ // Provider slots
38
+ // ══════════════════════════════════════════════════════
39
+
40
+ /** @type {any} */
41
+ let _ttsProvider = null;
42
+ /** @type {any} */
43
+ let _sttProvider = null;
44
+
45
+ // ══════════════════════════════════════════════════════
46
+ // TTS state
47
+ // ══════════════════════════════════════════════════════
48
+
49
+ let _speaking = false;
50
+ /** @type {Array<{ text: string, opts: any }>} */
51
+ let _ttsQueue = [];
52
+
53
+ // ══════════════════════════════════════════════════════
54
+ // STT state
55
+ // ══════════════════════════════════════════════════════
56
+
57
+ let _listening = false;
58
+ /** @type {any} */
59
+ let _recognition = null;
60
+ /** @type {MediaRecorder | null} */
61
+ let _mediaRecorder = null;
62
+
63
+ // ══════════════════════════════════════════════════════
64
+ // Voices
65
+ // ══════════════════════════════════════════════════════
66
+
67
+ let _voicesLoaded = false;
68
+ /** @type {Array<{ name: string, lang: string }>} */
69
+ let _voicesList = [];
70
+
71
+ function loadVoices() {
72
+ if (!_supported.tts) return [];
73
+ _voicesList = speechSynthesis.getVoices().map(function (v) {
74
+ return { name: v.name, lang: v.lang };
75
+ });
76
+ _voicesLoaded = _voicesList.length > 0;
77
+ return _voicesList;
78
+ }
79
+ if (typeof window !== 'undefined' && _supported.tts) {
80
+ speechSynthesis.addEventListener('voiceschanged', loadVoices);
81
+ loadVoices();
82
+ }
83
+
84
+ // ══════════════════════════════════════════════════════
85
+ // TTS: Native implementation
86
+ // ══════════════════════════════════════════════════════
87
+
88
+ function nativeSay(text, opts) {
89
+ return new Promise(function (resolve) {
90
+ const utt = new SpeechSynthesisUtterance(text);
91
+ if (opts && opts.lang) utt.lang = opts.lang;
92
+ if (opts && opts.rate !== undefined) utt.rate = opts.rate;
93
+ if (opts && opts.pitch !== undefined) utt.pitch = opts.pitch;
94
+ if (opts && opts.volume !== undefined) utt.volume = opts.volume;
95
+ if (opts && opts.voice) {
96
+ const voices = speechSynthesis.getVoices();
97
+ const match = voices.find(function (v) {
98
+ return v.name === opts.voice || v.name.indexOf(opts.voice) >= 0;
99
+ });
100
+ if (match) utt.voice = match;
101
+ }
102
+ utt.onstart = function () { emit('start', {}); };
103
+ utt.onend = function () { _speaking = false; processQueue(); emit('end', {}); resolve(undefined); };
104
+ utt.onboundary = function (e) {
105
+ if (e.name === 'word') emit('word', { word: text.substr(e.charIndex, e.charLength || 10).split(/\s/)[0], index: e.charIndex });
106
+ };
107
+ utt.onerror = function (e) { _speaking = false; processQueue(); emit('error', { error: e.error }); resolve(undefined); };
108
+ _speaking = true;
109
+ speechSynthesis.speak(utt);
110
+ });
111
+ }
112
+
113
+ // ══════════════════════════════════════════════════════
114
+ // TTS: Cloud provider playback
115
+ // ══════════════════════════════════════════════════════
116
+
117
+ function cloudSay(text, opts) {
118
+ if (!_ttsProvider || !_ttsProvider.say) return Promise.resolve();
119
+ _speaking = true;
120
+ emit('start', {});
121
+ return _ttsProvider.say(text, opts || {}).then(function (blob) {
122
+ if (!blob) { _speaking = false; processQueue(); emit('end', {}); return; }
123
+ const ac = new (window.AudioContext || window.webkitAudioContext)();
124
+ return blob.arrayBuffer().then(function (ab) { return ac.decodeAudioData(ab); }).then(function (buf) {
125
+ const source = ac.createBufferSource();
126
+ source.buffer = buf;
127
+ source.connect(ac.destination);
128
+ source.onended = function () { _speaking = false; processQueue(); emit('end', {}); };
129
+ source.start();
130
+ });
131
+ }).catch(function (e) {
132
+ _speaking = false; processQueue();
133
+ emit('error', { error: e.message });
134
+ });
135
+ }
136
+
137
+ function processQueue() {
138
+ if (_ttsQueue.length > 0 && !_speaking) {
139
+ const next = _ttsQueue.shift();
140
+ if (next) doSay(next.text, next.opts);
141
+ }
142
+ }
143
+
144
+ function doSay(text, opts) {
145
+ if (_ttsProvider) return cloudSay(text, opts);
146
+ if (!_supported.tts) { console.warn('[aimeat-speech] TTS not supported in this browser'); return Promise.resolve(); }
147
+ return nativeSay(text, opts);
148
+ }
149
+
150
+ // ══════════════════════════════════════════════════════
151
+ // STT: Native implementation
152
+ // ══════════════════════════════════════════════════════
153
+
154
+ function nativeListen(opts) {
155
+ return new Promise(function (resolve, reject) {
156
+ const SpeechRecog = window.SpeechRecognition || window.webkitSpeechRecognition;
157
+ if (!SpeechRecog) { reject(new Error('SpeechRecognition not supported')); return; }
158
+
159
+ _recognition = new SpeechRecog();
160
+ _recognition.lang = (opts && opts.lang) || 'en-US';
161
+ _recognition.continuous = (opts && opts.continuous) || false;
162
+ _recognition.interimResults = (opts && opts.interimResults) || false;
163
+
164
+ const commands = (opts && opts.commands) || null;
165
+
166
+ _recognition.onstart = function () { _listening = true; emit('listening', {}); };
167
+ _recognition.onresult = function (e) {
168
+ for (let i = e.resultIndex; i < e.results.length; i++) {
169
+ const result = e.results[i];
170
+ const text = result[0].transcript.trim();
171
+ const final = result.isFinal;
172
+ const confidence = result[0].confidence;
173
+ emit('result', { text: text, final: final, confidence: confidence });
174
+ if (final && commands) matchCommand(text, commands);
175
+ if (final && !_recognition.continuous) {
176
+ resolve({ text: text, confidence: confidence, lang: _recognition.lang });
177
+ }
178
+ }
179
+ };
180
+ _recognition.onerror = function (e) {
181
+ _listening = false;
182
+ emit('error', { error: e.error });
183
+ if (!_recognition.continuous) reject(new Error(e.error));
184
+ };
185
+ _recognition.onend = function () {
186
+ _listening = false;
187
+ emit('stopped', {});
188
+ if (opts && opts.continuous && _recognition) {
189
+ try { _recognition.start(); } catch { /* recognition already stopped */ }
190
+ }
191
+ };
192
+
193
+ _recognition.start();
194
+ });
195
+ }
196
+
197
+ // ══════════════════════════════════════════════════════
198
+ // STT: Cloud provider (MediaRecorder -> blob -> provider)
199
+ // ══════════════════════════════════════════════════════
200
+
201
+ function cloudListen(opts) {
202
+ if (!_sttProvider || !_sttProvider.listen) return Promise.reject(new Error('No STT provider configured'));
203
+
204
+ return navigator.mediaDevices.getUserMedia({ audio: true }).then(function (stream) {
205
+ return new Promise(function (resolve, reject) {
206
+ /** @type {Blob[]} */
207
+ const chunks = [];
208
+ _mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' });
209
+ _listening = true;
210
+ emit('listening', {});
211
+
212
+ _mediaRecorder.ondataavailable = function (e) { if (e.data.size > 0) chunks.push(e.data); };
213
+ _mediaRecorder.onstop = function () {
214
+ _listening = false;
215
+ stream.getTracks().forEach(function (t) { t.stop(); });
216
+ emit('stopped', {});
217
+ const blob = new Blob(chunks, { type: 'audio/webm' });
218
+ _sttProvider.listen(blob, opts || {}).then(function (result) {
219
+ const text = typeof result === 'string' ? result : (result.text || result.transcript || '');
220
+ const confidence = typeof result === 'object' ? (result.confidence || 1) : 1;
221
+ emit('result', { text: text, final: true, confidence: confidence });
222
+ resolve({ text: text, confidence: confidence, lang: (opts && opts.lang) || 'en-US' });
223
+ }).catch(function (e) {
224
+ emit('error', { error: e.message }); reject(e);
225
+ });
226
+ };
227
+
228
+ _mediaRecorder.start();
229
+ if (!(opts && opts.continuous)) {
230
+ setTimeout(function () {
231
+ if (_mediaRecorder && _mediaRecorder.state === 'recording') _mediaRecorder.stop();
232
+ }, (opts && opts.timeout) || 5000);
233
+ }
234
+ });
235
+ });
236
+ }
237
+
238
+ // ══════════════════════════════════════════════════════
239
+ // Voice Command matching
240
+ // ══════════════════════════════════════════════════════
241
+
242
+ function matchCommand(text, commands) {
243
+ const lower = text.toLowerCase();
244
+ Object.keys(commands).forEach(function (pattern) {
245
+ const parts = pattern.toLowerCase().split(/\s+/);
246
+ const regex = '^' + parts.map(function (p) {
247
+ if (p.startsWith('*')) return '(.+)';
248
+ return p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
249
+ }).join('\\s+') + '$';
250
+ const match = lower.match(new RegExp(regex));
251
+ if (match) {
252
+ const captures = match.slice(1);
253
+ commands[pattern].apply(null, captures);
254
+ }
255
+ });
256
+ }
257
+
258
+ // ══════════════════════════════════════════════════════
259
+ // Public API
260
+ // ══════════════════════════════════════════════════════
261
+
262
+ const speech = {
263
+ say: function (text, opts) {
264
+ if (_speaking) {
265
+ _ttsQueue.push({ text: text, opts: opts });
266
+ return;
267
+ }
268
+ return doSay(text, opts);
269
+ },
270
+
271
+ stop: function () {
272
+ if (_supported.tts) speechSynthesis.cancel();
273
+ _speaking = false;
274
+ _ttsQueue = [];
275
+ },
276
+
277
+ get speaking() { return _speaking; },
278
+
279
+ voices: function (opts) {
280
+ if (!_voicesLoaded) loadVoices();
281
+ if (opts && opts.lang) {
282
+ const lang = opts.lang.toLowerCase();
283
+ return _voicesList.filter(function (v) { return v.lang.toLowerCase().startsWith(lang); });
284
+ }
285
+ return _voicesList;
286
+ },
287
+
288
+ listen: function (opts) {
289
+ if (_sttProvider) return cloudListen(opts);
290
+ return nativeListen(opts);
291
+ },
292
+
293
+ stopListening: function () {
294
+ if (_recognition) { _recognition.continuous = false; try { _recognition.stop(); } catch { /* already stopped */ } _recognition = null; }
295
+ if (_mediaRecorder && _mediaRecorder.state === 'recording') { _mediaRecorder.stop(); _mediaRecorder = null; }
296
+ _listening = false;
297
+ },
298
+
299
+ get listening() { return _listening; },
300
+
301
+ get supported() { return _supported; },
302
+
303
+ use: function (type, provider) {
304
+ if (type === 'tts') _ttsProvider = provider;
305
+ else if (type === 'stt') _sttProvider = provider;
306
+ else console.warn('[aimeat-speech] Unknown provider type:', type);
307
+ },
308
+
309
+ on: function (event, fn) {
310
+ if (!_listeners[event]) _listeners[event] = [];
311
+ _listeners[event].push(fn);
312
+ },
313
+
314
+ off: function (event, fn) {
315
+ if (!_listeners[event]) return;
316
+ _listeners[event] = _listeners[event].filter(function (f) { return f !== fn; });
317
+ },
318
+ };
319
+
320
+ // ── Expose globally ──
321
+ attach('speech', speech);
@@ -0,0 +1,189 @@
1
+ /**
2
+ * @file storage/index.js
3
+ * @description The aimeat-storage library (SDK-libs migration Phase 2). Exposes AIMEAT.storage — the
4
+ * file upload/download SDK: upload (File/Blob/base64, chunked for large files), download/metadata,
5
+ * list/delete, publicUrl, and an enableDropZone() drag-&-drop helper. Over the AIMEAT.auth session,
6
+ * with direct NODE_URL fetches for binary GET/HEAD/chunk PUT. Componentized ESM source esbuild
7
+ * bundles to the IIFE served, unchanged, at /v1/libs/aimeat-storage.js. Ported verbatim from
8
+ * lib-storage.ts; NODE_URL now comes from _core/config.
9
+ * @structure imports NODE_URL (config) + getSession/authFetch (session) + attach (namespace); the
10
+ * `storage` object incl. uploadChunked + enableDropZone; attach('storage', …).
11
+ * @usage <script src="/v1/libs/aimeat-auth.js"></script><script src="/v1/libs/aimeat-storage.js"></script>
12
+ * await AIMEAT.storage.upload(file); await AIMEAT.storage.download('key');
13
+ * @version-history
14
+ * v1.0.0 — 2026-07-19 — Migrated from src/routes/lib-storage.ts (SDK-libs migration Phase 2).
15
+ */
16
+ import { NODE_URL } from '../_core/config.js';
17
+ import { makeSession } from '../_core/session.js';
18
+ const { getSession, authFetch } = makeSession('aimeat-storage.js');
19
+ import { attach } from '../_core/namespace.js';
20
+
21
+ const storage = {
22
+ // Upload a file (File object, Blob, or base64 string)
23
+ async upload(fileOrData, opts) {
24
+ let key, data, mime_type, visibility;
25
+
26
+ if (fileOrData instanceof File || fileOrData instanceof Blob) {
27
+ // A bare Blob has no .name (only File does) — reading it yields undefined → the fallback.
28
+ const file = /** @type {File} */ (fileOrData);
29
+ key = opts?.key || file.name || ('file-' + Date.now());
30
+ mime_type = opts?.mime_type || file.type || 'application/octet-stream';
31
+ visibility = opts?.visibility || 'private';
32
+ const buf = await file.arrayBuffer();
33
+ const bytes = new Uint8Array(buf);
34
+ let binary = '';
35
+ for (let i = 0; i < bytes.length; i += 8192) {
36
+ binary += String.fromCharCode.apply(null, bytes.subarray(i, i + 8192));
37
+ }
38
+ data = btoa(binary);
39
+ } else if (typeof fileOrData === 'string') {
40
+ // Assume base64
41
+ key = opts?.key || ('file-' + Date.now());
42
+ data = fileOrData;
43
+ mime_type = opts?.mime_type || 'application/octet-stream';
44
+ visibility = opts?.visibility || 'private';
45
+ } else {
46
+ throw new Error('upload() expects a File, Blob, or base64 string');
47
+ }
48
+
49
+ const res = await authFetch('/v1/storage', {
50
+ method: 'POST',
51
+ body: JSON.stringify({ key, data, mime_type, visibility }),
52
+ });
53
+ if (!res.ok) throw new Error(res.error?.message || 'Upload failed');
54
+ return res.data;
55
+ },
56
+
57
+ // Download a file as Blob
58
+ async download(key) {
59
+ const session = getSession();
60
+ const jwt = session.jwt;
61
+ const r = await fetch(NODE_URL + '/v1/storage/' + encodeURIComponent(key), {
62
+ headers: { 'Authorization': 'Bearer ' + jwt },
63
+ });
64
+ if (!r.ok) throw new Error('Download failed: ' + r.status);
65
+ return r.blob();
66
+ },
67
+
68
+ // Get a direct URL for embedding (e.g. in <img src="">)
69
+ // Note: requires auth header, so only works with public files or session.fetch
70
+ publicUrl(key) {
71
+ return NODE_URL + '/v1/storage/' + encodeURIComponent(key);
72
+ },
73
+
74
+ // List all files
75
+ async list() {
76
+ const res = await authFetch('/v1/storage');
77
+ if (!res.ok) throw new Error(res.error?.message || 'Failed to list files');
78
+ return res.data;
79
+ },
80
+
81
+ // Get file metadata (HEAD request)
82
+ async metadata(key) {
83
+ const session = getSession();
84
+ const jwt = session.jwt;
85
+ const r = await fetch(NODE_URL + '/v1/storage/' + encodeURIComponent(key), {
86
+ method: 'HEAD',
87
+ headers: { 'Authorization': 'Bearer ' + jwt },
88
+ });
89
+ if (!r.ok) throw new Error('Metadata fetch failed: ' + r.status);
90
+ return {
91
+ contentType: r.headers.get('Content-Type'),
92
+ contentLength: parseInt(r.headers.get('Content-Length') || '0'),
93
+ visibility: r.headers.get('X-AIMEAT-Visibility'),
94
+ createdAt: r.headers.get('X-AIMEAT-Created'),
95
+ };
96
+ },
97
+
98
+ // Delete a file
99
+ async delete(key) {
100
+ const res = await authFetch('/v1/storage/' + encodeURIComponent(key), { method: 'DELETE' });
101
+ if (!res.ok) throw new Error(res.error?.message || 'Delete failed');
102
+ return res.data;
103
+ },
104
+
105
+ // ── Chunked upload for large files ──
106
+ async uploadChunked(file, opts) {
107
+ const chunkSize = opts?.chunkSize || (1024 * 1024); // 1MB default
108
+ const key = opts?.key || file.name || ('file-' + Date.now());
109
+ const mime_type = opts?.mime_type || file.type || 'application/octet-stream';
110
+ const visibility = opts?.visibility || 'private';
111
+ const totalChunks = Math.ceil(file.size / chunkSize);
112
+
113
+ // Init
114
+ const initRes = await authFetch('/v1/storage/upload/init', {
115
+ method: 'POST',
116
+ body: JSON.stringify({ key, mime_type, visibility, chunk_size: chunkSize, total_chunks: totalChunks }),
117
+ });
118
+ if (!initRes.ok) throw new Error(initRes.error?.message || 'Chunked upload init failed');
119
+ const uploadId = initRes.data.upload_id;
120
+
121
+ // Upload chunks
122
+ const session = getSession();
123
+ for (let i = 0; i < totalChunks; i++) {
124
+ const start = i * chunkSize;
125
+ const end = Math.min(start + chunkSize, file.size);
126
+ const chunk = file.slice(start, end);
127
+ const buf = await chunk.arrayBuffer();
128
+
129
+ const r = await fetch(NODE_URL + '/v1/storage/upload/' + uploadId + '/' + i, {
130
+ method: 'PUT',
131
+ headers: {
132
+ 'Authorization': 'Bearer ' + session.jwt,
133
+ 'Content-Type': 'application/octet-stream',
134
+ },
135
+ body: buf,
136
+ });
137
+ if (!r.ok) throw new Error('Chunk ' + i + ' upload failed: ' + r.status);
138
+ if (opts?.onProgress) opts.onProgress({ chunk: i, total: totalChunks, percent: Math.round(((i + 1) / totalChunks) * 100) });
139
+ }
140
+
141
+ // Complete
142
+ const completeRes = await authFetch('/v1/storage/upload/' + uploadId + '/complete', { method: 'POST' });
143
+ if (!completeRes.ok) throw new Error(completeRes.error?.message || 'Chunked upload complete failed');
144
+ return completeRes.data;
145
+ },
146
+
147
+ // Abort a chunked upload
148
+ async abortUpload(uploadId) {
149
+ const res = await authFetch('/v1/storage/upload/' + uploadId, { method: 'DELETE' });
150
+ if (!res.ok) throw new Error(res.error?.message || 'Abort failed');
151
+ return res.data;
152
+ },
153
+
154
+ // ── Drag & Drop helper ──
155
+ enableDropZone(selector, opts) {
156
+ const el = /** @type {HTMLElement} */ (typeof selector === 'string' ? document.querySelector(selector) : selector);
157
+ if (!el) throw new Error('Drop zone element not found: ' + selector);
158
+
159
+ const accept = opts?.accept || '*/*';
160
+ const maxSize = opts?.maxSize || (10 * 1024 * 1024);
161
+
162
+ el.addEventListener('dragover', (e) => { e.preventDefault(); el.style.outline = '2px dashed #38bdf8'; });
163
+ el.addEventListener('dragleave', () => { el.style.outline = ''; });
164
+ el.addEventListener('drop', async (e) => {
165
+ e.preventDefault();
166
+ el.style.outline = '';
167
+ const files = Array.from(e.dataTransfer.files);
168
+ for (const file of files) {
169
+ if (accept !== '*/*' && !file.type.match(accept.replace('*', '.*'))) {
170
+ if (opts?.onError) opts.onError(new Error('File type not accepted: ' + file.type));
171
+ continue;
172
+ }
173
+ if (file.size > maxSize) {
174
+ if (opts?.onError) opts.onError(new Error('File too large: ' + file.name + ' (' + file.size + ' bytes)'));
175
+ continue;
176
+ }
177
+ try {
178
+ const ref = await storage.upload(file, opts);
179
+ if (opts?.onUpload) opts.onUpload(ref, file);
180
+ } catch (err) {
181
+ if (opts?.onError) opts.onError(err);
182
+ }
183
+ }
184
+ });
185
+ },
186
+ };
187
+
188
+ // ── Expose globally ──
189
+ attach('storage', storage);