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
|
@@ -1,108 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file db.js
|
|
3
|
-
* @description
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
3
|
+
* @description Transient in-memory working-set for the catalog. The catalog is SERVER-ONLY —
|
|
4
|
+
* there is no browser persistence (no IndexedDB). This module holds a page-session array of
|
|
5
|
+
* app records that the detail view materializes on demand for editing (downloaded from the
|
|
6
|
+
* server, edited in memory, then published back). The set is empty on every load and rebuilt
|
|
7
|
+
* from the server; nothing here survives a reload. Keeps the getAllApps/saveApp/deleteApp
|
|
8
|
+
* surface the rest of the catalog imports, so callers are unchanged.
|
|
9
|
+
* @usage import { getAllApps, saveApp, deleteApp } from './db.js'
|
|
8
10
|
* @version-history
|
|
9
11
|
* v1.0.0 — 2026-07-10 — Initial extraction (TARGET-021 Aalto 3 modularization, phase 2).
|
|
12
|
+
* v2.0.0 — 2026-07-20 — Server-only catalog: drop IndexedDB + the Shared/Mine DB-mode entirely;
|
|
13
|
+
* back the same CRUD surface with a transient in-memory working-set (no browser persistence).
|
|
10
14
|
*/
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let dbInstance = null;
|
|
17
|
-
let currentDbMode = localStorage.getItem('appCatalogMode') || 'global';
|
|
18
|
-
|
|
19
|
-
export function getDbMode() { return currentDbMode; }
|
|
20
|
-
|
|
21
|
-
export function setDbMode(mode) {
|
|
22
|
-
currentDbMode = mode;
|
|
23
|
-
try { localStorage.setItem('appCatalogMode', mode); } catch (e) { /* private mode */ }
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function closeDbInstance() {
|
|
27
|
-
if (dbInstance) { try { dbInstance.close(); } catch (e) {} dbInstance = null; }
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** DB name is per-account in Personal mode (falls back to the shared Global DB otherwise). */
|
|
31
|
-
export function getDbName() {
|
|
32
|
-
if (currentDbMode === 'personal') {
|
|
33
|
-
var owner = null;
|
|
34
|
-
try {
|
|
35
|
-
if (window.AIMEAT && window.AIMEAT.auth && window.AIMEAT.auth.getSession()) {
|
|
36
|
-
owner = window.AIMEAT.auth.getSession().owner || null;
|
|
37
|
-
}
|
|
38
|
-
if (!owner) {
|
|
39
|
-
var stored = localStorage.getItem('aimeat_session');
|
|
40
|
-
if (stored) owner = JSON.parse(stored).owner || null;
|
|
41
|
-
}
|
|
42
|
-
} catch (e) {}
|
|
43
|
-
if (owner) return DB_NAME_GLOBAL + '_' + owner;
|
|
44
|
-
}
|
|
45
|
-
return DB_NAME_GLOBAL;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function openDB() {
|
|
49
|
-
var name = getDbName();
|
|
50
|
-
if (dbInstance && dbInstance.name === name) return Promise.resolve(dbInstance);
|
|
51
|
-
if (dbInstance) { dbInstance.close(); dbInstance = null; }
|
|
52
|
-
return new Promise(function (resolve, reject) {
|
|
53
|
-
const request = indexedDB.open(name, DB_VERSION);
|
|
54
|
-
request.onupgradeneeded = function (event) {
|
|
55
|
-
const db = event.target.result;
|
|
56
|
-
var store;
|
|
57
|
-
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
58
|
-
store = db.createObjectStore(STORE_NAME, { keyPath: 'id' });
|
|
59
|
-
store.createIndex('tags', 'tags', { multiEntry: true });
|
|
60
|
-
store.createIndex('source', 'source', { unique: false });
|
|
61
|
-
store.createIndex('favorite', 'favorite', { unique: false });
|
|
62
|
-
store.createIndex('sortOrder', 'sortOrder', { unique: false });
|
|
63
|
-
} else {
|
|
64
|
-
store = event.target.transaction.objectStore(STORE_NAME);
|
|
65
|
-
if (!store.indexNames.contains('sortOrder')) {
|
|
66
|
-
store.createIndex('sortOrder', 'sortOrder', { unique: false });
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
request.onsuccess = function (event) { dbInstance = event.target.result; resolve(dbInstance); };
|
|
71
|
-
request.onerror = function (event) { reject(event.target.error); };
|
|
72
|
-
});
|
|
73
|
-
}
|
|
16
|
+
// Page-session working set. Holds only transient records the detail view materialized for editing;
|
|
17
|
+
// empty on load, discarded on unload. NOT a store — the server is the sole source of truth.
|
|
18
|
+
let workingSet = [];
|
|
74
19
|
|
|
20
|
+
/** Resolve the current working set (a copy so callers can't mutate our array by reference). */
|
|
75
21
|
export function getAllApps() {
|
|
76
|
-
return
|
|
77
|
-
return new Promise(function (resolve, reject) {
|
|
78
|
-
const tx = db.transaction(STORE_NAME, 'readonly');
|
|
79
|
-
const request = tx.objectStore(STORE_NAME).getAll();
|
|
80
|
-
request.onsuccess = function () { resolve(request.result); };
|
|
81
|
-
request.onerror = function () { reject(request.error); };
|
|
82
|
-
});
|
|
83
|
-
});
|
|
22
|
+
return Promise.resolve(workingSet.slice());
|
|
84
23
|
}
|
|
85
24
|
|
|
25
|
+
/** Upsert a transient record by id (in memory only — persistence is publishing to the server). */
|
|
86
26
|
export function saveApp(app) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
tx.onerror = function () { reject(tx.error); };
|
|
93
|
-
tx.onabort = function () { reject(tx.error); };
|
|
94
|
-
});
|
|
95
|
-
});
|
|
27
|
+
if (app && app.id) {
|
|
28
|
+
var idx = workingSet.findIndex(function (a) { return a.id === app.id; });
|
|
29
|
+
if (idx >= 0) workingSet[idx] = app; else workingSet.push(app);
|
|
30
|
+
}
|
|
31
|
+
return Promise.resolve();
|
|
96
32
|
}
|
|
97
33
|
|
|
34
|
+
/** Drop a transient record by id (does NOT delete the server app — that is deleteServerApp). */
|
|
98
35
|
export function deleteApp(id) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
102
|
-
tx.objectStore(STORE_NAME).delete(id);
|
|
103
|
-
tx.oncomplete = function () { resolve(); };
|
|
104
|
-
tx.onerror = function () { reject(tx.error); };
|
|
105
|
-
tx.onabort = function () { reject(tx.error); };
|
|
106
|
-
});
|
|
107
|
-
});
|
|
36
|
+
workingSet = workingSet.filter(function (a) { return a.id !== id; });
|
|
37
|
+
return Promise.resolve();
|
|
108
38
|
}
|
|
@@ -8,8 +8,12 @@
|
|
|
8
8
|
* injected once via initDetail(deps) — so there is no import cycle back through the entry module.
|
|
9
9
|
* @usage import { initDetail, openDetailView, mountLoginPill, ... } from './detail.js'; initDetail({...})
|
|
10
10
|
* @version-history
|
|
11
|
+
* v1.4.0 — 2026-07-20 — Server-only cutover: drop the local-only favourite star; the detail view
|
|
12
|
+
* always operates on a server app (materialized in memory on demand for editing).
|
|
11
13
|
* v1.3.0 — 2026-07-16 — Add openStagingPreview(owner, filename): mint a preview token for an
|
|
12
14
|
* EXISTING staging draft and open it top-level, driving a library card's "Open staging" button.
|
|
15
|
+
* v1.3.0 — 2026-07-20 — Cost & Contracts section (EXCHANGE G3 / TARGET-045): own published apps get a
|
|
16
|
+
* read-only per-app EXCHANGE entitlement surface (cost.js) after Monetize.
|
|
13
17
|
* v1.2.0 — 2026-07-14 — Monetize section (TARGET-034 phase B): own published apps get the
|
|
14
18
|
* apps.{appId}.tools tool editor (monetize.js) between Skills and Manage-on-server.
|
|
15
19
|
* v1.1.0 — 2026-07-11 — Own-published apps: "Edit Access Code" in serverMgmtInner + "Attach skill"
|
|
@@ -18,11 +22,13 @@
|
|
|
18
22
|
* v1.0.0 — 2026-07-10 — Initial extraction (TARGET-021 Aalto 3 modularization, phase 7).
|
|
19
23
|
*/
|
|
20
24
|
import { escapeHtml, jsArg, sourceLabel, sourceLabelText, currentOwnerName } from './util.js';
|
|
21
|
-
import { saveApp, deleteApp
|
|
25
|
+
import { saveApp, deleteApp } from './db.js';
|
|
22
26
|
import { dtlBtn, showConfirm, showNotice } from './ui.js';
|
|
23
27
|
import { loadConfig } from './config.js';
|
|
24
|
-
import { t } from './i18n.js';
|
|
28
|
+
import { t, getLang } from './i18n.js';
|
|
29
|
+
import { getPromotion, setPromotion, loadPromoted } from './promote.js';
|
|
25
30
|
import { monetizeSectionInner, monetizeOnOpen } from './monetize.js';
|
|
31
|
+
import { costSectionInner, costOnOpen } from './cost.js';
|
|
26
32
|
import { appManifestAgents } from './app-agents.js';
|
|
27
33
|
|
|
28
34
|
// Injected once at bootstrap by main.js. Functions are main-local; the get* return main's LIVE
|
|
@@ -163,6 +169,8 @@ function openDetailView(appId) {
|
|
|
163
169
|
// Monetize (TARGET-034): reset + async-load the apps.{appId}.tools manifest for OWN published
|
|
164
170
|
// apps before the first render so the section shell picks up the loading state.
|
|
165
171
|
monetizeOnOpen(detailServerOwner(app), app.publishedFilename || '', detailIsOwnPublished(app));
|
|
172
|
+
// Cost & contracts (EXCHANGE G3): async-load this app's EXCHANGE entitlements for OWN published apps.
|
|
173
|
+
costOnOpen(detailServerOwner(app), app.publishedFilename || '', detailIsOwnPublished(app));
|
|
166
174
|
document.getElementById('detail-view').hidden = false;
|
|
167
175
|
renderDetailView();
|
|
168
176
|
// AI availability + published versions load asynchronously and re-render in place.
|
|
@@ -235,15 +243,8 @@ function loadScriptOnce(src) {
|
|
|
235
243
|
}
|
|
236
244
|
|
|
237
245
|
function onAuthChanged() {
|
|
238
|
-
//
|
|
239
|
-
//
|
|
240
|
-
if (getDbMode() === 'personal' && !currentOwnerName()) {
|
|
241
|
-
setDbMode('global');
|
|
242
|
-
}
|
|
243
|
-
// The per-account IndexedDB changes with the signed-in owner, so re-open it and re-render the
|
|
244
|
-
// LOCAL grid + tags too — not just the server sections (the stale-grid-after-login bug).
|
|
245
|
-
closeDbInstance();
|
|
246
|
-
updateModeToggle();
|
|
246
|
+
// Server-only catalog: the grid is rebuilt from the server on every auth change, so a sign-in /
|
|
247
|
+
// sign-out just re-fetches the owner's apps (their parked/listed apps appear or drop away).
|
|
247
248
|
try { refreshAll(); } catch (e) { try { loadPublishedApps(); } catch (e2) {} }
|
|
248
249
|
var sub = document.getElementById('publish-submit-btn');
|
|
249
250
|
var st = document.getElementById('publish-status');
|
|
@@ -339,10 +340,9 @@ function renderDetailView() {
|
|
|
339
340
|
var tags = (app.tags && app.tags.length) ? app.tags.join(', ') : '—';
|
|
340
341
|
var cortex = (app.usesCortex && app.usesCortex.length) ? app.usesCortex.join(', ') : '—';
|
|
341
342
|
var created = app.addedAt ? new Date(app.addedAt).toLocaleString() : '—';
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
: '';
|
|
343
|
+
// Favourites are a Phase-2 (server-backed) feature; the old local-only star was dropped with the
|
|
344
|
+
// server-only cutover so it isn't shown here anymore.
|
|
345
|
+
var favBtn = '';
|
|
346
346
|
var aboutHeader =
|
|
347
347
|
'<h3 style="display:flex;align-items:center;justify-content:space-between;gap:8px">' +
|
|
348
348
|
'<span>' + t('detail.about') + '</span>' +
|
|
@@ -351,13 +351,26 @@ function renderDetailView() {
|
|
|
351
351
|
((canEditAbout && !detailEditingAbout) ? dtlBtn(t('detail.editDetails'), 'window._launcher.detailAboutEdit()') : '') +
|
|
352
352
|
'</span>' +
|
|
353
353
|
'</h3>';
|
|
354
|
+
// Per-locale descriptions: EN + FI (extensible). Seed from the manifest's descriptions map,
|
|
355
|
+
// falling back to the canonical description for the default language so an app that only ever had
|
|
356
|
+
// a single description pre-fills English.
|
|
357
|
+
var descs = app.descriptions || {};
|
|
358
|
+
var descEnVal = descs.en || (app.description || '');
|
|
359
|
+
var descFiVal = descs.fi || '';
|
|
354
360
|
var aboutBody;
|
|
355
361
|
if (detailEditingAbout) {
|
|
356
362
|
aboutBody =
|
|
357
363
|
'<label class="dtl-stat-label" for="detail-name-input">' + t('detail.nameLabel') + '</label>' +
|
|
358
364
|
'<input id="detail-name-input" class="modal-input" maxlength="120" value="' + escapeHtml(app.name || '') + '" style="margin:4px 0 10px" />' +
|
|
359
|
-
'<label class="dtl-stat-label" for="detail-desc-
|
|
360
|
-
'<textarea id="detail-desc-
|
|
365
|
+
'<label class="dtl-stat-label" for="detail-desc-en">' + t('detail.descEn') + '</label>' +
|
|
366
|
+
'<textarea id="detail-desc-en" class="modal-input" rows="3" maxlength="2000" style="margin:4px 0 6px;resize:vertical">' + escapeHtml(descEnVal) + '</textarea>' +
|
|
367
|
+
'<label class="dtl-stat-label" for="detail-desc-fi">' + t('detail.descFi') + '</label>' +
|
|
368
|
+
'<textarea id="detail-desc-fi" class="modal-input" rows="3" maxlength="2000" style="margin:4px 0 6px;resize:vertical">' + escapeHtml(descFiVal) + '</textarea>' +
|
|
369
|
+
'<div class="dtl-btn-row" style="margin:0 0 4px">' +
|
|
370
|
+
dtlBtn('🌐 ' + t('detail.translateEnFi'), 'window._launcher.detailTranslateDesc(\'en\',\'fi\')', {id:'detail-tr-enfi'}) +
|
|
371
|
+
dtlBtn('🌐 ' + t('detail.translateFiEn'), 'window._launcher.detailTranslateDesc(\'fi\',\'en\')', {id:'detail-tr-fien'}) +
|
|
372
|
+
'</div>' +
|
|
373
|
+
'<div class="dtl-ai-status" id="detail-tr-status" style="margin:0 0 8px"></div>' +
|
|
361
374
|
'<label class="dtl-stat-label" for="detail-icon-input">' + t('detail.iconLabel') + '</label>' +
|
|
362
375
|
'<input id="detail-icon-input" class="modal-input" maxlength="4" value="' + escapeHtml(app.icon || '') + '" style="margin:4px 0 10px;text-align:center;font-size:1.2rem" />' +
|
|
363
376
|
'<label class="dtl-stat-label" for="detail-tags-input">' + t('detail.tagsLabel') + '</label>' +
|
|
@@ -368,8 +381,10 @@ function renderDetailView() {
|
|
|
368
381
|
dtlBtn(t('detail.cancelEdit'), 'window._launcher.detailAboutCancel()') +
|
|
369
382
|
'</div>';
|
|
370
383
|
} else {
|
|
384
|
+
// Show the description in the current UI language, falling back to the canonical one.
|
|
385
|
+
var shownDesc = (app.descriptions && app.descriptions[getLang()]) || app.description || '';
|
|
371
386
|
aboutBody =
|
|
372
|
-
(
|
|
387
|
+
(shownDesc ? '<p class="dtl-desc">' + escapeHtml(shownDesc) + '</p>' : '') +
|
|
373
388
|
'<div class="dtl-meta-grid">' +
|
|
374
389
|
metaItem(t('detail.category'), app.category || 'utility') +
|
|
375
390
|
metaItem(t('detail.tags'), tags) +
|
|
@@ -479,6 +494,17 @@ function renderDetailView() {
|
|
|
479
494
|
? '<div class="dtl-section" id="detail-monetize">' + monetizeSectionInner() + '</div>'
|
|
480
495
|
: '';
|
|
481
496
|
|
|
497
|
+
// ── COST & CONTRACTS (EXCHANGE G3 / TARGET-045) — what this app SOURCES (own published apps only) ──
|
|
498
|
+
// Stable container: cost.js re-renders #detail-cost in place after the async load.
|
|
499
|
+
var costHtml = (app.published && detailIsOwnPublished(app))
|
|
500
|
+
? '<div class="dtl-section" id="detail-cost">' + costSectionInner() + '</div>'
|
|
501
|
+
: '';
|
|
502
|
+
|
|
503
|
+
// ── PROMOTE (Phase 2c) — showcase this app on your public profile with EN/FI pitch copy.
|
|
504
|
+
// Own published apps only; persists to the PUBLIC app-catalog.promoted memory doc.
|
|
505
|
+
var promoteHtml = (app.published && detailIsOwnPublished(app))
|
|
506
|
+
? buildPromoteSection(app) : '';
|
|
507
|
+
|
|
482
508
|
// ── BUNDLED AGENTS (Agent-Bundled Apps) — crew-defs this app ships. The section lists the
|
|
483
509
|
// agent names and opens the shared Bundled-agents modal (inspector + hosted instances with
|
|
484
510
|
// prices + deploy-your-own). Manifest read from the server-manifest cache.
|
|
@@ -502,7 +528,56 @@ function renderDetailView() {
|
|
|
502
528
|
}
|
|
503
529
|
|
|
504
530
|
document.getElementById('detail-body').innerHTML =
|
|
505
|
-
statusHtml + aboutHtml + aiHtml + versionsHtml + skillsHtml + agentsHtml + monetizeHtml + mgmtHtml + actionsHtml;
|
|
531
|
+
statusHtml + aboutHtml + aiHtml + versionsHtml + skillsHtml + agentsHtml + monetizeHtml + costHtml + promoteHtml + mgmtHtml + actionsHtml;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// The Promote section: a short EN/FI pitch that surfaces this app on the owner's public profile.
|
|
535
|
+
// Saving writes the PUBLIC app-catalog.promoted doc; clearing both fields un-promotes the app.
|
|
536
|
+
function promoteRef(app) { return detailServerOwner(app) + '/' + (app.publishedFilename || ''); }
|
|
537
|
+
function buildPromoteSection(app) {
|
|
538
|
+
var ref = promoteRef(app);
|
|
539
|
+
var cur = getPromotion(ref) || {};
|
|
540
|
+
var on = !!(cur.en || cur.fi);
|
|
541
|
+
return '<div class="dtl-section" id="detail-promote">' +
|
|
542
|
+
'<h3 style="display:flex;align-items:center;gap:8px">📣 ' + t('promote.title') +
|
|
543
|
+
(on ? ' <span class="dtl-badge-on">' + t('promote.on') + '</span>' : '') + '</h3>' +
|
|
544
|
+
'<p class="dtl-desc">' + t('promote.hint') + '</p>' +
|
|
545
|
+
'<label class="dtl-stat-label" for="detail-promo-en">' + t('promote.en') + '</label>' +
|
|
546
|
+
'<textarea id="detail-promo-en" class="modal-input" rows="2" maxlength="500" style="margin:4px 0 6px;resize:vertical">' + escapeHtml(cur.en || '') + '</textarea>' +
|
|
547
|
+
'<label class="dtl-stat-label" for="detail-promo-fi">' + t('promote.fi') + '</label>' +
|
|
548
|
+
'<textarea id="detail-promo-fi" class="modal-input" rows="2" maxlength="500" style="margin:4px 0 6px;resize:vertical">' + escapeHtml(cur.fi || '') + '</textarea>' +
|
|
549
|
+
'<div class="dtl-btn-row" style="margin:0 0 4px">' +
|
|
550
|
+
dtlBtn('🌐 ' + t('detail.translateEnFi'), 'window._launcher.detailTranslateDesc(\'en\',\'fi\',\'detail-promo-\',\'detail-promo-tr-status\')') +
|
|
551
|
+
dtlBtn('🌐 ' + t('detail.translateFiEn'), 'window._launcher.detailTranslateDesc(\'fi\',\'en\',\'detail-promo-\',\'detail-promo-tr-status\')') +
|
|
552
|
+
'</div>' +
|
|
553
|
+
'<div class="dtl-ai-status" id="detail-promo-tr-status" style="margin:0 0 8px"></div>' +
|
|
554
|
+
'<div class="dtl-btn-row">' +
|
|
555
|
+
dtlBtn(t('promote.save'), 'window._launcher.detailPromoteSave()', {variant:'primary'}) +
|
|
556
|
+
(on ? dtlBtn(t('promote.remove'), 'window._launcher.detailPromoteClear()') : '') +
|
|
557
|
+
'</div>' +
|
|
558
|
+
'<div class="dtl-ai-status" id="detail-promo-status"></div>' +
|
|
559
|
+
'</div>';
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function detailPromoteSave() {
|
|
563
|
+
var app = detailGetApp();
|
|
564
|
+
if (!app || !detailIsOwnPublished(app)) return;
|
|
565
|
+
var en = (document.getElementById('detail-promo-en') || {}).value || '';
|
|
566
|
+
var fi = (document.getElementById('detail-promo-fi') || {}).value || '';
|
|
567
|
+
var statusEl = document.getElementById('detail-promo-status');
|
|
568
|
+
if (statusEl) { statusEl.style.color = 'var(--text-muted)'; statusEl.textContent = t('promote.saving'); }
|
|
569
|
+
setPromotion(promoteRef(app), { en: en, fi: fi }).then(function (nowOn) {
|
|
570
|
+
renderApps();
|
|
571
|
+
renderDetailView();
|
|
572
|
+
var s2 = document.getElementById('detail-promo-status');
|
|
573
|
+
if (s2) { s2.style.color = '#34d399'; s2.textContent = nowOn ? '✔ ' + t('promote.saved') : '✔ ' + t('promote.removed'); }
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
function detailPromoteClear() {
|
|
578
|
+
var en = document.getElementById('detail-promo-en'); if (en) en.value = '';
|
|
579
|
+
var fi = document.getElementById('detail-promo-fi'); if (fi) fi.value = '';
|
|
580
|
+
detailPromoteSave();
|
|
506
581
|
}
|
|
507
582
|
|
|
508
583
|
// Bound skills (skills registry): skills whose frontmatter metadata.binding names this app.
|
|
@@ -808,22 +883,31 @@ function detailAboutSave() {
|
|
|
808
883
|
var app = detailGetApp();
|
|
809
884
|
if (!app) return;
|
|
810
885
|
var nameEl = document.getElementById('detail-name-input');
|
|
811
|
-
var
|
|
886
|
+
var enEl = document.getElementById('detail-desc-en');
|
|
887
|
+
var fiEl = document.getElementById('detail-desc-fi');
|
|
812
888
|
var iconEl = document.getElementById('detail-icon-input');
|
|
813
889
|
var tagsEl = document.getElementById('detail-tags-input');
|
|
814
890
|
var newName = nameEl ? nameEl.value.trim() : '';
|
|
815
|
-
var
|
|
891
|
+
var enDesc = enEl ? enEl.value.trim() : '';
|
|
892
|
+
var fiDesc = fiEl ? fiEl.value.trim() : '';
|
|
893
|
+
// Per-locale map (drop blanks); the canonical description is the English one, or Finnish when
|
|
894
|
+
// English is blank, so an app always has a non-empty fallback description.
|
|
895
|
+
var newDescriptions = {};
|
|
896
|
+
if (enDesc) newDescriptions.en = enDesc;
|
|
897
|
+
if (fiDesc) newDescriptions.fi = fiDesc;
|
|
898
|
+
var newDesc = enDesc || fiDesc || '';
|
|
816
899
|
// icon + tags are LOCAL metadata (same as the context-menu Edit modal) — no server round-trip.
|
|
817
900
|
var newIcon = iconEl ? iconEl.value.trim() : (app.icon || '');
|
|
818
901
|
var newTags = tagsEl
|
|
819
902
|
? tagsEl.value.split(',').map(function (s) { return s.trim(); }).filter(Boolean)
|
|
820
903
|
: (app.tags || []);
|
|
821
904
|
if (!newName) { showNotice(t('detail.nameRequired') || 'Name cannot be empty.'); if (nameEl) nameEl.focus(); return; }
|
|
822
|
-
if (app.published && !newDesc) { showNotice(t('detail.descRequired') || 'Description cannot be empty.'); if (
|
|
905
|
+
if (app.published && !newDesc) { showNotice(t('detail.descRequired') || 'Description cannot be empty.'); if (enEl) enEl.focus(); return; }
|
|
823
906
|
|
|
824
907
|
function finishLocal() {
|
|
825
908
|
app.name = newName;
|
|
826
909
|
app.description = newDesc;
|
|
910
|
+
app.descriptions = newDescriptions;
|
|
827
911
|
app.icon = newIcon;
|
|
828
912
|
app.tags = newTags;
|
|
829
913
|
saveApp(app).then(function() {
|
|
@@ -846,16 +930,17 @@ function detailAboutSave() {
|
|
|
846
930
|
fetch(aimeatUrl + '/v1/apps/' + encodeURIComponent(filename), {
|
|
847
931
|
method: 'PATCH',
|
|
848
932
|
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
|
|
849
|
-
body: JSON.stringify({ name: newName, description: newDesc })
|
|
933
|
+
body: JSON.stringify({ name: newName, description: newDesc, descriptions: newDescriptions })
|
|
850
934
|
})
|
|
851
935
|
.then(function(resp) { return resp.json().then(function(j) { return { ok: resp.ok, j: j }; }); })
|
|
852
936
|
.then(function(res) {
|
|
853
937
|
if (res.ok && res.j && res.j.ok !== false) {
|
|
854
|
-
// Keep the cached server manifest in sync so a re-render shows the new name.
|
|
938
|
+
// Keep the cached server manifest in sync so a re-render shows the new name + descriptions.
|
|
855
939
|
var key = owner + '\n' + filename;
|
|
856
940
|
getServerManifests()[key] = getServerManifests()[key] || {};
|
|
857
941
|
getServerManifests()[key].name = newName;
|
|
858
942
|
getServerManifests()[key].description = newDesc;
|
|
943
|
+
getServerManifests()[key].descriptions = newDescriptions;
|
|
859
944
|
finishLocal();
|
|
860
945
|
} else {
|
|
861
946
|
showNotice('Failed: ' + ((res.j && res.j.error && res.j.error.message) || 'Unknown error'));
|
|
@@ -864,6 +949,50 @@ function detailAboutSave() {
|
|
|
864
949
|
.catch(function(err) { showNotice('Error: ' + (err.message || err)); });
|
|
865
950
|
}
|
|
866
951
|
|
|
952
|
+
// Translate one language field to another via the owner's OpenRouter key (/v1/ai/complete).
|
|
953
|
+
// srcLang/dstLang are 'en'|'fi'; fills the destination textarea in place. `prefix` picks the field
|
|
954
|
+
// pair ('detail-desc-' for the description editor, 'detail-promo-' for the promotion editor);
|
|
955
|
+
// `statusId` picks the status line. Reused by both the description and promotion editors.
|
|
956
|
+
function detailTranslateDesc(srcLang, dstLang, prefix, statusId) {
|
|
957
|
+
prefix = prefix || 'detail-desc-';
|
|
958
|
+
var srcEl = document.getElementById(prefix + srcLang);
|
|
959
|
+
var dstEl = document.getElementById(prefix + dstLang);
|
|
960
|
+
var statusEl = document.getElementById(statusId || 'detail-tr-status');
|
|
961
|
+
if (!srcEl || !dstEl) return;
|
|
962
|
+
var text = (srcEl.value || '').trim();
|
|
963
|
+
if (!text) { if (statusEl) statusEl.textContent = t('detail.trNeedSource'); return; }
|
|
964
|
+
var token = getCortexOwnerToken();
|
|
965
|
+
if (!token) { if (statusEl) statusEl.textContent = t('detail.aiLoginNeeded'); return; }
|
|
966
|
+
var config = loadConfig();
|
|
967
|
+
var aimeatUrl = (config.aimeatUrl || '').replace(/\/+$/, '');
|
|
968
|
+
if (!aimeatUrl) { if (statusEl) statusEl.textContent = t('detail.aiUnavailable'); return; }
|
|
969
|
+
var langName = { en: 'English', fi: 'Finnish' };
|
|
970
|
+
if (statusEl) { statusEl.style.color = 'var(--text-muted)'; statusEl.textContent = t('detail.translating'); }
|
|
971
|
+
var systemPrompt = 'You are a professional translator for short app-store copy. '
|
|
972
|
+
+ 'Translate the text from ' + (langName[srcLang] || srcLang) + ' to ' + (langName[dstLang] || dstLang) + '. '
|
|
973
|
+
+ 'Return ONLY the translated text — no quotes, no notes, no explanation. Keep it concise and natural.';
|
|
974
|
+
fetch(aimeatUrl + '/v1/ai/complete', {
|
|
975
|
+
method: 'POST',
|
|
976
|
+
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
|
|
977
|
+
body: JSON.stringify({ prompt: text, systemPrompt: systemPrompt, app_id: 'app-catalog' })
|
|
978
|
+
})
|
|
979
|
+
.then(function(resp) { return resp.json(); })
|
|
980
|
+
.then(function(json) {
|
|
981
|
+
if (!json || !json.ok) {
|
|
982
|
+
var msg = (json && json.error && json.error.message) || 'Translation failed';
|
|
983
|
+
if (statusEl) { statusEl.style.color = 'var(--accent)'; statusEl.textContent = '✘ ' + msg; }
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
var out = (json.data && json.data.content ? json.data.content : '').trim();
|
|
987
|
+
if (!out) { if (statusEl) { statusEl.style.color = 'var(--accent)'; statusEl.textContent = '✘ ' + t('detail.trEmpty'); } return; }
|
|
988
|
+
dstEl.value = out;
|
|
989
|
+
if (statusEl) { statusEl.style.color = '#34d399'; statusEl.textContent = '✔ ' + t('detail.trDone'); }
|
|
990
|
+
})
|
|
991
|
+
.catch(function(err) {
|
|
992
|
+
if (statusEl) { statusEl.style.color = 'var(--accent)'; statusEl.textContent = '✘ ' + (err.message || 'Translation failed'); }
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
|
|
867
996
|
// Manual override: upload a custom image as this published app's thumbnail. (Bulk auto-capture is
|
|
868
997
|
// the server-side `aimeat screenshot-worker`; the browser can't grab the cross-origin sandboxed app
|
|
869
998
|
// itself, so this is a file picker, not an in-page capture.)
|
|
@@ -1326,6 +1455,7 @@ function openPublishedDetail(owner, filename, localId, versionNumber) {
|
|
|
1326
1455
|
id: generateId(),
|
|
1327
1456
|
name: meta.name || filename.replace(/\.html?$/i, ''),
|
|
1328
1457
|
description: meta.description || '',
|
|
1458
|
+
descriptions: meta.descriptions || null,
|
|
1329
1459
|
category: meta.category || 'utility',
|
|
1330
1460
|
tags: meta.tags || [],
|
|
1331
1461
|
usesCortex: meta.usesCortex || [],
|
|
@@ -1560,6 +1690,7 @@ async function restoreVersion(owner, filename, version) {
|
|
|
1560
1690
|
mime_type: 'text/html',
|
|
1561
1691
|
name: meta.name || filename.replace(/\.html?$/i, ''),
|
|
1562
1692
|
description: meta.description || '',
|
|
1693
|
+
descriptions: meta.descriptions || null,
|
|
1563
1694
|
category: meta.category || 'utility',
|
|
1564
1695
|
tags: meta.tags || [],
|
|
1565
1696
|
uses_cortex: meta.usesCortex || []
|
|
@@ -1647,6 +1778,9 @@ export {
|
|
|
1647
1778
|
detailAboutEdit,
|
|
1648
1779
|
detailAboutCancel,
|
|
1649
1780
|
detailAboutSave,
|
|
1781
|
+
detailTranslateDesc,
|
|
1782
|
+
detailPromoteSave,
|
|
1783
|
+
detailPromoteClear,
|
|
1650
1784
|
detailToggleFavorite,
|
|
1651
1785
|
detailAccessCodeEdit,
|
|
1652
1786
|
detailAccessCodeCancel,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file favorites.js
|
|
3
|
+
* @description Server-backed favourites for the catalog. A per-owner PRIVATE memory doc
|
|
4
|
+
* (`app-catalog.favorites` = { version, updatedAt, refs: ["owner/filename", …] }) read/written
|
|
5
|
+
* via /v1/memory with the owner token, so favourites follow the account across devices. Any app
|
|
6
|
+
* (own or community) can be favourited; the Library pins a "⭐ Favourites" group on top. Holds the
|
|
7
|
+
* in-memory Set + the star-button HTML helper; the grid/group rendering lives in render/server-io.
|
|
8
|
+
* @usage import { loadFavorites, toggleFavorite, isFavorite, getFavoriteRefs, favStarHtml } from './favorites.js'
|
|
9
|
+
* @version-history
|
|
10
|
+
* v1.0.0 — 2026-07-20 — initial (Phase 2b server-backed favourites).
|
|
11
|
+
*/
|
|
12
|
+
import { loadConfig } from './config.js';
|
|
13
|
+
import { getCortexOwnerToken } from './cortex.js';
|
|
14
|
+
import { t } from './i18n.js';
|
|
15
|
+
|
|
16
|
+
const KEY = 'app-catalog.favorites';
|
|
17
|
+
let favSet = new Set();
|
|
18
|
+
|
|
19
|
+
function base() { return (loadConfig().aimeatUrl || '').replace(/\/+$/, ''); }
|
|
20
|
+
|
|
21
|
+
export function isFavorite(ref) { return favSet.has(ref); }
|
|
22
|
+
export function getFavoriteRefs() { return Array.from(favSet); }
|
|
23
|
+
export function hasFavorites() { return favSet.size > 0; }
|
|
24
|
+
|
|
25
|
+
// Load the owner's favourites doc. Requires a signed-in owner (favourites are per-account); logged
|
|
26
|
+
// out → empty set. Never throws — a missing doc (404) just means no favourites yet.
|
|
27
|
+
export function loadFavorites() {
|
|
28
|
+
var token = getCortexOwnerToken();
|
|
29
|
+
var b = base();
|
|
30
|
+
if (!token || !b) { favSet = new Set(); return Promise.resolve(); }
|
|
31
|
+
return fetch(b + '/v1/memory/' + encodeURIComponent(KEY), { headers: { 'Authorization': 'Bearer ' + token } })
|
|
32
|
+
.then(function (r) { return r.ok ? r.json() : null; })
|
|
33
|
+
.then(function (j) {
|
|
34
|
+
var refs = (j && j.data && j.data.value && Array.isArray(j.data.value.refs)) ? j.data.value.refs : [];
|
|
35
|
+
favSet = new Set(refs.filter(function (x) { return typeof x === 'string'; }));
|
|
36
|
+
})
|
|
37
|
+
.catch(function () { /* leave the set as-is on a transient error */ });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function persist() {
|
|
41
|
+
var token = getCortexOwnerToken();
|
|
42
|
+
var b = base();
|
|
43
|
+
if (!token || !b) return Promise.resolve();
|
|
44
|
+
return fetch(b + '/v1/memory', {
|
|
45
|
+
method: 'POST',
|
|
46
|
+
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
key: KEY,
|
|
49
|
+
value: { version: 1, updatedAt: new Date().toISOString(), refs: Array.from(favSet) },
|
|
50
|
+
visibility: 'private',
|
|
51
|
+
}),
|
|
52
|
+
}).catch(function () { /* best-effort persist */ });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Toggle a favourite (ref = "owner/filename"). Updates the set optimistically, persists, and
|
|
56
|
+
// resolves so the caller can re-render. Returns the new state (true = now a favourite).
|
|
57
|
+
export function toggleFavorite(ref) {
|
|
58
|
+
var now;
|
|
59
|
+
if (favSet.has(ref)) { favSet.delete(ref); now = false; } else { favSet.add(ref); now = true; }
|
|
60
|
+
return persist().then(function () { return now; });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// The ⭐/☆ toggle button for a card. `ref` is "owner/filename". Stops propagation so a click on the
|
|
64
|
+
// star never opens the card's detail view.
|
|
65
|
+
export function favStarHtml(ref) {
|
|
66
|
+
var on = favSet.has(ref);
|
|
67
|
+
var title = on ? (t('fav.remove') || 'Remove from favourites') : (t('fav.add') || 'Add to favourites');
|
|
68
|
+
return '<button class="fav-toggle' + (on ? ' on' : '') + '"'
|
|
69
|
+
+ ' onclick="event.stopPropagation(); window._launcher.toggleFavorite(\'' + String(ref).replace(/'/g, "\\'") + '\')"'
|
|
70
|
+
+ ' title="' + title + '">' + (on ? '⭐' : '☆') + '</button>';
|
|
71
|
+
}
|