@agent-native/core 0.7.13 → 0.7.14
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/a2a/client.d.ts +44 -1
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +88 -11
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts +10 -0
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +287 -62
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +95 -17
- package/dist/a2a/server.js.map +1 -1
- package/dist/a2a/task-store.d.ts +11 -1
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +38 -2
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +7 -25
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/engine/builtin.js +1 -1
- package/dist/agent/engine/builtin.js.map +1 -1
- package/dist/chat-threads/store.d.ts +3 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +32 -0
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +11 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +3 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +21 -10
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AgentTaskCard.d.ts.map +1 -1
- package/dist/client/AgentTaskCard.js +2 -0
- package/dist/client/AgentTaskCard.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +2 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +111 -75
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ErrorBoundary.d.ts +1 -3
- package/dist/client/ErrorBoundary.d.ts.map +1 -1
- package/dist/client/ErrorBoundary.js +37 -9
- package/dist/client/ErrorBoundary.js.map +1 -1
- package/dist/client/FeedbackButton.d.ts.map +1 -1
- package/dist/client/FeedbackButton.js +4 -3
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +145 -49
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat.d.ts +11 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +1 -1
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/components/AgentPresenceChip.d.ts +12 -0
- package/dist/client/components/AgentPresenceChip.d.ts.map +1 -0
- package/dist/client/components/AgentPresenceChip.js +42 -0
- package/dist/client/components/AgentPresenceChip.js.map +1 -0
- package/dist/client/components/PresenceBar.d.ts +17 -0
- package/dist/client/components/PresenceBar.d.ts.map +1 -0
- package/dist/client/components/PresenceBar.js +118 -0
- package/dist/client/components/PresenceBar.js.map +1 -0
- package/dist/client/composer/ComposerPlusMenu.d.ts +6 -1
- package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
- package/dist/client/composer/ComposerPlusMenu.js +22 -83
- package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +237 -16
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/types.d.ts +1 -0
- package/dist/client/composer/types.d.ts.map +1 -1
- package/dist/client/composer/useVoiceDictation.d.ts +2 -0
- package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
- package/dist/client/composer/useVoiceDictation.js +85 -10
- package/dist/client/composer/useVoiceDictation.js.map +1 -1
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +5 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/RequireActiveOrg.d.ts.map +1 -1
- package/dist/client/org/RequireActiveOrg.js +15 -10
- package/dist/client/org/RequireActiveOrg.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +125 -4
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/org/hooks.d.ts +30 -0
- package/dist/client/org/hooks.d.ts.map +1 -1
- package/dist/client/org/hooks.js +65 -0
- package/dist/client/org/hooks.js.map +1 -1
- package/dist/client/org/index.d.ts +2 -2
- package/dist/client/org/index.d.ts.map +1 -1
- package/dist/client/org/index.js +1 -1
- package/dist/client/org/index.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +5 -1
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
- package/dist/client/settings/AutomationsSection.js +1 -0
- package/dist/client/settings/AutomationsSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +24 -11
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +10 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/tools/ToolEditor.d.ts +5 -0
- package/dist/client/tools/ToolEditor.d.ts.map +1 -0
- package/dist/client/tools/ToolEditor.js +98 -0
- package/dist/client/tools/ToolEditor.js.map +1 -0
- package/dist/client/tools/ToolViewer.d.ts +5 -0
- package/dist/client/tools/ToolViewer.d.ts.map +1 -0
- package/dist/client/tools/ToolViewer.js +309 -0
- package/dist/client/tools/ToolViewer.js.map +1 -0
- package/dist/client/tools/ToolViewerPage.d.ts +2 -0
- package/dist/client/tools/ToolViewerPage.d.ts.map +1 -0
- package/dist/client/tools/ToolViewerPage.js +23 -0
- package/dist/client/tools/ToolViewerPage.js.map +1 -0
- package/dist/client/tools/ToolsListPage.d.ts +2 -0
- package/dist/client/tools/ToolsListPage.d.ts.map +1 -0
- package/dist/client/tools/ToolsListPage.js +72 -0
- package/dist/client/tools/ToolsListPage.js.map +1 -0
- package/dist/client/tools/ToolsSidebarSection.d.ts +2 -0
- package/dist/client/tools/ToolsSidebarSection.d.ts.map +1 -0
- package/dist/client/tools/ToolsSidebarSection.js +188 -0
- package/dist/client/tools/ToolsSidebarSection.js.map +1 -0
- package/dist/client/tools/index.d.ts +6 -0
- package/dist/client/tools/index.d.ts.map +1 -0
- package/dist/client/tools/index.js +6 -0
- package/dist/client/tools/index.js.map +1 -0
- package/dist/client/use-chat-threads.d.ts +1 -0
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +29 -0
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/use-db-sync.js +6 -6
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/collab/agent-identity.d.ts +15 -0
- package/dist/collab/agent-identity.d.ts.map +1 -0
- package/dist/collab/agent-identity.js +14 -0
- package/dist/collab/agent-identity.js.map +1 -0
- package/dist/collab/agent-presence.d.ts +59 -0
- package/dist/collab/agent-presence.d.ts.map +1 -0
- package/dist/collab/agent-presence.js +165 -0
- package/dist/collab/agent-presence.js.map +1 -0
- package/dist/collab/awareness.d.ts +7 -0
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/awareness.js +2 -2
- package/dist/collab/awareness.js.map +1 -1
- package/dist/collab/client-struct.d.ts +43 -0
- package/dist/collab/client-struct.d.ts.map +1 -0
- package/dist/collab/client-struct.js +272 -0
- package/dist/collab/client-struct.js.map +1 -0
- package/dist/collab/client.d.ts +2 -0
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +15 -1
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/index.d.ts +6 -1
- package/dist/collab/index.d.ts.map +1 -1
- package/dist/collab/index.js +11 -1
- package/dist/collab/index.js.map +1 -1
- package/dist/collab/json-to-yjs.d.ts +72 -0
- package/dist/collab/json-to-yjs.d.ts.map +1 -0
- package/dist/collab/json-to-yjs.js +456 -0
- package/dist/collab/json-to-yjs.js.map +1 -0
- package/dist/collab/struct-routes.d.ts +52 -0
- package/dist/collab/struct-routes.d.ts.map +1 -0
- package/dist/collab/struct-routes.js +74 -0
- package/dist/collab/struct-routes.js.map +1 -0
- package/dist/collab/ydoc-manager.d.ts +19 -0
- package/dist/collab/ydoc-manager.d.ts.map +1 -1
- package/dist/collab/ydoc-manager.js +49 -0
- package/dist/collab/ydoc-manager.js.map +1 -1
- package/dist/deploy/build.js +1 -1
- package/dist/file-upload/builder.d.ts.map +1 -1
- package/dist/file-upload/builder.js +2 -1
- package/dist/file-upload/builder.js.map +1 -1
- package/dist/integrations/adapters/email.d.ts +17 -0
- package/dist/integrations/adapters/email.d.ts.map +1 -0
- package/dist/integrations/adapters/email.js +620 -0
- package/dist/integrations/adapters/email.js.map +1 -0
- package/dist/integrations/adapters/telegram.d.ts.map +1 -1
- package/dist/integrations/adapters/telegram.js +19 -3
- package/dist/integrations/adapters/telegram.js.map +1 -1
- package/dist/integrations/index.d.ts +1 -0
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +1 -0
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/internal-token.d.ts +18 -0
- package/dist/integrations/internal-token.d.ts.map +1 -0
- package/dist/integrations/internal-token.js +86 -0
- package/dist/integrations/internal-token.js.map +1 -0
- package/dist/integrations/pending-tasks-retry-job.d.ts +15 -0
- package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -0
- package/dist/integrations/pending-tasks-retry-job.js +199 -0
- package/dist/integrations/pending-tasks-retry-job.js.map +1 -0
- package/dist/integrations/pending-tasks-store.d.ts +40 -0
- package/dist/integrations/pending-tasks-store.d.ts.map +1 -0
- package/dist/integrations/pending-tasks-store.js +151 -0
- package/dist/integrations/pending-tasks-store.js.map +1 -0
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +151 -9
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/task-queue-stats.d.ts +22 -0
- package/dist/integrations/task-queue-stats.d.ts.map +1 -0
- package/dist/integrations/task-queue-stats.js +117 -0
- package/dist/integrations/task-queue-stats.js.map +1 -0
- package/dist/integrations/types.d.ts +2 -0
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.d.ts +23 -4
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +217 -59
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/mcp-client/manager.d.ts +3 -0
- package/dist/mcp-client/manager.d.ts.map +1 -1
- package/dist/mcp-client/manager.js +5 -0
- package/dist/mcp-client/manager.js.map +1 -1
- package/dist/oauth-tokens/google-refresh.d.ts.map +1 -1
- package/dist/oauth-tokens/google-refresh.js +6 -0
- package/dist/oauth-tokens/google-refresh.js.map +1 -1
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +10 -3
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/org/context.d.ts +35 -0
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +136 -0
- package/dist/org/context.js.map +1 -1
- package/dist/org/handlers.d.ts +76 -0
- package/dist/org/handlers.d.ts.map +1 -1
- package/dist/org/handlers.js +411 -2
- package/dist/org/handlers.js.map +1 -1
- package/dist/org/index.d.ts +2 -2
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +2 -2
- package/dist/org/index.js.map +1 -1
- package/dist/org/migrations.d.ts.map +1 -1
- package/dist/org/migrations.js +8 -0
- package/dist/org/migrations.js.map +1 -1
- package/dist/org/plugin.d.ts +6 -0
- package/dist/org/plugin.d.ts.map +1 -1
- package/dist/org/plugin.js +71 -7
- package/dist/org/plugin.js.map +1 -1
- package/dist/org/schema.d.ts +38 -0
- package/dist/org/schema.d.ts.map +1 -1
- package/dist/org/schema.js +2 -0
- package/dist/org/schema.js.map +1 -1
- package/dist/org/types.d.ts +7 -0
- package/dist/org/types.d.ts.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +90 -18
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/scripts/db/index.d.ts.map +1 -1
- package/dist/scripts/db/index.js +2 -0
- package/dist/scripts/db/index.js.map +1 -1
- package/dist/scripts/db/migrate-user-api-keys.d.ts +24 -0
- package/dist/scripts/db/migrate-user-api-keys.d.ts.map +1 -0
- package/dist/scripts/db/migrate-user-api-keys.js +224 -0
- package/dist/scripts/db/migrate-user-api-keys.js.map +1 -0
- package/dist/scripts/db/wipe-leaked-builder-keys.d.ts +27 -0
- package/dist/scripts/db/wipe-leaked-builder-keys.d.ts.map +1 -0
- package/dist/scripts/db/wipe-leaked-builder-keys.js +163 -0
- package/dist/scripts/db/wipe-leaked-builder-keys.js.map +1 -0
- package/dist/secrets/register-framework-secrets.d.ts +5 -0
- package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
- package/dist/secrets/register-framework-secrets.js +7 -44
- package/dist/secrets/register-framework-secrets.js.map +1 -1
- package/dist/secrets/substitution.d.ts.map +1 -1
- package/dist/secrets/substitution.js +14 -2
- package/dist/secrets/substitution.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +39 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/action-routes.js +1 -1
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +192 -45
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth.d.ts +14 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +232 -17
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-browser.d.ts +1 -1
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +12 -12
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/collab-plugin.d.ts +4 -0
- package/dist/server/collab-plugin.d.ts.map +1 -1
- package/dist/server/collab-plugin.js +30 -4
- package/dist/server/collab-plugin.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +106 -100
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +43 -2
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +115 -2
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/design-token-utils.d.ts +132 -0
- package/dist/server/design-token-utils.d.ts.map +1 -0
- package/dist/server/design-token-utils.js +714 -0
- package/dist/server/design-token-utils.js.map +1 -0
- package/dist/server/email.d.ts +10 -0
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +63 -16
- package/dist/server/email.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +38 -3
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/google-oauth.d.ts +18 -1
- package/dist/server/google-oauth.d.ts.map +1 -1
- package/dist/server/google-oauth.js +21 -4
- package/dist/server/google-oauth.js.map +1 -1
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +14 -1
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts.map +1 -1
- package/dist/server/transcribe-voice.js +89 -24
- package/dist/server/transcribe-voice.js.map +1 -1
- package/dist/sharing/schema.d.ts +1 -1
- package/dist/styles/agent-native.css +5 -0
- package/dist/templates/default/app/root.tsx +50 -13
- package/dist/templates/default/react-router.config.ts +3 -0
- package/dist/terminal/terminal-plugin.d.ts.map +1 -1
- package/dist/terminal/terminal-plugin.js +23 -3
- package/dist/terminal/terminal-plugin.js.map +1 -1
- package/dist/tools/actions.d.ts +3 -0
- package/dist/tools/actions.d.ts.map +1 -0
- package/dist/tools/actions.js +140 -0
- package/dist/tools/actions.js.map +1 -0
- package/dist/tools/fetch-tool.js +1 -1
- package/dist/tools/fetch-tool.js.map +1 -1
- package/dist/tools/html-shell.d.ts +2 -0
- package/dist/tools/html-shell.d.ts.map +1 -0
- package/dist/tools/html-shell.js +387 -0
- package/dist/tools/html-shell.js.map +1 -0
- package/dist/tools/routes.d.ts +2 -0
- package/dist/tools/routes.d.ts.map +1 -0
- package/dist/tools/routes.js +576 -0
- package/dist/tools/routes.js.map +1 -0
- package/dist/tools/schema.d.ts +575 -0
- package/dist/tools/schema.d.ts.map +1 -0
- package/dist/tools/schema.js +112 -0
- package/dist/tools/schema.js.map +1 -0
- package/dist/tools/store.d.ts +40 -0
- package/dist/tools/store.d.ts.map +1 -0
- package/dist/tools/store.js +190 -0
- package/dist/tools/store.js.map +1 -0
- package/dist/tools/theme.d.ts +2 -0
- package/dist/tools/theme.d.ts.map +1 -0
- package/dist/tools/theme.js +67 -0
- package/dist/tools/theme.js.map +1 -0
- package/dist/transcription/builder-transcription.d.ts.map +1 -1
- package/dist/transcription/builder-transcription.js +26 -14
- package/dist/transcription/builder-transcription.js.map +1 -1
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +10 -2
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +26 -6
- package/dist/vite/client.js.map +1 -1
- package/docs/content/a2a-protocol.md +2 -2
- package/docs/content/authentication.md +51 -0
- package/docs/content/cloneable-saas.md +59 -62
- package/docs/content/faq.md +73 -43
- package/docs/content/getting-started.md +37 -61
- package/docs/content/mcp-clients.md +14 -1
- package/docs/content/messaging.md +284 -0
- package/docs/content/pure-agent-apps.md +55 -28
- package/docs/content/template-calendar.md +61 -56
- package/docs/content/template-clips.md +22 -18
- package/docs/content/template-content.md +36 -26
- package/docs/content/template-dispatch.md +2 -1
- package/docs/content/template-forms.md +13 -11
- package/docs/content/template-slides.md +43 -31
- package/docs/content/template-video.md +49 -22
- package/docs/content/tools.md +107 -0
- package/docs/content/what-is-agent-native.md +89 -105
- package/package.json +4 -1
- package/src/templates/default/app/root.tsx +50 -13
- package/src/templates/default/react-router.config.ts +3 -0
- package/docs/content/integrations.md +0 -198
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core script: db-migrate-user-api-keys
|
|
3
|
+
*
|
|
4
|
+
* One-shot migration: copy legacy `user-api-key:<provider>:<email>` and
|
|
5
|
+
* `user-anthropic-api-key:<email>` rows from the unscoped `settings` table
|
|
6
|
+
* into `app_secrets` (encrypted, scope=user, scopeId=email), then delete
|
|
7
|
+
* the legacy rows.
|
|
8
|
+
*
|
|
9
|
+
* Background. The pre-secrets-migration `agent-chat-plugin` save-key endpoint
|
|
10
|
+
* persisted user-pasted LLM API keys to `settings` under email-prefixed
|
|
11
|
+
* keys. The `app_secrets` system (encrypted, properly scoped) now owns
|
|
12
|
+
* user-pasted credentials. `getOwnerApiKey()` reads `app_secrets` first
|
|
13
|
+
* and falls back to the legacy settings rows for compat. This script
|
|
14
|
+
* clears that compat tail so the legacy rows don't sit around indefinitely.
|
|
15
|
+
*
|
|
16
|
+
* Idempotent — re-running on an already-migrated DB is a no-op.
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* DATABASE_URL=postgres://... pnpm action db-migrate-user-api-keys
|
|
20
|
+
* pnpm action db-migrate-user-api-keys --db ./data/app.db
|
|
21
|
+
* pnpm action db-migrate-user-api-keys --dry-run
|
|
22
|
+
*/
|
|
23
|
+
import path from "path";
|
|
24
|
+
import { createClient } from "@libsql/client";
|
|
25
|
+
import { getDatabaseUrl, getDatabaseAuthToken } from "../../db/client.js";
|
|
26
|
+
import { parseArgs } from "../utils.js";
|
|
27
|
+
import { PROVIDER_TO_ENV } from "../../agent/engine/provider-env-vars.js";
|
|
28
|
+
function isPostgresUrl(url) {
|
|
29
|
+
return url.startsWith("postgres://") || url.startsWith("postgresql://");
|
|
30
|
+
}
|
|
31
|
+
function parseLegacyKey(settingsKey) {
|
|
32
|
+
// user-api-key:<provider>:<email>
|
|
33
|
+
// (email may itself contain `:` if someone has a weird local-part — split
|
|
34
|
+
// on the first two segments only.)
|
|
35
|
+
if (settingsKey.startsWith("user-api-key:")) {
|
|
36
|
+
const rest = settingsKey.slice("user-api-key:".length);
|
|
37
|
+
const colonIdx = rest.indexOf(":");
|
|
38
|
+
if (colonIdx <= 0)
|
|
39
|
+
return null;
|
|
40
|
+
const provider = rest.slice(0, colonIdx);
|
|
41
|
+
const email = rest.slice(colonIdx + 1);
|
|
42
|
+
if (!provider || !email)
|
|
43
|
+
return null;
|
|
44
|
+
return { provider, email };
|
|
45
|
+
}
|
|
46
|
+
// user-anthropic-api-key:<email> (legacy alias)
|
|
47
|
+
if (settingsKey.startsWith("user-anthropic-api-key:")) {
|
|
48
|
+
const email = settingsKey.slice("user-anthropic-api-key:".length);
|
|
49
|
+
if (!email)
|
|
50
|
+
return null;
|
|
51
|
+
return { provider: "anthropic", email };
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
function secretKeyForProvider(provider) {
|
|
56
|
+
return PROVIDER_TO_ENV[provider] ?? `${provider.toUpperCase()}_API_KEY`;
|
|
57
|
+
}
|
|
58
|
+
function maskApiKey(value) {
|
|
59
|
+
if (!value)
|
|
60
|
+
return "(empty)";
|
|
61
|
+
if (value.length <= 8)
|
|
62
|
+
return "***";
|
|
63
|
+
return `${value.slice(0, 4)}…${value.slice(-4)} (len=${value.length})`;
|
|
64
|
+
}
|
|
65
|
+
export default async function dbMigrateUserApiKeys(args) {
|
|
66
|
+
const parsed = parseArgs(args);
|
|
67
|
+
if (parsed.help === "true") {
|
|
68
|
+
console.log(`Usage: pnpm action db-migrate-user-api-keys [options]
|
|
69
|
+
|
|
70
|
+
Copies legacy user-api-key:* + user-anthropic-api-key:* settings rows
|
|
71
|
+
into app_secrets (encrypted, scope=user) and deletes the originals.
|
|
72
|
+
|
|
73
|
+
Options:
|
|
74
|
+
--db <path> Path to SQLite database (default: data/app.db)
|
|
75
|
+
--dry-run Print what would be migrated without writing
|
|
76
|
+
--help Show this help message`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const dryRun = parsed["dry-run"] === "true";
|
|
80
|
+
let url;
|
|
81
|
+
if (parsed.db) {
|
|
82
|
+
url = "file:" + path.resolve(parsed.db);
|
|
83
|
+
}
|
|
84
|
+
else if (getDatabaseUrl()) {
|
|
85
|
+
url = getDatabaseUrl();
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
url = "file:" + path.resolve(process.cwd(), "data", "app.db");
|
|
89
|
+
}
|
|
90
|
+
const dbLabel = url.startsWith("file:")
|
|
91
|
+
? url.slice("file:".length)
|
|
92
|
+
: new URL(url).host || url;
|
|
93
|
+
console.log(`[migrate-user-api-keys] target: ${dbLabel}${dryRun ? " (dry-run)" : ""}`);
|
|
94
|
+
const legacy = await fetchLegacyRows(url);
|
|
95
|
+
if (legacy.length === 0) {
|
|
96
|
+
console.log("[migrate-user-api-keys] nothing to migrate.");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
console.log(`[migrate-user-api-keys] found ${legacy.length} legacy row(s):`);
|
|
100
|
+
for (const row of legacy) {
|
|
101
|
+
const target = secretKeyForProvider(row.provider);
|
|
102
|
+
console.log(` - ${row.email} ${row.provider} → app_secrets[${target}] ${maskApiKey(row.apiKey)}`);
|
|
103
|
+
}
|
|
104
|
+
if (dryRun)
|
|
105
|
+
return;
|
|
106
|
+
const { writeAppSecret } = await import("../../secrets/storage.js");
|
|
107
|
+
let migrated = 0;
|
|
108
|
+
let skipped = 0;
|
|
109
|
+
for (const row of legacy) {
|
|
110
|
+
try {
|
|
111
|
+
await writeAppSecret({
|
|
112
|
+
key: secretKeyForProvider(row.provider),
|
|
113
|
+
value: row.apiKey,
|
|
114
|
+
scope: "user",
|
|
115
|
+
scopeId: row.email,
|
|
116
|
+
});
|
|
117
|
+
await deleteLegacyRow(url, row.settingsKey);
|
|
118
|
+
migrated++;
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
console.error(` ! failed to migrate ${row.settingsKey}:`, err instanceof Error ? err.message : err);
|
|
122
|
+
skipped++;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
console.log(`[migrate-user-api-keys] done. migrated=${migrated} skipped=${skipped}`);
|
|
126
|
+
}
|
|
127
|
+
async function fetchLegacyRows(url) {
|
|
128
|
+
const out = [];
|
|
129
|
+
if (isPostgresUrl(url)) {
|
|
130
|
+
const { default: pg } = await import("postgres");
|
|
131
|
+
const sql = pg(url);
|
|
132
|
+
try {
|
|
133
|
+
const rows = (await sql.unsafe(`SELECT key, value FROM settings WHERE key LIKE 'user-api-key:%' OR key LIKE 'user-anthropic-api-key:%'`));
|
|
134
|
+
for (const row of rows) {
|
|
135
|
+
const parsed = parseLegacyKey(row.key);
|
|
136
|
+
if (!parsed)
|
|
137
|
+
continue;
|
|
138
|
+
const apiKey = extractKeyFromValue(row.value);
|
|
139
|
+
if (!apiKey)
|
|
140
|
+
continue;
|
|
141
|
+
out.push({
|
|
142
|
+
settingsKey: row.key,
|
|
143
|
+
provider: parsed.provider,
|
|
144
|
+
email: parsed.email,
|
|
145
|
+
apiKey,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
await sql.end();
|
|
151
|
+
}
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
const client = createClient({ url, authToken: getDatabaseAuthToken() });
|
|
155
|
+
try {
|
|
156
|
+
const result = await client.execute({
|
|
157
|
+
sql: `SELECT key, value FROM settings WHERE key LIKE 'user-api-key:%' OR key LIKE 'user-anthropic-api-key:%'`,
|
|
158
|
+
args: [],
|
|
159
|
+
});
|
|
160
|
+
for (const row of result.rows) {
|
|
161
|
+
const settingsKey = row.key;
|
|
162
|
+
const value = row.value;
|
|
163
|
+
const parsed = parseLegacyKey(settingsKey);
|
|
164
|
+
if (!parsed)
|
|
165
|
+
continue;
|
|
166
|
+
const apiKey = extractKeyFromValue(value);
|
|
167
|
+
if (!apiKey)
|
|
168
|
+
continue;
|
|
169
|
+
out.push({
|
|
170
|
+
settingsKey,
|
|
171
|
+
provider: parsed.provider,
|
|
172
|
+
email: parsed.email,
|
|
173
|
+
apiKey,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
client.close();
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
function extractKeyFromValue(value) {
|
|
183
|
+
// Settings rows store JSON. The save-key endpoint historically wrote
|
|
184
|
+
// `{ key: "sk-..." }`. Tolerate raw strings just in case.
|
|
185
|
+
if (!value)
|
|
186
|
+
return null;
|
|
187
|
+
try {
|
|
188
|
+
const parsed = JSON.parse(value);
|
|
189
|
+
if (typeof parsed === "string" && parsed.trim())
|
|
190
|
+
return parsed.trim();
|
|
191
|
+
if (parsed && typeof parsed.key === "string" && parsed.key.trim()) {
|
|
192
|
+
return parsed.key.trim();
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
const trimmed = value.trim();
|
|
198
|
+
return trimmed || null;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
async function deleteLegacyRow(url, key) {
|
|
202
|
+
if (isPostgresUrl(url)) {
|
|
203
|
+
const { default: pg } = await import("postgres");
|
|
204
|
+
const sql = pg(url);
|
|
205
|
+
try {
|
|
206
|
+
await sql.unsafe(`DELETE FROM settings WHERE key = $1`, [key]);
|
|
207
|
+
}
|
|
208
|
+
finally {
|
|
209
|
+
await sql.end();
|
|
210
|
+
}
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const client = createClient({ url, authToken: getDatabaseAuthToken() });
|
|
214
|
+
try {
|
|
215
|
+
await client.execute({
|
|
216
|
+
sql: `DELETE FROM settings WHERE key = ?`,
|
|
217
|
+
args: [key],
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
client.close();
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=migrate-user-api-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-user-api-keys.js","sourceRoot":"","sources":["../../../src/scripts/db/migrate-user-api-keys.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core script: db-wipe-leaked-builder-keys
|
|
3
|
+
*
|
|
4
|
+
* One-shot cleanup for the legacy cross-tenant Builder credential leak.
|
|
5
|
+
*
|
|
6
|
+
* Pre-migration, the Builder OAuth callback wrote BUILDER_PRIVATE_KEY,
|
|
7
|
+
* BUILDER_PUBLIC_KEY, BUILDER_USER_ID, BUILDER_ORG_NAME, BUILDER_ORG_KIND
|
|
8
|
+
* into the unscoped `persisted-env-vars` settings row. On shared-DB
|
|
9
|
+
* hosted templates that row was global, so the first user to connect
|
|
10
|
+
* left their Builder identity sitting in `process.env` for every
|
|
11
|
+
* subsequent tenant on the same serverless instance — anyone without
|
|
12
|
+
* their own per-user app_secrets record fell back to the leaked key.
|
|
13
|
+
*
|
|
14
|
+
* Per-user Builder credentials now live in `app_secrets` (scope=user,
|
|
15
|
+
* scopeId=email). The plugin init scrubs BUILDER_* on every boot, but
|
|
16
|
+
* this script lets you wipe the row immediately, before redeploying.
|
|
17
|
+
*
|
|
18
|
+
* Idempotent. Re-running on a clean row is a no-op.
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* DATABASE_URL=postgres://... pnpm action db-wipe-leaked-builder-keys
|
|
22
|
+
* DATABASE_URL=file:./data/app.db pnpm action db-wipe-leaked-builder-keys
|
|
23
|
+
* pnpm action db-wipe-leaked-builder-keys --db ./data/app.db
|
|
24
|
+
* pnpm action db-wipe-leaked-builder-keys --dry-run
|
|
25
|
+
*/
|
|
26
|
+
export default function dbWipeLeakedBuilderKeys(args: string[]): Promise<void>;
|
|
27
|
+
//# sourceMappingURL=wipe-leaked-builder-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wipe-leaked-builder-keys.d.ts","sourceRoot":"","sources":["../../../src/scripts/db/wipe-leaked-builder-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAyBH,wBAA8B,uBAAuB,CACnD,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,IAAI,CAAC,CA4Gf"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core script: db-wipe-leaked-builder-keys
|
|
3
|
+
*
|
|
4
|
+
* One-shot cleanup for the legacy cross-tenant Builder credential leak.
|
|
5
|
+
*
|
|
6
|
+
* Pre-migration, the Builder OAuth callback wrote BUILDER_PRIVATE_KEY,
|
|
7
|
+
* BUILDER_PUBLIC_KEY, BUILDER_USER_ID, BUILDER_ORG_NAME, BUILDER_ORG_KIND
|
|
8
|
+
* into the unscoped `persisted-env-vars` settings row. On shared-DB
|
|
9
|
+
* hosted templates that row was global, so the first user to connect
|
|
10
|
+
* left their Builder identity sitting in `process.env` for every
|
|
11
|
+
* subsequent tenant on the same serverless instance — anyone without
|
|
12
|
+
* their own per-user app_secrets record fell back to the leaked key.
|
|
13
|
+
*
|
|
14
|
+
* Per-user Builder credentials now live in `app_secrets` (scope=user,
|
|
15
|
+
* scopeId=email). The plugin init scrubs BUILDER_* on every boot, but
|
|
16
|
+
* this script lets you wipe the row immediately, before redeploying.
|
|
17
|
+
*
|
|
18
|
+
* Idempotent. Re-running on a clean row is a no-op.
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* DATABASE_URL=postgres://... pnpm action db-wipe-leaked-builder-keys
|
|
22
|
+
* DATABASE_URL=file:./data/app.db pnpm action db-wipe-leaked-builder-keys
|
|
23
|
+
* pnpm action db-wipe-leaked-builder-keys --db ./data/app.db
|
|
24
|
+
* pnpm action db-wipe-leaked-builder-keys --dry-run
|
|
25
|
+
*/
|
|
26
|
+
import path from "path";
|
|
27
|
+
import { createClient } from "@libsql/client";
|
|
28
|
+
import { getDatabaseUrl, getDatabaseAuthToken } from "../../db/client.js";
|
|
29
|
+
import { parseArgs } from "../utils.js";
|
|
30
|
+
const BUILDER_KEYS = [
|
|
31
|
+
"BUILDER_PRIVATE_KEY",
|
|
32
|
+
"BUILDER_PUBLIC_KEY",
|
|
33
|
+
"BUILDER_USER_ID",
|
|
34
|
+
"BUILDER_ORG_NAME",
|
|
35
|
+
"BUILDER_ORG_KIND",
|
|
36
|
+
];
|
|
37
|
+
function isPostgresUrl(url) {
|
|
38
|
+
return url.startsWith("postgres://") || url.startsWith("postgresql://");
|
|
39
|
+
}
|
|
40
|
+
function maskValue(v) {
|
|
41
|
+
if (typeof v !== "string")
|
|
42
|
+
return String(v);
|
|
43
|
+
if (v.length <= 8)
|
|
44
|
+
return "***";
|
|
45
|
+
return `${v.slice(0, 4)}…${v.slice(-4)} (len=${v.length})`;
|
|
46
|
+
}
|
|
47
|
+
export default async function dbWipeLeakedBuilderKeys(args) {
|
|
48
|
+
const parsed = parseArgs(args);
|
|
49
|
+
if (parsed.help === "true") {
|
|
50
|
+
console.log(`Usage: pnpm action db-wipe-leaked-builder-keys [options]
|
|
51
|
+
|
|
52
|
+
Removes BUILDER_* keys from the persisted-env-vars row in the settings
|
|
53
|
+
table. Run this once per hosted template database.
|
|
54
|
+
|
|
55
|
+
Options:
|
|
56
|
+
--db <path> Path to SQLite database (default: data/app.db when no DATABASE_URL set)
|
|
57
|
+
--dry-run Print what would be removed without writing
|
|
58
|
+
--help Show this help message
|
|
59
|
+
|
|
60
|
+
Database resolution:
|
|
61
|
+
--db flag → DATABASE_URL env → ./data/app.db`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const dryRun = parsed["dry-run"] === "true";
|
|
65
|
+
let url;
|
|
66
|
+
if (parsed.db) {
|
|
67
|
+
url = "file:" + path.resolve(parsed.db);
|
|
68
|
+
}
|
|
69
|
+
else if (getDatabaseUrl()) {
|
|
70
|
+
url = getDatabaseUrl();
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
url = "file:" + path.resolve(process.cwd(), "data", "app.db");
|
|
74
|
+
}
|
|
75
|
+
const dbLabel = url.startsWith("file:")
|
|
76
|
+
? url.slice("file:".length)
|
|
77
|
+
: new URL(url).host || url;
|
|
78
|
+
console.log(`[wipe-leaked-builder-keys] target: ${dbLabel}${dryRun ? " (dry-run)" : ""}`);
|
|
79
|
+
let row = null;
|
|
80
|
+
if (isPostgresUrl(url)) {
|
|
81
|
+
const { default: pg } = await import("postgres");
|
|
82
|
+
const pgSql = pg(url);
|
|
83
|
+
try {
|
|
84
|
+
const result = await pgSql.unsafe(`SELECT value FROM settings WHERE key = 'persisted-env-vars'`);
|
|
85
|
+
const rows = Array.from(result);
|
|
86
|
+
if (rows.length === 0) {
|
|
87
|
+
console.log("[wipe-leaked-builder-keys] no persisted-env-vars row.");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
row = JSON.parse(rows[0].value);
|
|
91
|
+
const { cleaned, removed } = stripBuilderKeys(row ?? {});
|
|
92
|
+
if (removed.length === 0) {
|
|
93
|
+
console.log("[wipe-leaked-builder-keys] row already clean — nothing to do.");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
logRemoved(removed, row ?? {});
|
|
97
|
+
if (dryRun)
|
|
98
|
+
return;
|
|
99
|
+
await pgSql.unsafe(`UPDATE settings SET value = $1, updated_at = $2 WHERE key = 'persisted-env-vars'`, [JSON.stringify(cleaned), Date.now()]);
|
|
100
|
+
console.log(`[wipe-leaked-builder-keys] removed ${removed.length} key(s) from persisted-env-vars.`);
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
await pgSql.end();
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
// libsql / SQLite
|
|
108
|
+
const client = createClient({
|
|
109
|
+
url,
|
|
110
|
+
authToken: getDatabaseAuthToken(),
|
|
111
|
+
});
|
|
112
|
+
try {
|
|
113
|
+
const result = await client.execute({
|
|
114
|
+
sql: `SELECT value FROM settings WHERE key = ?`,
|
|
115
|
+
args: ["persisted-env-vars"],
|
|
116
|
+
});
|
|
117
|
+
if (result.rows.length === 0) {
|
|
118
|
+
console.log("[wipe-leaked-builder-keys] no persisted-env-vars row.");
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
row = JSON.parse(result.rows[0].value);
|
|
122
|
+
const { cleaned, removed } = stripBuilderKeys(row ?? {});
|
|
123
|
+
if (removed.length === 0) {
|
|
124
|
+
console.log("[wipe-leaked-builder-keys] row already clean — nothing to do.");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
logRemoved(removed, row ?? {});
|
|
128
|
+
if (dryRun)
|
|
129
|
+
return;
|
|
130
|
+
await client.execute({
|
|
131
|
+
sql: `UPDATE settings SET value = ?, updated_at = ? WHERE key = ?`,
|
|
132
|
+
args: [JSON.stringify(cleaned), Date.now(), "persisted-env-vars"],
|
|
133
|
+
});
|
|
134
|
+
console.log(`[wipe-leaked-builder-keys] removed ${removed.length} key(s) from persisted-env-vars.`);
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
client.close();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function stripBuilderKeys(row) {
|
|
141
|
+
const builderSet = new Set(BUILDER_KEYS);
|
|
142
|
+
const cleaned = {};
|
|
143
|
+
const removed = [];
|
|
144
|
+
for (const [k, v] of Object.entries(row)) {
|
|
145
|
+
if (builderSet.has(k)) {
|
|
146
|
+
removed.push(k);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
cleaned[k] = v;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return { cleaned, removed };
|
|
153
|
+
}
|
|
154
|
+
function logRemoved(removed, row) {
|
|
155
|
+
console.log(`[wipe-leaked-builder-keys] BUILDER_* keys present:`);
|
|
156
|
+
for (const k of removed) {
|
|
157
|
+
const masked = k === "BUILDER_ORG_NAME" || k === "BUILDER_ORG_KIND"
|
|
158
|
+
? String(row[k])
|
|
159
|
+
: maskValue(row[k]);
|
|
160
|
+
console.log(` - ${k}: ${masked}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=wipe-leaked-builder-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wipe-leaked-builder-keys.js","sourceRoot":"","sources":["../../../src/scripts/db/wipe-leaked-builder-keys.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
* Each call uses a `getRequiredSecret` guard so a template that has already
|
|
9
9
|
* registered the same key (often with stricter settings like `required: true`)
|
|
10
10
|
* wins — the framework registration is a fallback, not an override.
|
|
11
|
+
*
|
|
12
|
+
* NOTE: The framework previously registered OPENAI_API_KEY here for Whisper
|
|
13
|
+
* voice transcription. Voice transcription now routes through the Builder.io
|
|
14
|
+
* gateway (or Groq as a BYOK fallback), so the framework no longer registers
|
|
15
|
+
* the OpenAI key. Templates that need it (e.g. Clips) register it themselves.
|
|
11
16
|
*/
|
|
12
17
|
export declare function registerFrameworkSecrets(): void;
|
|
13
18
|
//# sourceMappingURL=register-framework-secrets.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-framework-secrets.d.ts","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"register-framework-secrets.d.ts","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C"}
|
|
@@ -8,52 +8,15 @@
|
|
|
8
8
|
* Each call uses a `getRequiredSecret` guard so a template that has already
|
|
9
9
|
* registered the same key (often with stricter settings like `required: true`)
|
|
10
10
|
* wins — the framework registration is a fallback, not an override.
|
|
11
|
-
*/
|
|
12
|
-
import { getRequiredSecret, registerRequiredSecret } from "./register.js";
|
|
13
|
-
/**
|
|
14
|
-
* OpenAI API key.
|
|
15
11
|
*
|
|
16
|
-
* The framework
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* onboarding checklist step.
|
|
12
|
+
* NOTE: The framework previously registered OPENAI_API_KEY here for Whisper
|
|
13
|
+
* voice transcription. Voice transcription now routes through the Builder.io
|
|
14
|
+
* gateway (or Groq as a BYOK fallback), so the framework no longer registers
|
|
15
|
+
* the OpenAI key. Templates that need it (e.g. Clips) register it themselves.
|
|
21
16
|
*/
|
|
22
|
-
function registerOpenAiKey() {
|
|
23
|
-
if (getRequiredSecret("OPENAI_API_KEY"))
|
|
24
|
-
return;
|
|
25
|
-
registerRequiredSecret({
|
|
26
|
-
key: "OPENAI_API_KEY",
|
|
27
|
-
label: "OpenAI API Key",
|
|
28
|
-
description: "Used for voice transcription (Whisper) in the agent composer. Without this, voice input falls back to your browser's built-in speech recognition.",
|
|
29
|
-
docsUrl: "https://platform.openai.com/api-keys",
|
|
30
|
-
scope: "user",
|
|
31
|
-
kind: "api-key",
|
|
32
|
-
required: false,
|
|
33
|
-
validator: async (value) => {
|
|
34
|
-
if (!value || typeof value !== "string" || value.length < 20) {
|
|
35
|
-
return { ok: false, error: "Key looks too short." };
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
const res = await fetch("https://api.openai.com/v1/models", {
|
|
39
|
-
headers: { Authorization: `Bearer ${value}` },
|
|
40
|
-
});
|
|
41
|
-
if (res.ok)
|
|
42
|
-
return true;
|
|
43
|
-
if (res.status === 401)
|
|
44
|
-
return { ok: false, error: "OpenAI rejected this key (401)." };
|
|
45
|
-
return { ok: false, error: `OpenAI returned ${res.status}.` };
|
|
46
|
-
}
|
|
47
|
-
catch (err) {
|
|
48
|
-
return {
|
|
49
|
-
ok: false,
|
|
50
|
-
error: `Could not reach OpenAI: ${err?.message ?? err}`,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
17
|
export function registerFrameworkSecrets() {
|
|
57
|
-
|
|
18
|
+
// No framework-level secrets at this time.
|
|
19
|
+
// Templates register their own keys via `registerRequiredSecret` in
|
|
20
|
+
// their own `register-secrets.ts`.
|
|
58
21
|
}
|
|
59
22
|
//# sourceMappingURL=register-framework-secrets.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-framework-secrets.js","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"register-framework-secrets.js","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,UAAU,wBAAwB;IACtC,2CAA2C;IAC3C,oEAAoE;IACpE,mCAAmC;AACrC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"substitution.d.ts","sourceRoot":"","sources":["../../src/secrets/substitution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"substitution.d.ts","sourceRoot":"","sources":["../../src/secrets/substitution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAQjD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,0BAA0B,CAAC,CAsCrC;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,GACzB,OAAO,CAeT;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAU1B"}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* keys without breaking automations that reference workspace defaults.
|
|
11
11
|
*/
|
|
12
12
|
import { readAppSecret, readAppSecretMeta } from "./storage.js";
|
|
13
|
+
import { getRequestOrgId, getRequestUserEmail, } from "../server/request-context.js";
|
|
13
14
|
const KEY_REFERENCE_REGEX = /\$\{keys\.([A-Za-z0-9_-]+)\}/g;
|
|
14
15
|
/**
|
|
15
16
|
* Resolve `${keys.NAME}` references in `text`. For each reference, looks up
|
|
@@ -31,7 +32,11 @@ export async function resolveKeyReferences(text, scope, scopeId) {
|
|
|
31
32
|
continue;
|
|
32
33
|
let result = await readAppSecret({ key: name, scope, scopeId });
|
|
33
34
|
if (!result && scope === "user") {
|
|
34
|
-
result = await readAppSecret({
|
|
35
|
+
result = await readAppSecret({
|
|
36
|
+
key: name,
|
|
37
|
+
scope: "workspace",
|
|
38
|
+
scopeId: getWorkspaceScopeId(scopeId),
|
|
39
|
+
});
|
|
35
40
|
}
|
|
36
41
|
if (!result) {
|
|
37
42
|
throw new Error(`Referenced key "${name}" is not defined for scope "${scope}". Create it in Settings or via the secrets API before using this automation.`);
|
|
@@ -85,9 +90,16 @@ export async function getKeyAllowlist(name, scope, scopeId) {
|
|
|
85
90
|
meta = await readAppSecretMeta({
|
|
86
91
|
key: name,
|
|
87
92
|
scope: "workspace",
|
|
88
|
-
scopeId,
|
|
93
|
+
scopeId: getWorkspaceScopeId(scopeId),
|
|
89
94
|
});
|
|
90
95
|
}
|
|
91
96
|
return meta?.urlAllowlist ?? null;
|
|
92
97
|
}
|
|
98
|
+
function getWorkspaceScopeId(userScopeId) {
|
|
99
|
+
const orgId = getRequestOrgId();
|
|
100
|
+
if (orgId)
|
|
101
|
+
return orgId;
|
|
102
|
+
const email = getRequestUserEmail() || userScopeId;
|
|
103
|
+
return `solo:${email}`;
|
|
104
|
+
}
|
|
93
105
|
//# sourceMappingURL=substitution.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"substitution.js","sourceRoot":"","sources":["../../src/secrets/substitution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"substitution.js","sourceRoot":"","sources":["../../src/secrets/substitution.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-discovery.d.ts","sourceRoot":"","sources":["../../src/server/action-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAkQhE;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAqC7B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"action-discovery.d.ts","sourceRoot":"","sources":["../../src/server/action-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAkQhE;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAqC7B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAuFtC;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED,oDAAoD;AACpD,eAAO,MAAM,mBAAmB,4BAAsB,CAAC"}
|
|
@@ -321,6 +321,45 @@ export async function autoDiscoverActions(from) {
|
|
|
321
321
|
catch (err) {
|
|
322
322
|
console.warn(`[autoDiscoverActions] Could not read actions directory: ${actionsDir} — ${err?.message}`);
|
|
323
323
|
}
|
|
324
|
+
// 1b. Fallback: if filesystem discovery found no template actions (common
|
|
325
|
+
// in bundled serverless environments like Netlify/Vercel where the
|
|
326
|
+
// actions/ directory doesn't exist on disk), try importing the
|
|
327
|
+
// generated static registry at .generated/actions-registry.
|
|
328
|
+
//
|
|
329
|
+
// This prevents the silent-empty-tools footgun where the agent has no
|
|
330
|
+
// template actions and falls back to generic tools like web-request.
|
|
331
|
+
// Prefer `loadActionsFromStaticRegistry` over `autoDiscoverActions` for
|
|
332
|
+
// production reliability — this fallback is a safety net, not the
|
|
333
|
+
// primary path.
|
|
334
|
+
if (Object.keys(registry).length === 0 && from) {
|
|
335
|
+
try {
|
|
336
|
+
let registryPath;
|
|
337
|
+
if (from.startsWith("file://") || from.startsWith("file:///")) {
|
|
338
|
+
const callerDir = nodePath.dirname(fileURLToPath(from));
|
|
339
|
+
registryPath = nodePath.resolve(callerDir, "../../.generated/actions-registry.js");
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
registryPath = nodePath.resolve(from, "../.generated/actions-registry.js");
|
|
343
|
+
}
|
|
344
|
+
const mod = await import(/* @vite-ignore */ registryPath);
|
|
345
|
+
const staticEntries = loadActionsFromStaticRegistry(mod.default || mod);
|
|
346
|
+
Object.assign(registry, staticEntries);
|
|
347
|
+
if (Object.keys(staticEntries).length > 0) {
|
|
348
|
+
console.log(`[autoDiscoverActions] Filesystem scan found 0 actions — loaded ${Object.keys(staticEntries).length} from .generated/actions-registry.ts instead. ` +
|
|
349
|
+
`Consider switching to loadActionsFromStaticRegistry(actionsRegistry) for production reliability.`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
// No generated registry available — registry stays empty.
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
// If still empty after all fallbacks, warn loudly.
|
|
357
|
+
if (Object.keys(registry).length === 0) {
|
|
358
|
+
console.warn(`[autoDiscoverActions] WARNING: No template actions found! ` +
|
|
359
|
+
`The agent will have no template-specific tools. ` +
|
|
360
|
+
`If in production, switch from autoDiscoverActions to loadActionsFromStaticRegistry. ` +
|
|
361
|
+
`See: https://docs.agent-native.com/actions#static-registry`);
|
|
362
|
+
}
|
|
324
363
|
// 2. Workspace-core actions — merged in with skipExisting so they can't
|
|
325
364
|
// overwrite template entries.
|
|
326
365
|
try {
|