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,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file audio/instruments.js
|
|
3
|
+
* @description The 6 built-in synthesized instruments for aimeat-audio (SDK-libs migration Phase 2):
|
|
4
|
+
* piano (2-op FM), guitar (Karplus-Strong), bass (saw + sub + lowpass), drums (per-hit noise/sine
|
|
5
|
+
* bursts: kick/snare/hihat/…/cowbell), flute (sine + breath noise + vibrato LFO), and synth
|
|
6
|
+
* (configurable oscillator). Importing this module populates the shared `instruments` registry from
|
|
7
|
+
* core.js (side-effect only — no exports). Split out of the merged audio module to keep every file
|
|
8
|
+
* under the 800-line cap.
|
|
9
|
+
* @structure side-effect: instruments.piano/guitar/bass/drums/flute/synth = { play(note, opts) }.
|
|
10
|
+
* @usage import './instruments.js'; // registers the built-ins onto the shared registry
|
|
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
|
+
import { ctx, noteToFreq, masterNode, registerActive, instruments } from './core.js';
|
|
15
|
+
|
|
16
|
+
// ── Piano: 2-operator FM synthesis ──
|
|
17
|
+
instruments.piano = {
|
|
18
|
+
play: function (note, opts) {
|
|
19
|
+
var freq = noteToFreq(note);
|
|
20
|
+
if (!freq) return;
|
|
21
|
+
var t = ctx().currentTime;
|
|
22
|
+
var vel = (opts && opts.velocity !== undefined) ? opts.velocity : 0.7;
|
|
23
|
+
var dur = (opts && opts.duration) || 2.0;
|
|
24
|
+
|
|
25
|
+
var mod = ctx().createOscillator(); mod.type = 'sine';
|
|
26
|
+
mod.frequency.value = freq * 2;
|
|
27
|
+
var modGain = ctx().createGain();
|
|
28
|
+
modGain.gain.setValueAtTime(freq * 1.5 * vel, t);
|
|
29
|
+
modGain.gain.exponentialRampToValueAtTime(freq * 0.01, t + dur * 0.8);
|
|
30
|
+
mod.connect(modGain);
|
|
31
|
+
|
|
32
|
+
var car = ctx().createOscillator(); car.type = 'sine';
|
|
33
|
+
car.frequency.value = freq;
|
|
34
|
+
modGain.connect(car.frequency);
|
|
35
|
+
|
|
36
|
+
var env = ctx().createGain();
|
|
37
|
+
env.gain.setValueAtTime(0, t);
|
|
38
|
+
env.gain.linearRampToValueAtTime(vel * 0.4, t + 0.005);
|
|
39
|
+
env.gain.exponentialRampToValueAtTime(vel * 0.15, t + 0.1);
|
|
40
|
+
env.gain.exponentialRampToValueAtTime(0.001, t + dur);
|
|
41
|
+
|
|
42
|
+
car.connect(env); env.connect(masterNode());
|
|
43
|
+
mod.start(t); car.start(t);
|
|
44
|
+
mod.stop(t + dur + 0.1); car.stop(t + dur + 0.1);
|
|
45
|
+
|
|
46
|
+
registerActive('piano', note, [mod, car], function () {
|
|
47
|
+
try { env.gain.cancelScheduledValues(ctx().currentTime);
|
|
48
|
+
env.gain.setValueAtTime(env.gain.value, ctx().currentTime);
|
|
49
|
+
env.gain.linearRampToValueAtTime(0, ctx().currentTime + 0.05);
|
|
50
|
+
mod.stop(ctx().currentTime + 0.1); car.stop(ctx().currentTime + 0.1); } catch { /* already stopped */ }
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// ── Guitar: Karplus-Strong plucked string ──
|
|
56
|
+
instruments.guitar = {
|
|
57
|
+
play: function (note, opts) {
|
|
58
|
+
var freq = noteToFreq(note);
|
|
59
|
+
if (!freq) return;
|
|
60
|
+
var t = ctx().currentTime;
|
|
61
|
+
var vel = (opts && opts.velocity !== undefined) ? opts.velocity : 0.7;
|
|
62
|
+
var dur = (opts && opts.duration) || 1.5;
|
|
63
|
+
|
|
64
|
+
var bufSize = Math.round(ctx().sampleRate / freq);
|
|
65
|
+
var noiseBuffer = ctx().createBuffer(1, bufSize, ctx().sampleRate);
|
|
66
|
+
var data = noiseBuffer.getChannelData(0);
|
|
67
|
+
for (var i = 0; i < bufSize; i++) data[i] = (Math.random() * 2 - 1) * vel;
|
|
68
|
+
|
|
69
|
+
var noise = ctx().createBufferSource();
|
|
70
|
+
noise.buffer = noiseBuffer;
|
|
71
|
+
noise.loop = true;
|
|
72
|
+
|
|
73
|
+
var filter = ctx().createBiquadFilter();
|
|
74
|
+
filter.type = 'lowpass';
|
|
75
|
+
filter.frequency.value = freq * 4;
|
|
76
|
+
filter.Q.value = 0.5;
|
|
77
|
+
|
|
78
|
+
var env = ctx().createGain();
|
|
79
|
+
env.gain.setValueAtTime(vel * 0.5, t);
|
|
80
|
+
env.gain.exponentialRampToValueAtTime(0.001, t + dur);
|
|
81
|
+
|
|
82
|
+
noise.connect(filter); filter.connect(env); env.connect(masterNode());
|
|
83
|
+
noise.start(t); noise.stop(t + dur + 0.05);
|
|
84
|
+
|
|
85
|
+
registerActive('guitar', note, [noise], function () {
|
|
86
|
+
try { env.gain.cancelScheduledValues(ctx().currentTime);
|
|
87
|
+
env.gain.linearRampToValueAtTime(0, ctx().currentTime + 0.05);
|
|
88
|
+
noise.stop(ctx().currentTime + 0.1); } catch { /* already stopped */ }
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// ── Bass: sawtooth + lowpass + sub-oscillator ──
|
|
94
|
+
instruments.bass = {
|
|
95
|
+
play: function (note, opts) {
|
|
96
|
+
var freq = noteToFreq(note);
|
|
97
|
+
if (!freq) return;
|
|
98
|
+
var t = ctx().currentTime;
|
|
99
|
+
var vel = (opts && opts.velocity !== undefined) ? opts.velocity : 0.7;
|
|
100
|
+
var dur = (opts && opts.duration) || 0.8;
|
|
101
|
+
|
|
102
|
+
var osc = ctx().createOscillator(); osc.type = 'sawtooth'; osc.frequency.value = freq;
|
|
103
|
+
var sub = ctx().createOscillator(); sub.type = 'sine'; sub.frequency.value = freq / 2;
|
|
104
|
+
var subGain = ctx().createGain(); subGain.gain.value = 0.5;
|
|
105
|
+
sub.connect(subGain);
|
|
106
|
+
|
|
107
|
+
var mix = ctx().createGain();
|
|
108
|
+
osc.connect(mix); subGain.connect(mix);
|
|
109
|
+
|
|
110
|
+
var filter = ctx().createBiquadFilter(); filter.type = 'lowpass';
|
|
111
|
+
filter.frequency.setValueAtTime(freq * 3, t);
|
|
112
|
+
filter.frequency.exponentialRampToValueAtTime(freq * 1.2, t + 0.15);
|
|
113
|
+
filter.Q.value = 2;
|
|
114
|
+
|
|
115
|
+
var env = ctx().createGain();
|
|
116
|
+
env.gain.setValueAtTime(0, t);
|
|
117
|
+
env.gain.linearRampToValueAtTime(vel * 0.5, t + 0.01);
|
|
118
|
+
env.gain.setValueAtTime(vel * 0.5, t + dur * 0.7);
|
|
119
|
+
env.gain.exponentialRampToValueAtTime(0.001, t + dur);
|
|
120
|
+
|
|
121
|
+
mix.connect(filter); filter.connect(env); env.connect(masterNode());
|
|
122
|
+
osc.start(t); sub.start(t);
|
|
123
|
+
osc.stop(t + dur + 0.05); sub.stop(t + dur + 0.05);
|
|
124
|
+
|
|
125
|
+
registerActive('bass', note, [osc, sub], function () {
|
|
126
|
+
try { env.gain.cancelScheduledValues(ctx().currentTime);
|
|
127
|
+
env.gain.linearRampToValueAtTime(0, ctx().currentTime + 0.05);
|
|
128
|
+
osc.stop(ctx().currentTime + 0.1); sub.stop(ctx().currentTime + 0.1); } catch { /* already stopped */ }
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// ── Drums: noise + sine bursts (per-hit) ──
|
|
134
|
+
instruments.drums = {
|
|
135
|
+
play: function (hit, opts) {
|
|
136
|
+
var t = ctx().currentTime;
|
|
137
|
+
var vel = (opts && opts.velocity !== undefined) ? opts.velocity : 0.7;
|
|
138
|
+
|
|
139
|
+
function makeTom(freq) {
|
|
140
|
+
var osc = ctx().createOscillator(); osc.type = 'sine';
|
|
141
|
+
osc.frequency.setValueAtTime(freq, t);
|
|
142
|
+
osc.frequency.exponentialRampToValueAtTime(freq * 0.6, t + 0.15);
|
|
143
|
+
var g = ctx().createGain();
|
|
144
|
+
g.gain.setValueAtTime(vel * 0.5, t);
|
|
145
|
+
g.gain.exponentialRampToValueAtTime(0.001, t + 0.3);
|
|
146
|
+
osc.connect(g); g.connect(masterNode());
|
|
147
|
+
osc.start(t); osc.stop(t + 0.4);
|
|
148
|
+
return [osc];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
var synths = {
|
|
152
|
+
'kick': function () {
|
|
153
|
+
var osc = ctx().createOscillator(); osc.type = 'sine';
|
|
154
|
+
osc.frequency.setValueAtTime(150, t);
|
|
155
|
+
osc.frequency.exponentialRampToValueAtTime(50, t + 0.1);
|
|
156
|
+
var g = ctx().createGain();
|
|
157
|
+
g.gain.setValueAtTime(vel, t);
|
|
158
|
+
g.gain.exponentialRampToValueAtTime(0.001, t + 0.4);
|
|
159
|
+
osc.connect(g); g.connect(masterNode());
|
|
160
|
+
var click = ctx().createOscillator(); click.type = 'square'; click.frequency.value = 800;
|
|
161
|
+
var cg = ctx().createGain();
|
|
162
|
+
cg.gain.setValueAtTime(vel * 0.3, t);
|
|
163
|
+
cg.gain.exponentialRampToValueAtTime(0.001, t + 0.02);
|
|
164
|
+
click.connect(cg); cg.connect(masterNode());
|
|
165
|
+
osc.start(t); osc.stop(t + 0.5);
|
|
166
|
+
click.start(t); click.stop(t + 0.05);
|
|
167
|
+
return [osc, click];
|
|
168
|
+
},
|
|
169
|
+
'snare': function () {
|
|
170
|
+
var bufLen = Math.round(ctx().sampleRate * 0.15);
|
|
171
|
+
var buf = ctx().createBuffer(1, bufLen, ctx().sampleRate);
|
|
172
|
+
var d = buf.getChannelData(0);
|
|
173
|
+
for (var i = 0; i < bufLen; i++) d[i] = (Math.random() * 2 - 1);
|
|
174
|
+
var noise = ctx().createBufferSource(); noise.buffer = buf;
|
|
175
|
+
var nf = ctx().createBiquadFilter(); nf.type = 'highpass'; nf.frequency.value = 1000;
|
|
176
|
+
var ng = ctx().createGain();
|
|
177
|
+
ng.gain.setValueAtTime(vel * 0.6, t);
|
|
178
|
+
ng.gain.exponentialRampToValueAtTime(0.001, t + 0.15);
|
|
179
|
+
noise.connect(nf); nf.connect(ng); ng.connect(masterNode());
|
|
180
|
+
var osc = ctx().createOscillator(); osc.type = 'sine'; osc.frequency.value = 200;
|
|
181
|
+
var og = ctx().createGain();
|
|
182
|
+
og.gain.setValueAtTime(vel * 0.5, t);
|
|
183
|
+
og.gain.exponentialRampToValueAtTime(0.001, t + 0.08);
|
|
184
|
+
osc.connect(og); og.connect(masterNode());
|
|
185
|
+
noise.start(t); osc.start(t); osc.stop(t + 0.2);
|
|
186
|
+
return [noise, osc];
|
|
187
|
+
},
|
|
188
|
+
'hihat': function () {
|
|
189
|
+
var bufLen = Math.round(ctx().sampleRate * 0.05);
|
|
190
|
+
var buf = ctx().createBuffer(1, bufLen, ctx().sampleRate);
|
|
191
|
+
var d = buf.getChannelData(0);
|
|
192
|
+
for (var i = 0; i < bufLen; i++) d[i] = (Math.random() * 2 - 1);
|
|
193
|
+
var noise = ctx().createBufferSource(); noise.buffer = buf;
|
|
194
|
+
var f = ctx().createBiquadFilter(); f.type = 'highpass'; f.frequency.value = 7000;
|
|
195
|
+
var g = ctx().createGain();
|
|
196
|
+
g.gain.setValueAtTime(vel * 0.3, t);
|
|
197
|
+
g.gain.exponentialRampToValueAtTime(0.001, t + 0.05);
|
|
198
|
+
noise.connect(f); f.connect(g); g.connect(masterNode());
|
|
199
|
+
noise.start(t);
|
|
200
|
+
return [noise];
|
|
201
|
+
},
|
|
202
|
+
'hihat-open': function () {
|
|
203
|
+
var bufLen = Math.round(ctx().sampleRate * 0.3);
|
|
204
|
+
var buf = ctx().createBuffer(1, bufLen, ctx().sampleRate);
|
|
205
|
+
var d = buf.getChannelData(0);
|
|
206
|
+
for (var i = 0; i < bufLen; i++) d[i] = (Math.random() * 2 - 1);
|
|
207
|
+
var noise = ctx().createBufferSource(); noise.buffer = buf;
|
|
208
|
+
var f = ctx().createBiquadFilter(); f.type = 'highpass'; f.frequency.value = 6000;
|
|
209
|
+
var g = ctx().createGain();
|
|
210
|
+
g.gain.setValueAtTime(vel * 0.3, t);
|
|
211
|
+
g.gain.exponentialRampToValueAtTime(0.001, t + 0.3);
|
|
212
|
+
noise.connect(f); f.connect(g); g.connect(masterNode());
|
|
213
|
+
noise.start(t);
|
|
214
|
+
return [noise];
|
|
215
|
+
},
|
|
216
|
+
'crash': function () {
|
|
217
|
+
var bufLen = Math.round(ctx().sampleRate * 1.0);
|
|
218
|
+
var buf = ctx().createBuffer(1, bufLen, ctx().sampleRate);
|
|
219
|
+
var d = buf.getChannelData(0);
|
|
220
|
+
for (var i = 0; i < bufLen; i++) d[i] = (Math.random() * 2 - 1);
|
|
221
|
+
var noise = ctx().createBufferSource(); noise.buffer = buf;
|
|
222
|
+
var f = ctx().createBiquadFilter(); f.type = 'highpass'; f.frequency.value = 4000;
|
|
223
|
+
var g = ctx().createGain();
|
|
224
|
+
g.gain.setValueAtTime(vel * 0.5, t);
|
|
225
|
+
g.gain.exponentialRampToValueAtTime(0.001, t + 1.0);
|
|
226
|
+
noise.connect(f); f.connect(g); g.connect(masterNode());
|
|
227
|
+
noise.start(t);
|
|
228
|
+
return [noise];
|
|
229
|
+
},
|
|
230
|
+
'ride': function () {
|
|
231
|
+
var bufLen = Math.round(ctx().sampleRate * 0.8);
|
|
232
|
+
var buf = ctx().createBuffer(1, bufLen, ctx().sampleRate);
|
|
233
|
+
var d = buf.getChannelData(0);
|
|
234
|
+
for (var i = 0; i < bufLen; i++) d[i] = (Math.random() * 2 - 1);
|
|
235
|
+
var noise = ctx().createBufferSource(); noise.buffer = buf;
|
|
236
|
+
var f = ctx().createBiquadFilter(); f.type = 'bandpass'; f.frequency.value = 8000; f.Q.value = 1;
|
|
237
|
+
var g = ctx().createGain();
|
|
238
|
+
g.gain.setValueAtTime(vel * 0.3, t);
|
|
239
|
+
g.gain.exponentialRampToValueAtTime(0.001, t + 0.8);
|
|
240
|
+
noise.connect(f); f.connect(g); g.connect(masterNode());
|
|
241
|
+
noise.start(t);
|
|
242
|
+
return [noise];
|
|
243
|
+
},
|
|
244
|
+
'tom-high': function () { return makeTom(300); },
|
|
245
|
+
'tom-mid': function () { return makeTom(220); },
|
|
246
|
+
'tom-low': function () { return makeTom(150); },
|
|
247
|
+
'clap': function () {
|
|
248
|
+
var nodes = [];
|
|
249
|
+
for (var ci = 0; ci < 3; ci++) {
|
|
250
|
+
var delay = ci * 0.01;
|
|
251
|
+
var bufLen = Math.round(ctx().sampleRate * 0.02);
|
|
252
|
+
var buf = ctx().createBuffer(1, bufLen, ctx().sampleRate);
|
|
253
|
+
var d = buf.getChannelData(0);
|
|
254
|
+
for (var j = 0; j < bufLen; j++) d[j] = (Math.random() * 2 - 1);
|
|
255
|
+
var noise = ctx().createBufferSource(); noise.buffer = buf;
|
|
256
|
+
var f = ctx().createBiquadFilter(); f.type = 'bandpass'; f.frequency.value = 2500; f.Q.value = 3;
|
|
257
|
+
var g = ctx().createGain();
|
|
258
|
+
g.gain.setValueAtTime(vel * 0.4, t + delay);
|
|
259
|
+
g.gain.exponentialRampToValueAtTime(0.001, t + delay + 0.08);
|
|
260
|
+
noise.connect(f); f.connect(g); g.connect(masterNode());
|
|
261
|
+
noise.start(t + delay);
|
|
262
|
+
nodes.push(noise);
|
|
263
|
+
}
|
|
264
|
+
return nodes;
|
|
265
|
+
},
|
|
266
|
+
'cowbell': function () {
|
|
267
|
+
var osc1 = ctx().createOscillator(); osc1.type = 'square'; osc1.frequency.value = 587;
|
|
268
|
+
var osc2 = ctx().createOscillator(); osc2.type = 'square'; osc2.frequency.value = 845;
|
|
269
|
+
var g = ctx().createGain();
|
|
270
|
+
g.gain.setValueAtTime(vel * 0.3, t);
|
|
271
|
+
g.gain.exponentialRampToValueAtTime(0.001, t + 0.4);
|
|
272
|
+
var f = ctx().createBiquadFilter(); f.type = 'bandpass'; f.frequency.value = 700; f.Q.value = 3;
|
|
273
|
+
osc1.connect(g); osc2.connect(g); g.connect(f); f.connect(masterNode());
|
|
274
|
+
osc1.start(t); osc2.start(t);
|
|
275
|
+
osc1.stop(t + 0.5); osc2.stop(t + 0.5);
|
|
276
|
+
return [osc1, osc2];
|
|
277
|
+
},
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
var fn = synths[hit];
|
|
281
|
+
if (!fn) { console.warn('[aimeat-audio] Unknown drum hit:', hit); return; }
|
|
282
|
+
var nodes = fn();
|
|
283
|
+
registerActive('drums', hit, nodes, function () {
|
|
284
|
+
nodes.forEach(function (n) { try { n.stop(ctx().currentTime + 0.01); } catch { /* already stopped */ } });
|
|
285
|
+
});
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// ── Flute: sine + breath noise + vibrato LFO ──
|
|
290
|
+
instruments.flute = {
|
|
291
|
+
play: function (note, opts) {
|
|
292
|
+
var freq = noteToFreq(note);
|
|
293
|
+
if (!freq) return;
|
|
294
|
+
var t = ctx().currentTime;
|
|
295
|
+
var vel = (opts && opts.velocity !== undefined) ? opts.velocity : 0.6;
|
|
296
|
+
var dur = (opts && opts.duration) || 1.5;
|
|
297
|
+
var vibDepth = (opts && opts.vibrato !== undefined) ? opts.vibrato : 0.15;
|
|
298
|
+
|
|
299
|
+
var osc = ctx().createOscillator(); osc.type = 'sine'; osc.frequency.value = freq;
|
|
300
|
+
|
|
301
|
+
var lfo = ctx().createOscillator(); lfo.type = 'sine'; lfo.frequency.value = 5.5;
|
|
302
|
+
var lfoGain = ctx().createGain(); lfoGain.gain.value = freq * vibDepth * 0.02;
|
|
303
|
+
lfo.connect(lfoGain); lfoGain.connect(osc.frequency);
|
|
304
|
+
|
|
305
|
+
var noiseBufLen = Math.round(ctx().sampleRate * dur);
|
|
306
|
+
var noiseBuf = ctx().createBuffer(1, noiseBufLen, ctx().sampleRate);
|
|
307
|
+
var nd = noiseBuf.getChannelData(0);
|
|
308
|
+
for (var i = 0; i < noiseBufLen; i++) nd[i] = (Math.random() * 2 - 1);
|
|
309
|
+
var noiseNode = ctx().createBufferSource(); noiseNode.buffer = noiseBuf;
|
|
310
|
+
var noiseFilt = ctx().createBiquadFilter(); noiseFilt.type = 'bandpass';
|
|
311
|
+
noiseFilt.frequency.value = freq; noiseFilt.Q.value = 2;
|
|
312
|
+
var noiseGain = ctx().createGain(); noiseGain.gain.value = vel * 0.06;
|
|
313
|
+
noiseNode.connect(noiseFilt); noiseFilt.connect(noiseGain);
|
|
314
|
+
|
|
315
|
+
var env = ctx().createGain();
|
|
316
|
+
env.gain.setValueAtTime(0, t);
|
|
317
|
+
env.gain.linearRampToValueAtTime(vel * 0.3, t + 0.08);
|
|
318
|
+
env.gain.setValueAtTime(vel * 0.3, t + dur - 0.1);
|
|
319
|
+
env.gain.linearRampToValueAtTime(0, t + dur);
|
|
320
|
+
|
|
321
|
+
osc.connect(env); noiseGain.connect(env); env.connect(masterNode());
|
|
322
|
+
lfo.start(t); osc.start(t); noiseNode.start(t);
|
|
323
|
+
lfo.stop(t + dur + 0.1); osc.stop(t + dur + 0.1);
|
|
324
|
+
|
|
325
|
+
registerActive('flute', note, [osc, lfo, noiseNode], function () {
|
|
326
|
+
try { env.gain.cancelScheduledValues(ctx().currentTime);
|
|
327
|
+
env.gain.linearRampToValueAtTime(0, ctx().currentTime + 0.05);
|
|
328
|
+
osc.stop(ctx().currentTime + 0.1); lfo.stop(ctx().currentTime + 0.1); } catch { /* already stopped */ }
|
|
329
|
+
});
|
|
330
|
+
},
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
// ── Synth: configurable oscillator ──
|
|
334
|
+
instruments.synth = {
|
|
335
|
+
play: function (note, opts) {
|
|
336
|
+
var freq = noteToFreq(note);
|
|
337
|
+
if (!freq) return;
|
|
338
|
+
var t = ctx().currentTime;
|
|
339
|
+
var vel = (opts && opts.velocity !== undefined) ? opts.velocity : 0.7;
|
|
340
|
+
var dur = (opts && opts.duration) || 1.0;
|
|
341
|
+
var wave = (opts && opts.wave) || 'sawtooth';
|
|
342
|
+
var filterFreq = (opts && opts.filter) || 2000;
|
|
343
|
+
|
|
344
|
+
var osc = ctx().createOscillator(); osc.type = wave; osc.frequency.value = freq;
|
|
345
|
+
var osc2 = ctx().createOscillator(); osc2.type = wave; osc2.frequency.value = freq; osc2.detune.value = 7;
|
|
346
|
+
var osc2Gain = ctx().createGain(); osc2Gain.gain.value = 0.5;
|
|
347
|
+
osc2.connect(osc2Gain);
|
|
348
|
+
|
|
349
|
+
var filter = ctx().createBiquadFilter(); filter.type = 'lowpass';
|
|
350
|
+
filter.frequency.value = filterFreq; filter.Q.value = 1;
|
|
351
|
+
|
|
352
|
+
var env = ctx().createGain();
|
|
353
|
+
env.gain.setValueAtTime(0, t);
|
|
354
|
+
env.gain.linearRampToValueAtTime(vel * 0.3, t + 0.02);
|
|
355
|
+
env.gain.setValueAtTime(vel * 0.3, t + dur * 0.7);
|
|
356
|
+
env.gain.exponentialRampToValueAtTime(0.001, t + dur);
|
|
357
|
+
|
|
358
|
+
osc.connect(filter); osc2Gain.connect(filter);
|
|
359
|
+
filter.connect(env); env.connect(masterNode());
|
|
360
|
+
osc.start(t); osc2.start(t);
|
|
361
|
+
osc.stop(t + dur + 0.05); osc2.stop(t + dur + 0.05);
|
|
362
|
+
|
|
363
|
+
registerActive('synth', note, [osc, osc2], function () {
|
|
364
|
+
try { env.gain.cancelScheduledValues(ctx().currentTime);
|
|
365
|
+
env.gain.linearRampToValueAtTime(0, ctx().currentTime + 0.05);
|
|
366
|
+
osc.stop(ctx().currentTime + 0.1); osc2.stop(ctx().currentTime + 0.1); } catch { /* already stopped */ }
|
|
367
|
+
});
|
|
368
|
+
},
|
|
369
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file auth/config.js
|
|
3
|
+
* @description aimeat-auth config (SDK-libs migration Phase 3). NODE_URL / APEX_URL / NODE_ID come
|
|
4
|
+
* from the shared _core/config (the same `<meta> → location.origin → prelude` resolution the whole
|
|
5
|
+
* SDK uses). The app-scope defaults + declaration reader, and the OIDC provider list + button
|
|
6
|
+
* glyphs, live here. AUTH_PROVIDERS is server-computed (`listEnabledProviderMeta`) and injected by
|
|
7
|
+
* the auth route as an EXTRA prelude line — `window.__AIMEAT_AUTH_CFG__.providers` — since the
|
|
8
|
+
* generic config prelude only carries nodeId/baseUrl. Extracted from auth-lib-part1.ts.
|
|
9
|
+
* @structure re-exports NODE_URL/APEX_URL/NODE_ID · APP_DEFAULT_SCOPES · appDeclaredScopes() ·
|
|
10
|
+
* AUTH_PROVIDERS · PROVIDER_ICONS.
|
|
11
|
+
* @usage import { NODE_URL, APEX_URL, AUTH_PROVIDERS, appDeclaredScopes } from './config.js';
|
|
12
|
+
* @version-history
|
|
13
|
+
* v1.0.0 — 2026-07-19 — Extracted from src/routes/libs/auth-lib-part1.ts (SDK-libs migration Phase 3).
|
|
14
|
+
*/
|
|
15
|
+
export { NODE_URL, APEX_URL, NODE_ID } from '../_core/config.js';
|
|
16
|
+
|
|
17
|
+
// Default scopes an app asks for in the H-2 silent SSO / grant flow when it does not declare its own.
|
|
18
|
+
// The common, foundational set: read/write the user's memory AND their stored files. (storage is a
|
|
19
|
+
// SEPARATE scope domain from memory — saving an image goes to /v1/storage, not /v1/memory.)
|
|
20
|
+
export const APP_DEFAULT_SCOPES = 'memory:read memory:write storage:read storage:write';
|
|
21
|
+
|
|
22
|
+
// An app declares the scopes it needs with <meta name="aimeat-scopes" content="scope scope …">.
|
|
23
|
+
// Only declared apps deviate from the default set — e.g. an AI app adds "ai:use" so its grant
|
|
24
|
+
// can spend the owner's AI budget. Falls back to APP_DEFAULT_SCOPES when undeclared, so existing
|
|
25
|
+
// apps are unaffected. The authorize endpoint still validates every scope against the node's
|
|
26
|
+
// grantable vocabulary, so a bogus meta value can only ever request LESS than the node allows.
|
|
27
|
+
export function appDeclaredScopes() {
|
|
28
|
+
try {
|
|
29
|
+
var m = document.querySelector('meta[name="aimeat-scopes"]');
|
|
30
|
+
var c = m && m.getAttribute('content');
|
|
31
|
+
if (c && c.trim()) return c.trim().replace(/\s+/g, ' ');
|
|
32
|
+
} catch { /* no document / detached */ }
|
|
33
|
+
return APP_DEFAULT_SCOPES;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Social login providers enabled on this node (server-computed from node config, injected by the
|
|
37
|
+
// auth route as an extra prelude line): each is { id, label, i18nKey } — the sign-in modal renders
|
|
38
|
+
// one button per entry.
|
|
39
|
+
export const AUTH_PROVIDERS = (window.__AIMEAT_AUTH_CFG__ && window.__AIMEAT_AUTH_CFG__.providers) || [];
|
|
40
|
+
|
|
41
|
+
// Per-provider button glyphs (inline SVG — no external fetch).
|
|
42
|
+
export const PROVIDER_ICONS = {
|
|
43
|
+
google: '<svg width="18" height="18" viewBox="0 0 18 18" aria-hidden="true"><path fill="#4285F4" d="M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.88 2.68-6.62z"/><path fill="#34A853" d="M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.8.54-1.84.86-3.04.86-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18z"/><path fill="#FBBC05" d="M3.97 10.72a5.4 5.4 0 0 1 0-3.44V4.95H.96a9 9 0 0 0 0 8.1l3.01-2.33z"/><path fill="#EA4335" d="M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.58A9 9 0 0 0 .96 4.95l3.01 2.33C4.68 5.16 6.66 3.58 9 3.58z"/></svg>',
|
|
44
|
+
entra: '<svg width="18" height="18" viewBox="0 0 21 21" aria-hidden="true"><rect x="1" y="1" width="9" height="9" fill="#F25022"/><rect x="11" y="1" width="9" height="9" fill="#7FBA00"/><rect x="1" y="11" width="9" height="9" fill="#00A4EF"/><rect x="11" y="11" width="9" height="9" fill="#FFB900"/></svg>',
|
|
45
|
+
casdoor: '<svg width="18" height="18" viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="3" width="16" height="18" rx="2" fill="#4757F6"/><circle cx="14" cy="11" r="1.6" fill="#fff"/><rect x="13.2" y="11.5" width="1.6" height="4" fill="#fff"/></svg>',
|
|
46
|
+
};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file auth/crypto.js
|
|
3
|
+
* @description aimeat-auth crypto + storage core (SDK-libs migration Phase 3). Self-contained, no
|
|
4
|
+
* shared auth state: Ed25519 via Web Crypto (generate/import-as-non-extractable/sign), the
|
|
5
|
+
* IndexedDB non-extractable CryptoKey store (open/store/load/delete + one-time localStorage→IDB
|
|
6
|
+
* migration), the localStorage metadata helpers (save/load/remove — NEVER private keys), and JWT
|
|
7
|
+
* helpers (parseJwt/isExpired). Extracted verbatim from auth-lib-part1.ts.
|
|
8
|
+
* @structure generateKeyPair/importEd25519Key/isCryptoKey/sign · openKeyDB/storeKey/loadKey/deleteKey/
|
|
9
|
+
* migrateKeysToIndexedDB · save/load/remove · parseJwt/isExpired.
|
|
10
|
+
* @usage import { sign, parseJwt, save, load } from './crypto.js';
|
|
11
|
+
* @version-history
|
|
12
|
+
* v1.0.0 — 2026-07-19 — Extracted from src/routes/libs/auth-lib-part1.ts (SDK-libs migration Phase 3).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// ── Ed25519 via Web Crypto ──
|
|
16
|
+
|
|
17
|
+
export async function generateKeyPair() {
|
|
18
|
+
const key = /** @type {CryptoKeyPair} */ (await crypto.subtle.generateKey('Ed25519', true, ['sign', 'verify']));
|
|
19
|
+
const privRaw = await crypto.subtle.exportKey('pkcs8', key.privateKey);
|
|
20
|
+
const pubRaw = await crypto.subtle.exportKey('spki', key.publicKey);
|
|
21
|
+
// Extract raw 32-byte keys from DER wrappers
|
|
22
|
+
const privBytes = new Uint8Array(privRaw).slice(-32);
|
|
23
|
+
const pubBytes = new Uint8Array(pubRaw).slice(-32);
|
|
24
|
+
return {
|
|
25
|
+
privateKey: btoa(String.fromCharCode(...privBytes)),
|
|
26
|
+
publicKey: btoa(String.fromCharCode(...pubBytes)),
|
|
27
|
+
cryptoKey: key,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// SECURITY: Import raw Ed25519 private key as non-extractable CryptoKey
|
|
32
|
+
export async function importEd25519Key(privateKeyBase64) {
|
|
33
|
+
const privBytes = Uint8Array.from(atob(privateKeyBase64), c => c.charCodeAt(0));
|
|
34
|
+
// Build PKCS8 DER wrapper for Ed25519
|
|
35
|
+
const pkcs8Prefix = new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32]);
|
|
36
|
+
const pkcs8 = new Uint8Array(pkcs8Prefix.length + privBytes.length);
|
|
37
|
+
pkcs8.set(pkcs8Prefix);
|
|
38
|
+
pkcs8.set(privBytes, pkcs8Prefix.length);
|
|
39
|
+
const cryptoKey = await crypto.subtle.importKey('pkcs8', pkcs8, 'Ed25519', false /* non-extractable */, ['sign']);
|
|
40
|
+
// Zero raw key bytes
|
|
41
|
+
privBytes.fill(0);
|
|
42
|
+
pkcs8.fill(0);
|
|
43
|
+
return cryptoKey;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function isCryptoKey(value) {
|
|
47
|
+
if (!value || typeof value !== 'object') return false;
|
|
48
|
+
if (typeof CryptoKey !== 'undefined' && value instanceof CryptoKey) return true;
|
|
49
|
+
return Object.prototype.toString.call(value) === '[object CryptoKey]';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Sign using CryptoKey (preferred) or base64 key string (fallback)
|
|
53
|
+
export async function sign(keyOrB64, message) {
|
|
54
|
+
let key = keyOrB64;
|
|
55
|
+
if (typeof keyOrB64 === 'string') {
|
|
56
|
+
// Legacy path: raw base64 key → import as CryptoKey
|
|
57
|
+
key = await importEd25519Key(keyOrB64);
|
|
58
|
+
}
|
|
59
|
+
if (!isCryptoKey(key)) {
|
|
60
|
+
throw new Error('AIMEAT signing key is missing or invalid. Please sign in again.');
|
|
61
|
+
}
|
|
62
|
+
const msgBytes = new TextEncoder().encode(message);
|
|
63
|
+
const sigBytes = await crypto.subtle.sign('Ed25519', key, msgBytes);
|
|
64
|
+
return btoa(String.fromCharCode(...new Uint8Array(sigBytes)));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ── IndexedDB Key Store (SECURITY: non-extractable CryptoKeys) ──
|
|
68
|
+
|
|
69
|
+
const KEY_DB_NAME = 'aimeat_keys';
|
|
70
|
+
const KEY_STORE_NAME = 'cryptokeys';
|
|
71
|
+
|
|
72
|
+
function openKeyDB() {
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
const req = indexedDB.open(KEY_DB_NAME, 1);
|
|
75
|
+
req.onupgradeneeded = () => req.result.createObjectStore(KEY_STORE_NAME);
|
|
76
|
+
req.onsuccess = () => resolve(req.result);
|
|
77
|
+
req.onerror = () => reject(req.error);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function storeKey(name, cryptoKey) {
|
|
82
|
+
const db = /** @type {IDBDatabase} */ (await openKeyDB());
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
const tx = db.transaction(KEY_STORE_NAME, 'readwrite');
|
|
85
|
+
tx.objectStore(KEY_STORE_NAME).put(cryptoKey, name);
|
|
86
|
+
tx.oncomplete = () => { db.close(); resolve(undefined); };
|
|
87
|
+
tx.onerror = () => { db.close(); reject(tx.error); };
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export async function loadKey(name) {
|
|
92
|
+
const db = /** @type {IDBDatabase} */ (await openKeyDB());
|
|
93
|
+
return new Promise((resolve) => {
|
|
94
|
+
const tx = db.transaction(KEY_STORE_NAME, 'readonly');
|
|
95
|
+
const req = tx.objectStore(KEY_STORE_NAME).get(name);
|
|
96
|
+
req.onsuccess = () => { db.close(); resolve(req.result || null); };
|
|
97
|
+
req.onerror = () => { db.close(); resolve(null); };
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export async function deleteKey(name) {
|
|
102
|
+
try {
|
|
103
|
+
const db = /** @type {IDBDatabase} */ (await openKeyDB());
|
|
104
|
+
return new Promise((resolve) => {
|
|
105
|
+
const tx = db.transaction(KEY_STORE_NAME, 'readwrite');
|
|
106
|
+
tx.objectStore(KEY_STORE_NAME).delete(name);
|
|
107
|
+
tx.oncomplete = () => { db.close(); resolve(undefined); };
|
|
108
|
+
tx.onerror = () => { db.close(); resolve(undefined); };
|
|
109
|
+
});
|
|
110
|
+
} catch { /* IndexedDB may not be available */ }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Migrate legacy localStorage keys to IndexedDB (one-time)
|
|
114
|
+
export async function migrateKeysToIndexedDB() {
|
|
115
|
+
try {
|
|
116
|
+
const session = load('session');
|
|
117
|
+
if (session && session.privateKey) {
|
|
118
|
+
const cryptoKey = await importEd25519Key(session.privateKey);
|
|
119
|
+
await storeKey('agent_key', cryptoKey);
|
|
120
|
+
// Remove private key from localStorage, keep metadata
|
|
121
|
+
delete session.privateKey;
|
|
122
|
+
save('session', session);
|
|
123
|
+
}
|
|
124
|
+
const ownerKey = load('owner_key');
|
|
125
|
+
if (typeof ownerKey === 'string' && ownerKey.length > 0) {
|
|
126
|
+
const cryptoKey = await importEd25519Key(ownerKey);
|
|
127
|
+
await storeKey('owner_key', cryptoKey);
|
|
128
|
+
remove('owner_key');
|
|
129
|
+
}
|
|
130
|
+
} catch (e) {
|
|
131
|
+
console.warn('AIMEAT: Key migration to IndexedDB failed, falling back to localStorage', e);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ── Storage helpers (metadata only — NO private keys) ──
|
|
136
|
+
|
|
137
|
+
const STORAGE_PREFIX = 'aimeat_';
|
|
138
|
+
|
|
139
|
+
export function save(key, value) {
|
|
140
|
+
try { localStorage.setItem(STORAGE_PREFIX + key, JSON.stringify(value)); } catch { /* storage blocked */ }
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function load(key) {
|
|
144
|
+
try { const v = localStorage.getItem(STORAGE_PREFIX + key); return v ? JSON.parse(v) : null; } catch { return null; }
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function remove(key) {
|
|
148
|
+
try { localStorage.removeItem(STORAGE_PREFIX + key); } catch { /* storage blocked */ }
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ── JWT helpers ──
|
|
152
|
+
|
|
153
|
+
export function parseJwt(token) {
|
|
154
|
+
try {
|
|
155
|
+
const parts = token.split('.');
|
|
156
|
+
if (parts.length !== 3) return null;
|
|
157
|
+
const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));
|
|
158
|
+
return payload;
|
|
159
|
+
} catch { return null; }
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function isExpired(jwt) {
|
|
163
|
+
const payload = parseJwt(jwt);
|
|
164
|
+
if (!payload || !payload.exp) return true;
|
|
165
|
+
return Date.now() / 1000 > payload.exp - 60; // 60s grace
|
|
166
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file auth/events.js
|
|
3
|
+
* @description aimeat-auth event bus (SDK-libs migration Phase 3). The shared listener registry +
|
|
4
|
+
* emit/on/off that the session layer, pill, modal and boot all use to broadcast
|
|
5
|
+
* 'login'/'logout'/'refreshed'/'expired'/'session-updated'/'scopes-stale'/'popup-blocked' events.
|
|
6
|
+
* `listeners` is only ever mutated in place (never reassigned), so importing it across modules is
|
|
7
|
+
* safe. Extracted from auth-lib-part2.ts.
|
|
8
|
+
* @structure listeners · emit(event, data) · on(event, fn) · off(event, fn).
|
|
9
|
+
* @usage import { emit, on, off } from './events.js';
|
|
10
|
+
* @version-history
|
|
11
|
+
* v1.0.0 — 2026-07-19 — Extracted from src/routes/libs/auth-lib-part2.ts (SDK-libs migration Phase 3).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** @type {Record<string, Array<(data: any) => void>>} */
|
|
15
|
+
export const listeners = {};
|
|
16
|
+
|
|
17
|
+
export function emit(event, data) { (listeners[event] || []).forEach(fn => fn(data)); }
|
|
18
|
+
|
|
19
|
+
export function on(event, fn) {
|
|
20
|
+
if (!listeners[event]) listeners[event] = [];
|
|
21
|
+
listeners[event].push(fn);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function off(event, fn) {
|
|
25
|
+
if (!listeners[event]) return;
|
|
26
|
+
listeners[event] = listeners[event].filter(f => f !== fn);
|
|
27
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file auth/i18n.js
|
|
3
|
+
* @description aimeat-auth sign-in-modal language helpers (SDK-libs migration Phase 3). The modal can
|
|
4
|
+
* be shown standalone (e.g. a custom portal page) where the canonical header + its language switcher
|
|
5
|
+
* is absent, so it owns its own EN/FI switch and loads translations itself, using the same
|
|
6
|
+
* 'aimeat-lang' localStorage key + cookie the header uses so the choice stays in sync with the SPA.
|
|
7
|
+
* loadModalI18n fetches en.json (base) + <lang>.json (overrides) from the node and returns just the
|
|
8
|
+
* modal.* strings with the 'modal.' prefix stripped. Extracted from auth-lib-part2.ts.
|
|
9
|
+
* @structure MODAL_LANG_KEY · currentModalLang() · flattenModalI18n() · loadModalI18n(lang).
|
|
10
|
+
* @usage import { currentModalLang, loadModalI18n } from './i18n.js';
|
|
11
|
+
* @version-history
|
|
12
|
+
* v1.0.0 — 2026-07-19 — Extracted from src/routes/libs/auth-lib-part2.ts (SDK-libs migration Phase 3).
|
|
13
|
+
*/
|
|
14
|
+
import { NODE_URL } from './config.js';
|
|
15
|
+
|
|
16
|
+
export var MODAL_LANG_KEY = 'aimeat-lang';
|
|
17
|
+
|
|
18
|
+
export function currentModalLang() {
|
|
19
|
+
try {
|
|
20
|
+
var u = new URLSearchParams(location.search).get('lang');
|
|
21
|
+
if (u === 'en' || u === 'fi') return u;
|
|
22
|
+
var s = localStorage.getItem(MODAL_LANG_KEY);
|
|
23
|
+
if (s === 'en' || s === 'fi') return s;
|
|
24
|
+
} catch { /* storage blocked */ }
|
|
25
|
+
return (navigator.language || 'en').slice(0, 2).toLowerCase() === 'fi' ? 'fi' : 'en';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function flattenModalI18n(obj, prefix, out) {
|
|
29
|
+
out = out || {}; prefix = prefix || '';
|
|
30
|
+
for (var k in obj) {
|
|
31
|
+
if (!Object.prototype.hasOwnProperty.call(obj, k)) continue;
|
|
32
|
+
var key = prefix ? prefix + '.' + k : k;
|
|
33
|
+
var v = obj[k];
|
|
34
|
+
if (v && typeof v === 'object' && !Array.isArray(v)) flattenModalI18n(v, key, out);
|
|
35
|
+
else out[key] = v;
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Fetch en.json (base) + <lang>.json (overrides) from the node and return just the modal.* strings
|
|
41
|
+
// with the 'modal.' prefix stripped — the shape the modal (and every mountLoginButton caller) expects
|
|
42
|
+
// for opts.i18n.
|
|
43
|
+
export async function loadModalI18n(lang) {
|
|
44
|
+
var v = Date.now();
|
|
45
|
+
var t = {};
|
|
46
|
+
try {
|
|
47
|
+
var enRes = await fetch(NODE_URL + '/locales/en.json?v=' + v);
|
|
48
|
+
if (enRes.ok) t = flattenModalI18n(await enRes.json());
|
|
49
|
+
} catch { /* offline / missing locales — fall through to fallbacks */ }
|
|
50
|
+
if (lang !== 'en') {
|
|
51
|
+
try {
|
|
52
|
+
var locRes = await fetch(NODE_URL + '/locales/' + lang + '.json?v=' + v);
|
|
53
|
+
if (locRes.ok) {
|
|
54
|
+
var loc = flattenModalI18n(await locRes.json());
|
|
55
|
+
for (var lk in loc) if (Object.prototype.hasOwnProperty.call(loc, lk)) t[lk] = loc[lk];
|
|
56
|
+
}
|
|
57
|
+
} catch { /* locale missing — English fallback stands */ }
|
|
58
|
+
}
|
|
59
|
+
var out = {};
|
|
60
|
+
for (var k in t) {
|
|
61
|
+
if (Object.prototype.hasOwnProperty.call(t, k) && k.indexOf('modal.') === 0) out[k.slice(6)] = t[k];
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|