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.
- package/dist/locales/en.json +35 -1
- package/dist/locales/fi.json +35 -1
- package/dist/public/components/LinkPreview.js +101 -0
- package/dist/public/components/NotificationBell.js +18 -1
- package/dist/public/css/theme.css +57 -7
- package/dist/public/css/views/admin.css +8 -1
- package/dist/public/css/views/app-grant.css +18 -0
- package/dist/public/css/views/inbox.css +46 -0
- package/dist/public/css/views/portfolio.css +46 -0
- package/dist/public/css/views/profile.css +29 -4
- package/dist/public/js/services/apps.js +19 -3
- package/dist/public/js/services/messages-ai-prompts.js +38 -0
- package/dist/public/js/services/messages.js +26 -4
- package/dist/public/js/services/notebook.js +76 -0
- package/dist/public/js/services/unfurl.js +43 -0
- package/dist/public/lib/samples/LICENSE.md +11 -0
- package/dist/public/lib/samples/bass/A1.mp3 +0 -0
- package/dist/public/lib/samples/bass/B2.mp3 +0 -0
- package/dist/public/lib/samples/bass/D2.mp3 +0 -0
- package/dist/public/lib/samples/bass/E1.mp3 +0 -0
- package/dist/public/lib/samples/bass/E3.mp3 +0 -0
- package/dist/public/lib/samples/bass/G2.mp3 +0 -0
- package/dist/public/lib/samples/epiano/C2.mp3 +0 -0
- package/dist/public/lib/samples/epiano/C3.mp3 +0 -0
- package/dist/public/lib/samples/epiano/C4.mp3 +0 -0
- package/dist/public/lib/samples/epiano/C5.mp3 +0 -0
- package/dist/public/lib/samples/epiano/C6.mp3 +0 -0
- package/dist/public/lib/samples/epiano/G2.mp3 +0 -0
- package/dist/public/lib/samples/epiano/G3.mp3 +0 -0
- package/dist/public/lib/samples/epiano/G4.mp3 +0 -0
- package/dist/public/lib/samples/epiano/G5.mp3 +0 -0
- package/dist/public/lib/samples/guitar-steel/A2.mp3 +0 -0
- package/dist/public/lib/samples/guitar-steel/A4.mp3 +0 -0
- package/dist/public/lib/samples/guitar-steel/B3.mp3 +0 -0
- package/dist/public/lib/samples/guitar-steel/D3.mp3 +0 -0
- package/dist/public/lib/samples/guitar-steel/E2.mp3 +0 -0
- package/dist/public/lib/samples/guitar-steel/E4.mp3 +0 -0
- package/dist/public/lib/samples/guitar-steel/E5.mp3 +0 -0
- package/dist/public/lib/samples/guitar-steel/G3.mp3 +0 -0
- package/dist/public/lib/samples/organ/C2.mp3 +0 -0
- package/dist/public/lib/samples/organ/C3.mp3 +0 -0
- package/dist/public/lib/samples/organ/C4.mp3 +0 -0
- package/dist/public/lib/samples/organ/C5.mp3 +0 -0
- package/dist/public/lib/samples/organ/C6.mp3 +0 -0
- package/dist/public/lib/samples/organ/G2.mp3 +0 -0
- package/dist/public/lib/samples/organ/G3.mp3 +0 -0
- package/dist/public/lib/samples/organ/G4.mp3 +0 -0
- package/dist/public/lib/samples/organ/G5.mp3 +0 -0
- package/dist/public/lib/samples/strings/C2.mp3 +0 -0
- package/dist/public/lib/samples/strings/C3.mp3 +0 -0
- package/dist/public/lib/samples/strings/C4.mp3 +0 -0
- package/dist/public/lib/samples/strings/C5.mp3 +0 -0
- package/dist/public/lib/samples/strings/C6.mp3 +0 -0
- package/dist/public/lib/samples/strings/G2.mp3 +0 -0
- package/dist/public/lib/samples/strings/G3.mp3 +0 -0
- package/dist/public/lib/samples/strings/G4.mp3 +0 -0
- package/dist/public/lib/samples/strings/G5.mp3 +0 -0
- package/dist/public/lib/samples/trumpet/A3.mp3 +0 -0
- package/dist/public/lib/samples/trumpet/A4.mp3 +0 -0
- package/dist/public/lib/samples/trumpet/A5.mp3 +0 -0
- package/dist/public/lib/samples/trumpet/C4.mp3 +0 -0
- package/dist/public/lib/samples/trumpet/C5.mp3 +0 -0
- package/dist/public/lib/samples/trumpet/E3.mp3 +0 -0
- package/dist/public/lib/samples/trumpet/E4.mp3 +0 -0
- package/dist/public/lib/samples/trumpet/E5.mp3 +0 -0
- package/dist/public/spa.html +2 -0
- package/dist/public/views/app-grant.js +24 -4
- package/dist/public/views/portfolio.js +61 -6
- package/dist/public/views/profile/apps-tab.js +18 -1
- package/dist/public/views/profile/inbox-tab/ai-actions.js +86 -0
- package/dist/public/views/profile/inbox-tab/components.js +124 -9
- package/dist/public/views/profile/inbox-tab/helpers.js +26 -0
- package/dist/public/views/profile/inbox-tab/panels.js +18 -3
- package/dist/public/views/profile/inbox-tab/use-thread-ux.js +18 -1
- package/dist/public/views/profile/inbox-tab.js +46 -49
- package/dist/public/views/profile/landing-page.cards.js +7 -0
- package/dist/public/views/profile/landing-page.js +12 -1
- package/dist/public/views/profile/skills-tab.js +1 -1
- package/dist/public/views/public-workspace-viewer.js +1 -1
- package/dist/public/views/start.js +2 -1
- package/dist/scripts/build-sdk-libs.d.ts +16 -0
- package/dist/scripts/build-sdk-libs.d.ts.map +1 -0
- package/dist/scripts/build-sdk-libs.js +112 -0
- package/dist/scripts/build-sdk-libs.js.map +1 -0
- package/dist/src/cli/connect/auth.d.ts +15 -0
- package/dist/src/cli/connect/auth.d.ts.map +1 -1
- package/dist/src/cli/connect/auth.js +25 -6
- package/dist/src/cli/connect/auth.js.map +1 -1
- package/dist/src/cli/connect/keychain.d.ts +9 -0
- package/dist/src/cli/connect/keychain.d.ts.map +1 -1
- package/dist/src/cli/connect/keychain.js +21 -8
- package/dist/src/cli/connect/keychain.js.map +1 -1
- package/dist/src/cli/connect/mcp/tools/exchange.d.ts +18 -0
- package/dist/src/cli/connect/mcp/tools/exchange.d.ts.map +1 -0
- package/dist/src/cli/connect/mcp/tools/exchange.js +170 -0
- package/dist/src/cli/connect/mcp/tools/exchange.js.map +1 -0
- package/dist/src/cli/connect/mcp/tools/index.d.ts.map +1 -1
- package/dist/src/cli/connect/mcp/tools/index.js +2 -0
- package/dist/src/cli/connect/mcp/tools/index.js.map +1 -1
- package/dist/src/cli/connect/tool-call-defs-exchange.d.ts +3 -0
- package/dist/src/cli/connect/tool-call-defs-exchange.d.ts.map +1 -0
- package/dist/src/cli/connect/tool-call-defs-exchange.js +146 -0
- package/dist/src/cli/connect/tool-call-defs-exchange.js.map +1 -0
- package/dist/src/cli/connect/tool-call.d.ts.map +1 -1
- package/dist/src/cli/connect/tool-call.js +2 -0
- package/dist/src/cli/connect/tool-call.js.map +1 -1
- package/dist/src/commerce/session-service.d.ts +14 -0
- package/dist/src/commerce/session-service.d.ts.map +1 -1
- package/dist/src/commerce/session-service.js +1 -1
- package/dist/src/commerce/session-service.js.map +1 -1
- package/dist/src/data/app-templates/shells.d.ts +7 -3
- package/dist/src/data/app-templates/shells.d.ts.map +1 -1
- package/dist/src/data/app-templates/shells.js +10 -6
- package/dist/src/data/app-templates/shells.js.map +1 -1
- package/dist/src/data/appdev-pitfalls.d.ts +2 -0
- package/dist/src/data/appdev-pitfalls.d.ts.map +1 -1
- package/dist/src/data/appdev-pitfalls.js +24 -1
- package/dist/src/data/appdev-pitfalls.js.map +1 -1
- package/dist/src/generated/api-types.d.ts +1565 -9
- package/dist/src/generated/api-types.d.ts.map +1 -1
- package/dist/src/mcp/annotations.d.ts.map +1 -1
- package/dist/src/mcp/annotations.js +20 -0
- package/dist/src/mcp/annotations.js.map +1 -1
- package/dist/src/mcp/apps.d.ts.map +1 -1
- package/dist/src/mcp/apps.js +8 -4
- package/dist/src/mcp/apps.js.map +1 -1
- package/dist/src/mcp/catalog/definitions/exchange.d.ts +18 -0
- package/dist/src/mcp/catalog/definitions/exchange.d.ts.map +1 -0
- package/dist/src/mcp/catalog/definitions/exchange.js +182 -0
- package/dist/src/mcp/catalog/definitions/exchange.js.map +1 -0
- package/dist/src/mcp/catalog/definitions.d.ts.map +1 -1
- package/dist/src/mcp/catalog/definitions.js +2 -0
- package/dist/src/mcp/catalog/definitions.js.map +1 -1
- package/dist/src/mcp/catalog/scopes.d.ts.map +1 -1
- package/dist/src/mcp/catalog/scopes.js +22 -0
- package/dist/src/mcp/catalog/scopes.js.map +1 -1
- package/dist/src/mcp/catalog/surfaces.d.ts.map +1 -1
- package/dist/src/mcp/catalog/surfaces.js +14 -0
- package/dist/src/mcp/catalog/surfaces.js.map +1 -1
- package/dist/src/mcp/exchange-run.d.ts +5 -0
- package/dist/src/mcp/exchange-run.d.ts.map +1 -0
- package/dist/src/mcp/exchange-run.js +226 -0
- package/dist/src/mcp/exchange-run.js.map +1 -0
- package/dist/src/mcp/exchange.d.ts +5 -0
- package/dist/src/mcp/exchange.d.ts.map +1 -0
- package/dist/src/mcp/exchange.js +351 -0
- package/dist/src/mcp/exchange.js.map +1 -0
- package/dist/src/mcp/extensions.d.ts.map +1 -1
- package/dist/src/mcp/extensions.js +11 -0
- package/dist/src/mcp/extensions.js.map +1 -1
- package/dist/src/mcp/index.d.ts.map +1 -1
- package/dist/src/mcp/index.js +6 -2
- package/dist/src/mcp/index.js.map +1 -1
- package/dist/src/models/app-tool-schemas.d.ts +55 -1
- package/dist/src/models/app-tool-schemas.d.ts.map +1 -1
- package/dist/src/models/app-tool-schemas.js +20 -1
- package/dist/src/models/app-tool-schemas.js.map +1 -1
- package/dist/src/models/offer-schemas.d.ts +2 -2
- package/dist/src/models/schemas.d.ts +1 -0
- package/dist/src/models/schemas.d.ts.map +1 -1
- package/dist/src/models/schemas.js +3 -0
- package/dist/src/models/schemas.js.map +1 -1
- package/dist/src/routes/agents/device-auth.d.ts +4 -0
- package/dist/src/routes/agents/device-auth.d.ts.map +1 -1
- package/dist/src/routes/agents/device-auth.js +19 -4
- package/dist/src/routes/agents/device-auth.js.map +1 -1
- package/dist/src/routes/app-grants.d.ts +6 -0
- package/dist/src/routes/app-grants.d.ts.map +1 -1
- package/dist/src/routes/app-grants.js +35 -2
- package/dist/src/routes/app-grants.js.map +1 -1
- package/dist/src/routes/apps/fork-manage.d.ts.map +1 -1
- package/dist/src/routes/apps/fork-manage.js +24 -1
- package/dist/src/routes/apps/fork-manage.js.map +1 -1
- package/dist/src/routes/apps/publish.d.ts +2 -0
- package/dist/src/routes/apps/publish.d.ts.map +1 -1
- package/dist/src/routes/apps/publish.js +27 -1
- package/dist/src/routes/apps/publish.js.map +1 -1
- package/dist/src/routes/apps-cost.d.ts +25 -0
- package/dist/src/routes/apps-cost.d.ts.map +1 -0
- package/dist/src/routes/apps-cost.js +107 -0
- package/dist/src/routes/apps-cost.js.map +1 -0
- package/dist/src/routes/exchange-market.d.ts +28 -0
- package/dist/src/routes/exchange-market.d.ts.map +1 -0
- package/dist/src/routes/exchange-market.js +454 -0
- package/dist/src/routes/exchange-market.js.map +1 -0
- package/dist/src/routes/exchange.d.ts +33 -0
- package/dist/src/routes/exchange.d.ts.map +1 -0
- package/dist/src/routes/exchange.js +395 -0
- package/dist/src/routes/exchange.js.map +1 -0
- package/dist/src/routes/extensions/entitlement-gate.d.ts +33 -0
- package/dist/src/routes/extensions/entitlement-gate.d.ts.map +1 -0
- package/dist/src/routes/extensions/entitlement-gate.js +143 -0
- package/dist/src/routes/extensions/entitlement-gate.js.map +1 -0
- package/dist/src/routes/extensions/manifest.d.ts +9 -0
- package/dist/src/routes/extensions/manifest.d.ts.map +1 -1
- package/dist/src/routes/extensions/manifest.js +33 -1
- package/dist/src/routes/extensions/manifest.js.map +1 -1
- package/dist/src/routes/extensions/paywall.d.ts.map +1 -1
- package/dist/src/routes/extensions/paywall.js +9 -0
- package/dist/src/routes/extensions/paywall.js.map +1 -1
- package/dist/src/routes/federation-sync/messaging.d.ts.map +1 -1
- package/dist/src/routes/federation-sync/messaging.js +3 -1
- package/dist/src/routes/federation-sync/messaging.js.map +1 -1
- package/dist/src/routes/ghii/recovery.d.ts +2 -0
- package/dist/src/routes/ghii/recovery.d.ts.map +1 -1
- package/dist/src/routes/ghii/recovery.js +7 -0
- package/dist/src/routes/ghii/recovery.js.map +1 -1
- package/dist/src/routes/ghii/register-login.d.ts +4 -0
- package/dist/src/routes/ghii/register-login.d.ts.map +1 -1
- package/dist/src/routes/ghii/register-login.js +45 -22
- package/dist/src/routes/ghii/register-login.js.map +1 -1
- package/dist/src/routes/ghii/web-verify.d.ts +5 -0
- package/dist/src/routes/ghii/web-verify.d.ts.map +1 -1
- package/dist/src/routes/ghii/web-verify.js +24 -3
- package/dist/src/routes/ghii/web-verify.js.map +1 -1
- package/dist/src/routes/libs/sdk-serve.d.ts +11 -0
- package/dist/src/routes/libs/sdk-serve.d.ts.map +1 -0
- package/dist/src/routes/libs/sdk-serve.js +53 -0
- package/dist/src/routes/libs/sdk-serve.js.map +1 -0
- package/dist/src/routes/libs.d.ts +7 -1
- package/dist/src/routes/libs.d.ts.map +1 -1
- package/dist/src/routes/libs.js +65 -146
- package/dist/src/routes/libs.js.map +1 -1
- package/dist/src/routes/messages.d.ts +3 -0
- package/dist/src/routes/messages.d.ts.map +1 -1
- package/dist/src/routes/messages.js +9 -0
- package/dist/src/routes/messages.js.map +1 -1
- package/dist/src/routes/notifications.d.ts +6 -3
- package/dist/src/routes/notifications.d.ts.map +1 -1
- package/dist/src/routes/notifications.js +32 -3
- package/dist/src/routes/notifications.js.map +1 -1
- package/dist/src/routes/organisms/workspace-access.d.ts.map +1 -1
- package/dist/src/routes/organisms/workspace-access.js +38 -20
- package/dist/src/routes/organisms/workspace-access.js.map +1 -1
- package/dist/src/routes/unfurl.d.ts +27 -0
- package/dist/src/routes/unfurl.d.ts.map +1 -0
- package/dist/src/routes/unfurl.js +180 -0
- package/dist/src/routes/unfurl.js.map +1 -0
- package/dist/src/routes/upload.d.ts +2 -0
- package/dist/src/routes/upload.d.ts.map +1 -1
- package/dist/src/routes/upload.js +7 -0
- package/dist/src/routes/upload.js.map +1 -1
- package/dist/src/routes/webmcp.d.ts +3 -0
- package/dist/src/routes/webmcp.d.ts.map +1 -1
- package/dist/src/routes/webmcp.js +55 -0
- package/dist/src/routes/webmcp.js.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.d.ts +1 -0
- package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.js +8 -0
- package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
- package/dist/src/services/agent-face.d.ts +10 -2
- package/dist/src/services/agent-face.d.ts.map +1 -1
- package/dist/src/services/agent-face.js +10 -4
- package/dist/src/services/agent-face.js.map +1 -1
- package/dist/src/services/app-tool-interfaces.d.ts +37 -0
- package/dist/src/services/app-tool-interfaces.d.ts.map +1 -0
- package/dist/src/services/app-tool-interfaces.js +101 -0
- package/dist/src/services/app-tool-interfaces.js.map +1 -0
- package/dist/src/services/build-app-prompt.d.ts +3 -0
- package/dist/src/services/build-app-prompt.d.ts.map +1 -1
- package/dist/src/services/build-app-prompt.js +12 -1
- package/dist/src/services/build-app-prompt.js.map +1 -1
- package/dist/src/services/contacts.d.ts +25 -1
- package/dist/src/services/contacts.d.ts.map +1 -1
- package/dist/src/services/contacts.js +30 -0
- package/dist/src/services/contacts.js.map +1 -1
- package/dist/src/services/entitlement-money.d.ts +55 -0
- package/dist/src/services/entitlement-money.d.ts.map +1 -0
- package/dist/src/services/entitlement-money.js +68 -0
- package/dist/src/services/entitlement-money.js.map +1 -0
- package/dist/src/services/exchange-market.d.ts +247 -0
- package/dist/src/services/exchange-market.d.ts.map +1 -0
- package/dist/src/services/exchange-market.js +254 -0
- package/dist/src/services/exchange-market.js.map +1 -0
- package/dist/src/services/exchange-proposals.d.ts +47 -0
- package/dist/src/services/exchange-proposals.d.ts.map +1 -0
- package/dist/src/services/exchange-proposals.js +71 -0
- package/dist/src/services/exchange-proposals.js.map +1 -0
- package/dist/src/services/exchange-work.d.ts +30 -0
- package/dist/src/services/exchange-work.d.ts.map +1 -0
- package/dist/src/services/exchange-work.js +43 -0
- package/dist/src/services/exchange-work.js.map +1 -0
- package/dist/src/services/message-send.d.ts.map +1 -1
- package/dist/src/services/message-send.js +4 -1
- package/dist/src/services/message-send.js.map +1 -1
- package/dist/src/services/metered-entitlements.d.ts +203 -0
- package/dist/src/services/metered-entitlements.d.ts.map +1 -0
- package/dist/src/services/metered-entitlements.js +264 -0
- package/dist/src/services/metered-entitlements.js.map +1 -0
- package/dist/src/services/notify.d.ts +7 -0
- package/dist/src/services/notify.d.ts.map +1 -1
- package/dist/src/services/notify.js +35 -0
- package/dist/src/services/notify.js.map +1 -1
- package/dist/src/services/owner-memory.d.ts +16 -0
- package/dist/src/services/owner-memory.d.ts.map +1 -1
- package/dist/src/services/owner-memory.js +23 -0
- package/dist/src/services/owner-memory.js.map +1 -1
- package/dist/src/services/owner-provisioning.d.ts +5 -0
- package/dist/src/services/owner-provisioning.d.ts.map +1 -1
- package/dist/src/services/owner-provisioning.js +20 -2
- package/dist/src/services/owner-provisioning.js.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/methods/apps.d.ts +1 -0
- package/dist/src/storage/providers/postgres-kysely/methods/apps.d.ts.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/methods/apps.js +2 -0
- package/dist/src/storage/providers/postgres-kysely/methods/apps.js.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/methods/identity.d.ts +1 -0
- package/dist/src/storage/providers/postgres-kysely/methods/identity.d.ts.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/methods/identity.js +4 -0
- package/dist/src/storage/providers/postgres-kysely/methods/identity.js.map +1 -1
- package/dist/src/storage/providers/postgres-kysely/migrations/0011_unique_verified_email.sql +25 -0
- package/dist/src/storage/providers/sqlite/methods/apps.d.ts +1 -0
- package/dist/src/storage/providers/sqlite/methods/apps.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/methods/apps.js +2 -0
- package/dist/src/storage/providers/sqlite/methods/apps.js.map +1 -1
- package/dist/src/storage/providers/sqlite/methods/identity-nodes.d.ts +1 -0
- package/dist/src/storage/providers/sqlite/methods/identity-nodes.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/methods/identity-nodes.js +4 -0
- package/dist/src/storage/providers/sqlite/methods/identity-nodes.js.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.js +20 -0
- package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
- package/dist/src/storage/repositories/app.repository.d.ts +0 -0
- package/dist/src/storage/repositories/app.repository.d.ts.map +1 -1
- package/dist/src/storage/repositories/identity.repository.d.ts +6 -0
- package/dist/src/storage/repositories/identity.repository.d.ts.map +1 -1
- package/dist/src/storage/types/apps.d.ts +1 -0
- package/dist/src/storage/types/apps.d.ts.map +1 -1
- package/dist/src/storage/types/organisms-federation.d.ts +21 -0
- package/dist/src/storage/types/organisms-federation.d.ts.map +1 -1
- package/dist/src/utils/app-mobile-lint.d.ts +17 -0
- package/dist/src/utils/app-mobile-lint.d.ts.map +1 -0
- package/dist/src/utils/app-mobile-lint.js +40 -0
- package/dist/src/utils/app-mobile-lint.js.map +1 -0
- package/dist/static/app-catalog/_template.html +12 -77
- package/dist/static/app-catalog/js/apps-io.js +51 -165
- package/dist/static/app-catalog/js/cost.js +100 -0
- package/dist/static/app-catalog/js/db.js +23 -93
- package/dist/static/app-catalog/js/detail.js +158 -24
- package/dist/static/app-catalog/js/favorites.js +71 -0
- package/dist/static/app-catalog/js/i18n-data.js +90 -16
- package/dist/static/app-catalog/js/main.js +23 -103
- package/dist/static/app-catalog/js/migrate.js +88 -0
- package/dist/static/app-catalog/js/monetize.js +1 -1
- package/dist/static/app-catalog/js/promote.js +70 -0
- package/dist/static/app-catalog/js/render.js +26 -139
- package/dist/static/app-catalog/js/server-io.js +126 -223
- package/dist/static/app-catalog/js/settings.js +11 -204
- package/dist/static/app-catalog/styles/app-catalog.css +40 -0
- package/dist/static/app-catalog.html +790 -912
- package/dist/static/sdk-libs/_core/config.js +52 -0
- package/dist/static/sdk-libs/_core/http.js +52 -0
- package/dist/static/sdk-libs/_core/namespace.js +33 -0
- package/dist/static/sdk-libs/_core/sdk-globals.d.ts +50 -0
- package/dist/static/sdk-libs/_core/session.js +66 -0
- package/dist/static/sdk-libs/agentface/index.js +102 -0
- package/dist/static/sdk-libs/agents/index.js +267 -0
- package/dist/static/sdk-libs/ai/index.js +153 -0
- package/dist/static/sdk-libs/audio/core.js +111 -0
- package/dist/static/sdk-libs/audio/index.js +380 -0
- package/dist/static/sdk-libs/audio/instruments.js +369 -0
- package/dist/static/sdk-libs/auth/config.js +46 -0
- package/dist/static/sdk-libs/auth/crypto.js +166 -0
- package/dist/static/sdk-libs/auth/events.js +27 -0
- package/dist/static/sdk-libs/auth/i18n.js +64 -0
- package/dist/static/sdk-libs/auth/index.js +37 -0
- package/dist/static/sdk-libs/auth/modal.js +545 -0
- package/dist/static/sdk-libs/auth/pill.js +167 -0
- package/dist/static/sdk-libs/auth/session.js +792 -0
- package/dist/static/sdk-libs/auth/signup.js +232 -0
- package/dist/static/sdk-libs/auth/theme.js +96 -0
- package/dist/static/sdk-libs/capabilities/index.js +179 -0
- package/dist/static/sdk-libs/commerce/index.js +243 -0
- package/dist/static/sdk-libs/data/index.js +188 -0
- package/dist/static/sdk-libs/dist/aimeat-agentface.js +91 -0
- package/dist/static/sdk-libs/dist/aimeat-agents.js +315 -0
- package/dist/static/sdk-libs/dist/aimeat-ai.js +168 -0
- package/dist/static/sdk-libs/dist/aimeat-audio.js +979 -0
- package/dist/static/sdk-libs/dist/aimeat-auth.js +1831 -0
- package/dist/static/sdk-libs/dist/aimeat-capabilities.js +177 -0
- package/dist/static/sdk-libs/dist/aimeat-commerce.js +265 -0
- package/dist/static/sdk-libs/dist/aimeat-data.js +205 -0
- package/dist/static/sdk-libs/dist/aimeat-editor.js +299 -0
- package/dist/static/sdk-libs/dist/aimeat-header.js +270 -0
- package/dist/static/sdk-libs/dist/aimeat-intake.js +94 -0
- package/dist/static/sdk-libs/dist/aimeat-live.js +265 -0
- package/dist/static/sdk-libs/dist/aimeat-markdown.js +602 -0
- package/dist/static/sdk-libs/dist/aimeat-organism.js +394 -0
- package/dist/static/sdk-libs/dist/aimeat-portfolio-standalone.js +90 -0
- package/dist/static/sdk-libs/dist/aimeat-social.js +157 -0
- package/dist/static/sdk-libs/dist/aimeat-speech.js +300 -0
- package/dist/static/sdk-libs/dist/aimeat-storage.js +210 -0
- package/dist/static/sdk-libs/dist/aimeat-tunnel.js +383 -0
- package/dist/static/sdk-libs/dist/aimeat-wallet.js +118 -0
- package/dist/static/sdk-libs/dist/aimeat-webmcp.js +187 -0
- package/dist/static/sdk-libs/dist/aimeat-work.js +213 -0
- package/dist/static/sdk-libs/dist/aimeat-workflows.js +147 -0
- package/dist/static/sdk-libs/editor/index.js +229 -0
- package/dist/static/sdk-libs/header/index.js +249 -0
- package/dist/static/sdk-libs/intake/index.js +75 -0
- package/dist/static/sdk-libs/live/index.js +156 -0
- package/dist/static/sdk-libs/markdown/index.js +522 -0
- package/dist/static/sdk-libs/organism/index.js +381 -0
- package/dist/static/sdk-libs/portfolio-standalone/index.js +78 -0
- package/dist/static/sdk-libs/social/index.js +140 -0
- package/dist/static/sdk-libs/speech/index.js +321 -0
- package/dist/static/sdk-libs/storage/index.js +189 -0
- package/dist/static/sdk-libs/tunnel/index.js +428 -0
- package/dist/static/sdk-libs/wallet/index.js +115 -0
- package/dist/static/sdk-libs/webmcp/index.js +185 -0
- package/dist/static/sdk-libs/work/index.js +191 -0
- package/dist/static/sdk-libs/workflows/index.js +113 -0
- 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);
|