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,153 @@
1
+ /**
2
+ * @file ai/index.js
3
+ * @description The aimeat-ai library (SDK-libs migration Phase 1). Exposes AIMEAT.ai — a facade
4
+ * (isAvailable/complete/completeJson/models/usage/invalidateCache) that proxies to /v1/ai/* using
5
+ * the user's own OpenRouter key via the AIMEAT.auth session, so the key never leaves the server;
6
+ * short in-memory caches + typed error `.code`s. Componentized ESM source esbuild bundles to the
7
+ * IIFE served, unchanged, at /v1/libs/aimeat-ai.js. Ported verbatim from lib-ai.ts.
8
+ * @structure imports authFetch (session) + attach (namespace); _availCache / _modelsCache; the `ai`
9
+ * facade; attach('ai', …).
10
+ * @usage <script src="/v1/libs/aimeat-auth.js"></script><script src="/v1/libs/aimeat-ai.js"></script>
11
+ * if (await AIMEAT.ai.isAvailable()) { const r = await AIMEAT.ai.complete({ prompt, app_id }); }
12
+ * @version-history
13
+ * v1.0.0 — 2026-07-19 — Migrated from src/routes/lib-ai.ts (SDK-libs migration Phase 1).
14
+ */
15
+ import { makeSession } from '../_core/session.js';
16
+ const { authFetch } = makeSession('aimeat-ai.js');
17
+ import { attach } from '../_core/namespace.js';
18
+
19
+ // 60s in-memory cache for isAvailable so apps can call it on every render
20
+ // without hammering the server. Cleared on logout via storage event.
21
+ /** @type {{ v: boolean, t: number } | null} */
22
+ let _availCache = null;
23
+
24
+ // 1h in-memory cache for models() — the list barely changes in practice.
25
+ /** @type {{ v: any, t: number } | null} */
26
+ let _modelsCache = null;
27
+
28
+ const ai = {
29
+ /**
30
+ * Returns true if the user has AI configured (an OpenRouter key, or a keyless
31
+ * self-hosted provider). Cached 60 seconds. Apps should call this before showing
32
+ * "Use AI" buttons. Uses GET /v1/ai/available, which an app-grant token (a sandboxed
33
+ * app on the isolated app origin) can call with the ai:use scope — unlike the
34
+ * owner-only /v1/openrouter/settings. Falls back to that settings probe on older nodes.
35
+ */
36
+ async isAvailable() {
37
+ const now = Date.now();
38
+ if (_availCache && (now - _availCache.t) < 60_000) return _availCache.v;
39
+ try {
40
+ const r = await authFetch('/v1/ai/available');
41
+ if (r && r.ok && r.data && typeof r.data.available === 'boolean') {
42
+ _availCache = { v: r.data.available, t: now };
43
+ return r.data.available;
44
+ }
45
+ // Older node without /v1/ai/available: fall back to the owner-only settings probe.
46
+ const s = await authFetch('/v1/openrouter/settings');
47
+ const v = !!(s && s.ok && s.data && (s.data.hasApiKey || s.data.has_api_key));
48
+ _availCache = { v, t: now };
49
+ return v;
50
+ } catch { return false; }
51
+ },
52
+
53
+ /**
54
+ * Run a single completion. Returns { content, model, usage, budget }.
55
+ * Throws an Error with .code set on quota/permission/auth failures.
56
+ *
57
+ * Recognized error codes (see routes/ai.ts):
58
+ * NO_API_KEY — user hasn't set up a key yet
59
+ * QUOTA_EXHAUSTED — daily user budget hit
60
+ * APP_QUOTA_EXHAUSTED — per-app daily quota hit
61
+ * APP_NOT_ALLOWED — app_id not in user's allowlist
62
+ * APP_ID_REQUIRED — user has an allowlist; app must pass app_id
63
+ * INVALID_API_KEY — provider rejected the key
64
+ * RATE_LIMITED — provider rate limit
65
+ * PROVIDER_ERROR — upstream provider failed
66
+ */
67
+ async complete(opts) {
68
+ if (!opts || typeof opts !== 'object') throw new Error('opts object required');
69
+ if (!opts.prompt) throw new Error('opts.prompt required');
70
+ const body = {
71
+ prompt: opts.prompt,
72
+ systemPrompt: opts.systemPrompt,
73
+ model: opts.model,
74
+ modelRole: opts.modelRole,
75
+ temperature: opts.temperature,
76
+ top_p: opts.top_p,
77
+ max_tokens: opts.max_tokens,
78
+ app_id: opts.app_id,
79
+ };
80
+ const r = await authFetch('/v1/ai/complete', {
81
+ method: 'POST',
82
+ body: JSON.stringify(body),
83
+ });
84
+ if (!r || !r.ok) {
85
+ const code = (r && r.error && r.error.code) || 'UNKNOWN';
86
+ const msg = (r && r.error && r.error.message) || 'AI call failed';
87
+ const err = /** @type {Error & { code?: string }} */ (new Error(msg));
88
+ err.code = code;
89
+ throw err;
90
+ }
91
+ return r.data;
92
+ },
93
+
94
+ /**
95
+ * Convenience: complete + JSON.parse. Adds a "return ONLY valid JSON"
96
+ * suffix to systemPrompt. On parse failure, retries ONCE with a stronger
97
+ * instruction. Further failures throw — the user can retry by clicking.
98
+ */
99
+ async completeJson(opts) {
100
+ const suffix = '\nReturn ONLY valid JSON, no prose, no markdown fences.';
101
+ const first = await ai.complete({
102
+ ...opts,
103
+ systemPrompt: (opts.systemPrompt || '') + suffix,
104
+ });
105
+ try { return { ...first, parsed: JSON.parse(first.content) }; }
106
+ catch {
107
+ // One retry with a stronger instruction.
108
+ const retry = await ai.complete({
109
+ ...opts,
110
+ systemPrompt: (opts.systemPrompt || '') + suffix + '\nIMPORTANT: your previous attempt was not valid JSON. Output ONLY the JSON object, starting with { and ending with }. No other text.',
111
+ temperature: typeof opts.temperature === 'number' ? Math.max(0, opts.temperature - 0.3) : 0.2,
112
+ });
113
+ try { return { ...retry, parsed: JSON.parse(retry.content) }; }
114
+ catch {
115
+ const err = /** @type {Error & { code?: string }} */ (new Error('AI returned invalid JSON twice. Original response: ' + retry.content.slice(0, 200)));
116
+ err.code = 'JSON_PARSE_FAILED';
117
+ throw err;
118
+ }
119
+ }
120
+ },
121
+
122
+ /**
123
+ * List the models the user's account can hit. Cached 1 hour.
124
+ */
125
+ async models() {
126
+ const now = Date.now();
127
+ if (_modelsCache && (now - _modelsCache.t) < 3600_000) return _modelsCache.v;
128
+ const r = await authFetch('/v1/openrouter/models');
129
+ if (!r || !r.ok) throw new Error((r && r.error && r.error.message) || 'Failed to list models');
130
+ const v = r.data && r.data.models ? r.data.models : [];
131
+ _modelsCache = { v, t: now };
132
+ return v;
133
+ },
134
+
135
+ /**
136
+ * Today's spend snapshot (owner-only). Useful for "AI used: $0.04 / $1.00".
137
+ */
138
+ async usage() {
139
+ const r = await authFetch('/v1/ai/usage');
140
+ if (!r || !r.ok) throw new Error((r && r.error && r.error.message) || 'Failed to read usage');
141
+ return r.data;
142
+ },
143
+
144
+ /**
145
+ * Clear browser-side caches. Call after the user toggles their key/budget.
146
+ */
147
+ invalidateCache() {
148
+ _availCache = null;
149
+ _modelsCache = null;
150
+ },
151
+ };
152
+
153
+ attach('ai', ai);
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @file audio/core.js
3
+ * @description Shared core for the aimeat-audio library (SDK-libs migration Phase 2): the Web Audio
4
+ * context singleton (with autoplay-unlock on first gesture), the scientific-pitch note→frequency
5
+ * table, the master output node + volume/mute control, the active-notes registry (for stop), and
6
+ * the shared instrument / sample / custom-synth registries. Imported by instruments.js (which
7
+ * populates the built-ins) and index.js (soundboard/samples/custom-synth/realtime/public API).
8
+ * @structure ctx() · noteToFreq() · masterNode() · master · registerActive()/stopActive() ·
9
+ * instruments/sampleBuffers/customSynths registries.
10
+ * @usage import { ctx, noteToFreq, masterNode, registerActive } from './core.js';
11
+ * @version-history
12
+ * v1.0.0 — 2026-07-19 — Extracted from lib-audio.ts + audio-lib-part2.ts (SDK-libs migration Phase 2).
13
+ */
14
+
15
+ // ── AudioContext singleton ──
16
+ var _ctx = null;
17
+
18
+ export function ctx() {
19
+ if (!_ctx) {
20
+ _ctx = new (window.AudioContext || window.webkitAudioContext)();
21
+ if (_ctx.state === 'suspended') {
22
+ var resume = function () {
23
+ if (_ctx && _ctx.state === 'suspended') _ctx.resume();
24
+ };
25
+ ['click', 'touchstart', 'keydown'].forEach(function (e) {
26
+ document.addEventListener(e, resume, { once: false, passive: true });
27
+ });
28
+ }
29
+ }
30
+ return _ctx;
31
+ }
32
+
33
+ // ── Note frequency table (A0-C8, scientific pitch) ──
34
+ var NOTE_NAMES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];
35
+ var FLAT_MAP = { 'Db': 'C#', 'Eb': 'D#', 'Gb': 'F#', 'Ab': 'G#', 'Bb': 'A#', 'Cs': 'C#', 'Ds': 'D#', 'Fs': 'F#', 'Gs': 'G#', 'As': 'A#' };
36
+ var _freqCache = {};
37
+
38
+ export function noteToFreq(note) {
39
+ if (_freqCache[note]) return _freqCache[note];
40
+ var n = note.trim();
41
+ var flatKey = n.slice(0, 2);
42
+ if (FLAT_MAP[flatKey]) n = FLAT_MAP[flatKey] + n.slice(2);
43
+ var match = n.match(/^([A-G]#?)(\d)$/);
44
+ if (!match) return null;
45
+ var name = match[1];
46
+ var octave = parseInt(match[2]);
47
+ var semitone = NOTE_NAMES.indexOf(name);
48
+ if (semitone < 0) return null;
49
+ var midi = (octave + 1) * 12 + semitone;
50
+ var freq = 440 * Math.pow(2, (midi - 69) / 12);
51
+ _freqCache[note] = freq;
52
+ return freq;
53
+ }
54
+
55
+ // ── Master output ──
56
+ var _masterGain = null;
57
+
58
+ export function masterNode() {
59
+ if (!_masterGain) {
60
+ _masterGain = ctx().createGain();
61
+ _masterGain.connect(ctx().destination);
62
+ }
63
+ return _masterGain;
64
+ }
65
+
66
+ export var master = {
67
+ get volume() { return masterNode().gain.value; },
68
+ set volume(v) { masterNode().gain.value = Math.max(0, Math.min(1, v)); },
69
+ _muted: false,
70
+ _premuteVol: 1,
71
+ get mute() { return master._muted; },
72
+ set mute(v) {
73
+ if (v && !master._muted) {
74
+ master._premuteVol = masterNode().gain.value;
75
+ masterNode().gain.value = 0;
76
+ master._muted = true;
77
+ } else if (!v && master._muted) {
78
+ masterNode().gain.value = master._premuteVol;
79
+ master._muted = false;
80
+ }
81
+ },
82
+ };
83
+
84
+ // ── Active notes registry (for stop) ──
85
+ var _active = {};
86
+
87
+ export function registerActive(instrument, note, nodes, stopFn) {
88
+ var key = instrument + ':' + (note || '*');
89
+ if (_active[key]) _active[key].stop();
90
+ _active[key] = { nodes: nodes, stop: stopFn };
91
+ }
92
+
93
+ export function stopActive(instrument, note) {
94
+ if (!instrument) {
95
+ Object.keys(_active).forEach(function (k) { _active[k].stop(); delete _active[k]; });
96
+ return;
97
+ }
98
+ if (note) {
99
+ var key = instrument + ':' + note;
100
+ if (_active[key]) { _active[key].stop(); delete _active[key]; }
101
+ } else {
102
+ Object.keys(_active).forEach(function (k) {
103
+ if (k.startsWith(instrument + ':')) { _active[k].stop(); delete _active[k]; }
104
+ });
105
+ }
106
+ }
107
+
108
+ // ── Shared registries (populated by instruments.js + index.js's sample loader / custom synth) ──
109
+ export var instruments = {};
110
+ export var sampleBuffers = {};
111
+ export var customSynths = {};
@@ -0,0 +1,380 @@
1
+ /**
2
+ * @file audio/index.js
3
+ * @description Entry for the aimeat-audio library (SDK-libs migration Phase 2). Assembles the public
4
+ * AIMEAT.audio surface from the shared core (core.js: context/notes/master/active + registries) and
5
+ * the built-in instruments (instruments.js, imported for its registration side-effect), and adds the
6
+ * soundboard (audio-file playback), the sample loader (upgrade to recorded sounds under /lib/samples),
7
+ * the custom synth builder (oscillators + envelope + filter + effects chain), and the realtime bridge
8
+ * for networked jam sessions via AimeatRealtime. esbuild bundles this + its imports into the IIFE
9
+ * served, unchanged, at /v1/libs/aimeat-audio.js. Merges the former lib-audio.ts + audio-lib-part2.ts;
10
+ * NODE_URL now comes from _core/config.
11
+ * @structure imports core + './instruments.js' + NODE_URL/attach; soundboard; loadSamples/hasSamples/
12
+ * findNearestSample/playSample; createCustomSynth; realtime bridge; the `audio` API; attach('audio', …).
13
+ * @usage <script src="/v1/libs/aimeat-audio.js"></script> AIMEAT.audio.play('piano', 'C4');
14
+ * @version-history
15
+ * v1.0.0 — 2026-07-19 — Migrated + merged from lib-audio.ts + audio-lib-part2.ts (SDK-libs migration Phase 2).
16
+ */
17
+ import { NODE_URL } from '../_core/config.js';
18
+ import { attach } from '../_core/namespace.js';
19
+ import { ctx, noteToFreq, masterNode, master, registerActive, stopActive, instruments, sampleBuffers, customSynths } from './core.js';
20
+ import './instruments.js'; // side-effect: registers the 6 built-in instruments onto the shared registry
21
+
22
+ // ══════════════════════════════════════════════════════
23
+ // Soundboard: load and play audio files
24
+ // ══════════════════════════════════════════════════════
25
+
26
+ var _soundboardBuffers = {};
27
+ var _soundboardSources = {};
28
+
29
+ var soundboard = {
30
+ load: function (name, url) {
31
+ return fetch(url).then(function (resp) {
32
+ if (!resp.ok) throw new Error('Failed to load sound: ' + url);
33
+ return resp.arrayBuffer();
34
+ }).then(function (arrayBuf) {
35
+ return ctx().decodeAudioData(arrayBuf);
36
+ }).then(function (decoded) {
37
+ _soundboardBuffers[name] = decoded;
38
+ });
39
+ },
40
+
41
+ loadAll: function (map) {
42
+ var entries = Object.keys(map);
43
+ return Promise.all(entries.map(function (k) { return soundboard.load(k, map[k]); }));
44
+ },
45
+
46
+ play: function (name, opts) {
47
+ var buf = _soundboardBuffers[name];
48
+ if (!buf) { console.warn('[aimeat-audio] Sound not loaded:', name); return; }
49
+ var source = ctx().createBufferSource();
50
+ source.buffer = buf;
51
+ source.loop = (opts && opts.loop) || false;
52
+ var gain = ctx().createGain();
53
+ gain.gain.value = (opts && opts.volume !== undefined) ? opts.volume : 1;
54
+ source.connect(gain); gain.connect(masterNode());
55
+ source.start();
56
+ _soundboardSources[name] = source;
57
+ source.onended = function () { if (_soundboardSources[name] === source) delete _soundboardSources[name]; };
58
+ },
59
+
60
+ stop: function (name) {
61
+ if (_soundboardSources[name]) {
62
+ try { _soundboardSources[name].stop(); } catch { /* already stopped */ }
63
+ delete _soundboardSources[name];
64
+ }
65
+ },
66
+ };
67
+
68
+ // ══════════════════════════════════════════════════════
69
+ // Sample Loader
70
+ // ══════════════════════════════════════════════════════
71
+
72
+ var SAMPLE_NOTES = {
73
+ piano: ['A2', 'C3', 'Ds3', 'A3', 'C4', 'Ds4', 'A4', 'C5', 'Ds5', 'C6', 'C7'],
74
+ guitar: ['E2', 'A2', 'D3', 'G3', 'B3', 'E4', 'A4', 'E5'],
75
+ 'guitar-steel': ['E2', 'A2', 'D3', 'G3', 'B3', 'E4', 'A4', 'E5'],
76
+ 'guitar-el': ['E2', 'A2', 'D3', 'G3', 'B3', 'E4', 'A4', 'E5'],
77
+ bass: ['E1', 'A1', 'D2', 'G2', 'B2', 'E3'],
78
+ flute: ['C4', 'E4', 'A4', 'C5', 'E5', 'A5', 'C6'],
79
+ strings: ['C2', 'G2', 'C3', 'G3', 'C4', 'G4', 'C5', 'G5', 'C6'],
80
+ organ: ['C2', 'G2', 'C3', 'G3', 'C4', 'G4', 'C5', 'G5', 'C6'],
81
+ epiano: ['C2', 'G2', 'C3', 'G3', 'C4', 'G4', 'C5', 'G5', 'C6'],
82
+ trumpet: ['E3', 'A3', 'C4', 'E4', 'A4', 'C5', 'E5', 'A5'],
83
+ drums: ['kick', 'snare', 'hihat', 'hihat-open', 'crash', 'ride', 'tom-high', 'tom-mid', 'tom-low', 'clap', 'cowbell'],
84
+ };
85
+
86
+ function loadSamples(instrument, opts) {
87
+ var source = (opts && opts.source) || (NODE_URL + '/lib/samples/' + instrument + '/');
88
+ var notes = SAMPLE_NOTES[instrument];
89
+ if (!notes) { console.warn('[aimeat-audio] No sample map for:', instrument); return Promise.resolve(); }
90
+ if (!sampleBuffers[instrument]) sampleBuffers[instrument] = {};
91
+
92
+ return Promise.all(notes.map(function (note) {
93
+ var url = source + note + '.mp3';
94
+ return fetch(url).then(function (resp) {
95
+ if (!resp.ok) return null;
96
+ return resp.arrayBuffer();
97
+ }).then(function (buf) {
98
+ if (!buf) return;
99
+ return ctx().decodeAudioData(buf);
100
+ }).then(function (decoded) {
101
+ if (decoded) sampleBuffers[instrument][note] = decoded;
102
+ }).catch(function () {
103
+ console.warn('[aimeat-audio] Failed to load sample:', url);
104
+ });
105
+ }));
106
+ }
107
+
108
+ function hasSamples(instrument) {
109
+ return !!sampleBuffers[instrument] && Object.keys(sampleBuffers[instrument]).length > 0;
110
+ }
111
+
112
+ function findNearestSample(instrument, note) {
113
+ var samples = sampleBuffers[instrument];
114
+ if (!samples) return null;
115
+ if (instrument === 'drums') return samples[note] ? { buffer: samples[note], rate: 1 } : null;
116
+ var targetFreq = noteToFreq(note);
117
+ if (!targetFreq) return null;
118
+ var nearest = null;
119
+ var nearestDist = Infinity;
120
+ Object.keys(samples).forEach(function (sn) {
121
+ var sf = noteToFreq(sn);
122
+ if (!sf) return;
123
+ var dist = Math.abs(Math.log2(targetFreq / sf));
124
+ if (dist < nearestDist) { nearestDist = dist; nearest = { buffer: samples[sn], rate: targetFreq / sf }; }
125
+ });
126
+ return nearest;
127
+ }
128
+
129
+ function playSample(instrument, note, opts) {
130
+ var s = findNearestSample(instrument, note);
131
+ if (!s) return false;
132
+ var vel = (opts && opts.velocity !== undefined) ? opts.velocity : 0.7;
133
+ var source = ctx().createBufferSource();
134
+ source.buffer = s.buffer;
135
+ source.playbackRate.value = s.rate;
136
+ var gain = ctx().createGain(); gain.gain.value = vel;
137
+ source.connect(gain); gain.connect(masterNode());
138
+ source.start();
139
+ registerActive(instrument, note, [source], function () {
140
+ try { source.stop(); } catch { /* already stopped */ }
141
+ });
142
+ return true;
143
+ }
144
+
145
+ // ══════════════════════════════════════════════════════
146
+ // Custom Synth Builder
147
+ // ══════════════════════════════════════════════════════
148
+
149
+ function createCustomSynth(config) {
150
+ var name = config.name || ('custom-' + Date.now());
151
+ var oscConfigs = config.oscillators || [{ wave: 'sawtooth', detune: 0 }];
152
+ var envConfig = config.envelope || { attack: 0.01, decay: 0.1, sustain: 0.7, release: 0.1 };
153
+ var filterConfig = config.filter || null;
154
+ var pitchEnvConfig = config.pitchEnvelope || null;
155
+ var effectsConfig = config.effects || [];
156
+
157
+ function buildEffectChain(input) {
158
+ var current = input;
159
+ effectsConfig.forEach(function (fx) {
160
+ if (fx.type === 'distortion') {
161
+ var ws = ctx().createWaveShaper();
162
+ var amount = fx.amount || 0.5;
163
+ var k = amount * 400;
164
+ var samples = 44100;
165
+ var curve = new Float32Array(samples);
166
+ for (var i = 0; i < samples; i++) {
167
+ var x = i * 2 / samples - 1;
168
+ curve[i] = (3 + k) * x * 20 * (Math.PI / 180) / (Math.PI + k * Math.abs(x));
169
+ }
170
+ ws.curve = curve;
171
+ current.connect(ws); current = ws;
172
+ } else if (fx.type === 'delay') {
173
+ var dryG = ctx().createGain(); dryG.gain.value = 1 - (fx.mix || 0.3);
174
+ var wetG = ctx().createGain(); wetG.gain.value = fx.mix || 0.3;
175
+ var dly = ctx().createDelay(5.0); dly.delayTime.value = fx.time || 0.3;
176
+ var fb = ctx().createGain(); fb.gain.value = fx.feedback || 0.4;
177
+ current.connect(dryG); current.connect(dly);
178
+ dly.connect(fb); fb.connect(dly); dly.connect(wetG);
179
+ var merge = ctx().createGain();
180
+ dryG.connect(merge); wetG.connect(merge);
181
+ current = merge;
182
+ } else if (fx.type === 'chorus') {
183
+ var cDry = ctx().createGain(); cDry.gain.value = 1 - (fx.mix || 0.5);
184
+ var cWet = ctx().createGain(); cWet.gain.value = fx.mix || 0.5;
185
+ var cDelay = ctx().createDelay(); cDelay.delayTime.value = 0.02;
186
+ var cLfo = ctx().createOscillator(); cLfo.type = 'sine'; cLfo.frequency.value = fx.rate || 1.5;
187
+ var cDepth = ctx().createGain(); cDepth.gain.value = (fx.depth || 0.7) * 0.01;
188
+ cLfo.connect(cDepth); cDepth.connect(cDelay.delayTime); cLfo.start();
189
+ current.connect(cDry); current.connect(cDelay); cDelay.connect(cWet);
190
+ var cMerge = ctx().createGain();
191
+ cDry.connect(cMerge); cWet.connect(cMerge);
192
+ current = cMerge;
193
+ } else if (fx.type === 'tremolo') {
194
+ var trem = ctx().createGain();
195
+ var tLfo = ctx().createOscillator(); tLfo.type = 'sine'; tLfo.frequency.value = fx.rate || 4;
196
+ var tDepth = ctx().createGain(); tDepth.gain.value = fx.depth || 0.5;
197
+ tLfo.connect(tDepth); tDepth.connect(trem.gain); tLfo.start();
198
+ trem.gain.value = 1 - (fx.depth || 0.5) / 2;
199
+ current.connect(trem); current = trem;
200
+ } else if (fx.type === 'reverb') {
201
+ var rDry = ctx().createGain(); rDry.gain.value = 1 - (fx.mix || 0.5);
202
+ var rWet = ctx().createGain(); rWet.gain.value = fx.mix || 0.5;
203
+ var d1 = ctx().createDelay(); d1.delayTime.value = 0.037;
204
+ var d2 = ctx().createDelay(); d2.delayTime.value = 0.053;
205
+ var d3 = ctx().createDelay(); d3.delayTime.value = 0.071;
206
+ var rFb = Math.min(0.85, (fx.decay || 2) / 5);
207
+ var fg1 = ctx().createGain(); fg1.gain.value = rFb;
208
+ var fg2 = ctx().createGain(); fg2.gain.value = rFb * 0.9;
209
+ var fg3 = ctx().createGain(); fg3.gain.value = rFb * 0.8;
210
+ d1.connect(fg1); fg1.connect(d1); d2.connect(fg2); fg2.connect(d2); d3.connect(fg3); fg3.connect(d3);
211
+ current.connect(rDry); current.connect(d1); current.connect(d2); current.connect(d3);
212
+ var rMerge = ctx().createGain();
213
+ rDry.connect(rMerge); d1.connect(rWet); d2.connect(rWet); d3.connect(rWet); rWet.connect(rMerge);
214
+ current = rMerge;
215
+ } else if (fx.type === 'filter') {
216
+ var ff = ctx().createBiquadFilter();
217
+ ff.type = fx.filterType || 'lowpass';
218
+ ff.frequency.value = fx.frequency || 1000;
219
+ ff.Q.value = fx.Q || 1;
220
+ current.connect(ff); current = ff;
221
+ }
222
+ });
223
+ return current;
224
+ }
225
+
226
+ var synth = {
227
+ name: name,
228
+ play: function (note, opts) {
229
+ var freq = noteToFreq(note);
230
+ if (!freq) return;
231
+ var t = ctx().currentTime;
232
+ var vel = (opts && opts.velocity !== undefined) ? opts.velocity : 0.7;
233
+ var dur = (opts && opts.duration) || 1.0;
234
+ var allOscs = [];
235
+ var mix = ctx().createGain();
236
+ mix.gain.value = vel * 0.4 / oscConfigs.length;
237
+
238
+ oscConfigs.forEach(function (oc) {
239
+ var o = ctx().createOscillator();
240
+ o.type = oc.wave || 'sawtooth';
241
+ o.frequency.value = freq;
242
+ o.detune.value = oc.detune || 0;
243
+ if (oc.gain !== undefined) {
244
+ var og = ctx().createGain(); og.gain.value = oc.gain;
245
+ o.connect(og); og.connect(mix);
246
+ } else {
247
+ o.connect(mix);
248
+ }
249
+ allOscs.push(o);
250
+ });
251
+
252
+ var chain = mix;
253
+ if (filterConfig) {
254
+ var cf = ctx().createBiquadFilter();
255
+ cf.type = filterConfig.type || 'lowpass';
256
+ cf.frequency.value = filterConfig.frequency || 1000;
257
+ cf.Q.value = filterConfig.Q || 1;
258
+ mix.connect(cf); chain = cf;
259
+ }
260
+
261
+ chain = buildEffectChain(chain);
262
+
263
+ var env = ctx().createGain();
264
+ var a = envConfig.attack || 0.01;
265
+ var d = envConfig.decay || 0.1;
266
+ var s = envConfig.sustain !== undefined ? envConfig.sustain : 0.7;
267
+ var r = envConfig.release || 0.1;
268
+ env.gain.setValueAtTime(0, t);
269
+ env.gain.linearRampToValueAtTime(1, t + a);
270
+ env.gain.linearRampToValueAtTime(s, t + a + d);
271
+ if (dur) {
272
+ env.gain.setValueAtTime(s, t + dur - r);
273
+ env.gain.linearRampToValueAtTime(0, t + dur);
274
+ }
275
+
276
+ chain.connect(env); env.connect(masterNode());
277
+
278
+ if (pitchEnvConfig) {
279
+ allOscs.forEach(function (o) {
280
+ o.frequency.setValueAtTime(pitchEnvConfig.start || freq, t);
281
+ o.frequency.exponentialRampToValueAtTime(pitchEnvConfig.end || freq, t + (pitchEnvConfig.time || 0.1));
282
+ });
283
+ }
284
+
285
+ allOscs.forEach(function (o) { o.start(t); if (dur) o.stop(t + dur + 0.1); });
286
+
287
+ registerActive(name, note, allOscs, function () {
288
+ try { env.gain.cancelScheduledValues(ctx().currentTime);
289
+ env.gain.linearRampToValueAtTime(0, ctx().currentTime + 0.05);
290
+ allOscs.forEach(function (o) { try { o.stop(ctx().currentTime + 0.1); } catch { /* already stopped */ } }); } catch { /* already stopped */ }
291
+ });
292
+ },
293
+ stop: function (note) { stopActive(name, note); },
294
+ };
295
+
296
+ instruments[name] = synth;
297
+ customSynths[name] = synth;
298
+ return synth;
299
+ }
300
+
301
+ // ══════════════════════════════════════════════════════
302
+ // Realtime Bridge
303
+ // ══════════════════════════════════════════════════════
304
+
305
+ var _rtInstance = null;
306
+ var _rtHandlerBroadcast = null;
307
+ var _rtHandlerPeerData = null;
308
+
309
+ function connectRealtime(rt) {
310
+ if (_rtInstance) disconnectRealtime();
311
+ _rtInstance = rt;
312
+
313
+ _rtHandlerBroadcast = function (msg) {
314
+ var d = msg.data || msg.payload || msg;
315
+ if (d && d.instrument && (d.note || d.hit)) {
316
+ audio.play(d.instrument, d.note || d.hit, d);
317
+ }
318
+ };
319
+ _rtHandlerPeerData = function (msg) {
320
+ var d = msg.data;
321
+ if (d && d.instrument && (d.note || d.hit)) {
322
+ audio.play(d.instrument, d.note || d.hit, d);
323
+ }
324
+ };
325
+
326
+ rt.on('broadcast', _rtHandlerBroadcast);
327
+ rt.on('peer-data', _rtHandlerPeerData);
328
+ }
329
+
330
+ function disconnectRealtime() {
331
+ if (_rtInstance) {
332
+ if (_rtHandlerBroadcast) _rtInstance.off('broadcast', _rtHandlerBroadcast);
333
+ if (_rtHandlerPeerData) _rtInstance.off('peer-data', _rtHandlerPeerData);
334
+ _rtInstance = null;
335
+ _rtHandlerBroadcast = null;
336
+ _rtHandlerPeerData = null;
337
+ }
338
+ }
339
+
340
+ // ══════════════════════════════════════════════════════
341
+ // Public API
342
+ // ══════════════════════════════════════════════════════
343
+
344
+ var audio = {
345
+ play: function (instrument, note, opts) {
346
+ if (sampleBuffers[instrument] && Object.keys(sampleBuffers[instrument]).length > 0) {
347
+ if (playSample(instrument, note, opts)) return;
348
+ }
349
+ if (customSynths[instrument]) {
350
+ customSynths[instrument].play(note, opts);
351
+ return;
352
+ }
353
+ var inst = instruments[instrument];
354
+ if (!inst) { console.warn('[aimeat-audio] Unknown instrument:', instrument); return; }
355
+ inst.play(note, opts);
356
+ },
357
+
358
+ stop: function (instrument, note) {
359
+ stopActive(instrument, note);
360
+ },
361
+
362
+ get instruments() {
363
+ var list = Object.keys(instruments);
364
+ Object.keys(customSynths).forEach(function (k) {
365
+ if (list.indexOf(k) < 0) list.push(k);
366
+ });
367
+ return list;
368
+ },
369
+
370
+ loadSamples: loadSamples,
371
+ hasSamples: hasSamples,
372
+ synth: createCustomSynth,
373
+ soundboard: soundboard,
374
+ master: master,
375
+ connectRealtime: connectRealtime,
376
+ disconnectRealtime: disconnectRealtime,
377
+ };
378
+
379
+ // ── Expose globally ──
380
+ attach('audio', audio);