aimeat 1.2.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/.env.example +300 -0
- package/dist/bin/aimeat.d.ts +3 -0
- package/dist/bin/aimeat.d.ts.map +1 -0
- package/dist/bin/aimeat.js +22 -0
- package/dist/bin/aimeat.js.map +1 -0
- package/dist/locales/en.json +4566 -0
- package/dist/locales/fi.json +4566 -0
- package/dist/public/BingSiteAuth.xml +4 -0
- package/dist/public/agent-consent.html +521 -0
- package/dist/public/aimeat-developers.html +679 -0
- package/dist/public/assets/mcp_1_add_custom_connector.png +0 -0
- package/dist/public/assets/mcp_2_connect_disconnect_connector.png +0 -0
- package/dist/public/components/Alert.js +18 -0
- package/dist/public/components/Card.js +19 -0
- package/dist/public/components/CopyButton.js +24 -0
- package/dist/public/components/FormField.js +16 -0
- package/dist/public/components/Modal.js +121 -0
- package/dist/public/components/Spinner.js +11 -0
- package/dist/public/components/Toast.js +26 -0
- package/dist/public/components/index.js +8 -0
- package/dist/public/components/useViewCSS.js +12 -0
- package/dist/public/cortex-bundled/aimeat-canvas.js +1408 -0
- package/dist/public/cortex-bundled/aimeat-canvas.yaml +241 -0
- package/dist/public/cortex-bundled/aimeat-charts.js +455 -0
- package/dist/public/cortex-bundled/aimeat-charts.yaml +178 -0
- package/dist/public/cortex-bundled/aimeat-ui-dialogs.js +667 -0
- package/dist/public/cortex-bundled/aimeat-ui-dialogs.yaml +66 -0
- package/dist/public/cortex-bundled/aimeat-ui-forms.js +1106 -0
- package/dist/public/cortex-bundled/aimeat-ui-forms.yaml +90 -0
- package/dist/public/cortex-bundled/aimeat-ui-layout.js +436 -0
- package/dist/public/cortex-bundled/aimeat-ui-layout.yaml +87 -0
- package/dist/public/cortex-bundled/aimeat-ui-nav.js +722 -0
- package/dist/public/cortex-bundled/aimeat-ui-nav.yaml +73 -0
- package/dist/public/cortex-bundled/aimeat-ui-viewers.js +602 -0
- package/dist/public/cortex-bundled/aimeat-ui-viewers.yaml +73 -0
- package/dist/public/css/components/tags.css +67 -0
- package/dist/public/css/theme.css +716 -0
- package/dist/public/css/views/admin.css +576 -0
- package/dist/public/css/views/aimeat-os.css +153 -0
- package/dist/public/css/views/calibrator.css +480 -0
- package/dist/public/css/views/foundry.css +1334 -0
- package/dist/public/css/views/help.css +136 -0
- package/dist/public/css/views/hobbies.css +73 -0
- package/dist/public/css/views/marketplace.css +134 -0
- package/dist/public/css/views/openclaw.css +33 -0
- package/dist/public/css/views/portal-classic.css +484 -0
- package/dist/public/css/views/portal-dev.css +139 -0
- package/dist/public/css/views/portal.css +365 -0
- package/dist/public/css/views/portfolio.css +322 -0
- package/dist/public/css/views/profile.css +1799 -0
- package/dist/public/echat.html +442 -0
- package/dist/public/img/genesis-001-badge.png +0 -0
- package/dist/public/img/platforms/chatgpt.png +0 -0
- package/dist/public/img/platforms/claude.png +0 -0
- package/dist/public/img/platforms/copilot.png +0 -0
- package/dist/public/img/platforms/deepseek.png +0 -0
- package/dist/public/img/platforms/gemini.png +0 -0
- package/dist/public/img/platforms/grok.png +0 -0
- package/dist/public/img/platforms/lmstudio.png +0 -0
- package/dist/public/img/platforms/m365copilot.png +0 -0
- package/dist/public/img/platforms/openclaw.png +0 -0
- package/dist/public/img/platforms/other.png +0 -0
- package/dist/public/js/api.js +123 -0
- package/dist/public/js/components/auth-image.js +59 -0
- package/dist/public/js/components/tag-cloud.js +31 -0
- package/dist/public/js/components/tag-editor.js +46 -0
- package/dist/public/js/hooks.js +63 -0
- package/dist/public/js/i18n.js +76 -0
- package/dist/public/js/services/admin.js +239 -0
- package/dist/public/js/services/agents.js +57 -0
- package/dist/public/js/services/apps.js +35 -0
- package/dist/public/js/services/auth.js +40 -0
- package/dist/public/js/services/boards.js +79 -0
- package/dist/public/js/services/calibrator.js +97 -0
- package/dist/public/js/services/catalogue.js +39 -0
- package/dist/public/js/services/consent.js +57 -0
- package/dist/public/js/services/cortex.js +95 -0
- package/dist/public/js/services/extensions.js +61 -0
- package/dist/public/js/services/federation.js +11 -0
- package/dist/public/js/services/foundry-context-bundle.js +128 -0
- package/dist/public/js/services/foundry-contract.js +117 -0
- package/dist/public/js/services/foundry-packaging.js +762 -0
- package/dist/public/js/services/foundry-probe-reconcile.js +52 -0
- package/dist/public/js/services/foundry-prompts-base.js +1886 -0
- package/dist/public/js/services/foundry-prompts-build.js +2187 -0
- package/dist/public/js/services/foundry-prompts-cortex-app.js +154 -0
- package/dist/public/js/services/foundry-prompts-cortex-data.js +241 -0
- package/dist/public/js/services/foundry-prompts-cortex-feature.js +281 -0
- package/dist/public/js/services/foundry-prompts-fix.js +408 -0
- package/dist/public/js/services/foundry-prompts-test.js +520 -0
- package/dist/public/js/services/foundry-prompts.js +31 -0
- package/dist/public/js/services/foundry-smoke.js +65 -0
- package/dist/public/js/services/foundry-testing.js +64 -0
- package/dist/public/js/services/foundry-validate.js +1082 -0
- package/dist/public/js/services/foundry.js +1194 -0
- package/dist/public/js/services/generator-context-bundle.js +134 -0
- package/dist/public/js/services/generator-contract.js +117 -0
- package/dist/public/js/services/generator-packaging.js +762 -0
- package/dist/public/js/services/generator-probe-reconcile.js +52 -0
- package/dist/public/js/services/generator-prompts-base.js +1890 -0
- package/dist/public/js/services/generator-prompts-build.js +1126 -0
- package/dist/public/js/services/generator-prompts-cortex-app.js +155 -0
- package/dist/public/js/services/generator-prompts-cortex-data.js +199 -0
- package/dist/public/js/services/generator-prompts-cortex-feature.js +276 -0
- package/dist/public/js/services/generator-prompts-fix.js +316 -0
- package/dist/public/js/services/generator-prompts-test.js +402 -0
- package/dist/public/js/services/generator-prompts.js +31 -0
- package/dist/public/js/services/generator-smoke.js +65 -0
- package/dist/public/js/services/generator-spec-tests.js +280 -0
- package/dist/public/js/services/generator-spec-validate.js +192 -0
- package/dist/public/js/services/generator-specs.js +369 -0
- package/dist/public/js/services/generator-testing.js +64 -0
- package/dist/public/js/services/generator-validate.js +916 -0
- package/dist/public/js/services/generator.js +952 -0
- package/dist/public/js/services/knowledge.js +120 -0
- package/dist/public/js/services/memory.js +112 -0
- package/dist/public/js/services/nodes.js +55 -0
- package/dist/public/js/services/organisms.js +74 -0
- package/dist/public/js/services/packages.js +97 -0
- package/dist/public/js/services/security.js +67 -0
- package/dist/public/js/services/stats.js +11 -0
- package/dist/public/js/services/wallet.js +24 -0
- package/dist/public/js/services/work.js +51 -0
- package/dist/public/js/utils.js +184 -0
- package/dist/public/lib/htm.mjs +4 -0
- package/dist/public/lib/live-updates.js +89 -0
- package/dist/public/lib/minidenticons.min.js +1 -0
- package/dist/public/lib/preact-hooks.mjs +3 -0
- package/dist/public/lib/preact.mjs +3 -0
- package/dist/public/lib/realtime.js +549 -0
- package/dist/public/lib/three.min.js +6 -0
- package/dist/public/lib/yaml.mjs +141 -0
- package/dist/public/llms-template.txt +1043 -0
- package/dist/public/oauth-consent.html +388 -0
- package/dist/public/og-image.png +0 -0
- package/dist/public/robots.txt +52 -0
- package/dist/public/spa.html +533 -0
- package/dist/public/sw.js +34 -0
- package/dist/public/tmp-paste.txt +223 -0
- package/dist/public/views/_template.js +85 -0
- package/dist/public/views/admin/actions-tab.js +41 -0
- package/dist/public/views/admin/agents-tab.js +84 -0
- package/dist/public/views/admin/boards-tab.js +154 -0
- package/dist/public/views/admin/chat-instances-tab.js +207 -0
- package/dist/public/views/admin/config-tab.js +151 -0
- package/dist/public/views/admin/consul-tab.js +77 -0
- package/dist/public/views/admin/cors-tab.js +240 -0
- package/dist/public/views/admin/cortex-tab.js +171 -0
- package/dist/public/views/admin/csm-tab.js +261 -0
- package/dist/public/views/admin/directory-tab.js +44 -0
- package/dist/public/views/admin/economy-tab.js +80 -0
- package/dist/public/views/admin/email-tab.js +460 -0
- package/dist/public/views/admin/federation-tab.js +412 -0
- package/dist/public/views/admin/generator-debug-tab.js +238 -0
- package/dist/public/views/admin/genesis-tab.js +70 -0
- package/dist/public/views/admin/ghii-tab.js +101 -0
- package/dist/public/views/admin/hooks-tab.js +69 -0
- package/dist/public/views/admin/knowledge-tab.js +297 -0
- package/dist/public/views/admin/maintenance-tab.js +98 -0
- package/dist/public/views/admin/matching-tab.js +44 -0
- package/dist/public/views/admin/memory-tab.js +222 -0
- package/dist/public/views/admin/msm-tab.js +342 -0
- package/dist/public/views/admin/overview-tab.js +90 -0
- package/dist/public/views/admin/owners-tab.js +55 -0
- package/dist/public/views/admin/packages-tab.js +510 -0
- package/dist/public/views/admin/portal-tab.js +211 -0
- package/dist/public/views/admin/prompts-tab.js +287 -0
- package/dist/public/views/admin/push-tab.js +291 -0
- package/dist/public/views/admin/realtime-tab.js +68 -0
- package/dist/public/views/admin/scheduler-tab.js +156 -0
- package/dist/public/views/admin/services-tab.js +981 -0
- package/dist/public/views/admin/shared.js +148 -0
- package/dist/public/views/admin/stats-tab.js +187 -0
- package/dist/public/views/admin/work-tab.js +45 -0
- package/dist/public/views/admin.js +400 -0
- package/dist/public/views/aimeat-os.js +259 -0
- package/dist/public/views/guides.js +402 -0
- package/dist/public/views/help.js +79 -0
- package/dist/public/views/hobbies.js +697 -0
- package/dist/public/views/marketplace.js +647 -0
- package/dist/public/views/openclaw.js +223 -0
- package/dist/public/views/portal-classic.js +519 -0
- package/dist/public/views/portal-dev.js +816 -0
- package/dist/public/views/portal.js +1354 -0
- package/dist/public/views/portfolio.js +795 -0
- package/dist/public/views/profile/access-tab.js +58 -0
- package/dist/public/views/profile/agents-tab.js +689 -0
- package/dist/public/views/profile/apps-tab.js +197 -0
- package/dist/public/views/profile/boards-tab.js +323 -0
- package/dist/public/views/profile/calibrator-batch.js +926 -0
- package/dist/public/views/profile/calibrator-chart.js +135 -0
- package/dist/public/views/profile/calibrator-llm-editor.js +205 -0
- package/dist/public/views/profile/calibrator-tab.js +535 -0
- package/dist/public/views/profile/chat-sessions-tab.js +184 -0
- package/dist/public/views/profile/data-wallet-tab.js +313 -0
- package/dist/public/views/profile/email-tab.js +157 -0
- package/dist/public/views/profile/extensions-tab.js +711 -0
- package/dist/public/views/profile/federation-tab.js +63 -0
- package/dist/public/views/profile/foundry-dashboard/DebugPanel.js +193 -0
- package/dist/public/views/profile/foundry-dashboard/DiagnosticsPanel.js +69 -0
- package/dist/public/views/profile/foundry-dashboard/EditModePanel.js +141 -0
- package/dist/public/views/profile/foundry-dashboard/PackageDialog.js +96 -0
- package/dist/public/views/profile/foundry-dashboard/RemovePanel.js +53 -0
- package/dist/public/views/profile/foundry-dashboard/use-autopilot-state.js +53 -0
- package/dist/public/views/profile/foundry-dashboard/use-autopilot.js +1016 -0
- package/dist/public/views/profile/foundry-dashboard/use-dashboard-core.js +154 -0
- package/dist/public/views/profile/foundry-dashboard/use-edit-mode.js +294 -0
- package/dist/public/views/profile/foundry-dashboard/use-lifecycle.js +101 -0
- package/dist/public/views/profile/foundry-dashboard/use-packaging.js +97 -0
- package/dist/public/views/profile/foundry-dashboard/use-test-execution.js +275 -0
- package/dist/public/views/profile/foundry-dashboard.js +395 -0
- package/dist/public/views/profile/foundry-detail.js +1178 -0
- package/dist/public/views/profile/foundry-settings.js +377 -0
- package/dist/public/views/profile/foundry-tab.js +546 -0
- package/dist/public/views/profile/generator-dashboard/DebugPanel.js +193 -0
- package/dist/public/views/profile/generator-dashboard/DiagnosticsPanel.js +69 -0
- package/dist/public/views/profile/generator-dashboard/EditModePanel.js +141 -0
- package/dist/public/views/profile/generator-dashboard/PackageDialog.js +96 -0
- package/dist/public/views/profile/generator-dashboard/RemovePanel.js +53 -0
- package/dist/public/views/profile/generator-dashboard/use-autopilot-state.js +53 -0
- package/dist/public/views/profile/generator-dashboard/use-autopilot.js +136 -0
- package/dist/public/views/profile/generator-dashboard/use-dashboard-core.js +143 -0
- package/dist/public/views/profile/generator-dashboard/use-edit-mode.js +296 -0
- package/dist/public/views/profile/generator-dashboard/use-lifecycle.js +101 -0
- package/dist/public/views/profile/generator-dashboard/use-packaging.js +97 -0
- package/dist/public/views/profile/generator-dashboard/use-test-execution.js +275 -0
- package/dist/public/views/profile/generator-dashboard.js +377 -0
- package/dist/public/views/profile/generator-detail.js +1007 -0
- package/dist/public/views/profile/generator-settings.js +417 -0
- package/dist/public/views/profile/generator-tab.js +544 -0
- package/dist/public/views/profile/inline-panels.js +277 -0
- package/dist/public/views/profile/knowledge-tab.js +735 -0
- package/dist/public/views/profile/landing-page.js +539 -0
- package/dist/public/views/profile/mcp-tab.js +140 -0
- package/dist/public/views/profile/memory-tab.js +599 -0
- package/dist/public/views/profile/node-stats-tab.js +132 -0
- package/dist/public/views/profile/nodes-tab.js +195 -0
- package/dist/public/views/profile/notifications-tab.js +274 -0
- package/dist/public/views/profile/organisms-tab.js +402 -0
- package/dist/public/views/profile/packages-tab.js +393 -0
- package/dist/public/views/profile/portfolio-tab.js +31 -0
- package/dist/public/views/profile/security-tab.js +219 -0
- package/dist/public/views/profile/services-tab.js +281 -0
- package/dist/public/views/profile/shared.js +58 -0
- package/dist/public/views/profile/wallet-tab.js +272 -0
- package/dist/public/views/profile/work-tab.js +220 -0
- package/dist/public/views/profile.js +271 -0
- package/dist/public/wizard.html +1320 -0
- package/dist/scripts/db-init.d.ts +19 -0
- package/dist/scripts/db-init.d.ts.map +1 -0
- package/dist/scripts/db-init.js +168 -0
- package/dist/scripts/db-init.js.map +1 -0
- package/dist/scripts/db-reset.d.ts +15 -0
- package/dist/scripts/db-reset.d.ts.map +1 -0
- package/dist/scripts/db-reset.js +162 -0
- package/dist/scripts/db-reset.js.map +1 -0
- package/dist/scripts/indexnow.d.ts +18 -0
- package/dist/scripts/indexnow.d.ts.map +1 -0
- package/dist/scripts/indexnow.js +104 -0
- package/dist/scripts/indexnow.js.map +1 -0
- package/dist/scripts/kill-port.d.ts +3 -0
- package/dist/scripts/kill-port.d.ts.map +1 -0
- package/dist/scripts/kill-port.js +89 -0
- package/dist/scripts/kill-port.js.map +1 -0
- package/dist/scripts/seed-digital-signage.d.ts +13 -0
- package/dist/scripts/seed-digital-signage.d.ts.map +1 -0
- package/dist/scripts/seed-digital-signage.js +85 -0
- package/dist/scripts/seed-digital-signage.js.map +1 -0
- package/dist/src/auth/jwt.d.ts +40 -0
- package/dist/src/auth/jwt.d.ts.map +1 -0
- package/dist/src/auth/jwt.js +139 -0
- package/dist/src/auth/jwt.js.map +1 -0
- package/dist/src/auth/keypair.d.ts +8 -0
- package/dist/src/auth/keypair.d.ts.map +1 -0
- package/dist/src/auth/keypair.js +35 -0
- package/dist/src/auth/keypair.js.map +1 -0
- package/dist/src/auth/middleware.d.ts +50 -0
- package/dist/src/auth/middleware.d.ts.map +1 -0
- package/dist/src/auth/middleware.js +241 -0
- package/dist/src/auth/middleware.js.map +1 -0
- package/dist/src/auth/node-keys.d.ts +7 -0
- package/dist/src/auth/node-keys.d.ts.map +1 -0
- package/dist/src/auth/node-keys.js +116 -0
- package/dist/src/auth/node-keys.js.map +1 -0
- package/dist/src/cli/config-export.d.ts +9 -0
- package/dist/src/cli/config-export.d.ts.map +1 -0
- package/dist/src/cli/config-export.js +90 -0
- package/dist/src/cli/config-export.js.map +1 -0
- package/dist/src/cli/config-import.d.ts +10 -0
- package/dist/src/cli/config-import.d.ts.map +1 -0
- package/dist/src/cli/config-import.js +124 -0
- package/dist/src/cli/config-import.js.map +1 -0
- package/dist/src/cli/federation-join.d.ts +13 -0
- package/dist/src/cli/federation-join.d.ts.map +1 -0
- package/dist/src/cli/federation-join.js +395 -0
- package/dist/src/cli/federation-join.js.map +1 -0
- package/dist/src/cli/init-wizard.d.ts +8 -0
- package/dist/src/cli/init-wizard.d.ts.map +1 -0
- package/dist/src/cli/init-wizard.js +1489 -0
- package/dist/src/cli/init-wizard.js.map +1 -0
- package/dist/src/cli/scaffold.d.ts +33 -0
- package/dist/src/cli/scaffold.d.ts.map +1 -0
- package/dist/src/cli/scaffold.js +142 -0
- package/dist/src/cli/scaffold.js.map +1 -0
- package/dist/src/config.d.ts +272 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +362 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/data/example-packages.d.ts +49 -0
- package/dist/src/data/example-packages.d.ts.map +1 -0
- package/dist/src/data/example-packages.js +814 -0
- package/dist/src/data/example-packages.js.map +1 -0
- package/dist/src/i18n.d.ts +19 -0
- package/dist/src/i18n.d.ts.map +1 -0
- package/dist/src/i18n.js +126 -0
- package/dist/src/i18n.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +608 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcp/boards.d.ts +18 -0
- package/dist/src/mcp/boards.d.ts.map +1 -0
- package/dist/src/mcp/boards.js +279 -0
- package/dist/src/mcp/boards.js.map +1 -0
- package/dist/src/mcp/catalogue.d.ts +17 -0
- package/dist/src/mcp/catalogue.d.ts.map +1 -0
- package/dist/src/mcp/catalogue.js +114 -0
- package/dist/src/mcp/catalogue.js.map +1 -0
- package/dist/src/mcp/chat-instances.d.ts +18 -0
- package/dist/src/mcp/chat-instances.d.ts.map +1 -0
- package/dist/src/mcp/chat-instances.js +161 -0
- package/dist/src/mcp/chat-instances.js.map +1 -0
- package/dist/src/mcp/consent.d.ts +18 -0
- package/dist/src/mcp/consent.d.ts.map +1 -0
- package/dist/src/mcp/consent.js +158 -0
- package/dist/src/mcp/consent.js.map +1 -0
- package/dist/src/mcp/core.d.ts +18 -0
- package/dist/src/mcp/core.d.ts.map +1 -0
- package/dist/src/mcp/core.js +489 -0
- package/dist/src/mcp/core.js.map +1 -0
- package/dist/src/mcp/extensions.d.ts +18 -0
- package/dist/src/mcp/extensions.d.ts.map +1 -0
- package/dist/src/mcp/extensions.js +299 -0
- package/dist/src/mcp/extensions.js.map +1 -0
- package/dist/src/mcp/flags.d.ts +18 -0
- package/dist/src/mcp/flags.d.ts.map +1 -0
- package/dist/src/mcp/flags.js +59 -0
- package/dist/src/mcp/flags.js.map +1 -0
- package/dist/src/mcp/index.d.ts +31 -0
- package/dist/src/mcp/index.d.ts.map +1 -0
- package/dist/src/mcp/index.js +694 -0
- package/dist/src/mcp/index.js.map +1 -0
- package/dist/src/mcp/knowledge.d.ts +18 -0
- package/dist/src/mcp/knowledge.d.ts.map +1 -0
- package/dist/src/mcp/knowledge.js +214 -0
- package/dist/src/mcp/knowledge.js.map +1 -0
- package/dist/src/mcp/memory-extended.d.ts +18 -0
- package/dist/src/mcp/memory-extended.d.ts.map +1 -0
- package/dist/src/mcp/memory-extended.js +73 -0
- package/dist/src/mcp/memory-extended.js.map +1 -0
- package/dist/src/mcp/organisms.d.ts +18 -0
- package/dist/src/mcp/organisms.d.ts.map +1 -0
- package/dist/src/mcp/organisms.js +291 -0
- package/dist/src/mcp/organisms.js.map +1 -0
- package/dist/src/mcp/prompts.d.ts +17 -0
- package/dist/src/mcp/prompts.d.ts.map +1 -0
- package/dist/src/mcp/prompts.js +65 -0
- package/dist/src/mcp/prompts.js.map +1 -0
- package/dist/src/mcp/wallet-extended.d.ts +17 -0
- package/dist/src/mcp/wallet-extended.d.ts.map +1 -0
- package/dist/src/mcp/wallet-extended.js +42 -0
- package/dist/src/mcp/wallet-extended.js.map +1 -0
- package/dist/src/middleware/__tests__/cookie-consent.test.d.ts +2 -0
- package/dist/src/middleware/__tests__/cookie-consent.test.d.ts.map +1 -0
- package/dist/src/middleware/__tests__/cookie-consent.test.js +432 -0
- package/dist/src/middleware/__tests__/cookie-consent.test.js.map +1 -0
- package/dist/src/middleware/cookie-consent.d.ts +19 -0
- package/dist/src/middleware/cookie-consent.d.ts.map +1 -0
- package/dist/src/middleware/cookie-consent.js +127 -0
- package/dist/src/middleware/cookie-consent.js.map +1 -0
- package/dist/src/middleware/cors.d.ts +12 -0
- package/dist/src/middleware/cors.d.ts.map +1 -0
- package/dist/src/middleware/cors.js +112 -0
- package/dist/src/middleware/cors.js.map +1 -0
- package/dist/src/middleware/envelope.d.ts +33 -0
- package/dist/src/middleware/envelope.d.ts.map +1 -0
- package/dist/src/middleware/envelope.js +32 -0
- package/dist/src/middleware/envelope.js.map +1 -0
- package/dist/src/middleware/idempotency.d.ts +3 -0
- package/dist/src/middleware/idempotency.d.ts.map +1 -0
- package/dist/src/middleware/idempotency.js +64 -0
- package/dist/src/middleware/idempotency.js.map +1 -0
- package/dist/src/middleware/metrics.d.ts +8 -0
- package/dist/src/middleware/metrics.d.ts.map +1 -0
- package/dist/src/middleware/metrics.js +25 -0
- package/dist/src/middleware/metrics.js.map +1 -0
- package/dist/src/middleware/rate-limit.d.ts +4 -0
- package/dist/src/middleware/rate-limit.d.ts.map +1 -0
- package/dist/src/middleware/rate-limit.js +73 -0
- package/dist/src/middleware/rate-limit.js.map +1 -0
- package/dist/src/middleware/request-id.d.ts +18 -0
- package/dist/src/middleware/request-id.d.ts.map +1 -0
- package/dist/src/middleware/request-id.js +23 -0
- package/dist/src/middleware/request-id.js.map +1 -0
- package/dist/src/middleware/stats.d.ts +4 -0
- package/dist/src/middleware/stats.d.ts.map +1 -0
- package/dist/src/middleware/stats.js +11 -0
- package/dist/src/middleware/stats.js.map +1 -0
- package/dist/src/middleware/workspace-access.d.ts +16 -0
- package/dist/src/middleware/workspace-access.d.ts.map +1 -0
- package/dist/src/middleware/workspace-access.js +115 -0
- package/dist/src/middleware/workspace-access.js.map +1 -0
- package/dist/src/models/schemas.d.ts +311 -0
- package/dist/src/models/schemas.d.ts.map +1 -0
- package/dist/src/models/schemas.js +281 -0
- package/dist/src/models/schemas.js.map +1 -0
- package/dist/src/routes/actions.d.ts +5 -0
- package/dist/src/routes/actions.d.ts.map +1 -0
- package/dist/src/routes/actions.js +199 -0
- package/dist/src/routes/actions.js.map +1 -0
- package/dist/src/routes/admin-agents.d.ts +5 -0
- package/dist/src/routes/admin-agents.d.ts.map +1 -0
- package/dist/src/routes/admin-agents.js +60 -0
- package/dist/src/routes/admin-agents.js.map +1 -0
- package/dist/src/routes/admin-config.d.ts +7 -0
- package/dist/src/routes/admin-config.d.ts.map +1 -0
- package/dist/src/routes/admin-config.js +209 -0
- package/dist/src/routes/admin-config.js.map +1 -0
- package/dist/src/routes/admin-economy.d.ts +5 -0
- package/dist/src/routes/admin-economy.d.ts.map +1 -0
- package/dist/src/routes/admin-economy.js +57 -0
- package/dist/src/routes/admin-economy.js.map +1 -0
- package/dist/src/routes/admin-extensions.d.ts +6 -0
- package/dist/src/routes/admin-extensions.d.ts.map +1 -0
- package/dist/src/routes/admin-extensions.js +619 -0
- package/dist/src/routes/admin-extensions.js.map +1 -0
- package/dist/src/routes/admin-features.d.ts +16 -0
- package/dist/src/routes/admin-features.d.ts.map +1 -0
- package/dist/src/routes/admin-features.js +672 -0
- package/dist/src/routes/admin-features.js.map +1 -0
- package/dist/src/routes/admin-maintenance.d.ts +8 -0
- package/dist/src/routes/admin-maintenance.d.ts.map +1 -0
- package/dist/src/routes/admin-maintenance.js +86 -0
- package/dist/src/routes/admin-maintenance.js.map +1 -0
- package/dist/src/routes/admin-memory.d.ts +12 -0
- package/dist/src/routes/admin-memory.d.ts.map +1 -0
- package/dist/src/routes/admin-memory.js +64 -0
- package/dist/src/routes/admin-memory.js.map +1 -0
- package/dist/src/routes/admin-monitoring.d.ts +5 -0
- package/dist/src/routes/admin-monitoring.d.ts.map +1 -0
- package/dist/src/routes/admin-monitoring.js +343 -0
- package/dist/src/routes/admin-monitoring.js.map +1 -0
- package/dist/src/routes/admin-prompts.d.ts +5 -0
- package/dist/src/routes/admin-prompts.d.ts.map +1 -0
- package/dist/src/routes/admin-prompts.js +198 -0
- package/dist/src/routes/admin-prompts.js.map +1 -0
- package/dist/src/routes/admin-scheduler.d.ts +6 -0
- package/dist/src/routes/admin-scheduler.d.ts.map +1 -0
- package/dist/src/routes/admin-scheduler.js +153 -0
- package/dist/src/routes/admin-scheduler.js.map +1 -0
- package/dist/src/routes/admin.d.ts +10 -0
- package/dist/src/routes/admin.d.ts.map +1 -0
- package/dist/src/routes/admin.js +847 -0
- package/dist/src/routes/admin.js.map +1 -0
- package/dist/src/routes/agents.d.ts +5 -0
- package/dist/src/routes/agents.d.ts.map +1 -0
- package/dist/src/routes/agents.js +946 -0
- package/dist/src/routes/agents.js.map +1 -0
- package/dist/src/routes/app-store.d.ts +25 -0
- package/dist/src/routes/app-store.d.ts.map +1 -0
- package/dist/src/routes/app-store.js +269 -0
- package/dist/src/routes/app-store.js.map +1 -0
- package/dist/src/routes/appeals.d.ts +5 -0
- package/dist/src/routes/appeals.d.ts.map +1 -0
- package/dist/src/routes/appeals.js +241 -0
- package/dist/src/routes/appeals.js.map +1 -0
- package/dist/src/routes/apps.d.ts +14 -0
- package/dist/src/routes/apps.d.ts.map +1 -0
- package/dist/src/routes/apps.js +395 -0
- package/dist/src/routes/apps.js.map +1 -0
- package/dist/src/routes/auth.d.ts +13 -0
- package/dist/src/routes/auth.d.ts.map +1 -0
- package/dist/src/routes/auth.js +517 -0
- package/dist/src/routes/auth.js.map +1 -0
- package/dist/src/routes/boards.d.ts +5 -0
- package/dist/src/routes/boards.d.ts.map +1 -0
- package/dist/src/routes/boards.js +614 -0
- package/dist/src/routes/boards.js.map +1 -0
- package/dist/src/routes/bootstrap.d.ts +6 -0
- package/dist/src/routes/bootstrap.d.ts.map +1 -0
- package/dist/src/routes/bootstrap.js +360 -0
- package/dist/src/routes/bootstrap.js.map +1 -0
- package/dist/src/routes/calibrator.d.ts +28 -0
- package/dist/src/routes/calibrator.d.ts.map +1 -0
- package/dist/src/routes/calibrator.js +556 -0
- package/dist/src/routes/calibrator.js.map +1 -0
- package/dist/src/routes/catalogue.d.ts +7 -0
- package/dist/src/routes/catalogue.d.ts.map +1 -0
- package/dist/src/routes/catalogue.js +377 -0
- package/dist/src/routes/catalogue.js.map +1 -0
- package/dist/src/routes/chat-instances.d.ts +5 -0
- package/dist/src/routes/chat-instances.d.ts.map +1 -0
- package/dist/src/routes/chat-instances.js +131 -0
- package/dist/src/routes/chat-instances.js.map +1 -0
- package/dist/src/routes/consent.d.ts +6 -0
- package/dist/src/routes/consent.d.ts.map +1 -0
- package/dist/src/routes/consent.js +188 -0
- package/dist/src/routes/consent.js.map +1 -0
- package/dist/src/routes/cortex.d.ts +5 -0
- package/dist/src/routes/cortex.d.ts.map +1 -0
- package/dist/src/routes/cortex.js +617 -0
- package/dist/src/routes/cortex.js.map +1 -0
- package/dist/src/routes/csm.d.ts +5 -0
- package/dist/src/routes/csm.d.ts.map +1 -0
- package/dist/src/routes/csm.js +258 -0
- package/dist/src/routes/csm.js.map +1 -0
- package/dist/src/routes/disputes.d.ts +5 -0
- package/dist/src/routes/disputes.d.ts.map +1 -0
- package/dist/src/routes/disputes.js +528 -0
- package/dist/src/routes/disputes.js.map +1 -0
- package/dist/src/routes/extensions.d.ts +6 -0
- package/dist/src/routes/extensions.d.ts.map +1 -0
- package/dist/src/routes/extensions.js +1149 -0
- package/dist/src/routes/extensions.js.map +1 -0
- package/dist/src/routes/federation-genesis.d.ts +11 -0
- package/dist/src/routes/federation-genesis.d.ts.map +1 -0
- package/dist/src/routes/federation-genesis.js +638 -0
- package/dist/src/routes/federation-genesis.js.map +1 -0
- package/dist/src/routes/federation-peer.d.ts +10 -0
- package/dist/src/routes/federation-peer.d.ts.map +1 -0
- package/dist/src/routes/federation-peer.js +613 -0
- package/dist/src/routes/federation-peer.js.map +1 -0
- package/dist/src/routes/federation-settlements.d.ts +10 -0
- package/dist/src/routes/federation-settlements.d.ts.map +1 -0
- package/dist/src/routes/federation-settlements.js +231 -0
- package/dist/src/routes/federation-settlements.js.map +1 -0
- package/dist/src/routes/federation-sync.d.ts +15 -0
- package/dist/src/routes/federation-sync.d.ts.map +1 -0
- package/dist/src/routes/federation-sync.js +629 -0
- package/dist/src/routes/federation-sync.js.map +1 -0
- package/dist/src/routes/federation.d.ts +15 -0
- package/dist/src/routes/federation.d.ts.map +1 -0
- package/dist/src/routes/federation.js +23 -0
- package/dist/src/routes/federation.js.map +1 -0
- package/dist/src/routes/flags.d.ts +5 -0
- package/dist/src/routes/flags.d.ts.map +1 -0
- package/dist/src/routes/flags.js +194 -0
- package/dist/src/routes/flags.js.map +1 -0
- package/dist/src/routes/foundry.d.ts +5 -0
- package/dist/src/routes/foundry.d.ts.map +1 -0
- package/dist/src/routes/foundry.js +955 -0
- package/dist/src/routes/foundry.js.map +1 -0
- package/dist/src/routes/generator-autopilot.d.ts +12 -0
- package/dist/src/routes/generator-autopilot.d.ts.map +1 -0
- package/dist/src/routes/generator-autopilot.js +71 -0
- package/dist/src/routes/generator-autopilot.js.map +1 -0
- package/dist/src/routes/generator.d.ts +5 -0
- package/dist/src/routes/generator.d.ts.map +1 -0
- package/dist/src/routes/generator.js +1313 -0
- package/dist/src/routes/generator.js.map +1 -0
- package/dist/src/routes/ghii.d.ts +16 -0
- package/dist/src/routes/ghii.d.ts.map +1 -0
- package/dist/src/routes/ghii.js +1115 -0
- package/dist/src/routes/ghii.js.map +1 -0
- package/dist/src/routes/instances.d.ts +31 -0
- package/dist/src/routes/instances.d.ts.map +1 -0
- package/dist/src/routes/instances.js +722 -0
- package/dist/src/routes/instances.js.map +1 -0
- package/dist/src/routes/knowledge.d.ts +33 -0
- package/dist/src/routes/knowledge.d.ts.map +1 -0
- package/dist/src/routes/knowledge.js +1108 -0
- package/dist/src/routes/knowledge.js.map +1 -0
- package/dist/src/routes/lib-data.d.ts +7 -0
- package/dist/src/routes/lib-data.d.ts.map +1 -0
- package/dist/src/routes/lib-data.js +189 -0
- package/dist/src/routes/lib-data.js.map +1 -0
- package/dist/src/routes/lib-social.d.ts +7 -0
- package/dist/src/routes/lib-social.d.ts.map +1 -0
- package/dist/src/routes/lib-social.js +159 -0
- package/dist/src/routes/lib-social.js.map +1 -0
- package/dist/src/routes/lib-storage.d.ts +7 -0
- package/dist/src/routes/lib-storage.d.ts.map +1 -0
- package/dist/src/routes/lib-storage.js +202 -0
- package/dist/src/routes/lib-storage.js.map +1 -0
- package/dist/src/routes/lib-tunnel.d.ts +8 -0
- package/dist/src/routes/lib-tunnel.d.ts.map +1 -0
- package/dist/src/routes/lib-tunnel.js +442 -0
- package/dist/src/routes/lib-tunnel.js.map +1 -0
- package/dist/src/routes/lib-wallet.d.ts +7 -0
- package/dist/src/routes/lib-wallet.d.ts.map +1 -0
- package/dist/src/routes/lib-wallet.js +129 -0
- package/dist/src/routes/lib-wallet.js.map +1 -0
- package/dist/src/routes/lib-work.d.ts +7 -0
- package/dist/src/routes/lib-work.d.ts.map +1 -0
- package/dist/src/routes/lib-work.js +210 -0
- package/dist/src/routes/lib-work.js.map +1 -0
- package/dist/src/routes/libs.d.ts +10 -0
- package/dist/src/routes/libs.d.ts.map +1 -0
- package/dist/src/routes/libs.js +989 -0
- package/dist/src/routes/libs.js.map +1 -0
- package/dist/src/routes/matches.d.ts +10 -0
- package/dist/src/routes/matches.d.ts.map +1 -0
- package/dist/src/routes/matches.js +218 -0
- package/dist/src/routes/matches.js.map +1 -0
- package/dist/src/routes/memory.d.ts +6 -0
- package/dist/src/routes/memory.d.ts.map +1 -0
- package/dist/src/routes/memory.js +796 -0
- package/dist/src/routes/memory.js.map +1 -0
- package/dist/src/routes/micro-memory.d.ts +5 -0
- package/dist/src/routes/micro-memory.d.ts.map +1 -0
- package/dist/src/routes/micro-memory.js +488 -0
- package/dist/src/routes/micro-memory.js.map +1 -0
- package/dist/src/routes/msm.d.ts +5 -0
- package/dist/src/routes/msm.d.ts.map +1 -0
- package/dist/src/routes/msm.js +242 -0
- package/dist/src/routes/msm.js.map +1 -0
- package/dist/src/routes/openrouter.d.ts +23 -0
- package/dist/src/routes/openrouter.d.ts.map +1 -0
- package/dist/src/routes/openrouter.js +337 -0
- package/dist/src/routes/openrouter.js.map +1 -0
- package/dist/src/routes/organisms.d.ts +5 -0
- package/dist/src/routes/organisms.d.ts.map +1 -0
- package/dist/src/routes/organisms.js +415 -0
- package/dist/src/routes/organisms.js.map +1 -0
- package/dist/src/routes/owners.d.ts +5 -0
- package/dist/src/routes/owners.d.ts.map +1 -0
- package/dist/src/routes/owners.js +637 -0
- package/dist/src/routes/owners.js.map +1 -0
- package/dist/src/routes/packages.d.ts +35 -0
- package/dist/src/routes/packages.d.ts.map +1 -0
- package/dist/src/routes/packages.js +600 -0
- package/dist/src/routes/packages.js.map +1 -0
- package/dist/src/routes/permissions.d.ts +5 -0
- package/dist/src/routes/permissions.d.ts.map +1 -0
- package/dist/src/routes/permissions.js +85 -0
- package/dist/src/routes/permissions.js.map +1 -0
- package/dist/src/routes/personal.d.ts +7 -0
- package/dist/src/routes/personal.d.ts.map +1 -0
- package/dist/src/routes/personal.js +594 -0
- package/dist/src/routes/personal.js.map +1 -0
- package/dist/src/routes/portal-api.d.ts +9 -0
- package/dist/src/routes/portal-api.d.ts.map +1 -0
- package/dist/src/routes/portal-api.js +49 -0
- package/dist/src/routes/portal-api.js.map +1 -0
- package/dist/src/routes/portal-human.d.ts +12 -0
- package/dist/src/routes/portal-human.d.ts.map +1 -0
- package/dist/src/routes/portal-human.js +2652 -0
- package/dist/src/routes/portal-human.js.map +1 -0
- package/dist/src/routes/portal.d.ts +24 -0
- package/dist/src/routes/portal.d.ts.map +1 -0
- package/dist/src/routes/portal.js +372 -0
- package/dist/src/routes/portal.js.map +1 -0
- package/dist/src/routes/portfolio.d.ts +5 -0
- package/dist/src/routes/portfolio.d.ts.map +1 -0
- package/dist/src/routes/portfolio.js +231 -0
- package/dist/src/routes/portfolio.js.map +1 -0
- package/dist/src/routes/profile.d.ts +5 -0
- package/dist/src/routes/profile.d.ts.map +1 -0
- package/dist/src/routes/profile.js +2042 -0
- package/dist/src/routes/profile.js.map +1 -0
- package/dist/src/routes/prompts.d.ts +5 -0
- package/dist/src/routes/prompts.d.ts.map +1 -0
- package/dist/src/routes/prompts.js +318 -0
- package/dist/src/routes/prompts.js.map +1 -0
- package/dist/src/routes/push.d.ts +6 -0
- package/dist/src/routes/push.d.ts.map +1 -0
- package/dist/src/routes/push.js +75 -0
- package/dist/src/routes/push.js.map +1 -0
- package/dist/src/routes/realtime.d.ts +7 -0
- package/dist/src/routes/realtime.d.ts.map +1 -0
- package/dist/src/routes/realtime.js +289 -0
- package/dist/src/routes/realtime.js.map +1 -0
- package/dist/src/routes/schemas.d.ts +5 -0
- package/dist/src/routes/schemas.d.ts.map +1 -0
- package/dist/src/routes/schemas.js +130 -0
- package/dist/src/routes/schemas.js.map +1 -0
- package/dist/src/routes/setup.d.ts +7 -0
- package/dist/src/routes/setup.d.ts.map +1 -0
- package/dist/src/routes/setup.js +243 -0
- package/dist/src/routes/setup.js.map +1 -0
- package/dist/src/routes/site.d.ts +6 -0
- package/dist/src/routes/site.d.ts.map +1 -0
- package/dist/src/routes/site.js +201 -0
- package/dist/src/routes/site.js.map +1 -0
- package/dist/src/routes/spec.d.ts +3 -0
- package/dist/src/routes/spec.d.ts.map +1 -0
- package/dist/src/routes/spec.js +47 -0
- package/dist/src/routes/spec.js.map +1 -0
- package/dist/src/routes/sse.d.ts +5 -0
- package/dist/src/routes/sse.d.ts.map +1 -0
- package/dist/src/routes/sse.js +66 -0
- package/dist/src/routes/sse.js.map +1 -0
- package/dist/src/routes/stats.d.ts +7 -0
- package/dist/src/routes/stats.d.ts.map +1 -0
- package/dist/src/routes/stats.js +98 -0
- package/dist/src/routes/stats.js.map +1 -0
- package/dist/src/routes/storage-files.d.ts +5 -0
- package/dist/src/routes/storage-files.d.ts.map +1 -0
- package/dist/src/routes/storage-files.js +460 -0
- package/dist/src/routes/storage-files.js.map +1 -0
- package/dist/src/routes/templates.d.ts +30 -0
- package/dist/src/routes/templates.d.ts.map +1 -0
- package/dist/src/routes/templates.js +511 -0
- package/dist/src/routes/templates.js.map +1 -0
- package/dist/src/routes/totp.d.ts +5 -0
- package/dist/src/routes/totp.d.ts.map +1 -0
- package/dist/src/routes/totp.js +166 -0
- package/dist/src/routes/totp.js.map +1 -0
- package/dist/src/routes/validate.d.ts +4 -0
- package/dist/src/routes/validate.d.ts.map +1 -0
- package/dist/src/routes/validate.js +71 -0
- package/dist/src/routes/validate.js.map +1 -0
- package/dist/src/routes/verification.d.ts +8 -0
- package/dist/src/routes/verification.d.ts.map +1 -0
- package/dist/src/routes/verification.js +259 -0
- package/dist/src/routes/verification.js.map +1 -0
- package/dist/src/routes/wallet.d.ts +18 -0
- package/dist/src/routes/wallet.d.ts.map +1 -0
- package/dist/src/routes/wallet.js +164 -0
- package/dist/src/routes/wallet.js.map +1 -0
- package/dist/src/routes/wellknown.d.ts +5 -0
- package/dist/src/routes/wellknown.d.ts.map +1 -0
- package/dist/src/routes/wellknown.js +57 -0
- package/dist/src/routes/wellknown.js.map +1 -0
- package/dist/src/routes/work.d.ts +21 -0
- package/dist/src/routes/work.d.ts.map +1 -0
- package/dist/src/routes/work.js +654 -0
- package/dist/src/routes/work.js.map +1 -0
- package/dist/src/schemas/knowledge-package.d.ts +203 -0
- package/dist/src/schemas/knowledge-package.d.ts.map +1 -0
- package/dist/src/schemas/knowledge-package.js +233 -0
- package/dist/src/schemas/knowledge-package.js.map +1 -0
- package/dist/src/server-bootstrap/config-init.d.ts +16 -0
- package/dist/src/server-bootstrap/config-init.d.ts.map +1 -0
- package/dist/src/server-bootstrap/config-init.js +113 -0
- package/dist/src/server-bootstrap/config-init.js.map +1 -0
- package/dist/src/server-bootstrap/middleware-guards.d.ts +15 -0
- package/dist/src/server-bootstrap/middleware-guards.d.ts.map +1 -0
- package/dist/src/server-bootstrap/middleware-guards.js +244 -0
- package/dist/src/server-bootstrap/middleware-guards.js.map +1 -0
- package/dist/src/server-bootstrap/routes-loader.d.ts +35 -0
- package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -0
- package/dist/src/server-bootstrap/routes-loader.js +290 -0
- package/dist/src/server-bootstrap/routes-loader.js.map +1 -0
- package/dist/src/server-bootstrap/service-init.d.ts +24 -0
- package/dist/src/server-bootstrap/service-init.d.ts.map +1 -0
- package/dist/src/server-bootstrap/service-init.js +195 -0
- package/dist/src/server-bootstrap/service-init.js.map +1 -0
- package/dist/src/server-bootstrap/static-files.d.ts +7 -0
- package/dist/src/server-bootstrap/static-files.d.ts.map +1 -0
- package/dist/src/server-bootstrap/static-files.js +119 -0
- package/dist/src/server-bootstrap/static-files.js.map +1 -0
- package/dist/src/server.d.ts +22 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/server.js +133 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/services/cache-cleanup.d.ts +31 -0
- package/dist/src/services/cache-cleanup.d.ts.map +1 -0
- package/dist/src/services/cache-cleanup.js +123 -0
- package/dist/src/services/cache-cleanup.js.map +1 -0
- package/dist/src/services/catalogue-sync.d.ts +45 -0
- package/dist/src/services/catalogue-sync.d.ts.map +1 -0
- package/dist/src/services/catalogue-sync.js +196 -0
- package/dist/src/services/catalogue-sync.js.map +1 -0
- package/dist/src/services/component-registrar.d.ts +46 -0
- package/dist/src/services/component-registrar.d.ts.map +1 -0
- package/dist/src/services/component-registrar.js +389 -0
- package/dist/src/services/component-registrar.js.map +1 -0
- package/dist/src/services/config-loader.d.ts +42 -0
- package/dist/src/services/config-loader.d.ts.map +1 -0
- package/dist/src/services/config-loader.js +187 -0
- package/dist/src/services/config-loader.js.map +1 -0
- package/dist/src/services/config-provenance.d.ts +32 -0
- package/dist/src/services/config-provenance.d.ts.map +1 -0
- package/dist/src/services/config-provenance.js +59 -0
- package/dist/src/services/config-provenance.js.map +1 -0
- package/dist/src/services/config-schema.d.ts +52 -0
- package/dist/src/services/config-schema.d.ts.map +1 -0
- package/dist/src/services/config-schema.js +288 -0
- package/dist/src/services/config-schema.js.map +1 -0
- package/dist/src/services/consent.d.ts +43 -0
- package/dist/src/services/consent.d.ts.map +1 -0
- package/dist/src/services/consent.js +137 -0
- package/dist/src/services/consent.js.map +1 -0
- package/dist/src/services/consul-config.d.ts +30 -0
- package/dist/src/services/consul-config.d.ts.map +1 -0
- package/dist/src/services/consul-config.js +110 -0
- package/dist/src/services/consul-config.js.map +1 -0
- package/dist/src/services/core-jobs.d.ts +8 -0
- package/dist/src/services/core-jobs.d.ts.map +1 -0
- package/dist/src/services/core-jobs.js +161 -0
- package/dist/src/services/core-jobs.js.map +1 -0
- package/dist/src/services/cortex-manifest.d.ts +17 -0
- package/dist/src/services/cortex-manifest.d.ts.map +1 -0
- package/dist/src/services/cortex-manifest.js +343 -0
- package/dist/src/services/cortex-manifest.js.map +1 -0
- package/dist/src/services/cortex-seeder.d.ts +18 -0
- package/dist/src/services/cortex-seeder.d.ts.map +1 -0
- package/dist/src/services/cortex-seeder.js +86 -0
- package/dist/src/services/cortex-seeder.js.map +1 -0
- package/dist/src/services/cross-node-matching.d.ts +23 -0
- package/dist/src/services/cross-node-matching.d.ts.map +1 -0
- package/dist/src/services/cross-node-matching.js +62 -0
- package/dist/src/services/cross-node-matching.js.map +1 -0
- package/dist/src/services/csm-parser.d.ts +57 -0
- package/dist/src/services/csm-parser.d.ts.map +1 -0
- package/dist/src/services/csm-parser.js +161 -0
- package/dist/src/services/csm-parser.js.map +1 -0
- package/dist/src/services/csm-seed.d.ts +15 -0
- package/dist/src/services/csm-seed.d.ts.map +1 -0
- package/dist/src/services/csm-seed.js +89 -0
- package/dist/src/services/csm-seed.js.map +1 -0
- package/dist/src/services/directory.d.ts +86 -0
- package/dist/src/services/directory.d.ts.map +1 -0
- package/dist/src/services/directory.js +307 -0
- package/dist/src/services/directory.js.map +1 -0
- package/dist/src/services/email-templates.d.ts +29 -0
- package/dist/src/services/email-templates.d.ts.map +1 -0
- package/dist/src/services/email-templates.js +204 -0
- package/dist/src/services/email-templates.js.map +1 -0
- package/dist/src/services/email.d.ts +18 -0
- package/dist/src/services/email.d.ts.map +1 -0
- package/dist/src/services/email.js +102 -0
- package/dist/src/services/email.js.map +1 -0
- package/dist/src/services/encryption.d.ts +31 -0
- package/dist/src/services/encryption.d.ts.map +1 -0
- package/dist/src/services/encryption.js +51 -0
- package/dist/src/services/encryption.js.map +1 -0
- package/dist/src/services/eudiw.d.ts +15 -0
- package/dist/src/services/eudiw.d.ts.map +1 -0
- package/dist/src/services/eudiw.js +89 -0
- package/dist/src/services/eudiw.js.map +1 -0
- package/dist/src/services/event-bus.d.ts +8 -0
- package/dist/src/services/event-bus.d.ts.map +1 -0
- package/dist/src/services/event-bus.js +13 -0
- package/dist/src/services/event-bus.js.map +1 -0
- package/dist/src/services/extension-runtime.d.ts +72 -0
- package/dist/src/services/extension-runtime.d.ts.map +1 -0
- package/dist/src/services/extension-runtime.js +282 -0
- package/dist/src/services/extension-runtime.js.map +1 -0
- package/dist/src/services/federation-helpers.d.ts +37 -0
- package/dist/src/services/federation-helpers.d.ts.map +1 -0
- package/dist/src/services/federation-helpers.js +100 -0
- package/dist/src/services/federation-helpers.js.map +1 -0
- package/dist/src/services/federation.d.ts +32 -0
- package/dist/src/services/federation.d.ts.map +1 -0
- package/dist/src/services/federation.js +201 -0
- package/dist/src/services/federation.js.map +1 -0
- package/dist/src/services/foundry-debug.d.ts +77 -0
- package/dist/src/services/foundry-debug.d.ts.map +1 -0
- package/dist/src/services/foundry-debug.js +214 -0
- package/dist/src/services/foundry-debug.js.map +1 -0
- package/dist/src/services/foundry-registration.d.ts +42 -0
- package/dist/src/services/foundry-registration.d.ts.map +1 -0
- package/dist/src/services/foundry-registration.js +330 -0
- package/dist/src/services/foundry-registration.js.map +1 -0
- package/dist/src/services/foundry-testing.d.ts +90 -0
- package/dist/src/services/foundry-testing.d.ts.map +1 -0
- package/dist/src/services/foundry-testing.js +253 -0
- package/dist/src/services/foundry-testing.js.map +1 -0
- package/dist/src/services/foundry-validate.d.ts +115 -0
- package/dist/src/services/foundry-validate.d.ts.map +1 -0
- package/dist/src/services/foundry-validate.js +781 -0
- package/dist/src/services/foundry-validate.js.map +1 -0
- package/dist/src/services/generator-autopilot.d.ts +37 -0
- package/dist/src/services/generator-autopilot.d.ts.map +1 -0
- package/dist/src/services/generator-autopilot.js +1076 -0
- package/dist/src/services/generator-autopilot.js.map +1 -0
- package/dist/src/services/generator-debug.d.ts +79 -0
- package/dist/src/services/generator-debug.d.ts.map +1 -0
- package/dist/src/services/generator-debug.js +218 -0
- package/dist/src/services/generator-debug.js.map +1 -0
- package/dist/src/services/generator-prompt-seeds.d.ts +13 -0
- package/dist/src/services/generator-prompt-seeds.d.ts.map +1 -0
- package/dist/src/services/generator-prompt-seeds.js +2694 -0
- package/dist/src/services/generator-prompt-seeds.js.map +1 -0
- package/dist/src/services/generator-prompts/bundle.d.ts +17 -0
- package/dist/src/services/generator-prompts/bundle.d.ts.map +1 -0
- package/dist/src/services/generator-prompts/bundle.js +95 -0
- package/dist/src/services/generator-prompts/bundle.js.map +1 -0
- package/dist/src/services/generator-prompts/index.d.ts +48 -0
- package/dist/src/services/generator-prompts/index.d.ts.map +1 -0
- package/dist/src/services/generator-prompts/index.js +97 -0
- package/dist/src/services/generator-prompts/index.js.map +1 -0
- package/dist/src/services/generator-prompts/resolvers.d.ts +21 -0
- package/dist/src/services/generator-prompts/resolvers.d.ts.map +1 -0
- package/dist/src/services/generator-prompts/resolvers.js +1553 -0
- package/dist/src/services/generator-prompts/resolvers.js.map +1 -0
- package/dist/src/services/generator-prompts/spec-validate.d.ts +29 -0
- package/dist/src/services/generator-prompts/spec-validate.d.ts.map +1 -0
- package/dist/src/services/generator-prompts/spec-validate.js +190 -0
- package/dist/src/services/generator-prompts/spec-validate.js.map +1 -0
- package/dist/src/services/generator-prompts/strip.d.ts +13 -0
- package/dist/src/services/generator-prompts/strip.d.ts.map +1 -0
- package/dist/src/services/generator-prompts/strip.js +60 -0
- package/dist/src/services/generator-prompts/strip.js.map +1 -0
- package/dist/src/services/generator-prompts/types.d.ts +229 -0
- package/dist/src/services/generator-prompts/types.d.ts.map +1 -0
- package/dist/src/services/generator-prompts/types.js +8 -0
- package/dist/src/services/generator-prompts/types.js.map +1 -0
- package/dist/src/services/generator-prompts/validate.d.ts +48 -0
- package/dist/src/services/generator-prompts/validate.d.ts.map +1 -0
- package/dist/src/services/generator-prompts/validate.js +927 -0
- package/dist/src/services/generator-prompts/validate.js.map +1 -0
- package/dist/src/services/generator-registration.d.ts +43 -0
- package/dist/src/services/generator-registration.d.ts.map +1 -0
- package/dist/src/services/generator-registration.js +343 -0
- package/dist/src/services/generator-registration.js.map +1 -0
- package/dist/src/services/generator-testing.d.ts +93 -0
- package/dist/src/services/generator-testing.d.ts.map +1 -0
- package/dist/src/services/generator-testing.js +300 -0
- package/dist/src/services/generator-testing.js.map +1 -0
- package/dist/src/services/generator-validate.d.ts +117 -0
- package/dist/src/services/generator-validate.d.ts.map +1 -0
- package/dist/src/services/generator-validate.js +790 -0
- package/dist/src/services/generator-validate.js.map +1 -0
- package/dist/src/services/genesis-peering.d.ts +12 -0
- package/dist/src/services/genesis-peering.d.ts.map +1 -0
- package/dist/src/services/genesis-peering.js +91 -0
- package/dist/src/services/genesis-peering.js.map +1 -0
- package/dist/src/services/genesis-sync.d.ts +29 -0
- package/dist/src/services/genesis-sync.d.ts.map +1 -0
- package/dist/src/services/genesis-sync.js +370 -0
- package/dist/src/services/genesis-sync.js.map +1 -0
- package/dist/src/services/hooks.d.ts +21 -0
- package/dist/src/services/hooks.d.ts.map +1 -0
- package/dist/src/services/hooks.js +85 -0
- package/dist/src/services/hooks.js.map +1 -0
- package/dist/src/services/job-seeding.d.ts +7 -0
- package/dist/src/services/job-seeding.d.ts.map +1 -0
- package/dist/src/services/job-seeding.js +39 -0
- package/dist/src/services/job-seeding.js.map +1 -0
- package/dist/src/services/knowledge.d.ts +13 -0
- package/dist/src/services/knowledge.d.ts.map +1 -0
- package/dist/src/services/knowledge.js +15 -0
- package/dist/src/services/knowledge.js.map +1 -0
- package/dist/src/services/mailbox-notification.d.ts +37 -0
- package/dist/src/services/mailbox-notification.d.ts.map +1 -0
- package/dist/src/services/mailbox-notification.js +249 -0
- package/dist/src/services/mailbox-notification.js.map +1 -0
- package/dist/src/services/mailbox.d.ts +16 -0
- package/dist/src/services/mailbox.d.ts.map +1 -0
- package/dist/src/services/mailbox.js +77 -0
- package/dist/src/services/mailbox.js.map +1 -0
- package/dist/src/services/match-notification.d.ts +12 -0
- package/dist/src/services/match-notification.d.ts.map +1 -0
- package/dist/src/services/match-notification.js +121 -0
- package/dist/src/services/match-notification.js.map +1 -0
- package/dist/src/services/matching.d.ts +54 -0
- package/dist/src/services/matching.d.ts.map +1 -0
- package/dist/src/services/matching.js +293 -0
- package/dist/src/services/matching.js.map +1 -0
- package/dist/src/services/memory-replication.d.ts +43 -0
- package/dist/src/services/memory-replication.d.ts.map +1 -0
- package/dist/src/services/memory-replication.js +213 -0
- package/dist/src/services/memory-replication.js.map +1 -0
- package/dist/src/services/morsel.d.ts +49 -0
- package/dist/src/services/morsel.d.ts.map +1 -0
- package/dist/src/services/morsel.js +174 -0
- package/dist/src/services/morsel.js.map +1 -0
- package/dist/src/services/msm-parser.d.ts +55 -0
- package/dist/src/services/msm-parser.d.ts.map +1 -0
- package/dist/src/services/msm-parser.js +186 -0
- package/dist/src/services/msm-parser.js.map +1 -0
- package/dist/src/services/mydata-receipt.d.ts +29 -0
- package/dist/src/services/mydata-receipt.d.ts.map +1 -0
- package/dist/src/services/mydata-receipt.js +31 -0
- package/dist/src/services/mydata-receipt.js.map +1 -0
- package/dist/src/services/notification-templates.d.ts +40 -0
- package/dist/src/services/notification-templates.d.ts.map +1 -0
- package/dist/src/services/notification-templates.js +109 -0
- package/dist/src/services/notification-templates.js.map +1 -0
- package/dist/src/services/openrouter.d.ts +30 -0
- package/dist/src/services/openrouter.d.ts.map +1 -0
- package/dist/src/services/openrouter.js +95 -0
- package/dist/src/services/openrouter.js.map +1 -0
- package/dist/src/services/organism-reputation.d.ts +7 -0
- package/dist/src/services/organism-reputation.d.ts.map +1 -0
- package/dist/src/services/organism-reputation.js +107 -0
- package/dist/src/services/organism-reputation.js.map +1 -0
- package/dist/src/services/package-hash.d.ts +19 -0
- package/dist/src/services/package-hash.d.ts.map +1 -0
- package/dist/src/services/package-hash.js +22 -0
- package/dist/src/services/package-hash.js.map +1 -0
- package/dist/src/services/package-zip.d.ts +60 -0
- package/dist/src/services/package-zip.d.ts.map +1 -0
- package/dist/src/services/package-zip.js +267 -0
- package/dist/src/services/package-zip.js.map +1 -0
- package/dist/src/services/password.d.ts +9 -0
- package/dist/src/services/password.d.ts.map +1 -0
- package/dist/src/services/password.js +32 -0
- package/dist/src/services/password.js.map +1 -0
- package/dist/src/services/personal-routing.d.ts +21 -0
- package/dist/src/services/personal-routing.d.ts.map +1 -0
- package/dist/src/services/personal-routing.js +77 -0
- package/dist/src/services/personal-routing.js.map +1 -0
- package/dist/src/services/personal-tunnel.d.ts +39 -0
- package/dist/src/services/personal-tunnel.d.ts.map +1 -0
- package/dist/src/services/personal-tunnel.js +371 -0
- package/dist/src/services/personal-tunnel.js.map +1 -0
- package/dist/src/services/profile-schemas.d.ts +12 -0
- package/dist/src/services/profile-schemas.d.ts.map +1 -0
- package/dist/src/services/profile-schemas.js +100 -0
- package/dist/src/services/profile-schemas.js.map +1 -0
- package/dist/src/services/prometheus.d.ts +32 -0
- package/dist/src/services/prometheus.d.ts.map +1 -0
- package/dist/src/services/prometheus.js +162 -0
- package/dist/src/services/prometheus.js.map +1 -0
- package/dist/src/services/prompt-defaults.d.ts +33 -0
- package/dist/src/services/prompt-defaults.d.ts.map +1 -0
- package/dist/src/services/prompt-defaults.js +1675 -0
- package/dist/src/services/prompt-defaults.js.map +1 -0
- package/dist/src/services/prompt-seeder.d.ts +8 -0
- package/dist/src/services/prompt-seeder.d.ts.map +1 -0
- package/dist/src/services/prompt-seeder.js +65 -0
- package/dist/src/services/prompt-seeder.js.map +1 -0
- package/dist/src/services/prompt-variables.d.ts +15 -0
- package/dist/src/services/prompt-variables.d.ts.map +1 -0
- package/dist/src/services/prompt-variables.js +34 -0
- package/dist/src/services/prompt-variables.js.map +1 -0
- package/dist/src/services/push.d.ts +26 -0
- package/dist/src/services/push.d.ts.map +1 -0
- package/dist/src/services/push.js +70 -0
- package/dist/src/services/push.js.map +1 -0
- package/dist/src/services/quota.d.ts +45 -0
- package/dist/src/services/quota.d.ts.map +1 -0
- package/dist/src/services/quota.js +129 -0
- package/dist/src/services/quota.js.map +1 -0
- package/dist/src/services/realtime-manager.d.ts +144 -0
- package/dist/src/services/realtime-manager.d.ts.map +1 -0
- package/dist/src/services/realtime-manager.js +640 -0
- package/dist/src/services/realtime-manager.js.map +1 -0
- package/dist/src/services/scheduler.d.ts +55 -0
- package/dist/src/services/scheduler.d.ts.map +1 -0
- package/dist/src/services/scheduler.js +420 -0
- package/dist/src/services/scheduler.js.map +1 -0
- package/dist/src/services/schema-validator.d.ts +20 -0
- package/dist/src/services/schema-validator.d.ts.map +1 -0
- package/dist/src/services/schema-validator.js +68 -0
- package/dist/src/services/schema-validator.js.map +1 -0
- package/dist/src/services/site-sync.d.ts +15 -0
- package/dist/src/services/site-sync.d.ts.map +1 -0
- package/dist/src/services/site-sync.js +99 -0
- package/dist/src/services/site-sync.js.map +1 -0
- package/dist/src/services/site.d.ts +65 -0
- package/dist/src/services/site.d.ts.map +1 -0
- package/dist/src/services/site.js +378 -0
- package/dist/src/services/site.js.map +1 -0
- package/dist/src/services/stats.d.ts +75 -0
- package/dist/src/services/stats.d.ts.map +1 -0
- package/dist/src/services/stats.js +124 -0
- package/dist/src/services/stats.js.map +1 -0
- package/dist/src/services/sync-health.d.ts +53 -0
- package/dist/src/services/sync-health.d.ts.map +1 -0
- package/dist/src/services/sync-health.js +122 -0
- package/dist/src/services/sync-health.js.map +1 -0
- package/dist/src/services/sync-scheduler.d.ts +25 -0
- package/dist/src/services/sync-scheduler.d.ts.map +1 -0
- package/dist/src/services/sync-scheduler.js +211 -0
- package/dist/src/services/sync-scheduler.js.map +1 -0
- package/dist/src/services/totp.d.ts +31 -0
- package/dist/src/services/totp.d.ts.map +1 -0
- package/dist/src/services/totp.js +96 -0
- package/dist/src/services/totp.js.map +1 -0
- package/dist/src/services/trust-broadcast.d.ts +37 -0
- package/dist/src/services/trust-broadcast.d.ts.map +1 -0
- package/dist/src/services/trust-broadcast.js +107 -0
- package/dist/src/services/trust-broadcast.js.map +1 -0
- package/dist/src/services/trust.d.ts +16 -0
- package/dist/src/services/trust.d.ts.map +1 -0
- package/dist/src/services/trust.js +109 -0
- package/dist/src/services/trust.js.map +1 -0
- package/dist/src/services/vc-issuer.d.ts +14 -0
- package/dist/src/services/vc-issuer.d.ts.map +1 -0
- package/dist/src/services/vc-issuer.js +24 -0
- package/dist/src/services/vc-issuer.js.map +1 -0
- package/dist/src/storage/interface.d.ts +1161 -0
- package/dist/src/storage/interface.d.ts.map +1 -0
- package/dist/src/storage/interface.js +2 -0
- package/dist/src/storage/interface.js.map +1 -0
- package/dist/src/storage/pattern-utils.d.ts +20 -0
- package/dist/src/storage/pattern-utils.d.ts.map +1 -0
- package/dist/src/storage/pattern-utils.js +57 -0
- package/dist/src/storage/pattern-utils.js.map +1 -0
- package/dist/src/storage/providers/mongodb/index.d.ts +608 -0
- package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -0
- package/dist/src/storage/providers/mongodb/index.js +4931 -0
- package/dist/src/storage/providers/mongodb/index.js.map +1 -0
- package/dist/src/storage/providers/sqlite/index.d.ts +602 -0
- package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/index.js +4156 -0
- package/dist/src/storage/providers/sqlite/index.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/action.d.ts +13 -0
- package/dist/src/storage/providers/sqlite/repos/action.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/action.js +79 -0
- package/dist/src/storage/providers/sqlite/repos/action.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/agent.d.ts +13 -0
- package/dist/src/storage/providers/sqlite/repos/agent.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/agent.js +103 -0
- package/dist/src/storage/providers/sqlite/repos/agent.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/auth.d.ts +56 -0
- package/dist/src/storage/providers/sqlite/repos/auth.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/auth.js +282 -0
- package/dist/src/storage/providers/sqlite/repos/auth.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/board.d.ts +24 -0
- package/dist/src/storage/providers/sqlite/repos/board.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/board.js +154 -0
- package/dist/src/storage/providers/sqlite/repos/board.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/community.d.ts +33 -0
- package/dist/src/storage/providers/sqlite/repos/community.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/community.js +202 -0
- package/dist/src/storage/providers/sqlite/repos/community.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/consent.d.ts +23 -0
- package/dist/src/storage/providers/sqlite/repos/consent.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/consent.js +187 -0
- package/dist/src/storage/providers/sqlite/repos/consent.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/dispute.d.ts +20 -0
- package/dist/src/storage/providers/sqlite/repos/dispute.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/dispute.js +118 -0
- package/dist/src/storage/providers/sqlite/repos/dispute.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/flag.d.ts +26 -0
- package/dist/src/storage/providers/sqlite/repos/flag.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/flag.js +147 -0
- package/dist/src/storage/providers/sqlite/repos/flag.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/identity.d.ts +36 -0
- package/dist/src/storage/providers/sqlite/repos/identity.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/identity.js +297 -0
- package/dist/src/storage/providers/sqlite/repos/identity.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/mailbox.d.ts +18 -0
- package/dist/src/storage/providers/sqlite/repos/mailbox.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/mailbox.js +91 -0
- package/dist/src/storage/providers/sqlite/repos/mailbox.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/memory.d.ts +28 -0
- package/dist/src/storage/providers/sqlite/repos/memory.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/memory.js +152 -0
- package/dist/src/storage/providers/sqlite/repos/memory.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/owner.d.ts +14 -0
- package/dist/src/storage/providers/sqlite/repos/owner.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/owner.js +124 -0
- package/dist/src/storage/providers/sqlite/repos/owner.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/service-manifest.d.ts +17 -0
- package/dist/src/storage/providers/sqlite/repos/service-manifest.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/service-manifest.js +114 -0
- package/dist/src/storage/providers/sqlite/repos/service-manifest.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/storage-file.d.ts +19 -0
- package/dist/src/storage/providers/sqlite/repos/storage-file.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/storage-file.js +128 -0
- package/dist/src/storage/providers/sqlite/repos/storage-file.js.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/work.d.ts +13 -0
- package/dist/src/storage/providers/sqlite/repos/work.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/repos/work.js +86 -0
- package/dist/src/storage/providers/sqlite/repos/work.js.map +1 -0
- package/dist/src/storage/providers/sqlite/schema.d.ts +7 -0
- package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -0
- package/dist/src/storage/providers/sqlite/schema.js +1090 -0
- package/dist/src/storage/providers/sqlite/schema.js.map +1 -0
- package/dist/src/storage/repositories/action.repository.d.ts +14 -0
- package/dist/src/storage/repositories/action.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/action.repository.js +2 -0
- package/dist/src/storage/repositories/action.repository.js.map +1 -0
- package/dist/src/storage/repositories/agent.repository.d.ts +18 -0
- package/dist/src/storage/repositories/agent.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/agent.repository.js +2 -0
- package/dist/src/storage/repositories/agent.repository.js.map +1 -0
- package/dist/src/storage/repositories/app-marketplace.repository.d.ts +9 -0
- package/dist/src/storage/repositories/app-marketplace.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/app-marketplace.repository.js +2 -0
- package/dist/src/storage/repositories/app-marketplace.repository.js.map +1 -0
- package/dist/src/storage/repositories/app.repository.d.ts +17 -0
- package/dist/src/storage/repositories/app.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/app.repository.js +2 -0
- package/dist/src/storage/repositories/app.repository.js.map +1 -0
- package/dist/src/storage/repositories/auth.repository.d.ts +6 -0
- package/dist/src/storage/repositories/auth.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/auth.repository.js +2 -0
- package/dist/src/storage/repositories/auth.repository.js.map +1 -0
- package/dist/src/storage/repositories/board.repository.d.ts +27 -0
- package/dist/src/storage/repositories/board.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/board.repository.js +2 -0
- package/dist/src/storage/repositories/board.repository.js.map +1 -0
- package/dist/src/storage/repositories/catalogue.repository.d.ts +18 -0
- package/dist/src/storage/repositories/catalogue.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/catalogue.repository.js +2 -0
- package/dist/src/storage/repositories/catalogue.repository.js.map +1 -0
- package/dist/src/storage/repositories/config.repository.d.ts +17 -0
- package/dist/src/storage/repositories/config.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/config.repository.js +2 -0
- package/dist/src/storage/repositories/config.repository.js.map +1 -0
- package/dist/src/storage/repositories/consent.repository.d.ts +19 -0
- package/dist/src/storage/repositories/consent.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/consent.repository.js +2 -0
- package/dist/src/storage/repositories/consent.repository.js.map +1 -0
- package/dist/src/storage/repositories/device-auth.repository.d.ts +11 -0
- package/dist/src/storage/repositories/device-auth.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/device-auth.repository.js +2 -0
- package/dist/src/storage/repositories/device-auth.repository.js.map +1 -0
- package/dist/src/storage/repositories/dispute.repository.d.ts +12 -0
- package/dist/src/storage/repositories/dispute.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/dispute.repository.js +2 -0
- package/dist/src/storage/repositories/dispute.repository.js.map +1 -0
- package/dist/src/storage/repositories/extension-instance.repository.d.ts +9 -0
- package/dist/src/storage/repositories/extension-instance.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/extension-instance.repository.js +2 -0
- package/dist/src/storage/repositories/extension-instance.repository.js.map +1 -0
- package/dist/src/storage/repositories/federation.repository.d.ts +37 -0
- package/dist/src/storage/repositories/federation.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/federation.repository.js +2 -0
- package/dist/src/storage/repositories/federation.repository.js.map +1 -0
- package/dist/src/storage/repositories/file.repository.d.ts +14 -0
- package/dist/src/storage/repositories/file.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/file.repository.js +2 -0
- package/dist/src/storage/repositories/file.repository.js.map +1 -0
- package/dist/src/storage/repositories/identity.repository.d.ts +29 -0
- package/dist/src/storage/repositories/identity.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/identity.repository.js +2 -0
- package/dist/src/storage/repositories/identity.repository.js.map +1 -0
- package/dist/src/storage/repositories/index.d.ts +34 -0
- package/dist/src/storage/repositories/index.d.ts.map +1 -0
- package/dist/src/storage/repositories/index.js +2 -0
- package/dist/src/storage/repositories/index.js.map +1 -0
- package/dist/src/storage/repositories/knowledge.repository.d.ts +18 -0
- package/dist/src/storage/repositories/knowledge.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/knowledge.repository.js +2 -0
- package/dist/src/storage/repositories/knowledge.repository.js.map +1 -0
- package/dist/src/storage/repositories/marketplace.repository.d.ts +23 -0
- package/dist/src/storage/repositories/marketplace.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/marketplace.repository.js +2 -0
- package/dist/src/storage/repositories/marketplace.repository.js.map +1 -0
- package/dist/src/storage/repositories/memory.repository.d.ts +32 -0
- package/dist/src/storage/repositories/memory.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/memory.repository.js +2 -0
- package/dist/src/storage/repositories/memory.repository.js.map +1 -0
- package/dist/src/storage/repositories/micro-memory.repository.d.ts +10 -0
- package/dist/src/storage/repositories/micro-memory.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/micro-memory.repository.js +2 -0
- package/dist/src/storage/repositories/micro-memory.repository.js.map +1 -0
- package/dist/src/storage/repositories/moderation.repository.d.ts +36 -0
- package/dist/src/storage/repositories/moderation.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/moderation.repository.js +2 -0
- package/dist/src/storage/repositories/moderation.repository.js.map +1 -0
- package/dist/src/storage/repositories/node.repository.d.ts +59 -0
- package/dist/src/storage/repositories/node.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/node.repository.js +2 -0
- package/dist/src/storage/repositories/node.repository.js.map +1 -0
- package/dist/src/storage/repositories/notification-template.repository.d.ts +8 -0
- package/dist/src/storage/repositories/notification-template.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/notification-template.repository.js +2 -0
- package/dist/src/storage/repositories/notification-template.repository.js.map +1 -0
- package/dist/src/storage/repositories/notification.repository.d.ts +14 -0
- package/dist/src/storage/repositories/notification.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/notification.repository.js +2 -0
- package/dist/src/storage/repositories/notification.repository.js.map +1 -0
- package/dist/src/storage/repositories/oauth.repository.d.ts +19 -0
- package/dist/src/storage/repositories/oauth.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/oauth.repository.js +2 -0
- package/dist/src/storage/repositories/oauth.repository.js.map +1 -0
- package/dist/src/storage/repositories/organism.repository.d.ts +34 -0
- package/dist/src/storage/repositories/organism.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/organism.repository.js +2 -0
- package/dist/src/storage/repositories/organism.repository.js.map +1 -0
- package/dist/src/storage/repositories/otk.repository.d.ts +9 -0
- package/dist/src/storage/repositories/otk.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/otk.repository.js +2 -0
- package/dist/src/storage/repositories/otk.repository.js.map +1 -0
- package/dist/src/storage/repositories/owner.repository.d.ts +9 -0
- package/dist/src/storage/repositories/owner.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/owner.repository.js +2 -0
- package/dist/src/storage/repositories/owner.repository.js.map +1 -0
- package/dist/src/storage/repositories/package-instance.repository.d.ts +26 -0
- package/dist/src/storage/repositories/package-instance.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/package-instance.repository.js +12 -0
- package/dist/src/storage/repositories/package-instance.repository.js.map +1 -0
- package/dist/src/storage/repositories/package.repository.d.ts +28 -0
- package/dist/src/storage/repositories/package.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/package.repository.js +12 -0
- package/dist/src/storage/repositories/package.repository.js.map +1 -0
- package/dist/src/storage/repositories/replication-queue.repository.d.ts +10 -0
- package/dist/src/storage/repositories/replication-queue.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/replication-queue.repository.js +2 -0
- package/dist/src/storage/repositories/replication-queue.repository.js.map +1 -0
- package/dist/src/storage/repositories/scheduler.repository.d.ts +30 -0
- package/dist/src/storage/repositories/scheduler.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/scheduler.repository.js +2 -0
- package/dist/src/storage/repositories/scheduler.repository.js.map +1 -0
- package/dist/src/storage/repositories/schema.repository.d.ts +9 -0
- package/dist/src/storage/repositories/schema.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/schema.repository.js +2 -0
- package/dist/src/storage/repositories/schema.repository.js.map +1 -0
- package/dist/src/storage/repositories/session.repository.d.ts +22 -0
- package/dist/src/storage/repositories/session.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/session.repository.js +2 -0
- package/dist/src/storage/repositories/session.repository.js.map +1 -0
- package/dist/src/storage/repositories/system-prompt.repository.d.ts +14 -0
- package/dist/src/storage/repositories/system-prompt.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/system-prompt.repository.js +2 -0
- package/dist/src/storage/repositories/system-prompt.repository.js.map +1 -0
- package/dist/src/storage/repositories/template-listing.repository.d.ts +44 -0
- package/dist/src/storage/repositories/template-listing.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/template-listing.repository.js +13 -0
- package/dist/src/storage/repositories/template-listing.repository.js.map +1 -0
- package/dist/src/storage/repositories/wallet.repository.d.ts +8 -0
- package/dist/src/storage/repositories/wallet.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/wallet.repository.js +2 -0
- package/dist/src/storage/repositories/wallet.repository.js.map +1 -0
- package/dist/src/storage/repositories/work.repository.d.ts +10 -0
- package/dist/src/storage/repositories/work.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/work.repository.js +2 -0
- package/dist/src/storage/repositories/work.repository.js.map +1 -0
- package/dist/src/storage/storage-factory.d.ts +9 -0
- package/dist/src/storage/storage-factory.d.ts.map +1 -0
- package/dist/src/storage/storage-factory.js +20 -0
- package/dist/src/storage/storage-factory.js.map +1 -0
- package/dist/src/types/route-manifest.d.ts +53 -0
- package/dist/src/types/route-manifest.d.ts.map +1 -0
- package/dist/src/types/route-manifest.js +44 -0
- package/dist/src/types/route-manifest.js.map +1 -0
- package/dist/src/utils/catalogue-hash.d.ts +10 -0
- package/dist/src/utils/catalogue-hash.d.ts.map +1 -0
- package/dist/src/utils/catalogue-hash.js +23 -0
- package/dist/src/utils/catalogue-hash.js.map +1 -0
- package/dist/src/utils/env-config.d.ts +8 -0
- package/dist/src/utils/env-config.d.ts.map +1 -0
- package/dist/src/utils/env-config.js +1264 -0
- package/dist/src/utils/env-config.js.map +1 -0
- package/dist/src/utils/env-validator.d.ts +14 -0
- package/dist/src/utils/env-validator.d.ts.map +1 -0
- package/dist/src/utils/env-validator.js +338 -0
- package/dist/src/utils/env-validator.js.map +1 -0
- package/dist/src/utils/fire-hook.d.ts +9 -0
- package/dist/src/utils/fire-hook.d.ts.map +1 -0
- package/dist/src/utils/fire-hook.js +12 -0
- package/dist/src/utils/fire-hook.js.map +1 -0
- package/dist/src/utils/gaii.d.ts +57 -0
- package/dist/src/utils/gaii.d.ts.map +1 -0
- package/dist/src/utils/gaii.js +148 -0
- package/dist/src/utils/gaii.js.map +1 -0
- package/dist/src/utils/ghii-resolver.d.ts +14 -0
- package/dist/src/utils/ghii-resolver.d.ts.map +1 -0
- package/dist/src/utils/ghii-resolver.js +21 -0
- package/dist/src/utils/ghii-resolver.js.map +1 -0
- package/dist/src/utils/logger.d.ts +9 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/logger.js +36 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/src/utils/otk.d.ts +2 -0
- package/dist/src/utils/otk.d.ts.map +1 -0
- package/dist/src/utils/otk.js +5 -0
- package/dist/src/utils/otk.js.map +1 -0
- package/dist/src/utils/tracking-code.d.ts +9 -0
- package/dist/src/utils/tracking-code.d.ts.map +1 -0
- package/dist/src/utils/tracking-code.js +16 -0
- package/dist/src/utils/tracking-code.js.map +1 -0
- package/dist/src/utils/url-validator.d.ts +5 -0
- package/dist/src/utils/url-validator.d.ts.map +1 -0
- package/dist/src/utils/url-validator.js +56 -0
- package/dist/src/utils/url-validator.js.map +1 -0
- package/dist/static/app-catalog.html +4401 -0
- package/dist/static/cookieconsent.css +1 -0
- package/dist/static/cookieconsent.umd.js +7 -0
- package/dist/static/icons/icon-maskable.svg +27 -0
- package/dist/static/icons/icon.svg +27 -0
- package/dist/static/manifest.json +17 -0
- package/dist/static/offline.html +167 -0
- package/dist/static/sw.js +260 -0
- package/package.json +182 -0
- package/prisma/schema.prisma +1086 -0
|
@@ -0,0 +1,4401 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8"/>
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
6
|
+
<meta name="theme-color" content="#FAFAF8"/>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com"/>
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&display=swap" rel="stylesheet"/>
|
|
10
|
+
<title>My Apps — AIMEAT</title>
|
|
11
|
+
<style>
|
|
12
|
+
:root {
|
|
13
|
+
--bg: #FAFAF8;
|
|
14
|
+
--surface: #FFFFFF;
|
|
15
|
+
--text: #1A1A2E;
|
|
16
|
+
--accent: #E8564A;
|
|
17
|
+
--accent2: #F3E8E6;
|
|
18
|
+
--surface-glass: rgba(255, 255, 255, .85);
|
|
19
|
+
--border-subtle: #E5E7EB;
|
|
20
|
+
--border-hover: #D1D5DB;
|
|
21
|
+
--text-muted: #6B7280;
|
|
22
|
+
--text-dim: #9CA3AF;
|
|
23
|
+
--radius: 16px;
|
|
24
|
+
--radius-sm: 10px;
|
|
25
|
+
--transition: .25s cubic-bezier(.16, 1, .3, 1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
29
|
+
|
|
30
|
+
body {
|
|
31
|
+
background: var(--bg);
|
|
32
|
+
color: var(--text);
|
|
33
|
+
font-family: 'DM Sans', system-ui, sans-serif;
|
|
34
|
+
min-height: 100vh;
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
overflow-x: hidden;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
body::before {
|
|
41
|
+
content: '';
|
|
42
|
+
position: fixed;
|
|
43
|
+
inset: 0;
|
|
44
|
+
background:
|
|
45
|
+
radial-gradient(ellipse at 20% 10%, rgba(232, 86, 74, .04) 0%, transparent 50%),
|
|
46
|
+
radial-gradient(ellipse at 80% 90%, rgba(232, 86, 74, .03) 0%, transparent 50%),
|
|
47
|
+
radial-gradient(ellipse at 50% 50%, rgba(243, 232, 230, .15) 0%, transparent 60%);
|
|
48
|
+
z-index: 0;
|
|
49
|
+
pointer-events: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* ── Header ─────────────────────────────────────── */
|
|
53
|
+
|
|
54
|
+
header {
|
|
55
|
+
position: sticky;
|
|
56
|
+
top: 0;
|
|
57
|
+
z-index: 100;
|
|
58
|
+
background: rgba(255, 255, 255, .92);
|
|
59
|
+
backdrop-filter: blur(24px);
|
|
60
|
+
-webkit-backdrop-filter: blur(24px);
|
|
61
|
+
border-bottom: 1px solid #E5E7EB;
|
|
62
|
+
padding: 16px 24px;
|
|
63
|
+
display: flex;
|
|
64
|
+
align-items: center;
|
|
65
|
+
gap: 16px;
|
|
66
|
+
flex-wrap: wrap;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
header h1 {
|
|
70
|
+
font-size: 1.3rem;
|
|
71
|
+
font-weight: 700;
|
|
72
|
+
color: #1A1A2E;
|
|
73
|
+
white-space: nowrap;
|
|
74
|
+
flex-shrink: 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#search-input {
|
|
78
|
+
flex: 1;
|
|
79
|
+
min-width: 160px;
|
|
80
|
+
background: var(--surface-glass);
|
|
81
|
+
border: 1px solid var(--border-subtle);
|
|
82
|
+
border-radius: var(--radius-sm);
|
|
83
|
+
padding: 10px 16px;
|
|
84
|
+
color: var(--text);
|
|
85
|
+
font-size: .9rem;
|
|
86
|
+
outline: none;
|
|
87
|
+
transition: border-color var(--transition), box-shadow var(--transition);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#search-input::placeholder {
|
|
91
|
+
color: var(--text-dim);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#search-input:focus {
|
|
95
|
+
border-color: var(--accent);
|
|
96
|
+
box-shadow: 0 0 0 3px rgba(232, 86, 74, .12);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.header-actions {
|
|
100
|
+
display: flex;
|
|
101
|
+
gap: 8px;
|
|
102
|
+
flex-shrink: 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.icon-btn {
|
|
106
|
+
width: 40px;
|
|
107
|
+
height: 40px;
|
|
108
|
+
display: inline-flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
justify-content: center;
|
|
111
|
+
background: var(--surface-glass);
|
|
112
|
+
border: 1px solid var(--border-subtle);
|
|
113
|
+
border-radius: var(--radius-sm);
|
|
114
|
+
color: var(--text);
|
|
115
|
+
font-size: 1.2rem;
|
|
116
|
+
cursor: pointer;
|
|
117
|
+
transition: border-color var(--transition), transform var(--transition),
|
|
118
|
+
box-shadow var(--transition), background var(--transition);
|
|
119
|
+
user-select: none;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.icon-btn:hover {
|
|
123
|
+
border-color: var(--border-hover);
|
|
124
|
+
transform: translateY(-1px);
|
|
125
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, .06);
|
|
126
|
+
background: #F3F4F6;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.icon-btn:active {
|
|
130
|
+
transform: translateY(0);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
#add-btn {
|
|
134
|
+
background: #E8564A;
|
|
135
|
+
border-color: transparent;
|
|
136
|
+
color: #fff;
|
|
137
|
+
font-weight: 700;
|
|
138
|
+
font-size: 1.4rem;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
#add-btn:hover {
|
|
142
|
+
box-shadow: 0 4px 20px rgba(232, 86, 74, .25);
|
|
143
|
+
border-color: transparent;
|
|
144
|
+
background: #D64A3F;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* ── Tag Bar ────────────────────────────────────── */
|
|
148
|
+
|
|
149
|
+
#tag-bar {
|
|
150
|
+
position: relative;
|
|
151
|
+
z-index: 1;
|
|
152
|
+
padding: 12px 24px;
|
|
153
|
+
display: flex;
|
|
154
|
+
gap: 8px;
|
|
155
|
+
overflow-x: auto;
|
|
156
|
+
scrollbar-width: none;
|
|
157
|
+
-ms-overflow-style: none;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
#tag-bar::-webkit-scrollbar {
|
|
161
|
+
display: none;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.tag {
|
|
165
|
+
display: inline-flex;
|
|
166
|
+
align-items: center;
|
|
167
|
+
padding: 6px 14px;
|
|
168
|
+
background: var(--surface-glass);
|
|
169
|
+
border: 1px solid var(--border-subtle);
|
|
170
|
+
border-radius: 20px;
|
|
171
|
+
color: var(--text-muted);
|
|
172
|
+
font-size: .8rem;
|
|
173
|
+
font-weight: 500;
|
|
174
|
+
cursor: pointer;
|
|
175
|
+
white-space: nowrap;
|
|
176
|
+
transition: all var(--transition);
|
|
177
|
+
user-select: none;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.tag:hover {
|
|
181
|
+
border-color: var(--border-hover);
|
|
182
|
+
color: var(--text);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.tag.active {
|
|
186
|
+
background: #E8564A;
|
|
187
|
+
border-color: transparent;
|
|
188
|
+
color: #fff;
|
|
189
|
+
font-weight: 600;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* ── App Grid ───────────────────────────────────── */
|
|
193
|
+
|
|
194
|
+
#app-grid {
|
|
195
|
+
position: relative;
|
|
196
|
+
z-index: 1;
|
|
197
|
+
flex: 1;
|
|
198
|
+
padding: 8px 24px 24px;
|
|
199
|
+
display: grid;
|
|
200
|
+
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
|
201
|
+
gap: 16px;
|
|
202
|
+
align-content: start;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.app-card {
|
|
206
|
+
background: #FFFFFF;
|
|
207
|
+
border: 1px solid #E5E7EB;
|
|
208
|
+
border-radius: var(--radius);
|
|
209
|
+
padding: 20px 16px;
|
|
210
|
+
display: flex;
|
|
211
|
+
flex-direction: column;
|
|
212
|
+
align-items: center;
|
|
213
|
+
gap: 10px;
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
transition: border-color var(--transition), transform var(--transition),
|
|
216
|
+
box-shadow var(--transition);
|
|
217
|
+
position: relative;
|
|
218
|
+
text-align: center;
|
|
219
|
+
animation: cardIn .5s cubic-bezier(.16, 1, .3, 1) both;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@keyframes cardIn {
|
|
223
|
+
from { opacity: 0; transform: translateY(12px) scale(.96); }
|
|
224
|
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.app-card:hover {
|
|
228
|
+
border-color: var(--border-hover);
|
|
229
|
+
transform: translateY(-3px);
|
|
230
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, .08);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.app-card:active {
|
|
234
|
+
transform: translateY(-1px);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.app-card.dragging {
|
|
238
|
+
opacity: .35;
|
|
239
|
+
transform: scale(.95);
|
|
240
|
+
box-shadow: none;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.app-card.drag-over {
|
|
244
|
+
border-color: var(--accent);
|
|
245
|
+
box-shadow: 0 0 0 2px var(--accent);
|
|
246
|
+
transform: translateY(-2px);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.app-card .app-icon {
|
|
250
|
+
width: 56px;
|
|
251
|
+
height: 56px;
|
|
252
|
+
border-radius: 14px;
|
|
253
|
+
display: flex;
|
|
254
|
+
align-items: center;
|
|
255
|
+
justify-content: center;
|
|
256
|
+
font-size: 1.8rem;
|
|
257
|
+
background: #F3E8E6;
|
|
258
|
+
border: 1px solid #E5E7EB;
|
|
259
|
+
flex-shrink: 0;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.app-card .app-name {
|
|
263
|
+
font-size: .85rem;
|
|
264
|
+
font-weight: 600;
|
|
265
|
+
line-height: 1.3;
|
|
266
|
+
word-break: break-word;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.app-card .app-source {
|
|
270
|
+
font-size: .7rem;
|
|
271
|
+
color: var(--text-dim);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.app-card .app-actions {
|
|
275
|
+
display: flex;
|
|
276
|
+
gap: 6px;
|
|
277
|
+
margin-top: 4px;
|
|
278
|
+
opacity: 0;
|
|
279
|
+
transition: opacity var(--transition);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.app-card:hover .app-actions {
|
|
283
|
+
opacity: 1;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.app-card .app-actions button {
|
|
287
|
+
padding: 4px 10px;
|
|
288
|
+
border-radius: 6px;
|
|
289
|
+
border: 1px solid var(--border-subtle);
|
|
290
|
+
background: var(--surface-glass);
|
|
291
|
+
color: var(--text-muted);
|
|
292
|
+
font-size: .7rem;
|
|
293
|
+
font-weight: 500;
|
|
294
|
+
cursor: pointer;
|
|
295
|
+
transition: all var(--transition);
|
|
296
|
+
font-family: inherit;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.app-card .app-actions button:hover {
|
|
300
|
+
border-color: var(--accent);
|
|
301
|
+
color: var(--text);
|
|
302
|
+
background: rgba(232, 86, 74, .08);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.app-card .fav-star {
|
|
306
|
+
position: absolute;
|
|
307
|
+
top: 8px;
|
|
308
|
+
left: 10px;
|
|
309
|
+
font-size: .85rem;
|
|
310
|
+
opacity: 0;
|
|
311
|
+
transition: opacity var(--transition);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.app-card:hover .fav-star,
|
|
315
|
+
.app-card .fav-star.visible {
|
|
316
|
+
opacity: 1;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/* ── Card Menu Button ─────────────────────────────── */
|
|
320
|
+
|
|
321
|
+
.card-menu-btn {
|
|
322
|
+
position: absolute;
|
|
323
|
+
top: 0.4rem;
|
|
324
|
+
right: 0.4rem;
|
|
325
|
+
background: var(--surface-glass);
|
|
326
|
+
border: 1px solid var(--border-subtle);
|
|
327
|
+
color: var(--text);
|
|
328
|
+
width: 28px;
|
|
329
|
+
height: 28px;
|
|
330
|
+
border-radius: 6px;
|
|
331
|
+
cursor: pointer;
|
|
332
|
+
font-size: 1.1rem;
|
|
333
|
+
display: flex;
|
|
334
|
+
align-items: center;
|
|
335
|
+
justify-content: center;
|
|
336
|
+
opacity: 0;
|
|
337
|
+
transition: opacity 0.2s;
|
|
338
|
+
z-index: 2;
|
|
339
|
+
}
|
|
340
|
+
.app-card:hover .card-menu-btn,
|
|
341
|
+
.card-menu-btn:focus { opacity: 1; }
|
|
342
|
+
.card-menu-btn:hover { background: var(--accent); }
|
|
343
|
+
|
|
344
|
+
/* ── Empty State ────────────────────────────────── */
|
|
345
|
+
|
|
346
|
+
.empty-state {
|
|
347
|
+
grid-column: 1 / -1;
|
|
348
|
+
display: flex;
|
|
349
|
+
flex-direction: column;
|
|
350
|
+
align-items: center;
|
|
351
|
+
justify-content: center;
|
|
352
|
+
padding: 72px 24px;
|
|
353
|
+
text-align: center;
|
|
354
|
+
color: var(--text-dim);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.empty-state .empty-icon {
|
|
358
|
+
font-size: 4rem;
|
|
359
|
+
margin-bottom: 20px;
|
|
360
|
+
opacity: .6;
|
|
361
|
+
filter: drop-shadow(0 4px 12px rgba(232, 86, 74, .10));
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.empty-state h3 {
|
|
365
|
+
font-size: 1.15rem;
|
|
366
|
+
font-weight: 600;
|
|
367
|
+
color: var(--text-muted);
|
|
368
|
+
margin-bottom: 8px;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.empty-state p {
|
|
372
|
+
font-size: .9rem;
|
|
373
|
+
line-height: 1.6;
|
|
374
|
+
max-width: 340px;
|
|
375
|
+
margin-bottom: 6px;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.empty-state .empty-formats {
|
|
379
|
+
font-size: .78rem;
|
|
380
|
+
color: var(--text-dim);
|
|
381
|
+
opacity: .7;
|
|
382
|
+
margin-top: 4px;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/* ── Footer ─────────────────────────────────────── */
|
|
386
|
+
|
|
387
|
+
footer {
|
|
388
|
+
position: relative;
|
|
389
|
+
z-index: 1;
|
|
390
|
+
padding: 14px 24px;
|
|
391
|
+
border-top: 1px solid var(--border-subtle);
|
|
392
|
+
display: flex;
|
|
393
|
+
align-items: center;
|
|
394
|
+
justify-content: space-between;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
#stats {
|
|
398
|
+
font-size: .75rem;
|
|
399
|
+
color: var(--text-dim);
|
|
400
|
+
letter-spacing: .04em;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.footer-brand {
|
|
404
|
+
font-size: .7rem;
|
|
405
|
+
color: var(--text-dim);
|
|
406
|
+
letter-spacing: .1em;
|
|
407
|
+
text-transform: uppercase;
|
|
408
|
+
opacity: .6;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/* ── Modal Overlay ──────────────────────────────── */
|
|
412
|
+
|
|
413
|
+
#modal-overlay {
|
|
414
|
+
position: fixed;
|
|
415
|
+
inset: 0;
|
|
416
|
+
z-index: 500;
|
|
417
|
+
background: rgba(0, 0, 0, .3);
|
|
418
|
+
backdrop-filter: blur(6px);
|
|
419
|
+
-webkit-backdrop-filter: blur(6px);
|
|
420
|
+
display: flex;
|
|
421
|
+
align-items: center;
|
|
422
|
+
justify-content: center;
|
|
423
|
+
padding: 24px;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
#modal-overlay[hidden] {
|
|
427
|
+
display: none;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.modal {
|
|
431
|
+
background: #FFFFFF;
|
|
432
|
+
border: 1px solid #E5E7EB;
|
|
433
|
+
border-radius: var(--radius);
|
|
434
|
+
padding: 32px;
|
|
435
|
+
max-width: 480px;
|
|
436
|
+
width: 100%;
|
|
437
|
+
box-shadow: 0 8px 40px rgba(0, 0, 0, .12);
|
|
438
|
+
animation: cardIn .4s cubic-bezier(.16, 1, .3, 1);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.modal h2 {
|
|
442
|
+
font-size: 1.15rem;
|
|
443
|
+
margin-bottom: 20px;
|
|
444
|
+
color: #1A1A2E;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/* ── Modal Form Elements ──────────────────────────── */
|
|
448
|
+
|
|
449
|
+
.modal-tabs {
|
|
450
|
+
display: flex;
|
|
451
|
+
gap: 0;
|
|
452
|
+
margin-bottom: 20px;
|
|
453
|
+
border: 1px solid var(--border-subtle);
|
|
454
|
+
border-radius: var(--radius-sm);
|
|
455
|
+
overflow: hidden;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.modal-tab {
|
|
459
|
+
flex: 1;
|
|
460
|
+
padding: 10px 16px;
|
|
461
|
+
background: transparent;
|
|
462
|
+
border: none;
|
|
463
|
+
color: var(--text-muted);
|
|
464
|
+
font-size: .85rem;
|
|
465
|
+
font-weight: 500;
|
|
466
|
+
cursor: pointer;
|
|
467
|
+
transition: all var(--transition);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.modal-tab:not(:last-child) {
|
|
471
|
+
border-right: 1px solid var(--border-subtle);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.modal-tab:hover {
|
|
475
|
+
color: var(--text);
|
|
476
|
+
background: #F9FAFB;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.modal-tab.active {
|
|
480
|
+
background: #E8564A;
|
|
481
|
+
color: #fff;
|
|
482
|
+
font-weight: 600;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.tab-content {
|
|
486
|
+
display: none;
|
|
487
|
+
margin-bottom: 16px;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
.tab-content.active {
|
|
491
|
+
display: block;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
.modal-label {
|
|
495
|
+
display: block;
|
|
496
|
+
font-size: .78rem;
|
|
497
|
+
font-weight: 600;
|
|
498
|
+
color: var(--text-muted);
|
|
499
|
+
margin-bottom: 6px;
|
|
500
|
+
text-transform: uppercase;
|
|
501
|
+
letter-spacing: .04em;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
.label-hint {
|
|
505
|
+
font-weight: 400;
|
|
506
|
+
text-transform: none;
|
|
507
|
+
letter-spacing: 0;
|
|
508
|
+
color: var(--text-dim);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
.modal-input {
|
|
512
|
+
width: 100%;
|
|
513
|
+
background: var(--surface-glass);
|
|
514
|
+
border: 1px solid var(--border-subtle);
|
|
515
|
+
border-radius: var(--radius-sm);
|
|
516
|
+
padding: 10px 14px;
|
|
517
|
+
color: var(--text);
|
|
518
|
+
font-size: .88rem;
|
|
519
|
+
outline: none;
|
|
520
|
+
transition: border-color var(--transition), box-shadow var(--transition);
|
|
521
|
+
font-family: inherit;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.modal-input::placeholder {
|
|
525
|
+
color: var(--text-dim);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.modal-input:focus {
|
|
529
|
+
border-color: var(--accent);
|
|
530
|
+
box-shadow: 0 0 0 3px rgba(232, 86, 74, .12);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
select.modal-input {
|
|
534
|
+
appearance: none;
|
|
535
|
+
-webkit-appearance: none;
|
|
536
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%236B7280' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
|
|
537
|
+
background-repeat: no-repeat;
|
|
538
|
+
background-position: right 12px center;
|
|
539
|
+
padding-right: 32px;
|
|
540
|
+
cursor: pointer;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
select.modal-input option {
|
|
544
|
+
background: var(--surface);
|
|
545
|
+
color: var(--text);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
.modal-fields {
|
|
549
|
+
display: flex;
|
|
550
|
+
flex-direction: column;
|
|
551
|
+
gap: 14px;
|
|
552
|
+
margin-bottom: 24px;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.modal-row {
|
|
556
|
+
display: flex;
|
|
557
|
+
gap: 12px;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
.modal-field {
|
|
561
|
+
display: flex;
|
|
562
|
+
flex-direction: column;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.modal-actions {
|
|
566
|
+
display: flex;
|
|
567
|
+
gap: 10px;
|
|
568
|
+
justify-content: flex-end;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
.modal-btn {
|
|
572
|
+
padding: 10px 22px;
|
|
573
|
+
border-radius: var(--radius-sm);
|
|
574
|
+
border: 1px solid var(--border-subtle);
|
|
575
|
+
font-size: .85rem;
|
|
576
|
+
font-weight: 600;
|
|
577
|
+
cursor: pointer;
|
|
578
|
+
transition: all var(--transition);
|
|
579
|
+
font-family: inherit;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
.modal-btn.secondary {
|
|
583
|
+
background: transparent;
|
|
584
|
+
color: var(--text-muted);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
.modal-btn.secondary:hover {
|
|
588
|
+
color: var(--text);
|
|
589
|
+
border-color: var(--border-hover);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
.modal-btn.primary {
|
|
593
|
+
background: #E8564A;
|
|
594
|
+
border-color: transparent;
|
|
595
|
+
color: #fff;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
.modal-btn.primary:hover:not(:disabled) {
|
|
599
|
+
box-shadow: 0 4px 20px rgba(232, 86, 74, .25);
|
|
600
|
+
background: #D64A3F;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
.modal-btn:disabled {
|
|
604
|
+
opacity: 0.4;
|
|
605
|
+
cursor: not-allowed;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/* ── Drop Zone ──────────────────────────────────── */
|
|
609
|
+
|
|
610
|
+
.drop-zone {
|
|
611
|
+
border: 2px dashed var(--border-subtle);
|
|
612
|
+
border-radius: var(--radius-sm);
|
|
613
|
+
padding: 28px 20px;
|
|
614
|
+
text-align: center;
|
|
615
|
+
transition: border-color var(--transition), background var(--transition);
|
|
616
|
+
cursor: pointer;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
.drop-zone.dragover {
|
|
620
|
+
border-color: var(--accent);
|
|
621
|
+
background: rgba(232, 86, 74, .04);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
.drop-zone-icon {
|
|
625
|
+
font-size: 2rem;
|
|
626
|
+
margin-bottom: 8px;
|
|
627
|
+
opacity: .5;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
.drop-zone-text {
|
|
631
|
+
font-size: .85rem;
|
|
632
|
+
color: var(--text-muted);
|
|
633
|
+
margin-bottom: 4px;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
.drop-zone-hint {
|
|
637
|
+
font-size: .75rem;
|
|
638
|
+
color: var(--text-dim);
|
|
639
|
+
margin-bottom: 10px;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
.browse-btn {
|
|
643
|
+
padding: 7px 18px;
|
|
644
|
+
border-radius: var(--radius-sm);
|
|
645
|
+
border: 1px solid var(--border-subtle);
|
|
646
|
+
background: var(--surface-glass);
|
|
647
|
+
color: var(--text);
|
|
648
|
+
font-size: .8rem;
|
|
649
|
+
font-weight: 500;
|
|
650
|
+
cursor: pointer;
|
|
651
|
+
transition: all var(--transition);
|
|
652
|
+
font-family: inherit;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
.browse-btn:hover {
|
|
656
|
+
border-color: var(--border-hover);
|
|
657
|
+
background: #F3F4F6;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
.drop-zone-selected {
|
|
661
|
+
margin-top: 10px;
|
|
662
|
+
font-size: .8rem;
|
|
663
|
+
color: var(--accent);
|
|
664
|
+
font-weight: 500;
|
|
665
|
+
min-height: 1.2em;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/* ── Iframe View ────────────────────────────────── */
|
|
669
|
+
|
|
670
|
+
#iframe-view {
|
|
671
|
+
position: fixed;
|
|
672
|
+
inset: 0;
|
|
673
|
+
z-index: 600;
|
|
674
|
+
background: var(--bg);
|
|
675
|
+
display: flex;
|
|
676
|
+
flex-direction: column;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
#iframe-view[hidden] {
|
|
680
|
+
display: none;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
#iframe-view .iframe-toolbar {
|
|
684
|
+
display: flex;
|
|
685
|
+
align-items: center;
|
|
686
|
+
gap: 12px;
|
|
687
|
+
padding: 10px 16px;
|
|
688
|
+
background: rgba(255, 255, 255, .95);
|
|
689
|
+
backdrop-filter: blur(20px);
|
|
690
|
+
-webkit-backdrop-filter: blur(20px);
|
|
691
|
+
border-bottom: 1px solid #E5E7EB;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
#iframe-view .iframe-toolbar .iframe-title {
|
|
695
|
+
flex: 1;
|
|
696
|
+
font-size: .85rem;
|
|
697
|
+
font-weight: 600;
|
|
698
|
+
color: var(--text);
|
|
699
|
+
overflow: hidden;
|
|
700
|
+
text-overflow: ellipsis;
|
|
701
|
+
white-space: nowrap;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
#iframe-view iframe {
|
|
705
|
+
flex: 1;
|
|
706
|
+
border: none;
|
|
707
|
+
width: 100%;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/* ── Context Menu ──────────────────────────────── */
|
|
711
|
+
|
|
712
|
+
#context-menu {
|
|
713
|
+
position: fixed;
|
|
714
|
+
z-index: 700;
|
|
715
|
+
background: rgba(255, 255, 255, .98);
|
|
716
|
+
backdrop-filter: blur(24px);
|
|
717
|
+
-webkit-backdrop-filter: blur(24px);
|
|
718
|
+
border: 1px solid #E5E7EB;
|
|
719
|
+
border-radius: var(--radius-sm);
|
|
720
|
+
padding: 6px 0;
|
|
721
|
+
min-width: 180px;
|
|
722
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, .12);
|
|
723
|
+
animation: cardIn .2s cubic-bezier(.16, 1, .3, 1);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
#context-menu[hidden] {
|
|
727
|
+
display: none;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
#context-menu button {
|
|
731
|
+
display: flex;
|
|
732
|
+
align-items: center;
|
|
733
|
+
gap: 8px;
|
|
734
|
+
width: 100%;
|
|
735
|
+
padding: 9px 16px;
|
|
736
|
+
background: none;
|
|
737
|
+
border: none;
|
|
738
|
+
color: var(--text);
|
|
739
|
+
font-size: .84rem;
|
|
740
|
+
font-family: inherit;
|
|
741
|
+
cursor: pointer;
|
|
742
|
+
transition: background var(--transition);
|
|
743
|
+
text-align: left;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
#context-menu button:hover {
|
|
747
|
+
background: #F3F4F6;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
#context-menu button.danger {
|
|
751
|
+
color: var(--accent);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
#context-menu button.danger:hover {
|
|
755
|
+
background: rgba(232, 86, 74, .08);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
#context-menu hr {
|
|
759
|
+
border: none;
|
|
760
|
+
border-top: 1px solid var(--border-subtle);
|
|
761
|
+
margin: 4px 0;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/* ── Responsive ─────────────────────────────────── */
|
|
765
|
+
|
|
766
|
+
@media (max-width: 480px) {
|
|
767
|
+
header {
|
|
768
|
+
padding: 12px 16px;
|
|
769
|
+
gap: 10px;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
header h1 {
|
|
773
|
+
font-size: 1.1rem;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
#search-input {
|
|
777
|
+
min-width: 0;
|
|
778
|
+
order: 3;
|
|
779
|
+
flex-basis: 100%;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
#tag-bar {
|
|
783
|
+
padding: 10px 16px;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
#app-grid {
|
|
787
|
+
padding: 8px 16px 20px;
|
|
788
|
+
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
|
789
|
+
gap: 12px;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
footer {
|
|
793
|
+
padding: 12px 16px;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/* Light theme is now the default — no data-theme overrides needed */
|
|
798
|
+
|
|
799
|
+
/* ── Source Modal ──────────────────────────────── */
|
|
800
|
+
|
|
801
|
+
#source-overlay {
|
|
802
|
+
position: fixed;
|
|
803
|
+
inset: 0;
|
|
804
|
+
z-index: 500;
|
|
805
|
+
background: rgba(0, 0, 0, .3);
|
|
806
|
+
backdrop-filter: blur(6px);
|
|
807
|
+
-webkit-backdrop-filter: blur(6px);
|
|
808
|
+
display: flex;
|
|
809
|
+
align-items: center;
|
|
810
|
+
justify-content: center;
|
|
811
|
+
padding: 24px;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
#source-overlay[hidden] {
|
|
815
|
+
display: none;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
.source-modal { max-width: 800px; width: 95vw; }
|
|
819
|
+
#source-code {
|
|
820
|
+
width: 100%;
|
|
821
|
+
min-height: 400px;
|
|
822
|
+
max-height: 60vh;
|
|
823
|
+
background: #F9FAFB;
|
|
824
|
+
color: #1A1A2E;
|
|
825
|
+
border: 1px solid var(--border-subtle);
|
|
826
|
+
border-radius: 8px;
|
|
827
|
+
padding: 1rem;
|
|
828
|
+
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
|
829
|
+
font-size: 0.85rem;
|
|
830
|
+
line-height: 1.5;
|
|
831
|
+
resize: vertical;
|
|
832
|
+
tab-size: 2;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
/* ── Settings Modal ──────────────────────────────── */
|
|
836
|
+
|
|
837
|
+
#settings-overlay {
|
|
838
|
+
position: fixed;
|
|
839
|
+
inset: 0;
|
|
840
|
+
z-index: 500;
|
|
841
|
+
background: rgba(0, 0, 0, .3);
|
|
842
|
+
backdrop-filter: blur(6px);
|
|
843
|
+
-webkit-backdrop-filter: blur(6px);
|
|
844
|
+
display: flex;
|
|
845
|
+
align-items: center;
|
|
846
|
+
justify-content: center;
|
|
847
|
+
padding: 24px;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
#settings-overlay[hidden] {
|
|
851
|
+
display: none;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.settings-section {
|
|
855
|
+
margin-bottom: 20px;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
.settings-section-title {
|
|
859
|
+
font-size: .78rem;
|
|
860
|
+
font-weight: 600;
|
|
861
|
+
color: var(--text-muted);
|
|
862
|
+
text-transform: uppercase;
|
|
863
|
+
letter-spacing: .04em;
|
|
864
|
+
margin-bottom: 12px;
|
|
865
|
+
padding-bottom: 6px;
|
|
866
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
.settings-row {
|
|
870
|
+
display: flex;
|
|
871
|
+
align-items: center;
|
|
872
|
+
gap: 12px;
|
|
873
|
+
margin-bottom: 10px;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
.settings-row label {
|
|
877
|
+
flex: 0 0 130px;
|
|
878
|
+
font-size: .84rem;
|
|
879
|
+
color: var(--text-muted);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
.settings-row .modal-input {
|
|
883
|
+
flex: 1;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
.settings-backup-actions {
|
|
887
|
+
display: flex;
|
|
888
|
+
gap: 10px;
|
|
889
|
+
flex-wrap: wrap;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
.modal-btn.danger {
|
|
893
|
+
background: transparent;
|
|
894
|
+
border-color: var(--accent);
|
|
895
|
+
color: var(--accent);
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
.modal-btn.danger:hover {
|
|
899
|
+
background: rgba(232, 86, 74, .08);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/* ── AIMEAT Import Dialog ─────────────────────────── */
|
|
903
|
+
|
|
904
|
+
#aimeat-import-overlay {
|
|
905
|
+
position: fixed;
|
|
906
|
+
inset: 0;
|
|
907
|
+
z-index: 550;
|
|
908
|
+
background: rgba(0, 0, 0, .3);
|
|
909
|
+
backdrop-filter: blur(6px);
|
|
910
|
+
-webkit-backdrop-filter: blur(6px);
|
|
911
|
+
display: flex;
|
|
912
|
+
align-items: center;
|
|
913
|
+
justify-content: center;
|
|
914
|
+
padding: 24px;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
#aimeat-import-overlay[hidden] {
|
|
918
|
+
display: none;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
.aimeat-app-list {
|
|
922
|
+
max-height: 300px;
|
|
923
|
+
overflow-y: auto;
|
|
924
|
+
margin-bottom: 16px;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
.aimeat-app-item {
|
|
928
|
+
display: flex;
|
|
929
|
+
align-items: center;
|
|
930
|
+
gap: 10px;
|
|
931
|
+
padding: 10px 12px;
|
|
932
|
+
border: 1px solid var(--border-subtle);
|
|
933
|
+
border-radius: var(--radius-sm);
|
|
934
|
+
margin-bottom: 8px;
|
|
935
|
+
transition: border-color var(--transition);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
.aimeat-app-item:hover {
|
|
939
|
+
border-color: var(--border-hover);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
.aimeat-app-item input[type="checkbox"] {
|
|
943
|
+
flex-shrink: 0;
|
|
944
|
+
width: 18px;
|
|
945
|
+
height: 18px;
|
|
946
|
+
cursor: pointer;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
.aimeat-app-info {
|
|
950
|
+
flex: 1;
|
|
951
|
+
min-width: 0;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
.aimeat-app-name {
|
|
955
|
+
font-size: .85rem;
|
|
956
|
+
font-weight: 600;
|
|
957
|
+
overflow: hidden;
|
|
958
|
+
text-overflow: ellipsis;
|
|
959
|
+
white-space: nowrap;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
.aimeat-app-size {
|
|
963
|
+
font-size: .72rem;
|
|
964
|
+
color: var(--text-dim);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
.aimeat-app-item select {
|
|
968
|
+
flex-shrink: 0;
|
|
969
|
+
background: var(--surface-glass);
|
|
970
|
+
border: 1px solid var(--border-subtle);
|
|
971
|
+
border-radius: 6px;
|
|
972
|
+
padding: 4px 8px;
|
|
973
|
+
color: var(--text);
|
|
974
|
+
font-size: .78rem;
|
|
975
|
+
font-family: inherit;
|
|
976
|
+
cursor: pointer;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
.aimeat-app-item select option {
|
|
980
|
+
background: var(--surface);
|
|
981
|
+
color: var(--text);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/* ── Publish Modal ──────────────────────────────── */
|
|
985
|
+
|
|
986
|
+
#publish-overlay {
|
|
987
|
+
position: fixed;
|
|
988
|
+
inset: 0;
|
|
989
|
+
z-index: 560;
|
|
990
|
+
background: rgba(0, 0, 0, .3);
|
|
991
|
+
backdrop-filter: blur(6px);
|
|
992
|
+
-webkit-backdrop-filter: blur(6px);
|
|
993
|
+
display: flex;
|
|
994
|
+
align-items: center;
|
|
995
|
+
justify-content: center;
|
|
996
|
+
padding: 24px;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
#publish-overlay[hidden] {
|
|
1000
|
+
display: none;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
/* ── Published Apps Section ──────────────────────── */
|
|
1004
|
+
|
|
1005
|
+
#published-section {
|
|
1006
|
+
margin: 0 24px 24px;
|
|
1007
|
+
position: relative;
|
|
1008
|
+
z-index: 1;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
.published-header {
|
|
1012
|
+
display: flex;
|
|
1013
|
+
align-items: center;
|
|
1014
|
+
justify-content: space-between;
|
|
1015
|
+
margin-bottom: 12px;
|
|
1016
|
+
cursor: pointer;
|
|
1017
|
+
user-select: none;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
.published-header h2 {
|
|
1021
|
+
font-size: 1rem;
|
|
1022
|
+
font-weight: 700;
|
|
1023
|
+
color: #34d399;
|
|
1024
|
+
display: flex;
|
|
1025
|
+
align-items: center;
|
|
1026
|
+
gap: 8px;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
.published-header .arrow {
|
|
1030
|
+
transition: transform var(--transition);
|
|
1031
|
+
font-size: .8rem;
|
|
1032
|
+
color: var(--text-muted);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
.published-header .arrow.open {
|
|
1036
|
+
transform: rotate(180deg);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
.published-grid {
|
|
1040
|
+
display: grid;
|
|
1041
|
+
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
1042
|
+
gap: 12px;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.published-card {
|
|
1046
|
+
background: var(--surface-glass);
|
|
1047
|
+
border: 1px solid rgba(52, 211, 153, .25);
|
|
1048
|
+
border-radius: var(--radius-sm);
|
|
1049
|
+
padding: 14px;
|
|
1050
|
+
display: flex;
|
|
1051
|
+
flex-direction: column;
|
|
1052
|
+
gap: 8px;
|
|
1053
|
+
transition: border-color var(--transition), box-shadow var(--transition);
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
.published-card:hover {
|
|
1057
|
+
border-color: rgba(52, 211, 153, .5);
|
|
1058
|
+
box-shadow: 0 4px 20px rgba(52, 211, 153, .08);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
.published-card-name {
|
|
1062
|
+
font-weight: 600;
|
|
1063
|
+
font-size: .88rem;
|
|
1064
|
+
overflow: hidden;
|
|
1065
|
+
text-overflow: ellipsis;
|
|
1066
|
+
white-space: nowrap;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
.published-card-meta {
|
|
1070
|
+
font-size: .72rem;
|
|
1071
|
+
color: var(--text-muted);
|
|
1072
|
+
display: flex;
|
|
1073
|
+
gap: 8px;
|
|
1074
|
+
flex-wrap: wrap;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
.published-card-actions {
|
|
1078
|
+
display: flex;
|
|
1079
|
+
gap: 6px;
|
|
1080
|
+
margin-top: 4px;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
.published-card-actions button {
|
|
1084
|
+
background: var(--surface-glass);
|
|
1085
|
+
border: 1px solid var(--border-subtle);
|
|
1086
|
+
border-radius: 6px;
|
|
1087
|
+
padding: 5px 10px;
|
|
1088
|
+
color: var(--text);
|
|
1089
|
+
font-size: .72rem;
|
|
1090
|
+
font-family: inherit;
|
|
1091
|
+
cursor: pointer;
|
|
1092
|
+
transition: background var(--transition), border-color var(--transition);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
.published-card-actions button:hover {
|
|
1096
|
+
border-color: var(--border-hover);
|
|
1097
|
+
background: #F3F4F6;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
.published-card-actions button.danger:hover {
|
|
1101
|
+
border-color: var(--accent);
|
|
1102
|
+
background: rgba(232, 86, 74, .08);
|
|
1103
|
+
color: var(--accent);
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
.published-empty {
|
|
1107
|
+
padding: 16px;
|
|
1108
|
+
text-align: center;
|
|
1109
|
+
color: var(--text-dim);
|
|
1110
|
+
font-size: .85rem;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
/* ── Cortex Extensions Bar ──────────────────────── */
|
|
1114
|
+
|
|
1115
|
+
.cortex-mini-card{background:#FFFFFF;border:1px solid #E5E7EB;border-radius:10px;padding:.75rem 1rem;cursor:pointer;min-width:160px;flex-shrink:0;transition:all .15s}
|
|
1116
|
+
.cortex-mini-card:hover{background:#F9FAFB;border-color:#D1D5DB}
|
|
1117
|
+
.cortex-mini-name{font-weight:600;font-size:.85rem;margin-bottom:.25rem;white-space:nowrap}
|
|
1118
|
+
.cortex-mini-meta{font-size:.7rem;color:#6B7280}
|
|
1119
|
+
|
|
1120
|
+
/* ── Prompt Builder Panel ──────────────────────── */
|
|
1121
|
+
#prompt-builder-overlay {
|
|
1122
|
+
position: fixed; inset: 0; z-index: 600;
|
|
1123
|
+
background: rgba(0,0,0,.3); backdrop-filter: blur(6px);
|
|
1124
|
+
display: none; align-items: center; justify-content: center; padding: 24px;
|
|
1125
|
+
}
|
|
1126
|
+
.prompt-builder-modal {
|
|
1127
|
+
background: #FFFFFF;
|
|
1128
|
+
border: 1px solid #E5E7EB; border-radius: 16px;
|
|
1129
|
+
padding: 28px; max-width: 900px; width: 96vw; max-height: 90vh;
|
|
1130
|
+
display: flex; flex-direction: column; overflow: hidden;
|
|
1131
|
+
box-shadow: 0 8px 40px rgba(0,0,0,.12);
|
|
1132
|
+
}
|
|
1133
|
+
.prompt-builder-modal h2 { margin: 0 0 16px; font-size: 1.1rem; }
|
|
1134
|
+
.pb-mode-row { display: flex; gap: 12px; margin-bottom: 14px; }
|
|
1135
|
+
.pb-mode-radio { display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: .88rem; }
|
|
1136
|
+
.pb-mode-radio input { accent-color: #E8564A; }
|
|
1137
|
+
.pb-desc-area {
|
|
1138
|
+
width: 100%; min-height: 60px; max-height: 120px; resize: vertical;
|
|
1139
|
+
background: #F9FAFB; border: 1px solid #E5E7EB;
|
|
1140
|
+
border-radius: 10px; padding: 10px 14px; color: inherit; font-size: .85rem;
|
|
1141
|
+
font-family: inherit; line-height: 1.5; margin-bottom: 14px;
|
|
1142
|
+
}
|
|
1143
|
+
.pb-desc-area:focus { outline: none; border-color: #E8564A; }
|
|
1144
|
+
.pb-ext-toggle { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: .85rem; margin-bottom: 10px; }
|
|
1145
|
+
.pb-ext-toggle input { accent-color: #E8564A; }
|
|
1146
|
+
.pb-ext-list {
|
|
1147
|
+
display: none; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; padding: 10px;
|
|
1148
|
+
background: #F9FAFB; border: 1px solid #E5E7EB;
|
|
1149
|
+
border-radius: 10px; max-height: 160px; overflow-y: auto;
|
|
1150
|
+
}
|
|
1151
|
+
.pb-ext-list.open { display: flex; }
|
|
1152
|
+
.pb-ext-chip {
|
|
1153
|
+
display: flex; align-items: center; gap: 6px; padding: 6px 12px;
|
|
1154
|
+
background: #F9FAFB; border: 1px solid #E5E7EB;
|
|
1155
|
+
border-radius: 8px; cursor: pointer; font-size: .8rem; transition: all .15s;
|
|
1156
|
+
}
|
|
1157
|
+
.pb-ext-chip:hover { background: #F3F4F6; }
|
|
1158
|
+
.pb-ext-chip.selected { background: rgba(232,86,74,.08); border-color: rgba(232,86,74,.35); }
|
|
1159
|
+
.pb-ext-chip input { accent-color: #E8564A; pointer-events: none; }
|
|
1160
|
+
.pb-preview {
|
|
1161
|
+
flex: 1; min-height: 120px; overflow-y: auto; margin-bottom: 14px; padding: 12px;
|
|
1162
|
+
background: #F9FAFB; border: 1px solid #E5E7EB;
|
|
1163
|
+
border-radius: 10px; font-family: 'Consolas','Monaco','Courier New',monospace;
|
|
1164
|
+
font-size: .75rem; line-height: 1.5; white-space: pre-wrap; word-break: break-word;
|
|
1165
|
+
color: #6B7280;
|
|
1166
|
+
}
|
|
1167
|
+
.pb-preview-label { font-size: .75rem; text-transform: uppercase; letter-spacing: .1em; color: #6B7280; margin-bottom: 6px; }
|
|
1168
|
+
</style>
|
|
1169
|
+
</head>
|
|
1170
|
+
<body>
|
|
1171
|
+
|
|
1172
|
+
<header>
|
|
1173
|
+
<h1>My Apps</h1>
|
|
1174
|
+
<input type="text" id="search-input" placeholder="Search apps..." autocomplete="off" spellcheck="false"/>
|
|
1175
|
+
<div class="header-actions">
|
|
1176
|
+
<button class="icon-btn" id="add-btn" title="Add app">+</button>
|
|
1177
|
+
<button class="icon-btn" id="generate-btn" title="Generate with AI">✨</button>
|
|
1178
|
+
<button class="icon-btn" id="homepage-btn" title="Generate Homepage">🏠</button>
|
|
1179
|
+
<button class="icon-btn" id="settings-btn" title="Settings">⚙</button>
|
|
1180
|
+
</div>
|
|
1181
|
+
</header>
|
|
1182
|
+
|
|
1183
|
+
<nav id="tag-bar"></nav>
|
|
1184
|
+
|
|
1185
|
+
<!-- Active Extensions Bar -->
|
|
1186
|
+
<div id="cortex-bar" style="display:none;margin:0 24px 1.5rem;position:relative;z-index:1">
|
|
1187
|
+
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem">
|
|
1188
|
+
<h3 style="margin:0;font-size:.95rem;color:#6B7280">🔌 Active Extensions</h3>
|
|
1189
|
+
<button onclick="document.getElementById('cortex-bar-grid').style.display=document.getElementById('cortex-bar-grid').style.display==='none'?'flex':'none'" style="background:none;border:none;color:#6B7280;cursor:pointer;font-size:.8rem">▼ toggle</button>
|
|
1190
|
+
</div>
|
|
1191
|
+
<div id="cortex-bar-grid" style="display:flex;gap:.75rem;overflow-x:auto;padding-bottom:.5rem"></div>
|
|
1192
|
+
</div>
|
|
1193
|
+
|
|
1194
|
+
<!-- Extension Popup Overlay -->
|
|
1195
|
+
<div id="cortex-popup-overlay" style="display:none;position:fixed;inset:0;z-index:500;background:rgba(0,0,0,.3);backdrop-filter:blur(6px);align-items:center;justify-content:center;padding:24px">
|
|
1196
|
+
<div style="background:#FFFFFF;border:1px solid #E5E7EB;border-radius:16px;padding:32px;max-width:500px;width:100%;max-height:80vh;overflow-y:auto;box-shadow:0 8px 40px rgba(0,0,0,.12)">
|
|
1197
|
+
<div id="cortex-popup-content"></div>
|
|
1198
|
+
<div style="display:flex;justify-content:flex-end;margin-top:1rem">
|
|
1199
|
+
<button onclick="document.getElementById('cortex-popup-overlay').style.display='none'" style="padding:6px 16px;border-radius:8px;border:1px solid #E5E7EB;background:transparent;color:#6B7280;cursor:pointer">Close</button>
|
|
1200
|
+
</div>
|
|
1201
|
+
</div>
|
|
1202
|
+
</div>
|
|
1203
|
+
|
|
1204
|
+
<!-- Cortex Extension Editor Overlay -->
|
|
1205
|
+
<div id="cortex-editor-overlay" style="display:none;position:fixed;inset:0;z-index:600;background:rgba(0,0,0,.35);backdrop-filter:blur(8px);align-items:center;justify-content:center;padding:24px">
|
|
1206
|
+
<div style="background:#FFFFFF;border:1px solid #E5E7EB;border-radius:16px;padding:32px;max-width:800px;width:100%;max-height:90vh;overflow-y:auto;box-shadow:0 8px 40px rgba(0,0,0,.12)">
|
|
1207
|
+
<h2 style="margin-top:0;font-size:1.1rem">🛠️ Extension Editor</h2>
|
|
1208
|
+
<p id="cortex-editor-name" style="color:#6B7280;font-size:.85rem;margin-top:-.5rem"></p>
|
|
1209
|
+
<div id="cortex-editor-status" style="font-size:.8rem;margin-bottom:1rem;min-height:1.2em;color:#34d399"></div>
|
|
1210
|
+
<div style="margin-bottom:1rem">
|
|
1211
|
+
<label style="font-size:.85rem;font-weight:600;display:block;margin-bottom:.5rem">Manifest (YAML)</label>
|
|
1212
|
+
<textarea id="cortex-editor-manifest" spellcheck="false" style="width:100%;min-height:300px;background:#F9FAFB;color:#1A1A2E;border:1px solid #E5E7EB;border-radius:8px;padding:12px;font-family:monospace;font-size:.8rem;resize:vertical;tab-size:2"></textarea>
|
|
1213
|
+
</div>
|
|
1214
|
+
<div id="cortex-editor-libs"></div>
|
|
1215
|
+
<div style="margin-bottom:1.5rem">
|
|
1216
|
+
<button onclick="window._launcher.cortexEditorAddLib()" style="font-size:.8rem;padding:4px 12px;border-radius:6px;border:1px solid #E5E7EB;background:transparent;color:#6B7280;cursor:pointer">+ Add Lib File</button>
|
|
1217
|
+
</div>
|
|
1218
|
+
<div style="display:flex;gap:.75rem;justify-content:flex-end;flex-wrap:wrap">
|
|
1219
|
+
<button onclick="window._launcher.cortexEditorExport()" style="padding:6px 16px;border-radius:8px;border:1px solid #E5E7EB;background:transparent;color:#6B7280;cursor:pointer">📥 Export Files</button>
|
|
1220
|
+
<button onclick="window._launcher.cortexEditorSave()" id="cortex-editor-save-btn" style="padding:6px 20px;border-radius:8px;border:none;background:#E8564A;color:#fff;font-weight:600;cursor:pointer">Save & Re-install</button>
|
|
1221
|
+
<button onclick="window._launcher.closeCortexEditor()" style="padding:6px 16px;border-radius:8px;border:1px solid #E5E7EB;background:transparent;color:#6B7280;cursor:pointer">Cancel</button>
|
|
1222
|
+
</div>
|
|
1223
|
+
</div>
|
|
1224
|
+
</div>
|
|
1225
|
+
|
|
1226
|
+
<!-- Published Apps Section -->
|
|
1227
|
+
<div id="published-section" style="display:none">
|
|
1228
|
+
<div class="published-header" onclick="window._launcher.togglePublished()">
|
|
1229
|
+
<h2>🚀 Published Apps <span id="published-count"></span></h2>
|
|
1230
|
+
<span class="arrow open" id="published-arrow">▼</span>
|
|
1231
|
+
</div>
|
|
1232
|
+
<div id="published-grid" class="published-grid"></div>
|
|
1233
|
+
</div>
|
|
1234
|
+
|
|
1235
|
+
<!-- Recently Opened Strip -->
|
|
1236
|
+
<div id="recent-section" style="display:none;margin:0 24px 1rem">
|
|
1237
|
+
<h3 style="margin:0 0 .5rem;font-size:.9rem;color:#6B7280">🕒 Recently Opened</h3>
|
|
1238
|
+
<div id="recent-strip" style="display:flex;gap:.75rem;overflow-x:auto;padding-bottom:.5rem"></div>
|
|
1239
|
+
</div>
|
|
1240
|
+
|
|
1241
|
+
<main id="app-grid"></main>
|
|
1242
|
+
|
|
1243
|
+
<footer>
|
|
1244
|
+
<span id="stats">0 apps</span>
|
|
1245
|
+
<span class="footer-brand">AIMEAT</span>
|
|
1246
|
+
</footer>
|
|
1247
|
+
|
|
1248
|
+
<div id="modal-overlay" hidden>
|
|
1249
|
+
<div class="modal" id="add-app-modal">
|
|
1250
|
+
<h2 id="modal-title">Add App</h2>
|
|
1251
|
+
|
|
1252
|
+
<!-- Source tabs -->
|
|
1253
|
+
<div class="modal-tabs">
|
|
1254
|
+
<button class="modal-tab active" data-tab="url">URL</button>
|
|
1255
|
+
<button class="modal-tab" data-tab="file">File</button>
|
|
1256
|
+
<button class="modal-tab" data-tab="paste">Paste</button>
|
|
1257
|
+
<button class="modal-tab" data-tab="aimeat">AIMEAT</button>
|
|
1258
|
+
</div>
|
|
1259
|
+
|
|
1260
|
+
<!-- URL tab content -->
|
|
1261
|
+
<div class="tab-content active" id="tab-url">
|
|
1262
|
+
<label class="modal-label" for="app-url">App URL</label>
|
|
1263
|
+
<input type="url" id="app-url" class="modal-input" placeholder="https://example.com/app.html" autocomplete="off"/>
|
|
1264
|
+
</div>
|
|
1265
|
+
|
|
1266
|
+
<!-- File tab content -->
|
|
1267
|
+
<div class="tab-content" id="tab-file">
|
|
1268
|
+
<label class="modal-label">HTML File</label>
|
|
1269
|
+
<div class="drop-zone" id="drop-zone">
|
|
1270
|
+
<div class="drop-zone-icon">📄</div>
|
|
1271
|
+
<p class="drop-zone-text">Drag & drop an HTML file here</p>
|
|
1272
|
+
<p class="drop-zone-hint">or</p>
|
|
1273
|
+
<button type="button" class="browse-btn" id="browse-btn">Browse files</button>
|
|
1274
|
+
<input type="file" id="file-input" accept=".html,.htm,.zip" hidden/>
|
|
1275
|
+
<p class="drop-zone-selected" id="selected-file-name"></p>
|
|
1276
|
+
</div>
|
|
1277
|
+
</div>
|
|
1278
|
+
|
|
1279
|
+
<!-- Paste tab content -->
|
|
1280
|
+
<div class="tab-content" id="tab-paste">
|
|
1281
|
+
<label class="modal-label" for="app-paste-code">Paste HTML Source Code</label>
|
|
1282
|
+
<textarea id="app-paste-code" class="modal-input" rows="10" placeholder="Paste your HTML source code here..." style="font-family:'Consolas','Monaco','Courier New',monospace;font-size:.8rem;resize:vertical;min-height:160px;line-height:1.4"></textarea>
|
|
1283
|
+
</div>
|
|
1284
|
+
|
|
1285
|
+
<!-- AIMEAT tab content -->
|
|
1286
|
+
<div class="tab-content" id="tab-aimeat">
|
|
1287
|
+
<p style="font-size:.85rem;color:var(--text-muted);margin-bottom:14px;line-height:1.5">
|
|
1288
|
+
Import apps from a connected AIMEAT server. Configure the server URL in Settings first.
|
|
1289
|
+
</p>
|
|
1290
|
+
<button type="button" class="modal-btn primary" onclick="window._launcher.importFromAimeat()" style="width:100%">
|
|
1291
|
+
Fetch Available Apps
|
|
1292
|
+
</button>
|
|
1293
|
+
</div>
|
|
1294
|
+
|
|
1295
|
+
<!-- Common fields -->
|
|
1296
|
+
<div class="modal-fields">
|
|
1297
|
+
<div class="modal-row">
|
|
1298
|
+
<div class="modal-field" style="flex:1">
|
|
1299
|
+
<label class="modal-label" for="app-name">App Name</label>
|
|
1300
|
+
<input type="text" id="app-name" class="modal-input" placeholder="My App" autocomplete="off"/>
|
|
1301
|
+
</div>
|
|
1302
|
+
<div class="modal-field" style="width:72px">
|
|
1303
|
+
<label class="modal-label" for="app-icon">Icon</label>
|
|
1304
|
+
<input type="text" id="app-icon" class="modal-input" maxlength="4" placeholder="📝" style="text-align:center;font-size:1.2rem"/>
|
|
1305
|
+
</div>
|
|
1306
|
+
</div>
|
|
1307
|
+
<div class="modal-field">
|
|
1308
|
+
<label class="modal-label" for="app-tags">Tags <span class="label-hint">(comma separated)</span></label>
|
|
1309
|
+
<input type="text" id="app-tags" class="modal-input" placeholder="tools, productivity" autocomplete="off"/>
|
|
1310
|
+
</div>
|
|
1311
|
+
<div class="modal-field">
|
|
1312
|
+
<label class="modal-label" for="app-open-mode">Open Mode</label>
|
|
1313
|
+
<select id="app-open-mode" class="modal-input">
|
|
1314
|
+
<option value="tab">New Tab</option>
|
|
1315
|
+
<option value="iframe">Inline (iframe)</option>
|
|
1316
|
+
</select>
|
|
1317
|
+
</div>
|
|
1318
|
+
</div>
|
|
1319
|
+
|
|
1320
|
+
<!-- Actions -->
|
|
1321
|
+
<div class="modal-actions">
|
|
1322
|
+
<button type="button" class="modal-btn secondary" id="modal-cancel-btn">Cancel</button>
|
|
1323
|
+
<button type="button" class="modal-btn primary" id="modal-save-btn">Save</button>
|
|
1324
|
+
</div>
|
|
1325
|
+
</div>
|
|
1326
|
+
</div>
|
|
1327
|
+
|
|
1328
|
+
<div id="iframe-view" hidden>
|
|
1329
|
+
<div class="iframe-toolbar">
|
|
1330
|
+
<button class="icon-btn" onclick="window._launcher.closeIframe()" title="Close">✕</button>
|
|
1331
|
+
<span class="iframe-title" id="iframe-title"></span>
|
|
1332
|
+
<button class="icon-btn" onclick="window._launcher.openExternal()" title="Open in new tab">↗</button>
|
|
1333
|
+
</div>
|
|
1334
|
+
<iframe id="app-iframe" sandbox="allow-scripts allow-forms allow-popups"></iframe>
|
|
1335
|
+
</div>
|
|
1336
|
+
|
|
1337
|
+
<div id="context-menu" hidden>
|
|
1338
|
+
<button data-action="edit">✏️ Edit</button>
|
|
1339
|
+
<button data-action="favorite">⭐ Toggle favorite</button>
|
|
1340
|
+
<button data-action="toggle-mode">🔄 Switch open mode</button>
|
|
1341
|
+
<button data-action="view-source">👁 View / Edit Source</button>
|
|
1342
|
+
<button data-action="improve-ai">✨ Improve with AI</button>
|
|
1343
|
+
<button data-action="share-prompt">📤 Share as Prompt</button>
|
|
1344
|
+
<hr>
|
|
1345
|
+
<button data-action="publish">🚀 Publish to server</button>
|
|
1346
|
+
<hr>
|
|
1347
|
+
<button data-action="delete" class="danger">🗑️ Delete</button>
|
|
1348
|
+
</div>
|
|
1349
|
+
|
|
1350
|
+
<!-- Settings Modal -->
|
|
1351
|
+
<div id="settings-overlay" hidden>
|
|
1352
|
+
<div class="modal" id="settings-modal">
|
|
1353
|
+
<h2>Settings</h2>
|
|
1354
|
+
|
|
1355
|
+
<div class="settings-section">
|
|
1356
|
+
<div class="settings-section-title">Appearance</div>
|
|
1357
|
+
<div class="settings-row">
|
|
1358
|
+
<label for="setting-theme">Theme</label>
|
|
1359
|
+
<select id="setting-theme" class="modal-input">
|
|
1360
|
+
<option value="dark">Dark</option>
|
|
1361
|
+
<option value="light">Light</option>
|
|
1362
|
+
</select>
|
|
1363
|
+
</div>
|
|
1364
|
+
</div>
|
|
1365
|
+
|
|
1366
|
+
<div class="settings-section">
|
|
1367
|
+
<div class="settings-section-title">Defaults</div>
|
|
1368
|
+
<div class="settings-row">
|
|
1369
|
+
<label for="setting-open-mode">Default open mode</label>
|
|
1370
|
+
<select id="setting-open-mode" class="modal-input">
|
|
1371
|
+
<option value="tab">New Tab</option>
|
|
1372
|
+
<option value="iframe">Inline (iframe)</option>
|
|
1373
|
+
</select>
|
|
1374
|
+
</div>
|
|
1375
|
+
</div>
|
|
1376
|
+
|
|
1377
|
+
<div class="settings-section">
|
|
1378
|
+
<div class="settings-section-title">AIMEAT Server</div>
|
|
1379
|
+
<div class="settings-row">
|
|
1380
|
+
<label for="setting-aimeat-url">Server URL</label>
|
|
1381
|
+
<input type="url" id="setting-aimeat-url" class="modal-input" placeholder="http://localhost:40050" autocomplete="off"/>
|
|
1382
|
+
</div>
|
|
1383
|
+
</div>
|
|
1384
|
+
|
|
1385
|
+
<div class="settings-section">
|
|
1386
|
+
<div class="settings-section-title">Backup & Restore</div>
|
|
1387
|
+
<div class="settings-backup-actions">
|
|
1388
|
+
<button type="button" class="modal-btn secondary" onclick="window._launcher.exportBackup()">Export JSON</button>
|
|
1389
|
+
<button type="button" class="modal-btn secondary" onclick="document.getElementById('import-file-input').click()">Import JSON</button>
|
|
1390
|
+
<input type="file" id="import-file-input" accept=".json" hidden/>
|
|
1391
|
+
</div>
|
|
1392
|
+
</div>
|
|
1393
|
+
|
|
1394
|
+
<div class="settings-section" style="margin-bottom:0">
|
|
1395
|
+
<div class="settings-section-title">Danger Zone</div>
|
|
1396
|
+
<button type="button" class="modal-btn danger" onclick="window._launcher.clearAllData()">Clear All Data</button>
|
|
1397
|
+
</div>
|
|
1398
|
+
|
|
1399
|
+
<div class="modal-actions" style="margin-top:24px">
|
|
1400
|
+
<button type="button" class="modal-btn secondary" id="settings-cancel-btn">Cancel</button>
|
|
1401
|
+
<button type="button" class="modal-btn primary" id="settings-save-btn">Save</button>
|
|
1402
|
+
</div>
|
|
1403
|
+
</div>
|
|
1404
|
+
</div>
|
|
1405
|
+
|
|
1406
|
+
<!-- View Source Modal -->
|
|
1407
|
+
<div id="source-overlay" hidden>
|
|
1408
|
+
<div class="modal source-modal">
|
|
1409
|
+
<h2 id="source-title">View Source</h2>
|
|
1410
|
+
<textarea id="source-code"></textarea>
|
|
1411
|
+
<div class="modal-actions">
|
|
1412
|
+
<button class="modal-btn secondary" id="copy-source-btn">Copy Source</button>
|
|
1413
|
+
<button class="modal-btn primary" id="copy-prompt-btn">Copy with AI Prompt</button>
|
|
1414
|
+
<button class="modal-btn primary" id="save-source-btn" disabled>Save Changes</button>
|
|
1415
|
+
<button class="modal-btn secondary" id="close-source-btn">Close</button>
|
|
1416
|
+
</div>
|
|
1417
|
+
</div>
|
|
1418
|
+
</div>
|
|
1419
|
+
|
|
1420
|
+
<!-- AIMEAT Import Dialog (dynamically populated) -->
|
|
1421
|
+
<div id="aimeat-import-overlay" hidden>
|
|
1422
|
+
<div class="modal" id="aimeat-import-modal">
|
|
1423
|
+
<h2>Import from AIMEAT</h2>
|
|
1424
|
+
<div class="aimeat-app-list" id="aimeat-app-list"></div>
|
|
1425
|
+
<div class="modal-actions">
|
|
1426
|
+
<button type="button" class="modal-btn secondary" onclick="document.getElementById('aimeat-import-overlay').hidden = true">Cancel</button>
|
|
1427
|
+
<button type="button" class="modal-btn primary" onclick="window._launcher.processAimeatImport()">Import Selected</button>
|
|
1428
|
+
</div>
|
|
1429
|
+
</div>
|
|
1430
|
+
</div>
|
|
1431
|
+
|
|
1432
|
+
<!-- Publish Modal -->
|
|
1433
|
+
<div id="publish-overlay" hidden>
|
|
1434
|
+
<div class="modal" id="publish-modal">
|
|
1435
|
+
<h2>🚀 Publish App</h2>
|
|
1436
|
+
<div class="form-group">
|
|
1437
|
+
<label for="publish-filename">Filename</label>
|
|
1438
|
+
<input type="text" id="publish-filename" class="modal-input" placeholder="my-app.html" autocomplete="off"/>
|
|
1439
|
+
<div style="font-size:.75rem;color:var(--text-muted);margin-top:4px">Letters, numbers, dots, hyphens, underscores. Must end in .html</div>
|
|
1440
|
+
</div>
|
|
1441
|
+
<div class="form-group">
|
|
1442
|
+
<label for="publish-access-code">Access Code (optional)</label>
|
|
1443
|
+
<input type="text" id="publish-access-code" class="modal-input" placeholder="Leave empty for public" autocomplete="off"/>
|
|
1444
|
+
<div style="font-size:.75rem;color:var(--text-muted);margin-top:4px">4-64 chars. If set, only people with the code can download.</div>
|
|
1445
|
+
</div>
|
|
1446
|
+
<div id="publish-status" style="margin-top:8px;font-size:.85rem"></div>
|
|
1447
|
+
<div class="modal-actions">
|
|
1448
|
+
<button type="button" class="modal-btn secondary" onclick="document.getElementById('publish-overlay').hidden = true">Cancel</button>
|
|
1449
|
+
<button type="button" class="modal-btn primary" id="publish-submit-btn" onclick="window._launcher.submitPublish()">Publish</button>
|
|
1450
|
+
</div>
|
|
1451
|
+
</div>
|
|
1452
|
+
</div>
|
|
1453
|
+
|
|
1454
|
+
<!-- Prompt Builder Panel -->
|
|
1455
|
+
<div id="prompt-builder-overlay">
|
|
1456
|
+
<div class="prompt-builder-modal">
|
|
1457
|
+
<h2 id="pb-title">✨ Generate App Prompt</h2>
|
|
1458
|
+
<div class="pb-mode-row">
|
|
1459
|
+
<label class="pb-mode-radio"><input type="radio" name="pb-mode" value="new" checked> New App</label>
|
|
1460
|
+
<label class="pb-mode-radio"><input type="radio" name="pb-mode" value="improve"> Improve This App</label>
|
|
1461
|
+
</div>
|
|
1462
|
+
<textarea class="pb-desc-area" id="pb-description" placeholder="Describe what the app should do, or what changes to make..."></textarea>
|
|
1463
|
+
<label class="pb-ext-toggle"><input type="checkbox" id="pb-ext-checkbox"> Include Cortex Extensions</label>
|
|
1464
|
+
<div class="pb-ext-list" id="pb-ext-list"></div>
|
|
1465
|
+
<div class="pb-preview-label">Live Preview</div>
|
|
1466
|
+
<div class="pb-preview" id="pb-preview"></div>
|
|
1467
|
+
<div class="modal-actions">
|
|
1468
|
+
<button class="modal-btn secondary" id="pb-cancel-btn">Cancel</button>
|
|
1469
|
+
<button class="modal-btn primary" id="pb-copy-btn">Copy Prompt</button>
|
|
1470
|
+
</div>
|
|
1471
|
+
</div>
|
|
1472
|
+
</div>
|
|
1473
|
+
|
|
1474
|
+
<!-- Published Apps Section (inserted before grid, toggled) -->
|
|
1475
|
+
|
|
1476
|
+
<script>
|
|
1477
|
+
(function () {
|
|
1478
|
+
'use strict';
|
|
1479
|
+
|
|
1480
|
+
// ── IndexedDB wrapper ──────────────────────────────
|
|
1481
|
+
|
|
1482
|
+
const DB_NAME = 'AppLauncherDB';
|
|
1483
|
+
const DB_VERSION = 2;
|
|
1484
|
+
const STORE_NAME = 'apps';
|
|
1485
|
+
|
|
1486
|
+
let dbInstance = null;
|
|
1487
|
+
|
|
1488
|
+
function openDB() {
|
|
1489
|
+
if (dbInstance) return Promise.resolve(dbInstance);
|
|
1490
|
+
return new Promise(function (resolve, reject) {
|
|
1491
|
+
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
1492
|
+
|
|
1493
|
+
request.onupgradeneeded = function (event) {
|
|
1494
|
+
const db = event.target.result;
|
|
1495
|
+
var store;
|
|
1496
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
1497
|
+
store = db.createObjectStore(STORE_NAME, { keyPath: 'id' });
|
|
1498
|
+
store.createIndex('tags', 'tags', { multiEntry: true });
|
|
1499
|
+
store.createIndex('source', 'source', { unique: false });
|
|
1500
|
+
store.createIndex('favorite', 'favorite', { unique: false });
|
|
1501
|
+
store.createIndex('sortOrder', 'sortOrder', { unique: false });
|
|
1502
|
+
} else {
|
|
1503
|
+
store = event.target.transaction.objectStore(STORE_NAME);
|
|
1504
|
+
if (!store.indexNames.contains('sortOrder')) {
|
|
1505
|
+
store.createIndex('sortOrder', 'sortOrder', { unique: false });
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
};
|
|
1509
|
+
|
|
1510
|
+
request.onsuccess = function (event) {
|
|
1511
|
+
dbInstance = event.target.result;
|
|
1512
|
+
resolve(dbInstance);
|
|
1513
|
+
};
|
|
1514
|
+
|
|
1515
|
+
request.onerror = function (event) {
|
|
1516
|
+
reject(event.target.error);
|
|
1517
|
+
};
|
|
1518
|
+
});
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
function getAllApps() {
|
|
1522
|
+
return openDB().then(function (db) {
|
|
1523
|
+
return new Promise(function (resolve, reject) {
|
|
1524
|
+
const tx = db.transaction(STORE_NAME, 'readonly');
|
|
1525
|
+
const store = tx.objectStore(STORE_NAME);
|
|
1526
|
+
const request = store.getAll();
|
|
1527
|
+
|
|
1528
|
+
request.onsuccess = function () {
|
|
1529
|
+
resolve(request.result);
|
|
1530
|
+
};
|
|
1531
|
+
request.onerror = function () {
|
|
1532
|
+
reject(request.error);
|
|
1533
|
+
};
|
|
1534
|
+
});
|
|
1535
|
+
});
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
function saveApp(app) {
|
|
1539
|
+
return openDB().then(function (db) {
|
|
1540
|
+
return new Promise(function (resolve, reject) {
|
|
1541
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
1542
|
+
tx.objectStore(STORE_NAME).put(app);
|
|
1543
|
+
tx.oncomplete = function () { resolve(); };
|
|
1544
|
+
tx.onerror = function () { reject(tx.error); };
|
|
1545
|
+
tx.onabort = function () { reject(tx.error); };
|
|
1546
|
+
});
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
function deleteApp(id) {
|
|
1551
|
+
return openDB().then(function (db) {
|
|
1552
|
+
return new Promise(function (resolve, reject) {
|
|
1553
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
1554
|
+
tx.objectStore(STORE_NAME).delete(id);
|
|
1555
|
+
tx.oncomplete = function () { resolve(); };
|
|
1556
|
+
tx.onerror = function () { reject(tx.error); };
|
|
1557
|
+
tx.onabort = function () { reject(tx.error); };
|
|
1558
|
+
});
|
|
1559
|
+
});
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
// ── Config (localStorage) ─────────────────────────
|
|
1563
|
+
|
|
1564
|
+
const DEFAULT_CONFIG = {
|
|
1565
|
+
theme: 'light',
|
|
1566
|
+
defaultOpenMode: 'tab',
|
|
1567
|
+
aimeatUrl: '',
|
|
1568
|
+
language: 'en'
|
|
1569
|
+
};
|
|
1570
|
+
|
|
1571
|
+
function loadConfig() {
|
|
1572
|
+
try {
|
|
1573
|
+
return Object.assign({}, DEFAULT_CONFIG, JSON.parse(localStorage.getItem('appLauncherConfig') || '{}'));
|
|
1574
|
+
} catch (e) {
|
|
1575
|
+
return Object.assign({}, DEFAULT_CONFIG);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
function saveConfig(config) {
|
|
1580
|
+
localStorage.setItem('appLauncherConfig', JSON.stringify(config));
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
// ── ID Generator ─────────────────────────────────
|
|
1584
|
+
|
|
1585
|
+
function generateId() {
|
|
1586
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
1587
|
+
return crypto.randomUUID();
|
|
1588
|
+
}
|
|
1589
|
+
// Fallback for older browsers
|
|
1590
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
1591
|
+
var r = Math.random() * 16 | 0;
|
|
1592
|
+
var v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
1593
|
+
return v.toString(16);
|
|
1594
|
+
});
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
// ── File Reading Helper ─────────────────────────
|
|
1598
|
+
|
|
1599
|
+
function readFileAsText(file) {
|
|
1600
|
+
return new Promise(function (resolve, reject) {
|
|
1601
|
+
var reader = new FileReader();
|
|
1602
|
+
reader.onload = function () {
|
|
1603
|
+
resolve(reader.result);
|
|
1604
|
+
};
|
|
1605
|
+
reader.onerror = function () {
|
|
1606
|
+
reject(reader.error);
|
|
1607
|
+
};
|
|
1608
|
+
reader.readAsText(file);
|
|
1609
|
+
});
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
// ── ZIP Helpers ────────────────────────────────
|
|
1613
|
+
|
|
1614
|
+
function mimeFromExtension(name) {
|
|
1615
|
+
var ext = (name.split('.').pop() || '').toLowerCase();
|
|
1616
|
+
var map = {
|
|
1617
|
+
html: 'text/html', htm: 'text/html',
|
|
1618
|
+
css: 'text/css',
|
|
1619
|
+
js: 'application/javascript', mjs: 'application/javascript',
|
|
1620
|
+
json: 'application/json',
|
|
1621
|
+
svg: 'image/svg+xml',
|
|
1622
|
+
png: 'image/png',
|
|
1623
|
+
jpg: 'image/jpeg', jpeg: 'image/jpeg',
|
|
1624
|
+
gif: 'image/gif',
|
|
1625
|
+
webp: 'image/webp',
|
|
1626
|
+
ico: 'image/x-icon',
|
|
1627
|
+
woff: 'font/woff', woff2: 'font/woff2',
|
|
1628
|
+
ttf: 'font/ttf', otf: 'font/otf',
|
|
1629
|
+
eot: 'application/vnd.ms-fontobject',
|
|
1630
|
+
mp3: 'audio/mpeg', ogg: 'audio/ogg', wav: 'audio/wav',
|
|
1631
|
+
mp4: 'video/mp4', webm: 'video/webm',
|
|
1632
|
+
xml: 'application/xml',
|
|
1633
|
+
txt: 'text/plain',
|
|
1634
|
+
pdf: 'application/pdf'
|
|
1635
|
+
};
|
|
1636
|
+
return map[ext] || 'application/octet-stream';
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
function toBase64(uint8arr) {
|
|
1640
|
+
var binary = '';
|
|
1641
|
+
for (var i = 0; i < uint8arr.length; i++) {
|
|
1642
|
+
binary += String.fromCharCode(uint8arr[i]);
|
|
1643
|
+
}
|
|
1644
|
+
return btoa(binary);
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
// ── Minimal ZIP Parser ────────────────────────────
|
|
1648
|
+
|
|
1649
|
+
async function extractZip(arrayBuffer) {
|
|
1650
|
+
var view = new DataView(arrayBuffer);
|
|
1651
|
+
var files = [];
|
|
1652
|
+
var offset = 0;
|
|
1653
|
+
|
|
1654
|
+
while (offset < view.byteLength - 4) {
|
|
1655
|
+
var sig = view.getUint32(offset, true);
|
|
1656
|
+
if (sig !== 0x04034b50) break; // Not a local file header
|
|
1657
|
+
|
|
1658
|
+
var compressionMethod = view.getUint16(offset + 8, true);
|
|
1659
|
+
var compressedSize = view.getUint32(offset + 18, true);
|
|
1660
|
+
var nameLen = view.getUint16(offset + 26, true);
|
|
1661
|
+
var extraLen = view.getUint16(offset + 28, true);
|
|
1662
|
+
var name = new TextDecoder().decode(new Uint8Array(arrayBuffer, offset + 30, nameLen));
|
|
1663
|
+
var dataStart = offset + 30 + nameLen + extraLen;
|
|
1664
|
+
var rawData = new Uint8Array(arrayBuffer, dataStart, compressedSize);
|
|
1665
|
+
|
|
1666
|
+
var data;
|
|
1667
|
+
if (compressionMethod === 0) {
|
|
1668
|
+
data = rawData; // Stored (no compression)
|
|
1669
|
+
} else if (compressionMethod === 8) {
|
|
1670
|
+
// Deflate — use browser's DecompressionStream
|
|
1671
|
+
var ds = new DecompressionStream('raw');
|
|
1672
|
+
var writer = ds.writable.getWriter();
|
|
1673
|
+
writer.write(rawData);
|
|
1674
|
+
writer.close();
|
|
1675
|
+
var reader = ds.readable.getReader();
|
|
1676
|
+
var chunks = [];
|
|
1677
|
+
while (true) {
|
|
1678
|
+
var result = await reader.read();
|
|
1679
|
+
if (result.done) break;
|
|
1680
|
+
chunks.push(result.value);
|
|
1681
|
+
}
|
|
1682
|
+
var totalLen = chunks.reduce(function (s, c) { return s + c.length; }, 0);
|
|
1683
|
+
data = new Uint8Array(totalLen);
|
|
1684
|
+
var pos = 0;
|
|
1685
|
+
for (var ci = 0; ci < chunks.length; ci++) {
|
|
1686
|
+
data.set(chunks[ci], pos);
|
|
1687
|
+
pos += chunks[ci].length;
|
|
1688
|
+
}
|
|
1689
|
+
} else {
|
|
1690
|
+
throw new Error('Unsupported compression method: ' + compressionMethod);
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
if (!name.endsWith('/')) { // Skip directories
|
|
1694
|
+
files.push({ name: name, data: data });
|
|
1695
|
+
}
|
|
1696
|
+
offset = dataStart + compressedSize;
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
return files;
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
// ── ZIP Inline Bundler ────────────────────────────
|
|
1703
|
+
|
|
1704
|
+
async function bundleZip(files) {
|
|
1705
|
+
// 1. Find index.html or any .html file as the base
|
|
1706
|
+
var htmlFile = null;
|
|
1707
|
+
for (var i = 0; i < files.length; i++) {
|
|
1708
|
+
var lowerName = files[i].name.toLowerCase();
|
|
1709
|
+
if (lowerName === 'index.html' || lowerName.endsWith('/index.html')) {
|
|
1710
|
+
htmlFile = files[i];
|
|
1711
|
+
break;
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
if (!htmlFile) {
|
|
1715
|
+
for (var i = 0; i < files.length; i++) {
|
|
1716
|
+
if (files[i].name.toLowerCase().match(/\.html?$/)) {
|
|
1717
|
+
htmlFile = files[i];
|
|
1718
|
+
break;
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
if (!htmlFile) {
|
|
1723
|
+
throw new Error('No HTML file found in ZIP');
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
// 2. Determine the base path (directory containing the HTML file)
|
|
1727
|
+
var lastSlash = htmlFile.name.lastIndexOf('/');
|
|
1728
|
+
var basePath = lastSlash >= 0 ? htmlFile.name.substring(0, lastSlash + 1) : '';
|
|
1729
|
+
|
|
1730
|
+
// 3. Build a map of relative file paths to file data
|
|
1731
|
+
var fileMap = {};
|
|
1732
|
+
for (var i = 0; i < files.length; i++) {
|
|
1733
|
+
var fname = files[i].name;
|
|
1734
|
+
// Store path relative to base
|
|
1735
|
+
if (basePath && fname.startsWith(basePath)) {
|
|
1736
|
+
fileMap[fname.substring(basePath.length)] = files[i].data;
|
|
1737
|
+
}
|
|
1738
|
+
// Also store the full path for lookup
|
|
1739
|
+
fileMap[fname] = files[i].data;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
// Helper: resolve a reference relative to the HTML file's directory
|
|
1743
|
+
function resolveRef(ref) {
|
|
1744
|
+
// Strip leading ./
|
|
1745
|
+
var cleaned = ref.replace(/^\.\//, '');
|
|
1746
|
+
// Try direct lookup
|
|
1747
|
+
if (fileMap[cleaned]) return fileMap[cleaned];
|
|
1748
|
+
// Try with basePath prepended
|
|
1749
|
+
if (fileMap[basePath + cleaned]) return fileMap[basePath + cleaned];
|
|
1750
|
+
return null;
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
// Helper: get file content as text
|
|
1754
|
+
function fileAsText(data) {
|
|
1755
|
+
return new TextDecoder().decode(data);
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
// Helper: get file content as data URL
|
|
1759
|
+
function fileAsDataUrl(ref, data) {
|
|
1760
|
+
var mime = mimeFromExtension(ref);
|
|
1761
|
+
return 'data:' + mime + ';base64,' + toBase64(data);
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
var html = fileAsText(htmlFile.data);
|
|
1765
|
+
|
|
1766
|
+
// 4. Replace <link rel="stylesheet" href="..."> with inline <style>
|
|
1767
|
+
html = html.replace(/<link\s+[^>]*rel\s*=\s*["']stylesheet["'][^>]*>/gi, function (tag) {
|
|
1768
|
+
var hrefMatch = tag.match(/href\s*=\s*["']([^"']+)["']/i);
|
|
1769
|
+
if (!hrefMatch) return tag;
|
|
1770
|
+
var href = hrefMatch[1];
|
|
1771
|
+
var fileData = resolveRef(href);
|
|
1772
|
+
if (!fileData) return tag; // keep original if file not found
|
|
1773
|
+
var cssContent = fileAsText(fileData);
|
|
1774
|
+
// Inline CSS url() references within the stylesheet
|
|
1775
|
+
cssContent = inlineCssUrls(cssContent);
|
|
1776
|
+
return '<style>/* ' + href + ' */\n' + cssContent + '</style>';
|
|
1777
|
+
});
|
|
1778
|
+
|
|
1779
|
+
// 5. Replace script-src tags with inline script blocks
|
|
1780
|
+
html = html.replace(/<script\s+[^>]*src\s*=\s*["']([^"']+)["'][^>]*>\s*<\/script>/gi, function (tag, src) {
|
|
1781
|
+
var fileData = resolveRef(src);
|
|
1782
|
+
if (!fileData) return tag; // keep original if file not found
|
|
1783
|
+
return '<script>/* ' + src + ' */\n' + fileAsText(fileData) + '<\/script>';
|
|
1784
|
+
});
|
|
1785
|
+
|
|
1786
|
+
// 6. Replace src="..." and href="..." pointing to binary assets with data URLs
|
|
1787
|
+
html = html.replace(/(src|href)\s*=\s*["']([^"']+)["']/gi, function (match, attr, ref) {
|
|
1788
|
+
// Skip data: URLs, http(s) URLs, # anchors, and javascript:
|
|
1789
|
+
if (ref.match(/^(data:|https?:|#|javascript:|mailto:)/i)) return match;
|
|
1790
|
+
// Skip already-inlined stylesheets and scripts (they won't match since already replaced)
|
|
1791
|
+
var fileData = resolveRef(ref);
|
|
1792
|
+
if (!fileData) return match;
|
|
1793
|
+
var mime = mimeFromExtension(ref);
|
|
1794
|
+
// Only inline binary/image/font assets, not html/css/js (already handled above)
|
|
1795
|
+
if (mime.match(/^(image|font|audio|video)\//)) {
|
|
1796
|
+
return attr + '="' + fileAsDataUrl(ref, fileData) + '"';
|
|
1797
|
+
}
|
|
1798
|
+
return match;
|
|
1799
|
+
});
|
|
1800
|
+
|
|
1801
|
+
// 7. Replace CSS url(...) references in inline <style> blocks
|
|
1802
|
+
html = html.replace(/<style[^>]*>([\s\S]*?)<\/style>/gi, function (tag, cssContent) {
|
|
1803
|
+
var inlined = inlineCssUrls(cssContent);
|
|
1804
|
+
if (inlined !== cssContent) {
|
|
1805
|
+
return tag.replace(cssContent, inlined);
|
|
1806
|
+
}
|
|
1807
|
+
return tag;
|
|
1808
|
+
});
|
|
1809
|
+
|
|
1810
|
+
function inlineCssUrls(css) {
|
|
1811
|
+
return css.replace(/url\(\s*["']?([^"')]+)["']?\s*\)/gi, function (match, ref) {
|
|
1812
|
+
if (ref.match(/^(data:|https?:|#)/i)) return match;
|
|
1813
|
+
var fileData = resolveRef(ref);
|
|
1814
|
+
if (!fileData) return match;
|
|
1815
|
+
return 'url("' + fileAsDataUrl(ref, fileData) + '")';
|
|
1816
|
+
});
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
return html;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
// ── App Creation from ZIP ─────────────────────────
|
|
1823
|
+
|
|
1824
|
+
async function addAppFromZip(name, arrayBuffer, icon, tags, openMode) {
|
|
1825
|
+
var files = await extractZip(arrayBuffer);
|
|
1826
|
+
var bundledHtml = await bundleZip(files);
|
|
1827
|
+
var encoded = btoa(unescape(encodeURIComponent(bundledHtml)));
|
|
1828
|
+
var app = {
|
|
1829
|
+
id: generateId(),
|
|
1830
|
+
name: name,
|
|
1831
|
+
description: '',
|
|
1832
|
+
source: 'zip',
|
|
1833
|
+
url: null,
|
|
1834
|
+
blob: encoded,
|
|
1835
|
+
tags: tags,
|
|
1836
|
+
openMode: openMode,
|
|
1837
|
+
icon: icon || '\u{1F4E6}',
|
|
1838
|
+
screenshot: null,
|
|
1839
|
+
favorite: false,
|
|
1840
|
+
addedAt: new Date().toISOString(),
|
|
1841
|
+
lastOpenedAt: null
|
|
1842
|
+
};
|
|
1843
|
+
await saveApp(app);
|
|
1844
|
+
return app;
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
// ── App Creation from URL ───────────────────────
|
|
1848
|
+
|
|
1849
|
+
function addAppFromUrl(name, url, icon, tags, openMode) {
|
|
1850
|
+
var app = {
|
|
1851
|
+
id: generateId(),
|
|
1852
|
+
name: name,
|
|
1853
|
+
description: '',
|
|
1854
|
+
source: 'url',
|
|
1855
|
+
url: url,
|
|
1856
|
+
blob: null,
|
|
1857
|
+
tags: tags,
|
|
1858
|
+
openMode: openMode,
|
|
1859
|
+
icon: icon || '\u{1F4DD}',
|
|
1860
|
+
screenshot: null,
|
|
1861
|
+
favorite: false,
|
|
1862
|
+
addedAt: new Date().toISOString(),
|
|
1863
|
+
lastOpenedAt: null
|
|
1864
|
+
};
|
|
1865
|
+
return saveApp(app).then(function () {
|
|
1866
|
+
return app;
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
// ── App Creation from File ──────────────────────
|
|
1871
|
+
|
|
1872
|
+
function addAppFromFile(name, file, icon, tags, openMode) {
|
|
1873
|
+
return readFileAsText(file).then(function (content) {
|
|
1874
|
+
var encoded = btoa(unescape(encodeURIComponent(content)));
|
|
1875
|
+
var app = {
|
|
1876
|
+
id: generateId(),
|
|
1877
|
+
name: name,
|
|
1878
|
+
description: '',
|
|
1879
|
+
source: 'local',
|
|
1880
|
+
url: null,
|
|
1881
|
+
blob: encoded,
|
|
1882
|
+
tags: tags,
|
|
1883
|
+
openMode: openMode,
|
|
1884
|
+
icon: icon || '\u{1F4DD}',
|
|
1885
|
+
screenshot: null,
|
|
1886
|
+
favorite: false,
|
|
1887
|
+
addedAt: new Date().toISOString(),
|
|
1888
|
+
lastOpenedAt: null
|
|
1889
|
+
};
|
|
1890
|
+
return saveApp(app).then(function () {
|
|
1891
|
+
return app;
|
|
1892
|
+
});
|
|
1893
|
+
});
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
// ── App Creation from Pasted Source ─────────────
|
|
1897
|
+
|
|
1898
|
+
function addAppFromSource(name, sourceCode, icon, tags, openMode) {
|
|
1899
|
+
var encoded = btoa(unescape(encodeURIComponent(sourceCode)));
|
|
1900
|
+
var app = {
|
|
1901
|
+
id: generateId(),
|
|
1902
|
+
name: name,
|
|
1903
|
+
description: '',
|
|
1904
|
+
source: 'local',
|
|
1905
|
+
url: null,
|
|
1906
|
+
blob: encoded,
|
|
1907
|
+
tags: tags,
|
|
1908
|
+
openMode: openMode,
|
|
1909
|
+
icon: icon || '\u{1F4DD}',
|
|
1910
|
+
screenshot: null,
|
|
1911
|
+
favorite: false,
|
|
1912
|
+
addedAt: new Date().toISOString(),
|
|
1913
|
+
lastOpenedAt: null
|
|
1914
|
+
};
|
|
1915
|
+
return saveApp(app).then(function () {
|
|
1916
|
+
return app;
|
|
1917
|
+
});
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
// ── Modal State ─────────────────────────────────
|
|
1921
|
+
|
|
1922
|
+
var selectedFile = null;
|
|
1923
|
+
var editingAppId = null;
|
|
1924
|
+
|
|
1925
|
+
function showModal() {
|
|
1926
|
+
document.getElementById('modal-overlay').hidden = false;
|
|
1927
|
+
document.getElementById('modal-title').textContent = 'Add App';
|
|
1928
|
+
// Default to URL tab
|
|
1929
|
+
switchTab('url');
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
function closeModal() {
|
|
1933
|
+
document.getElementById('modal-overlay').hidden = true;
|
|
1934
|
+
// Reset form
|
|
1935
|
+
document.getElementById('app-url').value = '';
|
|
1936
|
+
document.getElementById('app-name').value = '';
|
|
1937
|
+
document.getElementById('app-icon').value = '';
|
|
1938
|
+
document.getElementById('app-tags').value = '';
|
|
1939
|
+
document.getElementById('app-open-mode').value = 'tab';
|
|
1940
|
+
document.getElementById('selected-file-name').textContent = '';
|
|
1941
|
+
document.getElementById('file-input').value = '';
|
|
1942
|
+
document.getElementById('app-paste-code').value = '';
|
|
1943
|
+
selectedFile = null;
|
|
1944
|
+
editingAppId = null;
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
function switchTab(tabName) {
|
|
1948
|
+
// Toggle tab buttons
|
|
1949
|
+
var tabs = document.querySelectorAll('.modal-tab');
|
|
1950
|
+
tabs.forEach(function (tab) {
|
|
1951
|
+
if (tab.getAttribute('data-tab') === tabName) {
|
|
1952
|
+
tab.classList.add('active');
|
|
1953
|
+
} else {
|
|
1954
|
+
tab.classList.remove('active');
|
|
1955
|
+
}
|
|
1956
|
+
});
|
|
1957
|
+
// Toggle tab content
|
|
1958
|
+
var contents = document.querySelectorAll('.tab-content');
|
|
1959
|
+
contents.forEach(function (content) {
|
|
1960
|
+
if (content.id === 'tab-' + tabName) {
|
|
1961
|
+
content.classList.add('active');
|
|
1962
|
+
} else {
|
|
1963
|
+
content.classList.remove('active');
|
|
1964
|
+
}
|
|
1965
|
+
});
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
function handleFileDrop(file) {
|
|
1969
|
+
if (!file) return;
|
|
1970
|
+
if (file.name.toLowerCase().endsWith('.zip')) {
|
|
1971
|
+
selectedFile = file;
|
|
1972
|
+
document.getElementById('selected-file-name').textContent = file.name;
|
|
1973
|
+
var nameInput = document.getElementById('app-name');
|
|
1974
|
+
if (!nameInput.value.trim()) {
|
|
1975
|
+
nameInput.value = file.name.replace(/\.zip$/i, '');
|
|
1976
|
+
}
|
|
1977
|
+
return;
|
|
1978
|
+
}
|
|
1979
|
+
if (!file.name.match(/\.html?$/i)) {
|
|
1980
|
+
alert('Please select an HTML or ZIP file (.html, .htm, or .zip)');
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1983
|
+
selectedFile = file;
|
|
1984
|
+
document.getElementById('selected-file-name').textContent = file.name;
|
|
1985
|
+
// Auto-fill name from filename if empty
|
|
1986
|
+
var nameInput = document.getElementById('app-name');
|
|
1987
|
+
if (!nameInput.value.trim()) {
|
|
1988
|
+
nameInput.value = file.name.replace(/\.html?$/i, '');
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
function handleSave() {
|
|
1993
|
+
var name = document.getElementById('app-name').value.trim();
|
|
1994
|
+
var icon = document.getElementById('app-icon').value.trim();
|
|
1995
|
+
var tagsRaw = document.getElementById('app-tags').value.trim();
|
|
1996
|
+
var openMode = document.getElementById('app-open-mode').value;
|
|
1997
|
+
|
|
1998
|
+
var tags = tagsRaw ? tagsRaw.split(',').map(function (t) { return t.trim(); }).filter(Boolean) : [];
|
|
1999
|
+
|
|
2000
|
+
// ── Edit mode: update existing app ──
|
|
2001
|
+
if (editingAppId) {
|
|
2002
|
+
var app = null;
|
|
2003
|
+
for (var i = 0; i < allApps.length; i++) {
|
|
2004
|
+
if (allApps[i].id === editingAppId) { app = allApps[i]; break; }
|
|
2005
|
+
}
|
|
2006
|
+
if (!app) {
|
|
2007
|
+
closeModal();
|
|
2008
|
+
return;
|
|
2009
|
+
}
|
|
2010
|
+
if (!name) {
|
|
2011
|
+
alert('Please enter a name');
|
|
2012
|
+
return;
|
|
2013
|
+
}
|
|
2014
|
+
app.name = name;
|
|
2015
|
+
app.icon = icon || app.icon;
|
|
2016
|
+
app.tags = tags;
|
|
2017
|
+
app.openMode = openMode;
|
|
2018
|
+
saveApp(app).then(function () {
|
|
2019
|
+
closeModal();
|
|
2020
|
+
renderApps();
|
|
2021
|
+
});
|
|
2022
|
+
return;
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
// ── Create mode ──
|
|
2026
|
+
var activeTab = document.querySelector('.modal-tab.active');
|
|
2027
|
+
var tabName = activeTab ? activeTab.getAttribute('data-tab') : 'url';
|
|
2028
|
+
|
|
2029
|
+
if (tabName === 'url') {
|
|
2030
|
+
var url = document.getElementById('app-url').value.trim();
|
|
2031
|
+
if (!url) {
|
|
2032
|
+
alert('Please enter a URL');
|
|
2033
|
+
return;
|
|
2034
|
+
}
|
|
2035
|
+
if (!name) {
|
|
2036
|
+
// Derive name from URL
|
|
2037
|
+
try {
|
|
2038
|
+
name = new URL(url).hostname;
|
|
2039
|
+
} catch (e) {
|
|
2040
|
+
name = url;
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
addAppFromUrl(name, url, icon, tags, openMode).then(function () {
|
|
2044
|
+
closeModal();
|
|
2045
|
+
renderApps();
|
|
2046
|
+
});
|
|
2047
|
+
} else if (tabName === 'paste') {
|
|
2048
|
+
var pastedCode = document.getElementById('app-paste-code').value.trim();
|
|
2049
|
+
if (!pastedCode) {
|
|
2050
|
+
alert('Please paste your HTML source code');
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
2053
|
+
if (!name) {
|
|
2054
|
+
// Try to extract title from HTML
|
|
2055
|
+
var titleMatch = pastedCode.match(/<title[^>]*>([^<]+)<\/title>/i);
|
|
2056
|
+
name = titleMatch ? titleMatch[1].trim() : 'Pasted App';
|
|
2057
|
+
}
|
|
2058
|
+
addAppFromSource(name, pastedCode, icon, tags, openMode).then(function () {
|
|
2059
|
+
closeModal();
|
|
2060
|
+
renderApps();
|
|
2061
|
+
});
|
|
2062
|
+
} else if (tabName === 'file') {
|
|
2063
|
+
if (!selectedFile) {
|
|
2064
|
+
alert('Please select a file');
|
|
2065
|
+
return;
|
|
2066
|
+
}
|
|
2067
|
+
if (selectedFile.name.toLowerCase().endsWith('.zip')) {
|
|
2068
|
+
// ZIP file — extract and bundle
|
|
2069
|
+
if (!name) {
|
|
2070
|
+
name = selectedFile.name.replace(/\.zip$/i, '');
|
|
2071
|
+
}
|
|
2072
|
+
selectedFile.arrayBuffer().then(function (arrayBuffer) {
|
|
2073
|
+
return addAppFromZip(name, arrayBuffer, icon, tags, openMode);
|
|
2074
|
+
}).then(function () {
|
|
2075
|
+
closeModal();
|
|
2076
|
+
renderApps();
|
|
2077
|
+
}).catch(function (err) {
|
|
2078
|
+
alert('ZIP import failed: ' + (err.message || err));
|
|
2079
|
+
});
|
|
2080
|
+
} else {
|
|
2081
|
+
// HTML file
|
|
2082
|
+
if (!name) {
|
|
2083
|
+
name = selectedFile.name.replace(/\.html?$/i, '');
|
|
2084
|
+
}
|
|
2085
|
+
addAppFromFile(name, selectedFile, icon, tags, openMode).then(function () {
|
|
2086
|
+
closeModal();
|
|
2087
|
+
renderApps();
|
|
2088
|
+
});
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
// ── Module-level state ──────────────────────────────
|
|
2094
|
+
|
|
2095
|
+
var allApps = [];
|
|
2096
|
+
var activeTag = null;
|
|
2097
|
+
var searchQuery = '';
|
|
2098
|
+
|
|
2099
|
+
// ── Helpers ────────────────────────────────────────
|
|
2100
|
+
|
|
2101
|
+
function escapeHtml(str) {
|
|
2102
|
+
var div = document.createElement('div');
|
|
2103
|
+
div.textContent = str;
|
|
2104
|
+
return div.innerHTML;
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
function sourceLabel(source) {
|
|
2108
|
+
switch (source) {
|
|
2109
|
+
case 'local': return '\u{1F4C4} local';
|
|
2110
|
+
case 'url': return '\u{1F310} url';
|
|
2111
|
+
case 'aimeat': return '\u{1F4E6} aimeat';
|
|
2112
|
+
case 'zip': return '\u{1F4E6} zip';
|
|
2113
|
+
default: return source || 'unknown';
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
// ── Tag Rendering ─────────────────────────────────
|
|
2118
|
+
|
|
2119
|
+
function renderTags() {
|
|
2120
|
+
var tagBar = document.getElementById('tag-bar');
|
|
2121
|
+
var tagSet = {};
|
|
2122
|
+
var hasFavorites = false;
|
|
2123
|
+
|
|
2124
|
+
for (var i = 0; i < allApps.length; i++) {
|
|
2125
|
+
var app = allApps[i];
|
|
2126
|
+
if (app.favorite) hasFavorites = true;
|
|
2127
|
+
if (app.tags && app.tags.length) {
|
|
2128
|
+
for (var j = 0; j < app.tags.length; j++) {
|
|
2129
|
+
tagSet[app.tags[j]] = true;
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
var uniqueTags = Object.keys(tagSet).sort();
|
|
2135
|
+
var html = '';
|
|
2136
|
+
|
|
2137
|
+
// "All" button
|
|
2138
|
+
html += '<button class="tag' + (activeTag === null ? ' active' : '') + '" onclick="window._launcher.filterByTag(null)">All</button>';
|
|
2139
|
+
|
|
2140
|
+
// Favorites button (only if any favorites exist)
|
|
2141
|
+
if (hasFavorites) {
|
|
2142
|
+
html += '<button class="tag' + (activeTag === '__favorites__' ? ' active' : '') + '" onclick="window._launcher.filterByTag(\'__favorites__\')">\u2B50 Favorites</button>';
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
// One button per unique tag
|
|
2146
|
+
for (var k = 0; k < uniqueTags.length; k++) {
|
|
2147
|
+
var tag = uniqueTags[k];
|
|
2148
|
+
html += '<button class="tag' + (activeTag === tag ? ' active' : '') + '" onclick="window._launcher.filterByTag(\'' + escapeHtml(tag.replace(/'/g, "\\'")) + '\')">' + escapeHtml(tag) + '</button>';
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
tagBar.innerHTML = html;
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
// ── Tag Filtering ─────────────────────────────────
|
|
2155
|
+
|
|
2156
|
+
function filterByTag(tag) {
|
|
2157
|
+
activeTag = tag;
|
|
2158
|
+
renderApps();
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
// ── Launch App ──────────────────────────────────
|
|
2162
|
+
|
|
2163
|
+
function launchApp(id, mode) {
|
|
2164
|
+
var app = null;
|
|
2165
|
+
for (var i = 0; i < allApps.length; i++) {
|
|
2166
|
+
if (allApps[i].id === id) { app = allApps[i]; break; }
|
|
2167
|
+
}
|
|
2168
|
+
if (!app) return;
|
|
2169
|
+
|
|
2170
|
+
app.lastOpenedAt = new Date().toISOString();
|
|
2171
|
+
saveApp(app).then(function () {
|
|
2172
|
+
if (mode === 'tab') {
|
|
2173
|
+
launchInTab(app);
|
|
2174
|
+
} else if (mode === 'iframe') {
|
|
2175
|
+
launchInIframe(app);
|
|
2176
|
+
}
|
|
2177
|
+
});
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
function launchInTab(app) {
|
|
2181
|
+
if (app.source === 'url' && app.url) {
|
|
2182
|
+
window.open(app.url, '_blank', 'noopener');
|
|
2183
|
+
} else if (app.blob) {
|
|
2184
|
+
// Use blob URL instead of document.write to maintain browser sandbox
|
|
2185
|
+
var html = decodeURIComponent(escape(atob(app.blob)));
|
|
2186
|
+
var blob = new Blob([html], { type: 'text/html' });
|
|
2187
|
+
var blobUrl = URL.createObjectURL(blob);
|
|
2188
|
+
window.open(blobUrl, '_blank', 'noopener');
|
|
2189
|
+
// Revoke after a short delay to allow the tab to load
|
|
2190
|
+
setTimeout(function () { URL.revokeObjectURL(blobUrl); }, 5000);
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
function launchInIframe(app) {
|
|
2195
|
+
var view = document.getElementById('iframe-view');
|
|
2196
|
+
var iframe = document.getElementById('app-iframe');
|
|
2197
|
+
var title = document.getElementById('iframe-title');
|
|
2198
|
+
|
|
2199
|
+
title.textContent = app.name || 'App';
|
|
2200
|
+
iframe.dataset.appId = app.id;
|
|
2201
|
+
|
|
2202
|
+
if (app.source === 'url' && app.url) {
|
|
2203
|
+
iframe.removeAttribute('srcdoc');
|
|
2204
|
+
iframe.src = app.url;
|
|
2205
|
+
currentIframeUrl = app.url;
|
|
2206
|
+
} else if (app.blob) {
|
|
2207
|
+
var html = decodeURIComponent(escape(atob(app.blob)));
|
|
2208
|
+
iframe.removeAttribute('src');
|
|
2209
|
+
iframe.srcdoc = html;
|
|
2210
|
+
currentIframeUrl = '';
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
view.hidden = false;
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
// ── Rendering ─────────────────────────────────────
|
|
2217
|
+
|
|
2218
|
+
function renderApps() {
|
|
2219
|
+
getAllApps().then(function (apps) {
|
|
2220
|
+
allApps = apps;
|
|
2221
|
+
|
|
2222
|
+
// Sort: favorites first, then by sortOrder (if set), then by date
|
|
2223
|
+
allApps.sort(function (a, b) {
|
|
2224
|
+
// Favorites first
|
|
2225
|
+
if (a.favorite && !b.favorite) return -1;
|
|
2226
|
+
if (!a.favorite && b.favorite) return 1;
|
|
2227
|
+
// Then by explicit sortOrder if present
|
|
2228
|
+
var oA = typeof a.sortOrder === 'number' ? a.sortOrder : Infinity;
|
|
2229
|
+
var oB = typeof b.sortOrder === 'number' ? b.sortOrder : Infinity;
|
|
2230
|
+
if (oA !== oB) return oA - oB;
|
|
2231
|
+
// Then by most recently used/added
|
|
2232
|
+
var dateA = a.lastOpenedAt || a.addedAt || '';
|
|
2233
|
+
var dateB = b.lastOpenedAt || b.addedAt || '';
|
|
2234
|
+
if (dateA > dateB) return -1;
|
|
2235
|
+
if (dateA < dateB) return 1;
|
|
2236
|
+
return 0;
|
|
2237
|
+
});
|
|
2238
|
+
|
|
2239
|
+
// Filter by activeTag
|
|
2240
|
+
var filtered = allApps;
|
|
2241
|
+
if (activeTag === '__favorites__') {
|
|
2242
|
+
filtered = allApps.filter(function (app) { return app.favorite; });
|
|
2243
|
+
} else if (activeTag !== null) {
|
|
2244
|
+
filtered = allApps.filter(function (app) {
|
|
2245
|
+
return app.tags && app.tags.indexOf(activeTag) !== -1;
|
|
2246
|
+
});
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
// Filter by searchQuery
|
|
2250
|
+
if (searchQuery) {
|
|
2251
|
+
var q = searchQuery.toLowerCase();
|
|
2252
|
+
filtered = filtered.filter(function (app) {
|
|
2253
|
+
if (app.name && app.name.toLowerCase().indexOf(q) !== -1) return true;
|
|
2254
|
+
if (app.tags) {
|
|
2255
|
+
for (var i = 0; i < app.tags.length; i++) {
|
|
2256
|
+
if (app.tags[i].toLowerCase().indexOf(q) !== -1) return true;
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
return false;
|
|
2260
|
+
});
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
var grid = document.getElementById('app-grid');
|
|
2264
|
+
|
|
2265
|
+
if (filtered.length === 0) {
|
|
2266
|
+
if (!activeTag && !searchQuery && allApps.length === 0) {
|
|
2267
|
+
// No apps at all — show helpful empty state
|
|
2268
|
+
grid.innerHTML =
|
|
2269
|
+
'<div class="empty-state">' +
|
|
2270
|
+
'<div class="empty-icon">\u{1F680}</div>' +
|
|
2271
|
+
'<h3>No apps yet</h3>' +
|
|
2272
|
+
'<p>Add your first app using the <strong>+</strong> button above</p>' +
|
|
2273
|
+
'<span class="empty-formats">Supports: HTML files, URLs, ZIP packages, AIMEAT imports</span>' +
|
|
2274
|
+
'</div>';
|
|
2275
|
+
} else {
|
|
2276
|
+
// Filters active but no matches
|
|
2277
|
+
grid.innerHTML =
|
|
2278
|
+
'<div class="empty-state">' +
|
|
2279
|
+
'<div class="empty-icon">\u{1F50D}</div>' +
|
|
2280
|
+
'<h3>No matches</h3>' +
|
|
2281
|
+
'<p>No apps match the current filter. Try a different search term or tag.</p>' +
|
|
2282
|
+
'</div>';
|
|
2283
|
+
}
|
|
2284
|
+
} else {
|
|
2285
|
+
var html = '';
|
|
2286
|
+
for (var i = 0; i < filtered.length; i++) {
|
|
2287
|
+
var app = filtered[i];
|
|
2288
|
+
var iconDisplay = app.icon || '\u{1F4DD}';
|
|
2289
|
+
html +=
|
|
2290
|
+
'<div class="app-card" draggable="true" data-id="' + escapeHtml(app.id) + '" onclick="window._launcher.launchApp(\'' + escapeHtml(app.id) + '\', \'' + escapeHtml(app.openMode || 'tab') + '\')" oncontextmenu="window._launcher.showContextMenu(event, \'' + escapeHtml(app.id) + '\')" ondragstart="window._launcher.onCardDragStart(event)" ondragend="window._launcher.onCardDragEnd(event)" ondragover="window._launcher.onCardDragOver(event)" ondrop="window._launcher.onCardDrop(event)" style="animation-delay:' + (i * 0.04) + 's">' +
|
|
2291
|
+
'<button class="card-menu-btn" onclick="event.stopPropagation(); window._launcher.showContextMenu(event, \'' + escapeHtml(app.id) + '\')" title="Menu">\u22EE</button>' +
|
|
2292
|
+
'<div class="app-icon">' + escapeHtml(iconDisplay) + '</div>' +
|
|
2293
|
+
'<div class="app-name">' + escapeHtml(app.name) + '</div>' +
|
|
2294
|
+
'<div class="app-source">' + sourceLabel(app.source) + '</div>' +
|
|
2295
|
+
'<div class="app-actions">' +
|
|
2296
|
+
'<button onclick="event.stopPropagation(); window._launcher.launchApp(\'' + escapeHtml(app.id) + '\', \'tab\')" title="Open in tab">\u25B6 Tab</button>' +
|
|
2297
|
+
'<button onclick="event.stopPropagation(); window._launcher.launchApp(\'' + escapeHtml(app.id) + '\', \'iframe\')" title="Open in iframe">\u25FB</button>' +
|
|
2298
|
+
'</div>' +
|
|
2299
|
+
(app.favorite ? '<span class="fav-star visible">\u2B50</span>' : '') +
|
|
2300
|
+
'</div>';
|
|
2301
|
+
}
|
|
2302
|
+
grid.innerHTML = html;
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2305
|
+
// Update stats
|
|
2306
|
+
var statsEl = document.getElementById('stats');
|
|
2307
|
+
var totalSize = 0;
|
|
2308
|
+
for (var s = 0; s < allApps.length; s++) {
|
|
2309
|
+
if (allApps[s].blob) {
|
|
2310
|
+
totalSize += allApps[s].blob.length;
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
var sizeLabel = totalSize < 1024 ? totalSize + ' B'
|
|
2314
|
+
: totalSize < 1048576 ? (totalSize / 1024).toFixed(1) + ' KB'
|
|
2315
|
+
: (totalSize / 1048576).toFixed(1) + ' MB';
|
|
2316
|
+
statsEl.textContent = allApps.length + ' app' + (allApps.length !== 1 ? 's' : '') + ' \u00B7 ' + sizeLabel + ' stored';
|
|
2317
|
+
|
|
2318
|
+
// Render tag bar
|
|
2319
|
+
renderTags();
|
|
2320
|
+
|
|
2321
|
+
// Render recently opened strip
|
|
2322
|
+
renderRecentlyOpened();
|
|
2323
|
+
});
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
function renderRecentlyOpened() {
|
|
2327
|
+
var section = document.getElementById('recent-section');
|
|
2328
|
+
var strip = document.getElementById('recent-strip');
|
|
2329
|
+
var recent = allApps
|
|
2330
|
+
.filter(function(a) { return a.lastOpenedAt; })
|
|
2331
|
+
.sort(function(a, b) { return (b.lastOpenedAt || '') > (a.lastOpenedAt || '') ? 1 : -1; })
|
|
2332
|
+
.slice(0, 5);
|
|
2333
|
+
if (recent.length === 0) { section.style.display = 'none'; return; }
|
|
2334
|
+
section.style.display = 'block';
|
|
2335
|
+
strip.innerHTML = recent.map(function(app) {
|
|
2336
|
+
var icon = app.icon || '\u{1F4DD}';
|
|
2337
|
+
return '<div style="background:var(--surface-glass);border:1px solid var(--border-subtle);border-radius:10px;padding:.6rem .8rem;cursor:pointer;min-width:120px;flex-shrink:0;transition:all .15s" onclick="window._launcher.launchApp(\'' + escapeHtml(app.id) + '\', \'' + escapeHtml(app.openMode || 'tab') + '\')" onmouseover="this.style.borderColor=\'#D1D5DB\'" onmouseout="this.style.borderColor=\'#E5E7EB\'">' +
|
|
2338
|
+
'<div style="font-size:1.3rem;text-align:center">' + escapeHtml(icon) + '</div>' +
|
|
2339
|
+
'<div style="font-size:.75rem;font-weight:600;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100px">' + escapeHtml(app.name) + '</div>' +
|
|
2340
|
+
'</div>';
|
|
2341
|
+
}).join('');
|
|
2342
|
+
}
|
|
2343
|
+
|
|
2344
|
+
// ── Iframe helpers ────────────────────────────────
|
|
2345
|
+
|
|
2346
|
+
var currentIframeUrl = '';
|
|
2347
|
+
|
|
2348
|
+
function closeIframe() {
|
|
2349
|
+
var view = document.getElementById('iframe-view');
|
|
2350
|
+
var iframe = document.getElementById('app-iframe');
|
|
2351
|
+
view.hidden = true;
|
|
2352
|
+
iframe.removeAttribute('src');
|
|
2353
|
+
iframe.removeAttribute('srcdoc');
|
|
2354
|
+
delete iframe.dataset.appId;
|
|
2355
|
+
currentIframeUrl = '';
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
function openExternal() {
|
|
2359
|
+
var iframe = document.getElementById('app-iframe');
|
|
2360
|
+
var appId = iframe.dataset.appId;
|
|
2361
|
+
if (currentIframeUrl) {
|
|
2362
|
+
window.open(currentIframeUrl, '_blank');
|
|
2363
|
+
} else if (appId) {
|
|
2364
|
+
// Blob app — find it and launch in tab
|
|
2365
|
+
var app = null;
|
|
2366
|
+
for (var i = 0; i < allApps.length; i++) {
|
|
2367
|
+
if (allApps[i].id === appId) { app = allApps[i]; break; }
|
|
2368
|
+
}
|
|
2369
|
+
if (app) launchInTab(app);
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
// ── Context Menu ────────────────────────────────
|
|
2374
|
+
|
|
2375
|
+
var contextAppId = null;
|
|
2376
|
+
|
|
2377
|
+
function showContextMenu(event, id) {
|
|
2378
|
+
if (event.preventDefault) event.preventDefault();
|
|
2379
|
+
if (event.stopPropagation) event.stopPropagation();
|
|
2380
|
+
contextAppId = id;
|
|
2381
|
+
|
|
2382
|
+
var menu = document.getElementById('context-menu');
|
|
2383
|
+
menu.hidden = false;
|
|
2384
|
+
|
|
2385
|
+
// Position at cursor, but keep on screen
|
|
2386
|
+
var x = event.clientX;
|
|
2387
|
+
var y = event.clientY;
|
|
2388
|
+
var menuWidth = 200; // approximate min-width
|
|
2389
|
+
var menuHeight = 160; // approximate height
|
|
2390
|
+
|
|
2391
|
+
if (x + menuWidth > window.innerWidth) {
|
|
2392
|
+
x = window.innerWidth - menuWidth - 8;
|
|
2393
|
+
}
|
|
2394
|
+
if (y + menuHeight > window.innerHeight) {
|
|
2395
|
+
y = window.innerHeight - menuHeight - 8;
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
menu.style.left = x + 'px';
|
|
2399
|
+
menu.style.top = y + 'px';
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
function hideContextMenu() {
|
|
2403
|
+
var menu = document.getElementById('context-menu');
|
|
2404
|
+
menu.hidden = true;
|
|
2405
|
+
contextAppId = null;
|
|
2406
|
+
}
|
|
2407
|
+
|
|
2408
|
+
function handleContextAction(action) {
|
|
2409
|
+
if (!contextAppId) return;
|
|
2410
|
+
var appId = contextAppId;
|
|
2411
|
+
hideContextMenu();
|
|
2412
|
+
|
|
2413
|
+
var app = null;
|
|
2414
|
+
for (var i = 0; i < allApps.length; i++) {
|
|
2415
|
+
if (allApps[i].id === appId) { app = allApps[i]; break; }
|
|
2416
|
+
}
|
|
2417
|
+
if (!app) return;
|
|
2418
|
+
|
|
2419
|
+
switch (action) {
|
|
2420
|
+
case 'edit':
|
|
2421
|
+
// Open modal pre-filled with app data
|
|
2422
|
+
editingAppId = appId;
|
|
2423
|
+
document.getElementById('modal-title').textContent = 'Edit App';
|
|
2424
|
+
document.getElementById('app-name').value = app.name || '';
|
|
2425
|
+
document.getElementById('app-icon').value = app.icon || '';
|
|
2426
|
+
document.getElementById('app-tags').value = (app.tags || []).join(', ');
|
|
2427
|
+
document.getElementById('app-open-mode').value = app.openMode || 'tab';
|
|
2428
|
+
|
|
2429
|
+
// Set the correct source tab
|
|
2430
|
+
if (app.source === 'url') {
|
|
2431
|
+
switchTab('url');
|
|
2432
|
+
document.getElementById('app-url').value = app.url || '';
|
|
2433
|
+
} else {
|
|
2434
|
+
switchTab('file');
|
|
2435
|
+
document.getElementById('selected-file-name').textContent = '(existing file)';
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
document.getElementById('modal-overlay').hidden = false;
|
|
2439
|
+
break;
|
|
2440
|
+
|
|
2441
|
+
case 'favorite':
|
|
2442
|
+
app.favorite = !app.favorite;
|
|
2443
|
+
saveApp(app).then(function () {
|
|
2444
|
+
renderApps();
|
|
2445
|
+
});
|
|
2446
|
+
break;
|
|
2447
|
+
|
|
2448
|
+
case 'toggle-mode':
|
|
2449
|
+
app.openMode = app.openMode === 'iframe' ? 'tab' : 'iframe';
|
|
2450
|
+
saveApp(app).then(function () {
|
|
2451
|
+
renderApps();
|
|
2452
|
+
});
|
|
2453
|
+
break;
|
|
2454
|
+
|
|
2455
|
+
case 'view-source':
|
|
2456
|
+
viewSource(app);
|
|
2457
|
+
break;
|
|
2458
|
+
|
|
2459
|
+
case 'delete':
|
|
2460
|
+
if (confirm('Delete "' + (app.name || 'this app') + '"?')) {
|
|
2461
|
+
deleteApp(appId).then(function () {
|
|
2462
|
+
renderApps();
|
|
2463
|
+
loadPublishedApps();
|
|
2464
|
+
});
|
|
2465
|
+
}
|
|
2466
|
+
break;
|
|
2467
|
+
|
|
2468
|
+
case 'publish':
|
|
2469
|
+
showPublishModal(appId);
|
|
2470
|
+
break;
|
|
2471
|
+
|
|
2472
|
+
case 'improve-ai':
|
|
2473
|
+
openPromptBuilder(app);
|
|
2474
|
+
break;
|
|
2475
|
+
|
|
2476
|
+
case 'share-prompt':
|
|
2477
|
+
generateSharePrompt(app);
|
|
2478
|
+
break;
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2482
|
+
// ── View Source ──────────────────────────────────
|
|
2483
|
+
|
|
2484
|
+
function viewSource(app) {
|
|
2485
|
+
var overlay = document.getElementById('source-overlay');
|
|
2486
|
+
var textarea = document.getElementById('source-code');
|
|
2487
|
+
var title = document.getElementById('source-title');
|
|
2488
|
+
var saveBtn = document.getElementById('save-source-btn');
|
|
2489
|
+
|
|
2490
|
+
title.textContent = 'View / Edit Source: ' + (app.name || 'App');
|
|
2491
|
+
|
|
2492
|
+
var isEditable = !!app.blob; // Only blob-based apps can be edited
|
|
2493
|
+
if (app.blob) {
|
|
2494
|
+
textarea.value = decodeURIComponent(escape(atob(app.blob)));
|
|
2495
|
+
} else if (app.url) {
|
|
2496
|
+
textarea.value = '// This app is URL-based (' + app.url + ')\n// Source code is not stored locally.\n// Open the URL to view the app.';
|
|
2497
|
+
} else {
|
|
2498
|
+
textarea.value = '// No source available';
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
textarea.readOnly = !isEditable;
|
|
2502
|
+
saveBtn.disabled = true;
|
|
2503
|
+
saveBtn.style.display = isEditable ? '' : 'none';
|
|
2504
|
+
overlay.hidden = false;
|
|
2505
|
+
// Store app metadata for save and prompt
|
|
2506
|
+
overlay.dataset.appName = app.name || 'App';
|
|
2507
|
+
overlay.dataset.appId = app.id || '';
|
|
2508
|
+
overlay.dataset.originalSource = textarea.value;
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
// ── Share as Prompt ────────────────────────────
|
|
2512
|
+
|
|
2513
|
+
function generateSharePrompt(app) {
|
|
2514
|
+
if (!app || !app.blob) {
|
|
2515
|
+
alert('Only local HTML apps can be shared as prompts.');
|
|
2516
|
+
return;
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2519
|
+
var source = decodeURIComponent(escape(atob(app.blob)));
|
|
2520
|
+
var prompt = 'Recreate this HTML app exactly as provided.\n\n';
|
|
2521
|
+
prompt += 'App name: ' + (app.name || 'Untitled') + '\n';
|
|
2522
|
+
if (app.tags && app.tags.length) {
|
|
2523
|
+
prompt += 'Tags: ' + app.tags.join(', ') + '\n';
|
|
2524
|
+
}
|
|
2525
|
+
prompt += '\nReturn the COMPLETE HTML file below without modifications.\n';
|
|
2526
|
+
prompt += 'If the user asks for changes, apply them to this source.\n\n';
|
|
2527
|
+
prompt += '--- Source Code ---\n' + source;
|
|
2528
|
+
|
|
2529
|
+
navigator.clipboard.writeText(prompt).then(function() {
|
|
2530
|
+
alert('Share prompt copied! Paste it into any AI chat to recreate this app.');
|
|
2531
|
+
}).catch(function() {
|
|
2532
|
+
// Fallback: show in source overlay
|
|
2533
|
+
var overlay = document.getElementById('source-overlay');
|
|
2534
|
+
var textarea = document.getElementById('source-code');
|
|
2535
|
+
var title = document.getElementById('source-title');
|
|
2536
|
+
var saveBtn = document.getElementById('save-source-btn');
|
|
2537
|
+
title.textContent = 'Share Prompt: ' + (app.name || 'App');
|
|
2538
|
+
textarea.value = prompt;
|
|
2539
|
+
textarea.readOnly = true;
|
|
2540
|
+
saveBtn.style.display = 'none';
|
|
2541
|
+
overlay.hidden = false;
|
|
2542
|
+
overlay.dataset.appId = '';
|
|
2543
|
+
overlay.dataset.originalSource = '';
|
|
2544
|
+
});
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
// ── Generate Homepage Prompt ──────────────────────
|
|
2548
|
+
|
|
2549
|
+
function generateHomepagePrompt() {
|
|
2550
|
+
if (allApps.length === 0) {
|
|
2551
|
+
alert('Add some apps first before generating a homepage.');
|
|
2552
|
+
return;
|
|
2553
|
+
}
|
|
2554
|
+
|
|
2555
|
+
var appList = allApps.map(function(app) {
|
|
2556
|
+
var launchInfo = '';
|
|
2557
|
+
if (app.url) {
|
|
2558
|
+
launchInfo = 'URL: ' + app.url;
|
|
2559
|
+
} else {
|
|
2560
|
+
launchInfo = 'Local HTML app (user will open it from their launcher)';
|
|
2561
|
+
}
|
|
2562
|
+
return '- ' + (app.icon || '') + ' ' + app.name +
|
|
2563
|
+
(app.description ? ' (' + app.description + ')' : '') +
|
|
2564
|
+
' [' + launchInfo + ']' +
|
|
2565
|
+
(app.tags.length ? ' Tags: ' + app.tags.join(', ') : '');
|
|
2566
|
+
}).join('\n');
|
|
2567
|
+
|
|
2568
|
+
var prompt = 'Create a single HTML file that serves as my personal homepage/dashboard.\n\n' +
|
|
2569
|
+
'My apps:\n' + appList + '\n\n' +
|
|
2570
|
+
'Requirements:\n' +
|
|
2571
|
+
'- Show each app as a clickable card with its icon and name\n' +
|
|
2572
|
+
'- For URL-based apps, clicking opens the URL in a new tab\n' +
|
|
2573
|
+
'- For local apps, show a note that they can be opened from the App Launcher\n' +
|
|
2574
|
+
'- Modern, responsive design with light theme\n' +
|
|
2575
|
+
'- Group apps by their tags if they have tags\n' +
|
|
2576
|
+
'- Everything in one self-contained HTML file, no external dependencies\n' +
|
|
2577
|
+
'- Add a header with my name/title (I will customize this)\n' +
|
|
2578
|
+
'- Make it visually distinctive and professional';
|
|
2579
|
+
|
|
2580
|
+
// Reuse the source overlay for displaying the prompt
|
|
2581
|
+
var overlay = document.getElementById('source-overlay');
|
|
2582
|
+
var textarea = document.getElementById('source-code');
|
|
2583
|
+
var title = document.getElementById('source-title');
|
|
2584
|
+
|
|
2585
|
+
title.textContent = 'Generate Homepage - Copy this prompt to AI';
|
|
2586
|
+
textarea.value = prompt;
|
|
2587
|
+
overlay.dataset.appName = 'Homepage';
|
|
2588
|
+
overlay.hidden = false;
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
// ── Theme ────────────────────────────────────────
|
|
2592
|
+
|
|
2593
|
+
function applyTheme(theme) {
|
|
2594
|
+
if (theme === 'light') {
|
|
2595
|
+
document.documentElement.setAttribute('data-theme', 'light');
|
|
2596
|
+
} else {
|
|
2597
|
+
document.documentElement.removeAttribute('data-theme');
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2601
|
+
// ── Settings ────────────────────────────────────
|
|
2602
|
+
|
|
2603
|
+
function openSettings() {
|
|
2604
|
+
var config = loadConfig();
|
|
2605
|
+
document.getElementById('setting-theme').value = config.theme || 'dark';
|
|
2606
|
+
document.getElementById('setting-open-mode').value = config.defaultOpenMode || 'tab';
|
|
2607
|
+
document.getElementById('setting-aimeat-url').value = config.aimeatUrl || '';
|
|
2608
|
+
document.getElementById('settings-overlay').hidden = false;
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
function saveSettings() {
|
|
2612
|
+
var config = loadConfig();
|
|
2613
|
+
config.theme = document.getElementById('setting-theme').value;
|
|
2614
|
+
config.defaultOpenMode = document.getElementById('setting-open-mode').value;
|
|
2615
|
+
config.aimeatUrl = document.getElementById('setting-aimeat-url').value.trim();
|
|
2616
|
+
saveConfig(config);
|
|
2617
|
+
applyTheme(config.theme);
|
|
2618
|
+
document.getElementById('settings-overlay').hidden = true;
|
|
2619
|
+
// Sync config to server (best-effort)
|
|
2620
|
+
syncConfigToServer(config);
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
function syncConfigToServer(config) {
|
|
2624
|
+
var url = config.aimeatUrl;
|
|
2625
|
+
if (!url) return;
|
|
2626
|
+
url = url.replace(/\/+$/, '');
|
|
2627
|
+
// Only sync safe fields, not the URL itself
|
|
2628
|
+
var syncPayload = {
|
|
2629
|
+
theme: config.theme,
|
|
2630
|
+
defaultOpenMode: config.defaultOpenMode,
|
|
2631
|
+
language: config.language || 'en'
|
|
2632
|
+
};
|
|
2633
|
+
fetch(url + '/v1/auth/anonymous', { method: 'POST' })
|
|
2634
|
+
.then(function (r) { return r.json(); })
|
|
2635
|
+
.then(function (auth) {
|
|
2636
|
+
var token = auth.data && auth.data.token;
|
|
2637
|
+
if (!token) return;
|
|
2638
|
+
return fetch(url + '/v1/memory', {
|
|
2639
|
+
method: 'POST',
|
|
2640
|
+
headers: {
|
|
2641
|
+
'Content-Type': 'application/json',
|
|
2642
|
+
'Authorization': 'Bearer ' + token
|
|
2643
|
+
},
|
|
2644
|
+
body: JSON.stringify({
|
|
2645
|
+
key: 'app-launcher/config',
|
|
2646
|
+
value: syncPayload,
|
|
2647
|
+
visibility: 'private'
|
|
2648
|
+
})
|
|
2649
|
+
});
|
|
2650
|
+
})
|
|
2651
|
+
.catch(function () { /* best-effort */ });
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2654
|
+
function loadConfigFromServer() {
|
|
2655
|
+
var config = loadConfig();
|
|
2656
|
+
var url = config.aimeatUrl;
|
|
2657
|
+
if (!url) return;
|
|
2658
|
+
url = url.replace(/\/+$/, '');
|
|
2659
|
+
fetch(url + '/v1/auth/anonymous', { method: 'POST' })
|
|
2660
|
+
.then(function (r) { return r.json(); })
|
|
2661
|
+
.then(function (auth) {
|
|
2662
|
+
var token = auth.data && auth.data.token;
|
|
2663
|
+
if (!token) return;
|
|
2664
|
+
var gaii = auth.data.gaii || auth.data.sub || '';
|
|
2665
|
+
if (!gaii) return;
|
|
2666
|
+
return fetch(url + '/v1/memory/app-launcher%2Fconfig', {
|
|
2667
|
+
headers: { 'Authorization': 'Bearer ' + token }
|
|
2668
|
+
}).then(function (r) {
|
|
2669
|
+
if (!r.ok) return null;
|
|
2670
|
+
return r.json();
|
|
2671
|
+
});
|
|
2672
|
+
})
|
|
2673
|
+
.then(function (json) {
|
|
2674
|
+
if (!json || !json.data || !json.data.value) return;
|
|
2675
|
+
var remote = json.data.value;
|
|
2676
|
+
var local = loadConfig();
|
|
2677
|
+
var changed = false;
|
|
2678
|
+
// Merge remote into local (remote wins for preferences, but don't overwrite aimeatUrl)
|
|
2679
|
+
if (remote.theme && remote.theme !== local.theme) {
|
|
2680
|
+
local.theme = remote.theme;
|
|
2681
|
+
changed = true;
|
|
2682
|
+
}
|
|
2683
|
+
if (remote.defaultOpenMode && remote.defaultOpenMode !== local.defaultOpenMode) {
|
|
2684
|
+
local.defaultOpenMode = remote.defaultOpenMode;
|
|
2685
|
+
changed = true;
|
|
2686
|
+
}
|
|
2687
|
+
if (remote.language && remote.language !== local.language) {
|
|
2688
|
+
local.language = remote.language;
|
|
2689
|
+
changed = true;
|
|
2690
|
+
}
|
|
2691
|
+
if (changed) {
|
|
2692
|
+
saveConfig(local);
|
|
2693
|
+
applyTheme(local.theme);
|
|
2694
|
+
}
|
|
2695
|
+
})
|
|
2696
|
+
.catch(function () { /* best-effort */ });
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2699
|
+
function closeSettings() {
|
|
2700
|
+
document.getElementById('settings-overlay').hidden = true;
|
|
2701
|
+
}
|
|
2702
|
+
|
|
2703
|
+
// ── Export / Import ─────────────────────────────
|
|
2704
|
+
|
|
2705
|
+
function exportBackup() {
|
|
2706
|
+
getAllApps().then(function (apps) {
|
|
2707
|
+
var config = loadConfig();
|
|
2708
|
+
var backup = {
|
|
2709
|
+
version: 1,
|
|
2710
|
+
exportedAt: new Date().toISOString(),
|
|
2711
|
+
config: config,
|
|
2712
|
+
apps: apps
|
|
2713
|
+
};
|
|
2714
|
+
var json = JSON.stringify(backup, null, 2);
|
|
2715
|
+
var blob = new Blob([json], { type: 'application/json' });
|
|
2716
|
+
var url = URL.createObjectURL(blob);
|
|
2717
|
+
var a = document.createElement('a');
|
|
2718
|
+
a.href = url;
|
|
2719
|
+
a.download = 'app-catalog-backup-' + new Date().toISOString().slice(0, 10) + '.json';
|
|
2720
|
+
document.body.appendChild(a);
|
|
2721
|
+
a.click();
|
|
2722
|
+
document.body.removeChild(a);
|
|
2723
|
+
URL.revokeObjectURL(url);
|
|
2724
|
+
});
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2727
|
+
function handleImportBackup(file) {
|
|
2728
|
+
if (!file) return;
|
|
2729
|
+
var reader = new FileReader();
|
|
2730
|
+
reader.onload = function () {
|
|
2731
|
+
try {
|
|
2732
|
+
var backup = JSON.parse(reader.result);
|
|
2733
|
+
if (!backup.apps || !Array.isArray(backup.apps)) {
|
|
2734
|
+
alert('Invalid backup file: missing apps array');
|
|
2735
|
+
return;
|
|
2736
|
+
}
|
|
2737
|
+
// Import config if present
|
|
2738
|
+
if (backup.config && typeof backup.config === 'object') {
|
|
2739
|
+
var currentConfig = loadConfig();
|
|
2740
|
+
var merged = Object.assign({}, currentConfig, backup.config);
|
|
2741
|
+
saveConfig(merged);
|
|
2742
|
+
applyTheme(merged.theme);
|
|
2743
|
+
}
|
|
2744
|
+
// Import apps with new IDs to avoid conflicts
|
|
2745
|
+
var promises = [];
|
|
2746
|
+
for (var i = 0; i < backup.apps.length; i++) {
|
|
2747
|
+
var app = Object.assign({}, backup.apps[i]);
|
|
2748
|
+
app.id = generateId(); // New ID to avoid conflicts
|
|
2749
|
+
promises.push(saveApp(app));
|
|
2750
|
+
}
|
|
2751
|
+
Promise.all(promises).then(function () {
|
|
2752
|
+
alert('Imported ' + backup.apps.length + ' app(s) successfully');
|
|
2753
|
+
renderApps();
|
|
2754
|
+
});
|
|
2755
|
+
} catch (e) {
|
|
2756
|
+
alert('Failed to parse backup file: ' + (e.message || e));
|
|
2757
|
+
}
|
|
2758
|
+
};
|
|
2759
|
+
reader.readAsText(file);
|
|
2760
|
+
}
|
|
2761
|
+
|
|
2762
|
+
// ── Clear All Data ──────────────────────────────
|
|
2763
|
+
|
|
2764
|
+
function clearAllData() {
|
|
2765
|
+
if (!confirm('Are you sure you want to clear all data? This cannot be undone.')) return;
|
|
2766
|
+
if (!confirm('This will delete ALL apps and reset settings. Continue?')) return;
|
|
2767
|
+
|
|
2768
|
+
openDB().then(function (db) {
|
|
2769
|
+
return new Promise(function (resolve, reject) {
|
|
2770
|
+
var tx = db.transaction(STORE_NAME, 'readwrite');
|
|
2771
|
+
tx.objectStore(STORE_NAME).clear();
|
|
2772
|
+
tx.oncomplete = function () { resolve(); };
|
|
2773
|
+
tx.onerror = function () { reject(tx.error); };
|
|
2774
|
+
});
|
|
2775
|
+
}).then(function () {
|
|
2776
|
+
localStorage.removeItem('appLauncherConfig');
|
|
2777
|
+
applyTheme('dark');
|
|
2778
|
+
renderApps();
|
|
2779
|
+
document.getElementById('settings-overlay').hidden = true;
|
|
2780
|
+
alert('All data cleared');
|
|
2781
|
+
});
|
|
2782
|
+
}
|
|
2783
|
+
|
|
2784
|
+
// ── AIMEAT Import ───────────────────────────────
|
|
2785
|
+
|
|
2786
|
+
var aimeatAppsCache = [];
|
|
2787
|
+
|
|
2788
|
+
function formatFileSize(bytes) {
|
|
2789
|
+
if (bytes < 1024) return bytes + ' B';
|
|
2790
|
+
if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
|
|
2791
|
+
return (bytes / 1048576).toFixed(1) + ' MB';
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2794
|
+
function importFromAimeat() {
|
|
2795
|
+
var config = loadConfig();
|
|
2796
|
+
if (!config.aimeatUrl) {
|
|
2797
|
+
alert('Set AIMEAT server URL in Settings first');
|
|
2798
|
+
return;
|
|
2799
|
+
}
|
|
2800
|
+
|
|
2801
|
+
var aimeatUrl = config.aimeatUrl.replace(/\/+$/, ''); // strip trailing slash
|
|
2802
|
+
closeModal();
|
|
2803
|
+
|
|
2804
|
+
fetch(aimeatUrl + '/v1/apps?include_peers=true')
|
|
2805
|
+
.then(function (resp) {
|
|
2806
|
+
if (!resp.ok) throw new Error('Server returned ' + resp.status);
|
|
2807
|
+
return resp.json();
|
|
2808
|
+
})
|
|
2809
|
+
.then(function (json) {
|
|
2810
|
+
var apps = json.data && json.data.apps ? json.data.apps : [];
|
|
2811
|
+
var peerApps = json.data && json.data.peer_apps ? json.data.peer_apps : [];
|
|
2812
|
+
// Merge local and peer apps; tag peer apps with source info
|
|
2813
|
+
for (var p = 0; p < peerApps.length; p++) {
|
|
2814
|
+
peerApps[p]._from_peer = true;
|
|
2815
|
+
}
|
|
2816
|
+
var allFetched = apps.concat(peerApps);
|
|
2817
|
+
if (allFetched.length === 0) {
|
|
2818
|
+
alert('No apps found on the AIMEAT server');
|
|
2819
|
+
return;
|
|
2820
|
+
}
|
|
2821
|
+
aimeatAppsCache = allFetched;
|
|
2822
|
+
showAimeatImportDialog(allFetched, aimeatUrl);
|
|
2823
|
+
})
|
|
2824
|
+
.catch(function (err) {
|
|
2825
|
+
var msg = 'Failed to fetch apps from AIMEAT server.\n\n' + (err.message || err);
|
|
2826
|
+
if (err.message && err.message.indexOf('Failed to fetch') !== -1) {
|
|
2827
|
+
msg += '\n\nIf the launcher is opened via file://, CORS will block the request. Open it from the AIMEAT server instead.';
|
|
2828
|
+
}
|
|
2829
|
+
alert(msg);
|
|
2830
|
+
});
|
|
2831
|
+
}
|
|
2832
|
+
|
|
2833
|
+
function showAimeatImportDialog(apps, aimeatUrl) {
|
|
2834
|
+
var listEl = document.getElementById('aimeat-app-list');
|
|
2835
|
+
var html = '';
|
|
2836
|
+
for (var i = 0; i < apps.length; i++) {
|
|
2837
|
+
var app = apps[i];
|
|
2838
|
+
var displayName = (app.manifest && app.manifest.name) ? app.manifest.name : app.filename;
|
|
2839
|
+
var displayAuthor = (app.manifest && app.manifest.authorDisplay) ? app.manifest.authorDisplay : (app.owner || '');
|
|
2840
|
+
var displayDesc = (app.manifest && app.manifest.description) ? app.manifest.description : '';
|
|
2841
|
+
var displayVer = app.version_number ? 'v' + app.version_number : '';
|
|
2842
|
+
var displayCat = (app.manifest && app.manifest.category) ? app.manifest.category : '';
|
|
2843
|
+
var peerLabel = app._from_peer && app._peer_node ? ' \u00B7 \uD83C\uDF10 ' + escapeHtml(app._peer_node) : '';
|
|
2844
|
+
html +=
|
|
2845
|
+
'<div class="aimeat-app-item">' +
|
|
2846
|
+
'<input type="checkbox" data-index="' + i + '" checked/>' +
|
|
2847
|
+
'<div class="aimeat-app-info">' +
|
|
2848
|
+
'<div class="aimeat-app-name">' + escapeHtml(displayName) + (displayVer ? ' <span style="opacity:.5;font-size:.85em">' + escapeHtml(displayVer) + '</span>' : '') + '</div>' +
|
|
2849
|
+
'<div class="aimeat-app-size">' + formatFileSize(app.size) + (displayAuthor ? ' \u00B7 ' + escapeHtml(displayAuthor) : '') + (displayCat ? ' \u00B7 ' + escapeHtml(displayCat) : '') + peerLabel + '</div>' +
|
|
2850
|
+
(displayDesc ? '<div class="aimeat-app-size" style="opacity:.6">' + escapeHtml(displayDesc.substring(0, 100)) + '</div>' : '') +
|
|
2851
|
+
'</div>' +
|
|
2852
|
+
'<select data-index="' + i + '">' +
|
|
2853
|
+
'<option value="link">Link (online only)</option>' +
|
|
2854
|
+
'<option value="download">Download (offline)</option>' +
|
|
2855
|
+
'</select>' +
|
|
2856
|
+
'</div>';
|
|
2857
|
+
}
|
|
2858
|
+
listEl.innerHTML = html;
|
|
2859
|
+
// Store the aimeatUrl for processing
|
|
2860
|
+
listEl.dataset.aimeatUrl = aimeatUrl;
|
|
2861
|
+
document.getElementById('aimeat-import-overlay').hidden = false;
|
|
2862
|
+
}
|
|
2863
|
+
|
|
2864
|
+
function processAimeatImport() {
|
|
2865
|
+
var listEl = document.getElementById('aimeat-app-list');
|
|
2866
|
+
var aimeatUrl = listEl.dataset.aimeatUrl;
|
|
2867
|
+
var checkboxes = listEl.querySelectorAll('input[type="checkbox"]');
|
|
2868
|
+
var selects = listEl.querySelectorAll('select');
|
|
2869
|
+
var config = loadConfig();
|
|
2870
|
+
var defaultOpenMode = config.defaultOpenMode || 'tab';
|
|
2871
|
+
|
|
2872
|
+
var toImport = [];
|
|
2873
|
+
for (var i = 0; i < checkboxes.length; i++) {
|
|
2874
|
+
if (checkboxes[i].checked) {
|
|
2875
|
+
var idx = parseInt(checkboxes[i].getAttribute('data-index'), 10);
|
|
2876
|
+
var mode = selects[i].value;
|
|
2877
|
+
toImport.push({ app: aimeatAppsCache[idx], mode: mode });
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
if (toImport.length === 0) {
|
|
2882
|
+
alert('No apps selected');
|
|
2883
|
+
return;
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2886
|
+
var promises = [];
|
|
2887
|
+
for (var j = 0; j < toImport.length; j++) {
|
|
2888
|
+
(function (item) {
|
|
2889
|
+
var app = item.app;
|
|
2890
|
+
var name = (app.manifest && app.manifest.name) ? app.manifest.name : app.filename.replace(/\.html?$/i, '');
|
|
2891
|
+
var importedVersion = app.version_number || 1;
|
|
2892
|
+
// For peer apps, use the peer's URL as the base
|
|
2893
|
+
var baseUrl = (app._from_peer && app._peer_url) ? app._peer_url.replace(/\/+$/, '') : aimeatUrl;
|
|
2894
|
+
|
|
2895
|
+
if (item.mode === 'link') {
|
|
2896
|
+
// Link mode: store URL with ?mode=inline, pinned to latest
|
|
2897
|
+
var inlineUrl = baseUrl + app.download_url + '?mode=inline';
|
|
2898
|
+
promises.push(addAppFromUrl(name, inlineUrl, '\u{1F4E6}', ['aimeat'], defaultOpenMode));
|
|
2899
|
+
} else {
|
|
2900
|
+
// Download mode: fetch content and store blob (pinned to current version)
|
|
2901
|
+
var downloadUrl = baseUrl + app.download_url;
|
|
2902
|
+
promises.push(
|
|
2903
|
+
fetch(downloadUrl)
|
|
2904
|
+
.then(function (resp) {
|
|
2905
|
+
if (!resp.ok) throw new Error('Download failed: ' + resp.status);
|
|
2906
|
+
return resp.text();
|
|
2907
|
+
})
|
|
2908
|
+
.then(function (content) {
|
|
2909
|
+
var encoded = btoa(unescape(encodeURIComponent(content)));
|
|
2910
|
+
var record = {
|
|
2911
|
+
id: generateId(),
|
|
2912
|
+
name: name,
|
|
2913
|
+
description: (app.manifest && app.manifest.description) ? app.manifest.description : '',
|
|
2914
|
+
source: 'aimeat',
|
|
2915
|
+
aimeatOwner: app.owner || null,
|
|
2916
|
+
aimeatFilename: app.filename || null,
|
|
2917
|
+
aimeatVersion: importedVersion,
|
|
2918
|
+
url: null,
|
|
2919
|
+
blob: encoded,
|
|
2920
|
+
tags: ['aimeat'],
|
|
2921
|
+
openMode: defaultOpenMode,
|
|
2922
|
+
icon: '\u{1F4E6}',
|
|
2923
|
+
screenshot: null,
|
|
2924
|
+
favorite: false,
|
|
2925
|
+
addedAt: new Date().toISOString(),
|
|
2926
|
+
lastOpenedAt: null
|
|
2927
|
+
};
|
|
2928
|
+
return saveApp(record);
|
|
2929
|
+
})
|
|
2930
|
+
);
|
|
2931
|
+
}
|
|
2932
|
+
})(toImport[j]);
|
|
2933
|
+
}
|
|
2934
|
+
|
|
2935
|
+
Promise.all(promises).then(function () {
|
|
2936
|
+
document.getElementById('aimeat-import-overlay').hidden = true;
|
|
2937
|
+
renderApps();
|
|
2938
|
+
}).catch(function (err) {
|
|
2939
|
+
alert('Import error: ' + (err.message || err));
|
|
2940
|
+
});
|
|
2941
|
+
}
|
|
2942
|
+
|
|
2943
|
+
// ── Publish to AIMEAT ───────────────────────────
|
|
2944
|
+
|
|
2945
|
+
var publishAppId = null;
|
|
2946
|
+
|
|
2947
|
+
function showPublishModal(appId) {
|
|
2948
|
+
var app = null;
|
|
2949
|
+
for (var i = 0; i < allApps.length; i++) {
|
|
2950
|
+
if (allApps[i].id === appId) { app = allApps[i]; break; }
|
|
2951
|
+
}
|
|
2952
|
+
if (!app) return;
|
|
2953
|
+
|
|
2954
|
+
var config = loadConfig();
|
|
2955
|
+
if (!config.aimeatUrl) {
|
|
2956
|
+
alert('Set AIMEAT server URL in Settings first');
|
|
2957
|
+
return;
|
|
2958
|
+
}
|
|
2959
|
+
|
|
2960
|
+
publishAppId = appId;
|
|
2961
|
+
var safeName = (app.name || 'app').replace(/[^a-zA-Z0-9._-]/g, '-').replace(/-+/g, '-').toLowerCase();
|
|
2962
|
+
if (!/\.html?$/i.test(safeName)) safeName += '.html';
|
|
2963
|
+
document.getElementById('publish-filename').value = safeName;
|
|
2964
|
+
document.getElementById('publish-access-code').value = '';
|
|
2965
|
+
document.getElementById('publish-status').textContent = '';
|
|
2966
|
+
document.getElementById('publish-submit-btn').disabled = false;
|
|
2967
|
+
document.getElementById('publish-overlay').hidden = false;
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
function submitPublish() {
|
|
2971
|
+
if (!publishAppId) return;
|
|
2972
|
+
|
|
2973
|
+
var app = null;
|
|
2974
|
+
for (var i = 0; i < allApps.length; i++) {
|
|
2975
|
+
if (allApps[i].id === publishAppId) { app = allApps[i]; break; }
|
|
2976
|
+
}
|
|
2977
|
+
if (!app) return;
|
|
2978
|
+
|
|
2979
|
+
var config = loadConfig();
|
|
2980
|
+
var aimeatUrl = config.aimeatUrl.replace(/\/+$/, '');
|
|
2981
|
+
var filename = document.getElementById('publish-filename').value.trim();
|
|
2982
|
+
var accessCode = document.getElementById('publish-access-code').value.trim();
|
|
2983
|
+
var statusEl = document.getElementById('publish-status');
|
|
2984
|
+
var submitBtn = document.getElementById('publish-submit-btn');
|
|
2985
|
+
|
|
2986
|
+
if (!filename || !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,99}$/.test(filename)) {
|
|
2987
|
+
statusEl.textContent = 'Invalid filename. Use letters, numbers, dots, hyphens, underscores.';
|
|
2988
|
+
statusEl.style.color = 'var(--accent)';
|
|
2989
|
+
return;
|
|
2990
|
+
}
|
|
2991
|
+
|
|
2992
|
+
if (accessCode && (accessCode.length < 4 || accessCode.length > 64)) {
|
|
2993
|
+
statusEl.textContent = 'Access code must be 4-64 characters.';
|
|
2994
|
+
statusEl.style.color = 'var(--accent)';
|
|
2995
|
+
return;
|
|
2996
|
+
}
|
|
2997
|
+
|
|
2998
|
+
// Get the HTML content
|
|
2999
|
+
var htmlContent = '';
|
|
3000
|
+
if (app.blob) {
|
|
3001
|
+
htmlContent = app.blob; // already base64
|
|
3002
|
+
} else if (app.url) {
|
|
3003
|
+
statusEl.textContent = 'Cannot publish URL-linked apps. Download it first (right-click \u2192 View Source \u2192 Save).';
|
|
3004
|
+
statusEl.style.color = 'var(--accent)';
|
|
3005
|
+
return;
|
|
3006
|
+
} else {
|
|
3007
|
+
statusEl.textContent = 'No app content found.';
|
|
3008
|
+
statusEl.style.color = 'var(--accent)';
|
|
3009
|
+
return;
|
|
3010
|
+
}
|
|
3011
|
+
|
|
3012
|
+
statusEl.textContent = 'Publishing...';
|
|
3013
|
+
statusEl.style.color = '#34d399';
|
|
3014
|
+
submitBtn.disabled = true;
|
|
3015
|
+
|
|
3016
|
+
// Get auth token first
|
|
3017
|
+
fetch(aimeatUrl + '/v1/auth/anonymous', { method: 'POST' })
|
|
3018
|
+
.then(function(resp) { return resp.json(); })
|
|
3019
|
+
.then(function(authJson) {
|
|
3020
|
+
var token = authJson.data && authJson.data.token;
|
|
3021
|
+
if (!token) throw new Error('Could not get auth token');
|
|
3022
|
+
|
|
3023
|
+
var body = {
|
|
3024
|
+
filename: filename,
|
|
3025
|
+
content: htmlContent,
|
|
3026
|
+
mime_type: 'text/html',
|
|
3027
|
+
name: app.name || filename.replace(/\.html?$/i, ''),
|
|
3028
|
+
description: app.description || '',
|
|
3029
|
+
category: 'utility',
|
|
3030
|
+
tags: app.tags || [],
|
|
3031
|
+
uses_cortex: []
|
|
3032
|
+
};
|
|
3033
|
+
if (accessCode) body.access_code = accessCode;
|
|
3034
|
+
|
|
3035
|
+
return fetch(aimeatUrl + '/v1/apps', {
|
|
3036
|
+
method: 'POST',
|
|
3037
|
+
headers: {
|
|
3038
|
+
'Content-Type': 'application/json',
|
|
3039
|
+
'Authorization': 'Bearer ' + token
|
|
3040
|
+
},
|
|
3041
|
+
body: JSON.stringify(body)
|
|
3042
|
+
});
|
|
3043
|
+
})
|
|
3044
|
+
.then(function(resp) { return resp.json(); })
|
|
3045
|
+
.then(function(json) {
|
|
3046
|
+
if (json.ok) {
|
|
3047
|
+
statusEl.textContent = '\u2714 Published! ' + (json.data.download_url || '');
|
|
3048
|
+
statusEl.style.color = '#34d399';
|
|
3049
|
+
// Mark app as published in IndexedDB
|
|
3050
|
+
app.published = true;
|
|
3051
|
+
app.publishedFilename = filename;
|
|
3052
|
+
app.publishedAt = new Date().toISOString();
|
|
3053
|
+
app.publishedUrl = json.data.download_url || null;
|
|
3054
|
+
app.publishedVersionNumber = json.data.version_number || 1;
|
|
3055
|
+
app.publishedVersionsUrl = json.data.versions_url || null;
|
|
3056
|
+
saveApp(app).then(function() {
|
|
3057
|
+
loadPublishedApps();
|
|
3058
|
+
});
|
|
3059
|
+
} else {
|
|
3060
|
+
statusEl.textContent = '\u2718 ' + (json.error_description || json.error_code || 'Publish failed');
|
|
3061
|
+
statusEl.style.color = 'var(--accent)';
|
|
3062
|
+
submitBtn.disabled = false;
|
|
3063
|
+
}
|
|
3064
|
+
})
|
|
3065
|
+
.catch(function(err) {
|
|
3066
|
+
statusEl.textContent = '\u2718 ' + (err.message || 'Publish failed');
|
|
3067
|
+
statusEl.style.color = 'var(--accent)';
|
|
3068
|
+
submitBtn.disabled = false;
|
|
3069
|
+
});
|
|
3070
|
+
}
|
|
3071
|
+
|
|
3072
|
+
// ── Published Apps Section ──────────────────────
|
|
3073
|
+
|
|
3074
|
+
var publishedVisible = true;
|
|
3075
|
+
|
|
3076
|
+
function togglePublished() {
|
|
3077
|
+
publishedVisible = !publishedVisible;
|
|
3078
|
+
var grid = document.getElementById('published-grid');
|
|
3079
|
+
var arrow = document.getElementById('published-arrow');
|
|
3080
|
+
grid.style.display = publishedVisible ? '' : 'none';
|
|
3081
|
+
arrow.classList.toggle('open', publishedVisible);
|
|
3082
|
+
}
|
|
3083
|
+
|
|
3084
|
+
function loadPublishedApps() {
|
|
3085
|
+
getAllApps().then(function(apps) {
|
|
3086
|
+
var published = apps.filter(function(a) { return a.published; });
|
|
3087
|
+
var section = document.getElementById('published-section');
|
|
3088
|
+
var grid = document.getElementById('published-grid');
|
|
3089
|
+
var countEl = document.getElementById('published-count');
|
|
3090
|
+
|
|
3091
|
+
if (published.length === 0) {
|
|
3092
|
+
section.style.display = 'none';
|
|
3093
|
+
return;
|
|
3094
|
+
}
|
|
3095
|
+
|
|
3096
|
+
section.style.display = '';
|
|
3097
|
+
countEl.textContent = '(' + published.length + ')';
|
|
3098
|
+
var config = loadConfig();
|
|
3099
|
+
var aimeatUrl = config.aimeatUrl ? config.aimeatUrl.replace(/\/+$/, '') : '';
|
|
3100
|
+
|
|
3101
|
+
var html = '';
|
|
3102
|
+
for (var i = 0; i < published.length; i++) {
|
|
3103
|
+
var app = published[i];
|
|
3104
|
+
var url = app.publishedUrl ? (aimeatUrl + app.publishedUrl) : '';
|
|
3105
|
+
html +=
|
|
3106
|
+
'<div class="published-card">' +
|
|
3107
|
+
'<div class="published-card-name">' + escapeHtml(app.name || app.publishedFilename || 'Untitled') + (app.publishedVersionNumber ? ' <span style="opacity:.5;font-size:.85em">v' + app.publishedVersionNumber + '</span>' : '') + '</div>' +
|
|
3108
|
+
'<div class="published-card-meta">' +
|
|
3109
|
+
'<span>' + escapeHtml(app.publishedFilename || '') + '</span>' +
|
|
3110
|
+
'<span>' + (app.publishedAt ? new Date(app.publishedAt).toLocaleDateString() : '') + '</span>' +
|
|
3111
|
+
'</div>' +
|
|
3112
|
+
'<div class="published-card-actions">' +
|
|
3113
|
+
(url ? '<button onclick="window.open(\'' + escapeHtml(url) + '?mode=inline\', \'_blank\')">👁 View</button>' : '') +
|
|
3114
|
+
'<button onclick="window._launcher.unpublishApp(\'' + escapeHtml(app.id) + '\')" class="danger">🗑 Remove</button>' +
|
|
3115
|
+
'</div>' +
|
|
3116
|
+
'</div>';
|
|
3117
|
+
}
|
|
3118
|
+
grid.innerHTML = html;
|
|
3119
|
+
});
|
|
3120
|
+
}
|
|
3121
|
+
|
|
3122
|
+
function unpublishApp(appId) {
|
|
3123
|
+
if (!confirm('Remove this published app from the server?')) return;
|
|
3124
|
+
|
|
3125
|
+
var app = null;
|
|
3126
|
+
for (var i = 0; i < allApps.length; i++) {
|
|
3127
|
+
if (allApps[i].id === appId) { app = allApps[i]; break; }
|
|
3128
|
+
}
|
|
3129
|
+
if (!app || !app.publishedFilename) return;
|
|
3130
|
+
|
|
3131
|
+
var config = loadConfig();
|
|
3132
|
+
var aimeatUrl = config.aimeatUrl.replace(/\/+$/, '');
|
|
3133
|
+
|
|
3134
|
+
// Get auth token and delete
|
|
3135
|
+
fetch(aimeatUrl + '/v1/auth/anonymous', { method: 'POST' })
|
|
3136
|
+
.then(function(resp) { return resp.json(); })
|
|
3137
|
+
.then(function(authJson) {
|
|
3138
|
+
var token = authJson.data && authJson.data.token;
|
|
3139
|
+
if (!token) throw new Error('Could not get auth token');
|
|
3140
|
+
return fetch(aimeatUrl + '/v1/apps/' + encodeURIComponent(app.publishedFilename), {
|
|
3141
|
+
method: 'DELETE',
|
|
3142
|
+
headers: { 'Authorization': 'Bearer ' + token }
|
|
3143
|
+
});
|
|
3144
|
+
})
|
|
3145
|
+
.then(function(resp) { return resp.json(); })
|
|
3146
|
+
.then(function(json) {
|
|
3147
|
+
if (json.ok) {
|
|
3148
|
+
app.published = false;
|
|
3149
|
+
delete app.publishedFilename;
|
|
3150
|
+
delete app.publishedAt;
|
|
3151
|
+
delete app.publishedUrl;
|
|
3152
|
+
delete app.publishedVersionNumber;
|
|
3153
|
+
delete app.publishedVersionsUrl;
|
|
3154
|
+
saveApp(app).then(function() {
|
|
3155
|
+
loadPublishedApps();
|
|
3156
|
+
});
|
|
3157
|
+
} else {
|
|
3158
|
+
alert('Failed to remove: ' + (json.error_description || 'Unknown error'));
|
|
3159
|
+
}
|
|
3160
|
+
})
|
|
3161
|
+
.catch(function(err) {
|
|
3162
|
+
alert('Error: ' + (err.message || err));
|
|
3163
|
+
});
|
|
3164
|
+
}
|
|
3165
|
+
|
|
3166
|
+
// ── Cortex Extensions Bar ─────────────────────────
|
|
3167
|
+
|
|
3168
|
+
var cortexToken = null;
|
|
3169
|
+
|
|
3170
|
+
function cortexEsc(str) {
|
|
3171
|
+
var div = document.createElement('div');
|
|
3172
|
+
div.textContent = str;
|
|
3173
|
+
return div.innerHTML;
|
|
3174
|
+
}
|
|
3175
|
+
|
|
3176
|
+
function loadCortexExtensions() {
|
|
3177
|
+
var config = loadConfig();
|
|
3178
|
+
if (!config.aimeatUrl) return;
|
|
3179
|
+
var url = config.aimeatUrl.replace(/\/+$/, '');
|
|
3180
|
+
|
|
3181
|
+
// Get anonymous token first (same pattern as AIMEAT import)
|
|
3182
|
+
fetch(url + '/v1/auth/anonymous', { method: 'POST' })
|
|
3183
|
+
.then(function(r) { return r.json(); })
|
|
3184
|
+
.then(function(authData) {
|
|
3185
|
+
var token = authData.data && authData.data.token;
|
|
3186
|
+
if (!token) return;
|
|
3187
|
+
cortexToken = token;
|
|
3188
|
+
return fetch(url + '/v1/cortex?status=active', {
|
|
3189
|
+
headers: { 'Authorization': 'Bearer ' + token }
|
|
3190
|
+
});
|
|
3191
|
+
})
|
|
3192
|
+
.then(function(r) { return r ? r.json() : null; })
|
|
3193
|
+
.then(function(data) {
|
|
3194
|
+
if (!data || !data.data || !data.data.extensions) return;
|
|
3195
|
+
var exts = data.data.extensions;
|
|
3196
|
+
if (!exts.length) return;
|
|
3197
|
+
|
|
3198
|
+
document.getElementById('cortex-bar').style.display = 'block';
|
|
3199
|
+
var grid = document.getElementById('cortex-bar-grid');
|
|
3200
|
+
grid.innerHTML = exts.map(function(ext) {
|
|
3201
|
+
var types = ext.component_types || [];
|
|
3202
|
+
var libCount = types.filter(function(t) { return t === 'lib'; }).length;
|
|
3203
|
+
var schemaCount = types.filter(function(t) { return t === 'schema'; }).length;
|
|
3204
|
+
return '<div class="cortex-mini-card" onclick="showCortexPopup(\'' + encodeURIComponent(ext.name) + '\')">'
|
|
3205
|
+
+ '<div class="cortex-mini-name">📦 ' + cortexEsc(ext.short_name || ext.name) + '</div>'
|
|
3206
|
+
+ '<div class="cortex-mini-meta">' + libCount + ' lib · ' + schemaCount + ' schema</div>'
|
|
3207
|
+
+ '</div>';
|
|
3208
|
+
}).join('');
|
|
3209
|
+
})
|
|
3210
|
+
.catch(function(e) { console.warn('Cortex bar load failed:', e); });
|
|
3211
|
+
}
|
|
3212
|
+
|
|
3213
|
+
function showCortexPopup(encodedName) {
|
|
3214
|
+
var config = loadConfig();
|
|
3215
|
+
var url = config.aimeatUrl.replace(/\/+$/, '');
|
|
3216
|
+
var el = document.getElementById('cortex-popup-content');
|
|
3217
|
+
el.innerHTML = '<p>Loading...</p>';
|
|
3218
|
+
document.getElementById('cortex-popup-overlay').style.display = 'flex';
|
|
3219
|
+
|
|
3220
|
+
if (!cortexToken) { el.innerHTML = '<p>No auth token available</p>'; return; }
|
|
3221
|
+
|
|
3222
|
+
fetch(url + '/v1/cortex/' + encodedName, {
|
|
3223
|
+
headers: { 'Authorization': 'Bearer ' + cortexToken }
|
|
3224
|
+
})
|
|
3225
|
+
.then(function(r) { return r.json(); })
|
|
3226
|
+
.then(function(data) {
|
|
3227
|
+
var ext = data.data;
|
|
3228
|
+
var comps = ext.components || [];
|
|
3229
|
+
var html = '<h2 style="margin-top:0">' + cortexEsc(ext.name) + '</h2>';
|
|
3230
|
+
html += '<p style="color:#6B7280">' + cortexEsc(ext.description || '') + '</p>';
|
|
3231
|
+
html += '<h3 style="font-size:.9rem">Available for your apps:</h3>';
|
|
3232
|
+
|
|
3233
|
+
// Libs
|
|
3234
|
+
comps.filter(function(c) { return c.type === 'lib'; }).forEach(function(lib) {
|
|
3235
|
+
var scriptUrl = url + '/v1/cortex/' + encodedName + '/libs/' + encodeURIComponent(lib.filename);
|
|
3236
|
+
var tag = '<script src="' + scriptUrl + '"><\/script>';
|
|
3237
|
+
html += '<div style="margin-bottom:1rem">'
|
|
3238
|
+
+ '<div style="font-weight:600;font-size:.85rem">📦 Lib: ' + cortexEsc(lib.filename) + '</div>'
|
|
3239
|
+
+ '<div style="font-family:monospace;font-size:.75rem;background:#F3F4F6;padding:8px;border-radius:6px;margin-top:4px;word-break:break-all">' + cortexEsc(tag) + '</div>'
|
|
3240
|
+
+ '<button onclick="cortexCopy(\'' + tag.replace(/'/g, "\\'").replace(/"/g, '"') + '\',this)" style="font-size:.7rem;margin-top:4px;padding:2px 8px;border-radius:4px;border:1px solid #E5E7EB;background:transparent;color:#6B7280;cursor:pointer">Copy</button>';
|
|
3241
|
+
if (lib.api_surface) {
|
|
3242
|
+
html += '<div style="font-size:.8rem;font-weight:600;margin-top:8px">API Surface:</div>'
|
|
3243
|
+
+ '<div style="font-family:monospace;font-size:.75rem;background:#F3F4F6;padding:8px;border-radius:6px;margin-top:4px;white-space:pre-wrap">' + cortexEsc(lib.api_surface) + '</div>'
|
|
3244
|
+
+ '<button onclick="cortexCopy(\'' + (lib.api_surface || '').replace(/\\/g,'\\\\').replace(/'/g, "\\'").replace(/"/g, '"').replace(/\n/g, '\\n') + '\',this)" style="font-size:.7rem;margin-top:4px;padding:2px 8px;border-radius:4px;border:1px solid #E5E7EB;background:transparent;color:#6B7280;cursor:pointer">Copy API</button>';
|
|
3245
|
+
}
|
|
3246
|
+
html += '</div>';
|
|
3247
|
+
});
|
|
3248
|
+
|
|
3249
|
+
// Schemas
|
|
3250
|
+
comps.filter(function(c) { return c.type === 'schema'; }).forEach(function(s) {
|
|
3251
|
+
html += '<div style="margin-bottom:.5rem;font-size:.85rem">📐 Schema: <code>' + cortexEsc(s.key_pattern) + '</code> — data validated automatically</div>';
|
|
3252
|
+
});
|
|
3253
|
+
|
|
3254
|
+
// Prompts
|
|
3255
|
+
comps.filter(function(c) { return c.type === 'prompt'; }).forEach(function(p) {
|
|
3256
|
+
var preview = (p.content || '').substring(0, 150);
|
|
3257
|
+
html += '<div style="margin-bottom:.5rem">'
|
|
3258
|
+
+ '<div style="font-size:.85rem">💬 Prompt: ' + cortexEsc(p.name) + '</div>'
|
|
3259
|
+
+ '<div style="font-size:.75rem;color:#6B7280">“' + cortexEsc(preview) + '...”</div>'
|
|
3260
|
+
+ '<button onclick="cortexCopy(\'' + (p.content || '').replace(/\\/g,'\\\\').replace(/'/g, "\\'").replace(/"/g, '"').replace(/\n/g, '\\n') + '\',this)" style="font-size:.7rem;margin-top:2px;padding:2px 8px;border-radius:4px;border:1px solid #E5E7EB;background:transparent;color:#6B7280;cursor:pointer">Copy Prompt</button>'
|
|
3261
|
+
+ '</div>';
|
|
3262
|
+
});
|
|
3263
|
+
|
|
3264
|
+
// Edit button (only if owner session available)
|
|
3265
|
+
var hasSession = false;
|
|
3266
|
+
try { hasSession = !!getCortexOwnerToken(); } catch(e) {}
|
|
3267
|
+
if (hasSession) {
|
|
3268
|
+
html += '<div style="margin-top:1.5rem;padding-top:1rem;border-top:1px solid #E5E7EB">'
|
|
3269
|
+
+ '<button onclick="window._launcher.openCortexEditor(\'' + encodedName + '\')" style="padding:6px 16px;border-radius:8px;border:1px solid var(--accent,#34d399);background:transparent;color:var(--accent,#34d399);cursor:pointer;font-size:.85rem">🛠️ Edit Extension</button>'
|
|
3270
|
+
+ '</div>';
|
|
3271
|
+
}
|
|
3272
|
+
|
|
3273
|
+
el.innerHTML = html;
|
|
3274
|
+
})
|
|
3275
|
+
.catch(function(e) {
|
|
3276
|
+
el.innerHTML = '<p>Error: ' + cortexEsc(e.message) + '</p>';
|
|
3277
|
+
});
|
|
3278
|
+
}
|
|
3279
|
+
|
|
3280
|
+
function cortexCopy(text, btn) {
|
|
3281
|
+
navigator.clipboard.writeText(text.replace(/\\n/g, '\n')).then(function() {
|
|
3282
|
+
var orig = btn.textContent;
|
|
3283
|
+
btn.textContent = 'Copied!';
|
|
3284
|
+
setTimeout(function() { btn.textContent = orig; }, 1500);
|
|
3285
|
+
});
|
|
3286
|
+
}
|
|
3287
|
+
|
|
3288
|
+
// ── Cortex Extension Editor ───────────────────────
|
|
3289
|
+
|
|
3290
|
+
var cortexEditorExtName = null; // name of extension being edited
|
|
3291
|
+
var cortexEditorWasActive = false; // was it active before editing?
|
|
3292
|
+
var cortexEditorLibCounter = 0; // counter for unique lib section IDs
|
|
3293
|
+
|
|
3294
|
+
function getCortexOwnerToken() {
|
|
3295
|
+
try {
|
|
3296
|
+
if (window.AIMEAT && window.AIMEAT.auth && window.AIMEAT.auth.getSession()) {
|
|
3297
|
+
return window.AIMEAT.auth.getSession().jwt;
|
|
3298
|
+
}
|
|
3299
|
+
var stored = localStorage.getItem('aimeat_session');
|
|
3300
|
+
if (stored) {
|
|
3301
|
+
var parsed = JSON.parse(stored);
|
|
3302
|
+
return parsed.jwt || null;
|
|
3303
|
+
}
|
|
3304
|
+
} catch(e) {}
|
|
3305
|
+
return null;
|
|
3306
|
+
}
|
|
3307
|
+
|
|
3308
|
+
function openCortexEditor(encodedName) {
|
|
3309
|
+
var config = loadConfig();
|
|
3310
|
+
var url = config.aimeatUrl.replace(/\/+$/, '');
|
|
3311
|
+
var token = getCortexOwnerToken();
|
|
3312
|
+
if (!token) { alert('You must be logged in as an owner to edit extensions.'); return; }
|
|
3313
|
+
|
|
3314
|
+
var statusEl = document.getElementById('cortex-editor-status');
|
|
3315
|
+
statusEl.textContent = 'Loading extension data...';
|
|
3316
|
+
statusEl.style.color = '#34d399';
|
|
3317
|
+
document.getElementById('cortex-editor-manifest').value = '';
|
|
3318
|
+
document.getElementById('cortex-editor-libs').innerHTML = '';
|
|
3319
|
+
document.getElementById('cortex-editor-name').textContent = '';
|
|
3320
|
+
cortexEditorLibCounter = 0;
|
|
3321
|
+
|
|
3322
|
+
// Close the detail popup
|
|
3323
|
+
document.getElementById('cortex-popup-overlay').style.display = 'none';
|
|
3324
|
+
document.getElementById('cortex-editor-overlay').style.display = 'flex';
|
|
3325
|
+
|
|
3326
|
+
fetch(url + '/v1/cortex/' + encodedName + '/export', {
|
|
3327
|
+
headers: { 'Authorization': 'Bearer ' + token }
|
|
3328
|
+
})
|
|
3329
|
+
.then(function(r) { return r.json(); })
|
|
3330
|
+
.then(function(data) {
|
|
3331
|
+
if (!data.data) { statusEl.textContent = 'Error: ' + (data.error || 'Unknown error'); statusEl.style.color = 'var(--accent,#e74c6f)'; return; }
|
|
3332
|
+
var ext = data.data;
|
|
3333
|
+
cortexEditorExtName = ext.name;
|
|
3334
|
+
cortexEditorWasActive = (ext.status === 'active');
|
|
3335
|
+
document.getElementById('cortex-editor-name').textContent = ext.name + (cortexEditorWasActive ? ' (active)' : ' (inactive)');
|
|
3336
|
+
document.getElementById('cortex-editor-manifest').value = ext.manifest || '';
|
|
3337
|
+
|
|
3338
|
+
// Render lib editors
|
|
3339
|
+
var libsHtml = '';
|
|
3340
|
+
var libs = ext.libs || {};
|
|
3341
|
+
var filenames = Object.keys(libs);
|
|
3342
|
+
for (var i = 0; i < filenames.length; i++) {
|
|
3343
|
+
cortexEditorLibCounter++;
|
|
3344
|
+
var fname = filenames[i];
|
|
3345
|
+
libsHtml += cortexEditorLibSection(cortexEditorLibCounter, fname, libs[fname]);
|
|
3346
|
+
}
|
|
3347
|
+
document.getElementById('cortex-editor-libs').innerHTML = libsHtml;
|
|
3348
|
+
statusEl.textContent = 'Loaded. ' + filenames.length + ' lib file' + (filenames.length !== 1 ? 's' : '') + '.';
|
|
3349
|
+
})
|
|
3350
|
+
.catch(function(e) {
|
|
3351
|
+
statusEl.textContent = 'Error loading: ' + e.message;
|
|
3352
|
+
statusEl.style.color = 'var(--accent,#e74c6f)';
|
|
3353
|
+
});
|
|
3354
|
+
}
|
|
3355
|
+
|
|
3356
|
+
function cortexEditorLibSection(id, filename, content) {
|
|
3357
|
+
return '<div id="cortex-lib-' + id + '" style="margin-bottom:1rem;border:1px solid #E5E7EB;border-radius:8px;padding:12px">'
|
|
3358
|
+
+ '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:.5rem">'
|
|
3359
|
+
+ '<label style="font-size:.85rem;font-weight:600">Lib: <input type="text" value="' + cortexEsc(filename) + '" data-lib-name="' + id + '" style="background:#F9FAFB;border:1px solid #E5E7EB;border-radius:4px;padding:2px 6px;color:#1A1A2E;font-family:monospace;font-size:.8rem;width:200px" /></label>'
|
|
3360
|
+
+ '<button onclick="document.getElementById(\'cortex-lib-' + id + '\').remove()" style="font-size:.7rem;padding:2px 8px;border-radius:4px;border:1px solid rgba(232,86,74,.3);background:transparent;color:#E8564A;cursor:pointer">Remove</button>'
|
|
3361
|
+
+ '</div>'
|
|
3362
|
+
+ '<textarea data-lib-content="' + id + '" spellcheck="false" style="width:100%;min-height:150px;background:#F9FAFB;color:#1A1A2E;border:1px solid #E5E7EB;border-radius:8px;padding:10px;font-family:monospace;font-size:.78rem;resize:vertical;tab-size:2">' + cortexEsc(content || '') + '</textarea>'
|
|
3363
|
+
+ '</div>';
|
|
3364
|
+
}
|
|
3365
|
+
|
|
3366
|
+
function cortexEditorAddLib() {
|
|
3367
|
+
cortexEditorLibCounter++;
|
|
3368
|
+
var container = document.getElementById('cortex-editor-libs');
|
|
3369
|
+
container.insertAdjacentHTML('beforeend', cortexEditorLibSection(cortexEditorLibCounter, 'new-lib.js', ''));
|
|
3370
|
+
}
|
|
3371
|
+
|
|
3372
|
+
function cortexEditorCollectLibs() {
|
|
3373
|
+
var libs = {};
|
|
3374
|
+
var container = document.getElementById('cortex-editor-libs');
|
|
3375
|
+
var nameInputs = container.querySelectorAll('input[data-lib-name]');
|
|
3376
|
+
for (var i = 0; i < nameInputs.length; i++) {
|
|
3377
|
+
var id = nameInputs[i].getAttribute('data-lib-name');
|
|
3378
|
+
var fname = nameInputs[i].value.trim();
|
|
3379
|
+
var contentEl = container.querySelector('textarea[data-lib-content="' + id + '"]');
|
|
3380
|
+
if (fname && contentEl) {
|
|
3381
|
+
libs[fname] = contentEl.value;
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
return libs;
|
|
3385
|
+
}
|
|
3386
|
+
|
|
3387
|
+
function cortexEditorSave() {
|
|
3388
|
+
var config = loadConfig();
|
|
3389
|
+
var url = config.aimeatUrl.replace(/\/+$/, '');
|
|
3390
|
+
var token = getCortexOwnerToken();
|
|
3391
|
+
if (!token) { alert('No auth token available.'); return; }
|
|
3392
|
+
|
|
3393
|
+
var manifest = document.getElementById('cortex-editor-manifest').value;
|
|
3394
|
+
if (!manifest.trim()) { alert('Manifest cannot be empty.'); return; }
|
|
3395
|
+
|
|
3396
|
+
var libs = cortexEditorCollectLibs();
|
|
3397
|
+
var statusEl = document.getElementById('cortex-editor-status');
|
|
3398
|
+
var saveBtn = document.getElementById('cortex-editor-save-btn');
|
|
3399
|
+
var oldName = cortexEditorExtName;
|
|
3400
|
+
var wasActive = cortexEditorWasActive;
|
|
3401
|
+
|
|
3402
|
+
statusEl.textContent = 'Deleting old extension...';
|
|
3403
|
+
statusEl.style.color = '#34d399';
|
|
3404
|
+
saveBtn.disabled = true;
|
|
3405
|
+
|
|
3406
|
+
// Step 1: Delete old extension
|
|
3407
|
+
fetch(url + '/v1/cortex/' + encodeURIComponent(oldName), {
|
|
3408
|
+
method: 'DELETE',
|
|
3409
|
+
headers: { 'Authorization': 'Bearer ' + token }
|
|
3410
|
+
})
|
|
3411
|
+
.then(function(r) {
|
|
3412
|
+
if (!r.ok && r.status !== 404) throw new Error('Delete failed: ' + r.status);
|
|
3413
|
+
statusEl.textContent = 'Installing updated extension...';
|
|
3414
|
+
// Step 2: Install new
|
|
3415
|
+
return fetch(url + '/v1/cortex', {
|
|
3416
|
+
method: 'POST',
|
|
3417
|
+
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
|
|
3418
|
+
body: JSON.stringify({ manifest: manifest, libs: libs })
|
|
3419
|
+
});
|
|
3420
|
+
})
|
|
3421
|
+
.then(function(r) { return r.json(); })
|
|
3422
|
+
.then(function(data) {
|
|
3423
|
+
if (data.status !== 'ok') {
|
|
3424
|
+
var errMsg = data.error || 'Install failed';
|
|
3425
|
+
if (data.details && data.details.errors) errMsg += ': ' + data.details.errors.join('; ');
|
|
3426
|
+
throw new Error(errMsg);
|
|
3427
|
+
}
|
|
3428
|
+
var newName = data.data.name;
|
|
3429
|
+
cortexEditorExtName = newName;
|
|
3430
|
+
|
|
3431
|
+
// Step 3: Activate if was active before
|
|
3432
|
+
if (wasActive) {
|
|
3433
|
+
statusEl.textContent = 'Activating...';
|
|
3434
|
+
return fetch(url + '/v1/cortex/' + encodeURIComponent(newName) + '/activate', {
|
|
3435
|
+
method: 'POST',
|
|
3436
|
+
headers: { 'Authorization': 'Bearer ' + token }
|
|
3437
|
+
}).then(function(r) { return r.json(); });
|
|
3438
|
+
}
|
|
3439
|
+
return null;
|
|
3440
|
+
})
|
|
3441
|
+
.then(function(activateData) {
|
|
3442
|
+
saveBtn.disabled = false;
|
|
3443
|
+
if (activateData && activateData.status !== 'ok') {
|
|
3444
|
+
statusEl.textContent = 'Installed but activation failed: ' + (activateData.error || 'unknown');
|
|
3445
|
+
statusEl.style.color = 'orange';
|
|
3446
|
+
} else {
|
|
3447
|
+
statusEl.textContent = 'Saved and re-installed successfully!';
|
|
3448
|
+
statusEl.style.color = '#34d399';
|
|
3449
|
+
cortexEditorWasActive = wasActive; // preserve
|
|
3450
|
+
// Refresh the cortex bar
|
|
3451
|
+
loadCortexExtensions();
|
|
3452
|
+
}
|
|
3453
|
+
})
|
|
3454
|
+
.catch(function(e) {
|
|
3455
|
+
saveBtn.disabled = false;
|
|
3456
|
+
statusEl.textContent = 'Error: ' + e.message;
|
|
3457
|
+
statusEl.style.color = '#E8564A';
|
|
3458
|
+
});
|
|
3459
|
+
}
|
|
3460
|
+
|
|
3461
|
+
function cortexEditorExport() {
|
|
3462
|
+
var manifest = document.getElementById('cortex-editor-manifest').value;
|
|
3463
|
+
var libs = cortexEditorCollectLibs();
|
|
3464
|
+
var name = (cortexEditorExtName || 'extension').replace(/\//g, '-');
|
|
3465
|
+
|
|
3466
|
+
// Download manifest
|
|
3467
|
+
var manifestBlob = new Blob([manifest], { type: 'text/yaml' });
|
|
3468
|
+
var a = document.createElement('a');
|
|
3469
|
+
a.href = URL.createObjectURL(manifestBlob);
|
|
3470
|
+
a.download = name + '.yaml';
|
|
3471
|
+
a.click();
|
|
3472
|
+
URL.revokeObjectURL(a.href);
|
|
3473
|
+
|
|
3474
|
+
// Download each lib file
|
|
3475
|
+
var filenames = Object.keys(libs);
|
|
3476
|
+
for (var i = 0; i < filenames.length; i++) {
|
|
3477
|
+
var libBlob = new Blob([libs[filenames[i]]], { type: 'application/javascript' });
|
|
3478
|
+
var b = document.createElement('a');
|
|
3479
|
+
b.href = URL.createObjectURL(libBlob);
|
|
3480
|
+
b.download = filenames[i];
|
|
3481
|
+
b.click();
|
|
3482
|
+
URL.revokeObjectURL(b.href);
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
|
|
3486
|
+
function closeCortexEditor() {
|
|
3487
|
+
document.getElementById('cortex-editor-overlay').style.display = 'none';
|
|
3488
|
+
cortexEditorExtName = null;
|
|
3489
|
+
}
|
|
3490
|
+
|
|
3491
|
+
// ── Prompt Builder Panel ──────────────────────────
|
|
3492
|
+
|
|
3493
|
+
var pbExtensionsCache = null; // cached cortex extension list
|
|
3494
|
+
var pbExtDetailCache = {}; // cached extension details (name → detail object)
|
|
3495
|
+
var pbSourceApp = null; // app being improved (null = new app mode)
|
|
3496
|
+
|
|
3497
|
+
function openPromptBuilder(app) {
|
|
3498
|
+
pbSourceApp = app || null;
|
|
3499
|
+
var overlay = document.getElementById('prompt-builder-overlay');
|
|
3500
|
+
var desc = document.getElementById('pb-description');
|
|
3501
|
+
var extCheckbox = document.getElementById('pb-ext-checkbox');
|
|
3502
|
+
var extList = document.getElementById('pb-ext-list');
|
|
3503
|
+
|
|
3504
|
+
// Reset state
|
|
3505
|
+
desc.value = '';
|
|
3506
|
+
extCheckbox.checked = false;
|
|
3507
|
+
extList.classList.remove('open');
|
|
3508
|
+
|
|
3509
|
+
// Set mode based on whether we have a source app
|
|
3510
|
+
var radios = document.querySelectorAll('input[name="pb-mode"]');
|
|
3511
|
+
if (pbSourceApp) {
|
|
3512
|
+
radios[1].checked = true; // Improve This App
|
|
3513
|
+
desc.placeholder = 'Describe what changes to make to "' + (pbSourceApp.name || 'this app') + '"...';
|
|
3514
|
+
} else {
|
|
3515
|
+
radios[0].checked = true; // New App
|
|
3516
|
+
desc.placeholder = 'Describe what the app should do...';
|
|
3517
|
+
}
|
|
3518
|
+
|
|
3519
|
+
// Load Cortex extensions into picker
|
|
3520
|
+
loadPbExtensions();
|
|
3521
|
+
|
|
3522
|
+
overlay.style.display = 'flex';
|
|
3523
|
+
desc.focus();
|
|
3524
|
+
updatePbPreview();
|
|
3525
|
+
}
|
|
3526
|
+
|
|
3527
|
+
function closePbPanel() {
|
|
3528
|
+
document.getElementById('prompt-builder-overlay').style.display = 'none';
|
|
3529
|
+
pbSourceApp = null;
|
|
3530
|
+
}
|
|
3531
|
+
|
|
3532
|
+
function loadPbExtensions() {
|
|
3533
|
+
var list = document.getElementById('pb-ext-list');
|
|
3534
|
+
var config = loadConfig();
|
|
3535
|
+
if (!config.aimeatUrl) {
|
|
3536
|
+
list.innerHTML = '<span style="color:var(--text-muted);font-size:.8rem">Configure AIMEAT URL in Settings to load extensions</span>';
|
|
3537
|
+
return;
|
|
3538
|
+
}
|
|
3539
|
+
|
|
3540
|
+
// Use cached data if available
|
|
3541
|
+
if (pbExtensionsCache) {
|
|
3542
|
+
renderPbExtensions(pbExtensionsCache);
|
|
3543
|
+
return;
|
|
3544
|
+
}
|
|
3545
|
+
|
|
3546
|
+
list.innerHTML = '<span style="color:var(--text-muted);font-size:.8rem">Loading extensions...</span>';
|
|
3547
|
+
var url = config.aimeatUrl.replace(/\/+$/, '');
|
|
3548
|
+
|
|
3549
|
+
var token = cortexToken;
|
|
3550
|
+
var fetchExts = function(authToken) {
|
|
3551
|
+
fetch(url + '/v1/cortex?status=active', {
|
|
3552
|
+
headers: { 'Authorization': 'Bearer ' + authToken }
|
|
3553
|
+
})
|
|
3554
|
+
.then(function(r) { return r.json(); })
|
|
3555
|
+
.then(function(data) {
|
|
3556
|
+
if (!data || !data.data || !data.data.extensions) {
|
|
3557
|
+
list.innerHTML = '<span style="color:var(--text-muted);font-size:.8rem">No extensions available</span>';
|
|
3558
|
+
return;
|
|
3559
|
+
}
|
|
3560
|
+
pbExtensionsCache = data.data.extensions;
|
|
3561
|
+
renderPbExtensions(pbExtensionsCache);
|
|
3562
|
+
})
|
|
3563
|
+
.catch(function() {
|
|
3564
|
+
list.innerHTML = '<span style="color:var(--text-muted);font-size:.8rem">Failed to load extensions</span>';
|
|
3565
|
+
});
|
|
3566
|
+
};
|
|
3567
|
+
|
|
3568
|
+
if (token) {
|
|
3569
|
+
fetchExts(token);
|
|
3570
|
+
} else {
|
|
3571
|
+
fetch(url + '/v1/auth/anonymous', { method: 'POST' })
|
|
3572
|
+
.then(function(r) { return r.json(); })
|
|
3573
|
+
.then(function(authData) {
|
|
3574
|
+
var t = authData.data && authData.data.token;
|
|
3575
|
+
if (!t) { list.innerHTML = '<span style="color:var(--text-muted);font-size:.8rem">Auth failed</span>'; return; }
|
|
3576
|
+
cortexToken = t;
|
|
3577
|
+
fetchExts(t);
|
|
3578
|
+
})
|
|
3579
|
+
.catch(function() {
|
|
3580
|
+
list.innerHTML = '<span style="color:var(--text-muted);font-size:.8rem">Failed to authenticate</span>';
|
|
3581
|
+
});
|
|
3582
|
+
}
|
|
3583
|
+
}
|
|
3584
|
+
|
|
3585
|
+
function renderPbExtensions(extensions) {
|
|
3586
|
+
var list = document.getElementById('pb-ext-list');
|
|
3587
|
+
if (!extensions.length) {
|
|
3588
|
+
list.innerHTML = '<span style="color:var(--text-muted);font-size:.8rem">No active extensions</span>';
|
|
3589
|
+
return;
|
|
3590
|
+
}
|
|
3591
|
+
list.innerHTML = extensions.map(function(ext, i) {
|
|
3592
|
+
var types = (ext.component_types || []).join(', ');
|
|
3593
|
+
return '<label class="pb-ext-chip" data-ext-index="' + i + '">'
|
|
3594
|
+
+ '<input type="checkbox" data-ext-name="' + cortexEsc(ext.name) + '"> '
|
|
3595
|
+
+ cortexEsc(ext.short_name || ext.name)
|
|
3596
|
+
+ ' <span style="font-size:.7rem;color:var(--text-muted)">(' + cortexEsc(types) + ')</span>'
|
|
3597
|
+
+ '</label>';
|
|
3598
|
+
}).join('');
|
|
3599
|
+
|
|
3600
|
+
// Toggle selected class and update preview on change
|
|
3601
|
+
list.querySelectorAll('input[type="checkbox"]').forEach(function(cb) {
|
|
3602
|
+
cb.addEventListener('change', function() {
|
|
3603
|
+
this.closest('.pb-ext-chip').classList.toggle('selected', this.checked);
|
|
3604
|
+
if (this.checked) {
|
|
3605
|
+
fetchExtDetail(this.getAttribute('data-ext-name'));
|
|
3606
|
+
} else {
|
|
3607
|
+
updatePbPreview();
|
|
3608
|
+
}
|
|
3609
|
+
});
|
|
3610
|
+
});
|
|
3611
|
+
}
|
|
3612
|
+
|
|
3613
|
+
function getSelectedExtensions() {
|
|
3614
|
+
var selected = [];
|
|
3615
|
+
var checkboxes = document.querySelectorAll('#pb-ext-list input[type="checkbox"]:checked');
|
|
3616
|
+
checkboxes.forEach(function(cb) {
|
|
3617
|
+
var name = cb.getAttribute('data-ext-name');
|
|
3618
|
+
// Prefer detail cache, fall back to list data
|
|
3619
|
+
if (pbExtDetailCache[name]) {
|
|
3620
|
+
selected.push(pbExtDetailCache[name]);
|
|
3621
|
+
} else if (pbExtensionsCache) {
|
|
3622
|
+
for (var i = 0; i < pbExtensionsCache.length; i++) {
|
|
3623
|
+
if (pbExtensionsCache[i].name === name) {
|
|
3624
|
+
selected.push(pbExtensionsCache[i]);
|
|
3625
|
+
break;
|
|
3626
|
+
}
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3629
|
+
});
|
|
3630
|
+
return selected;
|
|
3631
|
+
}
|
|
3632
|
+
|
|
3633
|
+
function fetchExtDetail(extName) {
|
|
3634
|
+
// Already cached
|
|
3635
|
+
if (pbExtDetailCache[extName]) { updatePbPreview(); return; }
|
|
3636
|
+
var config = loadConfig();
|
|
3637
|
+
if (!config.aimeatUrl || !cortexToken) { updatePbPreview(); return; }
|
|
3638
|
+
var url = config.aimeatUrl.replace(/\/+$/, '');
|
|
3639
|
+
fetch(url + '/v1/cortex/' + encodeURIComponent(extName), {
|
|
3640
|
+
headers: { 'Authorization': 'Bearer ' + cortexToken }
|
|
3641
|
+
})
|
|
3642
|
+
.then(function(r) { return r.json(); })
|
|
3643
|
+
.then(function(data) {
|
|
3644
|
+
if (data && data.data) {
|
|
3645
|
+
pbExtDetailCache[extName] = data.data;
|
|
3646
|
+
}
|
|
3647
|
+
updatePbPreview();
|
|
3648
|
+
})
|
|
3649
|
+
.catch(function() { updatePbPreview(); });
|
|
3650
|
+
}
|
|
3651
|
+
|
|
3652
|
+
function buildPromptFromBuilder() {
|
|
3653
|
+
var config = loadConfig();
|
|
3654
|
+
var nodeUrl = config.aimeatUrl ? config.aimeatUrl.replace(/\/+$/, '') : 'https://your-aimeat-node.example';
|
|
3655
|
+
var mode = document.querySelector('input[name="pb-mode"]:checked').value;
|
|
3656
|
+
var description = document.getElementById('pb-description').value.trim();
|
|
3657
|
+
var selectedExts = document.getElementById('pb-ext-checkbox').checked ? getSelectedExtensions() : [];
|
|
3658
|
+
|
|
3659
|
+
var prompt = '';
|
|
3660
|
+
|
|
3661
|
+
// Header
|
|
3662
|
+
if (mode === 'improve' && pbSourceApp) {
|
|
3663
|
+
prompt += 'Here is an HTML app called "' + (pbSourceApp.name || 'Untitled') + '".\n';
|
|
3664
|
+
prompt += 'Make the following change: ' + (description || '[DESCRIBE YOUR CHANGE HERE]') + '\n\n';
|
|
3665
|
+
prompt += 'Return the COMPLETE updated HTML file. Do not omit any parts.\n\n';
|
|
3666
|
+
} else {
|
|
3667
|
+
prompt += 'Create a new single-file HTML app.\n';
|
|
3668
|
+
prompt += 'Description: ' + (description || '[DESCRIBE WHAT THE APP SHOULD DO]') + '\n\n';
|
|
3669
|
+
}
|
|
3670
|
+
|
|
3671
|
+
// AIMEAT Platform Instructions
|
|
3672
|
+
prompt += '## AIMEAT Platform Instructions\n\n';
|
|
3673
|
+
prompt += 'This app runs in the AIMEAT ecosystem. Here is what you need to know:\n\n';
|
|
3674
|
+
|
|
3675
|
+
// Core libraries
|
|
3676
|
+
prompt += '### Available Client Libraries\n';
|
|
3677
|
+
prompt += 'Load via script tags from the AIMEAT node (' + nodeUrl + '):\n';
|
|
3678
|
+
prompt += '- aimeat-auth (' + nodeUrl + '/v1/libs/aimeat-auth.js) - Identity, login, JWT, session management\n';
|
|
3679
|
+
prompt += '- aimeat-data (' + nodeUrl + '/v1/libs/aimeat-data.js) - Memory storage, search, key-value data\n';
|
|
3680
|
+
prompt += '- aimeat-storage (' + nodeUrl + '/v1/libs/aimeat-storage.js) - File upload/download\n';
|
|
3681
|
+
prompt += '- aimeat-social (' + nodeUrl + '/v1/libs/aimeat-social.js) - Boards, posts, reactions\n';
|
|
3682
|
+
prompt += '- aimeat-wallet (' + nodeUrl + '/v1/libs/aimeat-wallet.js) - Balance, transactions\n';
|
|
3683
|
+
prompt += '- aimeat-work (' + nodeUrl + '/v1/libs/aimeat-work.js) - Actions, work requests\n\n';
|
|
3684
|
+
|
|
3685
|
+
// Cortex extension instructions
|
|
3686
|
+
if (selectedExts.length > 0) {
|
|
3687
|
+
prompt += '### Cortex Extensions (include these)\n\n';
|
|
3688
|
+
selectedExts.forEach(function(ext) {
|
|
3689
|
+
prompt += '#### ' + ext.name + '\n';
|
|
3690
|
+
prompt += ext.description ? ext.description + '\n' : '';
|
|
3691
|
+
|
|
3692
|
+
// Use detailed components if available
|
|
3693
|
+
var comps = ext.components;
|
|
3694
|
+
if (comps && comps.length) {
|
|
3695
|
+
comps.forEach(function(c) {
|
|
3696
|
+
if (c.type === 'lib' && c.filename) {
|
|
3697
|
+
prompt += 'Load the library:\n```html\n';
|
|
3698
|
+
prompt += '<script src="' + nodeUrl + '/v1/cortex/' + encodeURIComponent(ext.name) + '/libs/' + encodeURIComponent(c.filename) + '"></' + 'script>\n';
|
|
3699
|
+
prompt += '```\n';
|
|
3700
|
+
if (c.api_surface) {
|
|
3701
|
+
prompt += 'API Surface:\n```\n' + c.api_surface + '\n```\n';
|
|
3702
|
+
}
|
|
3703
|
+
} else if (c.type === 'schema') {
|
|
3704
|
+
prompt += 'Data schema: `' + (c.key_pattern || '') + '` — data is validated automatically.\n';
|
|
3705
|
+
} else if (c.type === 'prompt') {
|
|
3706
|
+
prompt += 'Prompt template: ' + (c.name || '') + '\n';
|
|
3707
|
+
}
|
|
3708
|
+
});
|
|
3709
|
+
} else {
|
|
3710
|
+
// Fallback: only list-level type info
|
|
3711
|
+
var types = ext.component_types || [];
|
|
3712
|
+
if (types.indexOf('lib') !== -1) {
|
|
3713
|
+
prompt += 'Includes a JS library (load via `<script src="' + nodeUrl + '/v1/cortex/' + encodeURIComponent(ext.name) + '/libs/...">`).\n';
|
|
3714
|
+
}
|
|
3715
|
+
if (types.indexOf('schema') !== -1) {
|
|
3716
|
+
prompt += 'Provides validated data schemas.\n';
|
|
3717
|
+
}
|
|
3718
|
+
if (types.indexOf('prompt') !== -1) {
|
|
3719
|
+
prompt += 'Includes prompt templates.\n';
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3722
|
+
prompt += '\n';
|
|
3723
|
+
});
|
|
3724
|
+
}
|
|
3725
|
+
|
|
3726
|
+
// Auth pattern
|
|
3727
|
+
prompt += '### Auth Pattern\n';
|
|
3728
|
+
prompt += '```html\n';
|
|
3729
|
+
prompt += '<script src="' + nodeUrl + '/v1/libs/aimeat-auth.js"></' + 'script>\n';
|
|
3730
|
+
prompt += '<script>\n';
|
|
3731
|
+
prompt += 'AIMEAT.auth.mountLoginButton("#login", {\n';
|
|
3732
|
+
prompt += ' onLogin: function(session) { /* session.owner, session.jwt, session.fetch() */ },\n';
|
|
3733
|
+
prompt += ' onLogout: function() { /* hide content */ }\n';
|
|
3734
|
+
prompt += '});\n';
|
|
3735
|
+
prompt += '</' + 'script>\n';
|
|
3736
|
+
prompt += '```\n\n';
|
|
3737
|
+
|
|
3738
|
+
// Data storage
|
|
3739
|
+
prompt += '### Data Storage\n';
|
|
3740
|
+
prompt += '```javascript\n';
|
|
3741
|
+
prompt += 'await AIMEAT.data.set("key", "value", { visibility: "private", tags: ["t1"] });\n';
|
|
3742
|
+
prompt += 'var val = await AIMEAT.data.get("key");\n';
|
|
3743
|
+
prompt += 'var results = await AIMEAT.data.search("query");\n';
|
|
3744
|
+
prompt += '```\n\n';
|
|
3745
|
+
|
|
3746
|
+
// Design guidelines
|
|
3747
|
+
prompt += '### Design Guidelines\n';
|
|
3748
|
+
prompt += 'Recommended light theme:\n';
|
|
3749
|
+
prompt += '```css\n';
|
|
3750
|
+
prompt += ':root { --bg:#FAFAF8; --card:#FFFFFF; --text:#1A1A2E;\n';
|
|
3751
|
+
prompt += ' --accent:#E8564A; --border:#E5E7EB; --radius:12px; }\n';
|
|
3752
|
+
prompt += '```\n';
|
|
3753
|
+
prompt += 'Always include: <meta name="viewport" content="width=device-width, initial-scale=1.0">\n';
|
|
3754
|
+
prompt += 'Mobile-first responsive. Single HTML file with embedded CSS and JS.\n\n';
|
|
3755
|
+
|
|
3756
|
+
// Rules
|
|
3757
|
+
prompt += '### Important Rules\n';
|
|
3758
|
+
prompt += '- Return the COMPLETE HTML file, not fragments\n';
|
|
3759
|
+
prompt += '- Never use literal closing script tags in JS comments or strings\n';
|
|
3760
|
+
prompt += '- Keep it as a single self-contained HTML file\n';
|
|
3761
|
+
prompt += '- Include error handling and loading states for API calls\n\n';
|
|
3762
|
+
|
|
3763
|
+
// Source code for improve mode
|
|
3764
|
+
if (mode === 'improve' && pbSourceApp && pbSourceApp.blob) {
|
|
3765
|
+
var source = decodeURIComponent(escape(atob(pbSourceApp.blob)));
|
|
3766
|
+
prompt += '--- Source Code ---\n' + source;
|
|
3767
|
+
}
|
|
3768
|
+
|
|
3769
|
+
return prompt;
|
|
3770
|
+
}
|
|
3771
|
+
|
|
3772
|
+
function updatePbPreview() {
|
|
3773
|
+
var preview = document.getElementById('pb-preview');
|
|
3774
|
+
var prompt = buildPromptFromBuilder();
|
|
3775
|
+
// Show first ~2000 chars with truncation indicator
|
|
3776
|
+
if (prompt.length > 2000) {
|
|
3777
|
+
preview.textContent = prompt.substring(0, 2000) + '\n\n... (' + prompt.length + ' chars total)';
|
|
3778
|
+
} else {
|
|
3779
|
+
preview.textContent = prompt;
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
|
|
3783
|
+
// ── Drag & Drop Reordering ─────────────────────
|
|
3784
|
+
|
|
3785
|
+
var dragSourceId = null;
|
|
3786
|
+
|
|
3787
|
+
function onCardDragStart(e) {
|
|
3788
|
+
var card = e.target.closest('.app-card');
|
|
3789
|
+
if (!card) return;
|
|
3790
|
+
dragSourceId = card.dataset.id;
|
|
3791
|
+
card.classList.add('dragging');
|
|
3792
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
3793
|
+
e.dataTransfer.setData('text/plain', dragSourceId);
|
|
3794
|
+
}
|
|
3795
|
+
|
|
3796
|
+
function onCardDragEnd(e) {
|
|
3797
|
+
var card = e.target.closest('.app-card');
|
|
3798
|
+
if (card) card.classList.remove('dragging');
|
|
3799
|
+
// Remove all drag-over highlights
|
|
3800
|
+
var cards = document.querySelectorAll('.app-card.drag-over');
|
|
3801
|
+
for (var i = 0; i < cards.length; i++) cards[i].classList.remove('drag-over');
|
|
3802
|
+
dragSourceId = null;
|
|
3803
|
+
}
|
|
3804
|
+
|
|
3805
|
+
function onCardDragOver(e) {
|
|
3806
|
+
e.preventDefault();
|
|
3807
|
+
e.dataTransfer.dropEffect = 'move';
|
|
3808
|
+
var card = e.target.closest('.app-card');
|
|
3809
|
+
if (!card || card.dataset.id === dragSourceId) return;
|
|
3810
|
+
// Remove highlight from others
|
|
3811
|
+
var cards = document.querySelectorAll('.app-card.drag-over');
|
|
3812
|
+
for (var i = 0; i < cards.length; i++) cards[i].classList.remove('drag-over');
|
|
3813
|
+
card.classList.add('drag-over');
|
|
3814
|
+
}
|
|
3815
|
+
|
|
3816
|
+
function onCardDrop(e) {
|
|
3817
|
+
e.preventDefault();
|
|
3818
|
+
var targetCard = e.target.closest('.app-card');
|
|
3819
|
+
if (!targetCard) return;
|
|
3820
|
+
var targetId = targetCard.dataset.id;
|
|
3821
|
+
if (!dragSourceId || dragSourceId === targetId) return;
|
|
3822
|
+
|
|
3823
|
+
// Find indexes in the currently rendered/sorted allApps
|
|
3824
|
+
var srcIdx = -1, tgtIdx = -1;
|
|
3825
|
+
for (var i = 0; i < allApps.length; i++) {
|
|
3826
|
+
if (allApps[i].id === dragSourceId) srcIdx = i;
|
|
3827
|
+
if (allApps[i].id === targetId) tgtIdx = i;
|
|
3828
|
+
}
|
|
3829
|
+
if (srcIdx === -1 || tgtIdx === -1) return;
|
|
3830
|
+
|
|
3831
|
+
// Move the source app to the target position
|
|
3832
|
+
var moved = allApps.splice(srcIdx, 1)[0];
|
|
3833
|
+
allApps.splice(tgtIdx, 0, moved);
|
|
3834
|
+
|
|
3835
|
+
// Assign sortOrder values based on new positions
|
|
3836
|
+
var saves = [];
|
|
3837
|
+
for (var j = 0; j < allApps.length; j++) {
|
|
3838
|
+
allApps[j].sortOrder = j;
|
|
3839
|
+
saves.push(saveApp(allApps[j]));
|
|
3840
|
+
}
|
|
3841
|
+
|
|
3842
|
+
// Re-render immediately (no animation delay for reorder)
|
|
3843
|
+
var grid = document.getElementById('app-grid');
|
|
3844
|
+
var cards = grid.querySelectorAll('.app-card');
|
|
3845
|
+
for (var k = 0; k < cards.length; k++) {
|
|
3846
|
+
cards[k].classList.remove('drag-over', 'dragging');
|
|
3847
|
+
}
|
|
3848
|
+
|
|
3849
|
+
Promise.all(saves).then(function () {
|
|
3850
|
+
renderApps();
|
|
3851
|
+
});
|
|
3852
|
+
}
|
|
3853
|
+
|
|
3854
|
+
// ── Public API ────────────────────────────────────
|
|
3855
|
+
|
|
3856
|
+
window._launcher = {
|
|
3857
|
+
openDB: openDB,
|
|
3858
|
+
getAllApps: getAllApps,
|
|
3859
|
+
saveApp: saveApp,
|
|
3860
|
+
deleteApp: deleteApp,
|
|
3861
|
+
loadConfig: loadConfig,
|
|
3862
|
+
saveConfig: saveConfig,
|
|
3863
|
+
renderApps: renderApps,
|
|
3864
|
+
renderTags: renderTags,
|
|
3865
|
+
filterByTag: filterByTag,
|
|
3866
|
+
launchApp: launchApp,
|
|
3867
|
+
launchInTab: launchInTab,
|
|
3868
|
+
launchInIframe: launchInIframe,
|
|
3869
|
+
closeIframe: closeIframe,
|
|
3870
|
+
openExternal: openExternal,
|
|
3871
|
+
setCurrentIframeUrl: function (url) { currentIframeUrl = url; },
|
|
3872
|
+
showContextMenu: showContextMenu,
|
|
3873
|
+
hideContextMenu: hideContextMenu,
|
|
3874
|
+
handleContextAction: handleContextAction,
|
|
3875
|
+
generateId: generateId,
|
|
3876
|
+
readFileAsText: readFileAsText,
|
|
3877
|
+
addAppFromUrl: addAppFromUrl,
|
|
3878
|
+
addAppFromFile: addAppFromFile,
|
|
3879
|
+
addAppFromSource: addAppFromSource,
|
|
3880
|
+
addAppFromZip: addAppFromZip,
|
|
3881
|
+
showModal: showModal,
|
|
3882
|
+
closeModal: closeModal,
|
|
3883
|
+
openSettings: openSettings,
|
|
3884
|
+
saveSettings: saveSettings,
|
|
3885
|
+
closeSettings: closeSettings,
|
|
3886
|
+
applyTheme: applyTheme,
|
|
3887
|
+
exportBackup: exportBackup,
|
|
3888
|
+
clearAllData: clearAllData,
|
|
3889
|
+
importFromAimeat: importFromAimeat,
|
|
3890
|
+
processAimeatImport: processAimeatImport,
|
|
3891
|
+
viewSource: viewSource,
|
|
3892
|
+
generateHomepagePrompt: generateHomepagePrompt,
|
|
3893
|
+
showPublishModal: showPublishModal,
|
|
3894
|
+
submitPublish: submitPublish,
|
|
3895
|
+
loadPublishedApps: loadPublishedApps,
|
|
3896
|
+
togglePublished: togglePublished,
|
|
3897
|
+
unpublishApp: unpublishApp,
|
|
3898
|
+
renderRecentlyOpened: renderRecentlyOpened,
|
|
3899
|
+
loadCortexExtensions: loadCortexExtensions,
|
|
3900
|
+
showCortexPopup: showCortexPopup,
|
|
3901
|
+
cortexCopy: cortexCopy,
|
|
3902
|
+
openCortexEditor: openCortexEditor,
|
|
3903
|
+
closeCortexEditor: closeCortexEditor,
|
|
3904
|
+
cortexEditorAddLib: cortexEditorAddLib,
|
|
3905
|
+
cortexEditorSave: cortexEditorSave,
|
|
3906
|
+
cortexEditorExport: cortexEditorExport,
|
|
3907
|
+
openPromptBuilder: openPromptBuilder,
|
|
3908
|
+
closePbPanel: closePbPanel,
|
|
3909
|
+
onCardDragStart: onCardDragStart,
|
|
3910
|
+
onCardDragEnd: onCardDragEnd,
|
|
3911
|
+
onCardDragOver: onCardDragOver,
|
|
3912
|
+
onCardDrop: onCardDrop,
|
|
3913
|
+
syncConfigToServer: syncConfigToServer,
|
|
3914
|
+
loadConfigFromServer: loadConfigFromServer
|
|
3915
|
+
};
|
|
3916
|
+
|
|
3917
|
+
// Expose cortex functions globally for inline onclick handlers
|
|
3918
|
+
window.showCortexPopup = showCortexPopup;
|
|
3919
|
+
window.cortexCopy = cortexCopy;
|
|
3920
|
+
|
|
3921
|
+
// ── Bootstrap ─────────────────────────────────────
|
|
3922
|
+
|
|
3923
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
3924
|
+
// ── Apply theme on load ─────────────────────────
|
|
3925
|
+
applyTheme(loadConfig().theme);
|
|
3926
|
+
|
|
3927
|
+
renderApps();
|
|
3928
|
+
loadPublishedApps();
|
|
3929
|
+
loadCortexExtensions();
|
|
3930
|
+
loadConfigFromServer();
|
|
3931
|
+
|
|
3932
|
+
// ── Search input ─────────────────────────────────
|
|
3933
|
+
document.getElementById('search-input').addEventListener('input', function (e) {
|
|
3934
|
+
searchQuery = e.target.value.trim();
|
|
3935
|
+
renderApps();
|
|
3936
|
+
});
|
|
3937
|
+
|
|
3938
|
+
// ── Add App button ──────────────────────────────
|
|
3939
|
+
document.getElementById('add-btn').addEventListener('click', function () {
|
|
3940
|
+
showModal();
|
|
3941
|
+
});
|
|
3942
|
+
|
|
3943
|
+
// ── Generate with AI button ─────────────────────
|
|
3944
|
+
document.getElementById('generate-btn').addEventListener('click', function () {
|
|
3945
|
+
openPromptBuilder(null);
|
|
3946
|
+
});
|
|
3947
|
+
|
|
3948
|
+
// ── Settings button ─────────────────────────────
|
|
3949
|
+
document.getElementById('settings-btn').addEventListener('click', function () {
|
|
3950
|
+
openSettings();
|
|
3951
|
+
});
|
|
3952
|
+
|
|
3953
|
+
// ── Settings save / cancel ──────────────────────
|
|
3954
|
+
document.getElementById('settings-save-btn').addEventListener('click', function () {
|
|
3955
|
+
saveSettings();
|
|
3956
|
+
});
|
|
3957
|
+
|
|
3958
|
+
document.getElementById('settings-cancel-btn').addEventListener('click', function () {
|
|
3959
|
+
closeSettings();
|
|
3960
|
+
});
|
|
3961
|
+
|
|
3962
|
+
// ── Click settings overlay to close ─────────────
|
|
3963
|
+
document.getElementById('settings-overlay').addEventListener('click', function (e) {
|
|
3964
|
+
if (e.target === this) {
|
|
3965
|
+
closeSettings();
|
|
3966
|
+
}
|
|
3967
|
+
});
|
|
3968
|
+
|
|
3969
|
+
// ── Import backup file input ────────────────────
|
|
3970
|
+
document.getElementById('import-file-input').addEventListener('change', function () {
|
|
3971
|
+
if (this.files && this.files.length > 0) {
|
|
3972
|
+
handleImportBackup(this.files[0]);
|
|
3973
|
+
this.value = ''; // Reset for re-import
|
|
3974
|
+
}
|
|
3975
|
+
});
|
|
3976
|
+
|
|
3977
|
+
// ── Click AIMEAT import overlay to close ────────
|
|
3978
|
+
document.getElementById('aimeat-import-overlay').addEventListener('click', function (e) {
|
|
3979
|
+
if (e.target === this) {
|
|
3980
|
+
this.hidden = true;
|
|
3981
|
+
}
|
|
3982
|
+
});
|
|
3983
|
+
|
|
3984
|
+
// ── Click publish overlay to close ──────────────
|
|
3985
|
+
document.getElementById('publish-overlay').addEventListener('click', function (e) {
|
|
3986
|
+
if (e.target === this) {
|
|
3987
|
+
this.hidden = true;
|
|
3988
|
+
}
|
|
3989
|
+
});
|
|
3990
|
+
|
|
3991
|
+
// ── Click cortex popup overlay to close ─────────
|
|
3992
|
+
document.getElementById('cortex-popup-overlay').addEventListener('click', function (e) {
|
|
3993
|
+
if (e.target === this) {
|
|
3994
|
+
this.style.display = 'none';
|
|
3995
|
+
}
|
|
3996
|
+
});
|
|
3997
|
+
|
|
3998
|
+
// ── Click cortex editor overlay to close ────────
|
|
3999
|
+
document.getElementById('cortex-editor-overlay').addEventListener('click', function (e) {
|
|
4000
|
+
if (e.target === this) {
|
|
4001
|
+
closeCortexEditor();
|
|
4002
|
+
}
|
|
4003
|
+
});
|
|
4004
|
+
|
|
4005
|
+
// ── Tab switching ───────────────────────────────
|
|
4006
|
+
var tabBtns = document.querySelectorAll('#add-app-modal .modal-tab');
|
|
4007
|
+
tabBtns.forEach(function (btn) {
|
|
4008
|
+
btn.addEventListener('click', function () {
|
|
4009
|
+
switchTab(btn.getAttribute('data-tab'));
|
|
4010
|
+
});
|
|
4011
|
+
});
|
|
4012
|
+
|
|
4013
|
+
// ── Drop zone events ────────────────────────────
|
|
4014
|
+
var dropZone = document.getElementById('drop-zone');
|
|
4015
|
+
var fileInput = document.getElementById('file-input');
|
|
4016
|
+
var browseBtn = document.getElementById('browse-btn');
|
|
4017
|
+
|
|
4018
|
+
dropZone.addEventListener('dragover', function (e) {
|
|
4019
|
+
e.preventDefault();
|
|
4020
|
+
e.stopPropagation();
|
|
4021
|
+
dropZone.classList.add('dragover');
|
|
4022
|
+
});
|
|
4023
|
+
|
|
4024
|
+
dropZone.addEventListener('dragleave', function (e) {
|
|
4025
|
+
e.preventDefault();
|
|
4026
|
+
e.stopPropagation();
|
|
4027
|
+
dropZone.classList.remove('dragover');
|
|
4028
|
+
});
|
|
4029
|
+
|
|
4030
|
+
dropZone.addEventListener('drop', function (e) {
|
|
4031
|
+
e.preventDefault();
|
|
4032
|
+
e.stopPropagation();
|
|
4033
|
+
dropZone.classList.remove('dragover');
|
|
4034
|
+
if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
|
4035
|
+
handleFileDrop(e.dataTransfer.files[0]);
|
|
4036
|
+
}
|
|
4037
|
+
});
|
|
4038
|
+
|
|
4039
|
+
browseBtn.addEventListener('click', function (e) {
|
|
4040
|
+
e.stopPropagation();
|
|
4041
|
+
fileInput.click();
|
|
4042
|
+
});
|
|
4043
|
+
|
|
4044
|
+
fileInput.addEventListener('change', function () {
|
|
4045
|
+
if (fileInput.files && fileInput.files.length > 0) {
|
|
4046
|
+
handleFileDrop(fileInput.files[0]);
|
|
4047
|
+
}
|
|
4048
|
+
});
|
|
4049
|
+
|
|
4050
|
+
// ── Modal save / cancel ─────────────────────────
|
|
4051
|
+
document.getElementById('modal-save-btn').addEventListener('click', function () {
|
|
4052
|
+
handleSave();
|
|
4053
|
+
});
|
|
4054
|
+
|
|
4055
|
+
document.getElementById('modal-cancel-btn').addEventListener('click', function () {
|
|
4056
|
+
closeModal();
|
|
4057
|
+
});
|
|
4058
|
+
|
|
4059
|
+
// ── Click overlay to close ──────────────────────
|
|
4060
|
+
document.getElementById('modal-overlay').addEventListener('click', function (e) {
|
|
4061
|
+
if (e.target === this) {
|
|
4062
|
+
closeModal();
|
|
4063
|
+
}
|
|
4064
|
+
});
|
|
4065
|
+
|
|
4066
|
+
// ── Context menu action buttons ─────────────────
|
|
4067
|
+
var contextMenu = document.getElementById('context-menu');
|
|
4068
|
+
var contextBtns = contextMenu.querySelectorAll('button[data-action]');
|
|
4069
|
+
contextBtns.forEach(function (btn) {
|
|
4070
|
+
btn.addEventListener('click', function (e) {
|
|
4071
|
+
e.stopPropagation();
|
|
4072
|
+
handleContextAction(btn.getAttribute('data-action'));
|
|
4073
|
+
});
|
|
4074
|
+
});
|
|
4075
|
+
|
|
4076
|
+
// ── PostMessage auth protocol for sandboxed iframes ──
|
|
4077
|
+
window.addEventListener('message', function(e) {
|
|
4078
|
+
var iframe = document.getElementById('app-iframe');
|
|
4079
|
+
if (!iframe || !iframe.contentWindow) return;
|
|
4080
|
+
// Only respond to messages from our iframe
|
|
4081
|
+
if (e.source !== iframe.contentWindow) return;
|
|
4082
|
+
if (!e.data || e.data.type !== 'aimeat-request-auth') return;
|
|
4083
|
+
|
|
4084
|
+
// Get JWT from aimeat-auth library if available, else from localStorage
|
|
4085
|
+
var jwt = null;
|
|
4086
|
+
var nodeUrl = '';
|
|
4087
|
+
try {
|
|
4088
|
+
if (window.AIMEAT && window.AIMEAT.auth && window.AIMEAT.auth.getSession()) {
|
|
4089
|
+
var session = window.AIMEAT.auth.getSession();
|
|
4090
|
+
jwt = session.jwt;
|
|
4091
|
+
nodeUrl = session.nodeUrl || '';
|
|
4092
|
+
} else {
|
|
4093
|
+
var stored = localStorage.getItem('aimeat_session');
|
|
4094
|
+
if (stored) {
|
|
4095
|
+
var parsed = JSON.parse(stored);
|
|
4096
|
+
jwt = parsed.jwt || null;
|
|
4097
|
+
}
|
|
4098
|
+
var config = loadConfig();
|
|
4099
|
+
nodeUrl = config.aimeatUrl || '';
|
|
4100
|
+
}
|
|
4101
|
+
} catch(err) { /* ignore parse errors */ }
|
|
4102
|
+
|
|
4103
|
+
iframe.contentWindow.postMessage({
|
|
4104
|
+
type: 'aimeat-auth',
|
|
4105
|
+
jwt: jwt,
|
|
4106
|
+
nodeUrl: nodeUrl
|
|
4107
|
+
}, '*');
|
|
4108
|
+
});
|
|
4109
|
+
|
|
4110
|
+
// ── Click anywhere to close context menu ────────
|
|
4111
|
+
document.addEventListener('click', function () {
|
|
4112
|
+
hideContextMenu();
|
|
4113
|
+
});
|
|
4114
|
+
|
|
4115
|
+
// ── Keyboard shortcuts ──────────────────────────
|
|
4116
|
+
document.addEventListener('keydown', function (e) {
|
|
4117
|
+
// Escape — close modals / overlays (source-overlay first in cascade)
|
|
4118
|
+
if (e.key === 'Escape') {
|
|
4119
|
+
if (document.getElementById('cortex-editor-overlay').style.display === 'flex') {
|
|
4120
|
+
closeCortexEditor();
|
|
4121
|
+
} else if (document.getElementById('prompt-builder-overlay').style.display === 'flex') {
|
|
4122
|
+
closePbPanel();
|
|
4123
|
+
} else if (!document.getElementById('source-overlay').hidden) {
|
|
4124
|
+
document.getElementById('source-overlay').hidden = true;
|
|
4125
|
+
} else if (!document.getElementById('context-menu').hidden) {
|
|
4126
|
+
hideContextMenu();
|
|
4127
|
+
} else if (!document.getElementById('aimeat-import-overlay').hidden) {
|
|
4128
|
+
document.getElementById('aimeat-import-overlay').hidden = true;
|
|
4129
|
+
} else if (!document.getElementById('publish-overlay').hidden) {
|
|
4130
|
+
document.getElementById('publish-overlay').hidden = true;
|
|
4131
|
+
} else if (!document.getElementById('settings-overlay').hidden) {
|
|
4132
|
+
closeSettings();
|
|
4133
|
+
} else if (!document.getElementById('modal-overlay').hidden) {
|
|
4134
|
+
closeModal();
|
|
4135
|
+
}
|
|
4136
|
+
return;
|
|
4137
|
+
}
|
|
4138
|
+
// Ctrl+N / Cmd+N — open Add App modal
|
|
4139
|
+
if ((e.ctrlKey || e.metaKey) && e.key === 'n') {
|
|
4140
|
+
e.preventDefault();
|
|
4141
|
+
showModal();
|
|
4142
|
+
return;
|
|
4143
|
+
}
|
|
4144
|
+
// Ctrl+F / Cmd+F — focus search
|
|
4145
|
+
if ((e.ctrlKey || e.metaKey) && e.key === 'f') {
|
|
4146
|
+
e.preventDefault();
|
|
4147
|
+
document.getElementById('search-input').focus();
|
|
4148
|
+
}
|
|
4149
|
+
});
|
|
4150
|
+
|
|
4151
|
+
// ── Long-press for touch devices ─────────────────
|
|
4152
|
+
document.getElementById('app-grid').addEventListener('touchstart', function(e) {
|
|
4153
|
+
var card = e.target.closest('.app-card');
|
|
4154
|
+
if (!card) return;
|
|
4155
|
+
var appId = card.getAttribute('data-id');
|
|
4156
|
+
card._longPressTimer = setTimeout(function() {
|
|
4157
|
+
e.preventDefault();
|
|
4158
|
+
window._launcher.showContextMenu(e.touches[0], appId);
|
|
4159
|
+
}, 500);
|
|
4160
|
+
}, { passive: false });
|
|
4161
|
+
|
|
4162
|
+
document.getElementById('app-grid').addEventListener('touchend', function(e) {
|
|
4163
|
+
var card = e.target.closest('.app-card');
|
|
4164
|
+
if (card && card._longPressTimer) clearTimeout(card._longPressTimer);
|
|
4165
|
+
});
|
|
4166
|
+
|
|
4167
|
+
document.getElementById('app-grid').addEventListener('touchmove', function(e) {
|
|
4168
|
+
var card = e.target.closest('.app-card');
|
|
4169
|
+
if (card && card._longPressTimer) clearTimeout(card._longPressTimer);
|
|
4170
|
+
});
|
|
4171
|
+
|
|
4172
|
+
// ── Copy Source button ───────────────────────────
|
|
4173
|
+
document.getElementById('copy-source-btn').addEventListener('click', function() {
|
|
4174
|
+
var code = document.getElementById('source-code').value;
|
|
4175
|
+
var btn = this;
|
|
4176
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
4177
|
+
navigator.clipboard.writeText(code).then(function() {
|
|
4178
|
+
btn.textContent = 'Copied!';
|
|
4179
|
+
setTimeout(function() { btn.textContent = 'Copy Source'; }, 1500);
|
|
4180
|
+
});
|
|
4181
|
+
} else {
|
|
4182
|
+
// Fallback: select text in textarea
|
|
4183
|
+
var ta = document.getElementById('source-code');
|
|
4184
|
+
ta.select();
|
|
4185
|
+
document.execCommand('copy');
|
|
4186
|
+
btn.textContent = 'Copied!';
|
|
4187
|
+
setTimeout(function() { btn.textContent = 'Copy Source'; }, 1500);
|
|
4188
|
+
}
|
|
4189
|
+
});
|
|
4190
|
+
|
|
4191
|
+
// ── Build rich AI prompt with AIMEAT instructions ─
|
|
4192
|
+
function buildAiPrompt(appName, code) {
|
|
4193
|
+
var config = loadConfig();
|
|
4194
|
+
var nodeUrl = config.aimeatUrl ? config.aimeatUrl.replace(/\/+$/, '') : 'https://your-aimeat-node.example';
|
|
4195
|
+
|
|
4196
|
+
return 'Here is an HTML app called "' + appName + '".\n' +
|
|
4197
|
+
'Make the following change: [DESCRIBE YOUR CHANGE HERE]\n\n' +
|
|
4198
|
+
'Return the COMPLETE updated HTML file. Do not omit any parts.\n\n' +
|
|
4199
|
+
'## AIMEAT Platform Instructions\n\n' +
|
|
4200
|
+
'This app runs in the AIMEAT ecosystem. Here is what you need to know:\n\n' +
|
|
4201
|
+
'### Available Client Libraries\n' +
|
|
4202
|
+
'Load via script tags from the AIMEAT node (' + nodeUrl + '):\n' +
|
|
4203
|
+
'- aimeat-auth (' + nodeUrl + '/v1/libs/aimeat-auth.js) - Identity, login, JWT, session management\n' +
|
|
4204
|
+
'- aimeat-data (' + nodeUrl + '/v1/libs/aimeat-data.js) - Memory storage, search, key-value data\n' +
|
|
4205
|
+
'- aimeat-storage (' + nodeUrl + '/v1/libs/aimeat-storage.js) - File upload/download\n' +
|
|
4206
|
+
'- aimeat-social (' + nodeUrl + '/v1/libs/aimeat-social.js) - Boards, posts, reactions\n' +
|
|
4207
|
+
'- aimeat-wallet (' + nodeUrl + '/v1/libs/aimeat-wallet.js) - Balance, transactions\n' +
|
|
4208
|
+
'- aimeat-work (' + nodeUrl + '/v1/libs/aimeat-work.js) - Actions, work requests\n\n' +
|
|
4209
|
+
'### Auth Pattern\n' +
|
|
4210
|
+
'```html\n' +
|
|
4211
|
+
'<script src="' + nodeUrl + '/v1/libs/aimeat-auth.js"></' + 'script>\n' +
|
|
4212
|
+
'<script>\n' +
|
|
4213
|
+
'AIMEAT.auth.mountLoginButton("#login", {\n' +
|
|
4214
|
+
' onLogin: function(session) { /* session.owner, session.jwt, session.fetch() */ },\n' +
|
|
4215
|
+
' onLogout: function() { /* hide content */ }\n' +
|
|
4216
|
+
'});\n' +
|
|
4217
|
+
'</' + 'script>\n' +
|
|
4218
|
+
'```\n\n' +
|
|
4219
|
+
'### Data Storage\n' +
|
|
4220
|
+
'```javascript\n' +
|
|
4221
|
+
'await AIMEAT.data.set("key", "value", { visibility: "private", tags: ["t1"] });\n' +
|
|
4222
|
+
'var val = await AIMEAT.data.get("key");\n' +
|
|
4223
|
+
'var results = await AIMEAT.data.search("query");\n' +
|
|
4224
|
+
'```\n\n' +
|
|
4225
|
+
'### Upload to AIMEAT Node\n' +
|
|
4226
|
+
'After updating, the user can upload the app to their AIMEAT node:\n' +
|
|
4227
|
+
'```\n' +
|
|
4228
|
+
'POST ' + nodeUrl + '/v1/apps\n' +
|
|
4229
|
+
'Authorization: Bearer <jwt>\n' +
|
|
4230
|
+
'Content-Type: application/json\n' +
|
|
4231
|
+
'{ "filename": "app.html", "content": "<base64>", "mime_type": "text/html" }\n' +
|
|
4232
|
+
'```\n\n' +
|
|
4233
|
+
'### Self-Download Pattern\n' +
|
|
4234
|
+
'Include a download button so users can save the app:\n' +
|
|
4235
|
+
'```javascript\n' +
|
|
4236
|
+
'function downloadSelf() {\n' +
|
|
4237
|
+
' var html = document.documentElement.outerHTML;\n' +
|
|
4238
|
+
' var blob = new Blob(["<!DOCTYPE html>" + html], {type:"text/html"});\n' +
|
|
4239
|
+
' var a = document.createElement("a");\n' +
|
|
4240
|
+
' a.href = URL.createObjectURL(blob); a.download = "my-app.html"; a.click();\n' +
|
|
4241
|
+
'}\n' +
|
|
4242
|
+
'```\n\n' +
|
|
4243
|
+
'### Browser APIs Available\n' +
|
|
4244
|
+
'Canvas, WebGL, Web Audio, WebRTC, Camera, Geolocation, LocalStorage, IndexedDB,\n' +
|
|
4245
|
+
'Notifications, Drag & Drop, Clipboard, Speech API, Fullscreen, Web Workers,\n' +
|
|
4246
|
+
'CSS Animations, SVG, Gamepad API, Share API.\n\n' +
|
|
4247
|
+
'### Design Guidelines\n' +
|
|
4248
|
+
'Recommended light theme:\n' +
|
|
4249
|
+
'```css\n' +
|
|
4250
|
+
':root { --bg:#FAFAF8; --card:#FFFFFF; --text:#1A1A2E;\n' +
|
|
4251
|
+
' --accent:#E8564A; --border:#E5E7EB; --radius:12px; }\n' +
|
|
4252
|
+
'```\n' +
|
|
4253
|
+
'Always include: <meta name="viewport" content="width=device-width, initial-scale=1.0">\n' +
|
|
4254
|
+
'Mobile-first responsive. Single HTML file with embedded CSS and JS.\n\n' +
|
|
4255
|
+
'### Important Rules\n' +
|
|
4256
|
+
'- Return the COMPLETE HTML file, not fragments\n' +
|
|
4257
|
+
'- Never use literal closing script tags in JS comments or strings (breaks HTML parser)\n' +
|
|
4258
|
+
'- Keep it as a single self-contained HTML file\n' +
|
|
4259
|
+
'- Include error handling and loading states for API calls\n\n' +
|
|
4260
|
+
'--- Source Code ---\n' + code;
|
|
4261
|
+
}
|
|
4262
|
+
|
|
4263
|
+
// ── Copy with AI Prompt button → opens Prompt Builder ───
|
|
4264
|
+
document.getElementById('copy-prompt-btn').addEventListener('click', function() {
|
|
4265
|
+
var overlay = document.getElementById('source-overlay');
|
|
4266
|
+
var appId = overlay.dataset.appId;
|
|
4267
|
+
var app = null;
|
|
4268
|
+
for (var i = 0; i < allApps.length; i++) {
|
|
4269
|
+
if (allApps[i].id === appId) { app = allApps[i]; break; }
|
|
4270
|
+
}
|
|
4271
|
+
openPromptBuilder(app);
|
|
4272
|
+
});
|
|
4273
|
+
|
|
4274
|
+
// ── Enable/disable Save button when source changes ─
|
|
4275
|
+
document.getElementById('source-code').addEventListener('input', function() {
|
|
4276
|
+
var overlay = document.getElementById('source-overlay');
|
|
4277
|
+
var saveBtn = document.getElementById('save-source-btn');
|
|
4278
|
+
var original = overlay.dataset.originalSource || '';
|
|
4279
|
+
saveBtn.disabled = (this.value === original);
|
|
4280
|
+
});
|
|
4281
|
+
|
|
4282
|
+
// ── Save Changes button ──────────────────────────
|
|
4283
|
+
document.getElementById('save-source-btn').addEventListener('click', function() {
|
|
4284
|
+
var overlay = document.getElementById('source-overlay');
|
|
4285
|
+
var textarea = document.getElementById('source-code');
|
|
4286
|
+
var appId = overlay.dataset.appId;
|
|
4287
|
+
var btn = this;
|
|
4288
|
+
|
|
4289
|
+
if (!appId) {
|
|
4290
|
+
alert('Cannot save: no app ID found.');
|
|
4291
|
+
return;
|
|
4292
|
+
}
|
|
4293
|
+
|
|
4294
|
+
var newSource = textarea.value;
|
|
4295
|
+
// Encode to base64 blob
|
|
4296
|
+
var newBlob = btoa(unescape(encodeURIComponent(newSource)));
|
|
4297
|
+
|
|
4298
|
+
// Find the app in allApps and update it
|
|
4299
|
+
var app = null;
|
|
4300
|
+
for (var i = 0; i < allApps.length; i++) {
|
|
4301
|
+
if (allApps[i].id === appId) {
|
|
4302
|
+
app = allApps[i];
|
|
4303
|
+
break;
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
|
|
4307
|
+
if (!app) {
|
|
4308
|
+
alert('App not found in library.');
|
|
4309
|
+
return;
|
|
4310
|
+
}
|
|
4311
|
+
|
|
4312
|
+
app.blob = newBlob;
|
|
4313
|
+
btn.textContent = 'Saving...';
|
|
4314
|
+
btn.disabled = true;
|
|
4315
|
+
|
|
4316
|
+
saveApp(app).then(function() {
|
|
4317
|
+
btn.textContent = 'Saved!';
|
|
4318
|
+
overlay.dataset.originalSource = newSource;
|
|
4319
|
+
setTimeout(function() {
|
|
4320
|
+
btn.textContent = 'Save Changes';
|
|
4321
|
+
btn.disabled = true;
|
|
4322
|
+
}, 1500);
|
|
4323
|
+
renderApps();
|
|
4324
|
+
}).catch(function(err) {
|
|
4325
|
+
btn.textContent = 'Save Changes';
|
|
4326
|
+
btn.disabled = false;
|
|
4327
|
+
alert('Failed to save: ' + (err.message || err));
|
|
4328
|
+
});
|
|
4329
|
+
});
|
|
4330
|
+
|
|
4331
|
+
// ── Close source modal helper ─────────────────────
|
|
4332
|
+
function closeSourceModal() {
|
|
4333
|
+
var saveBtn = document.getElementById('save-source-btn');
|
|
4334
|
+
if (!saveBtn.disabled) {
|
|
4335
|
+
if (!confirm('You have unsaved changes. Close anyway?')) return;
|
|
4336
|
+
}
|
|
4337
|
+
document.getElementById('source-overlay').hidden = true;
|
|
4338
|
+
}
|
|
4339
|
+
|
|
4340
|
+
// ── Click source overlay background to close ─────
|
|
4341
|
+
document.getElementById('source-overlay').addEventListener('click', function(e) {
|
|
4342
|
+
if (e.target === this) closeSourceModal();
|
|
4343
|
+
});
|
|
4344
|
+
|
|
4345
|
+
// ── Close button in source modal ─────────────────
|
|
4346
|
+
document.getElementById('close-source-btn').addEventListener('click', closeSourceModal);
|
|
4347
|
+
|
|
4348
|
+
// ── Homepage button ──────────────────────────────
|
|
4349
|
+
document.getElementById('homepage-btn').addEventListener('click', generateHomepagePrompt);
|
|
4350
|
+
|
|
4351
|
+
// ── Prompt Builder event listeners ───────────────
|
|
4352
|
+
document.getElementById('pb-cancel-btn').addEventListener('click', closePbPanel);
|
|
4353
|
+
|
|
4354
|
+
document.getElementById('pb-copy-btn').addEventListener('click', function() {
|
|
4355
|
+
var prompt = buildPromptFromBuilder();
|
|
4356
|
+
var btn = this;
|
|
4357
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
4358
|
+
navigator.clipboard.writeText(prompt).then(function() {
|
|
4359
|
+
btn.textContent = 'Copied!';
|
|
4360
|
+
setTimeout(function() { btn.textContent = 'Copy Prompt'; closePbPanel(); }, 1200);
|
|
4361
|
+
});
|
|
4362
|
+
} else {
|
|
4363
|
+
var ta = document.createElement('textarea');
|
|
4364
|
+
ta.value = prompt;
|
|
4365
|
+
document.body.appendChild(ta);
|
|
4366
|
+
ta.select();
|
|
4367
|
+
document.execCommand('copy');
|
|
4368
|
+
document.body.removeChild(ta);
|
|
4369
|
+
btn.textContent = 'Copied!';
|
|
4370
|
+
setTimeout(function() { btn.textContent = 'Copy Prompt'; closePbPanel(); }, 1200);
|
|
4371
|
+
}
|
|
4372
|
+
});
|
|
4373
|
+
|
|
4374
|
+
document.getElementById('pb-ext-checkbox').addEventListener('change', function() {
|
|
4375
|
+
document.getElementById('pb-ext-list').classList.toggle('open', this.checked);
|
|
4376
|
+
updatePbPreview();
|
|
4377
|
+
});
|
|
4378
|
+
|
|
4379
|
+
document.querySelectorAll('input[name="pb-mode"]').forEach(function(radio) {
|
|
4380
|
+
radio.addEventListener('change', function() {
|
|
4381
|
+
var desc = document.getElementById('pb-description');
|
|
4382
|
+
if (this.value === 'improve' && pbSourceApp) {
|
|
4383
|
+
desc.placeholder = 'Describe what changes to make to "' + (pbSourceApp.name || 'this app') + '"...';
|
|
4384
|
+
} else {
|
|
4385
|
+
desc.placeholder = 'Describe what the app should do...';
|
|
4386
|
+
}
|
|
4387
|
+
updatePbPreview();
|
|
4388
|
+
});
|
|
4389
|
+
});
|
|
4390
|
+
|
|
4391
|
+
document.getElementById('pb-description').addEventListener('input', updatePbPreview);
|
|
4392
|
+
|
|
4393
|
+
document.getElementById('prompt-builder-overlay').addEventListener('click', function(e) {
|
|
4394
|
+
if (e.target === this) closePbPanel();
|
|
4395
|
+
});
|
|
4396
|
+
});
|
|
4397
|
+
|
|
4398
|
+
})();
|
|
4399
|
+
</script>
|
|
4400
|
+
</body>
|
|
4401
|
+
</html>
|