@agent-native/core 0.4.5 → 0.5.0-dev.b51eaae
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 +7 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +24 -3
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts +6 -3
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +45 -39
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/index.d.ts +1 -1
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +2 -2
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/server.d.ts +7 -2
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +54 -14
- package/dist/a2a/server.js.map +1 -1
- package/dist/a2a/task-store.d.ts +6 -6
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +102 -42
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/a2a/types.d.ts +2 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/action.d.ts +46 -0
- package/dist/action.d.ts.map +1 -0
- package/dist/action.js +35 -0
- package/dist/action.js.map +1 -0
- package/dist/adapters/sync/file-sync.js +1 -1
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/production-agent.d.ts +22 -6
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +336 -123
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +43 -0
- package/dist/agent/run-manager.d.ts.map +1 -0
- package/dist/agent/run-manager.js +358 -0
- package/dist/agent/run-manager.js.map +1 -0
- package/dist/agent/run-store.d.ts +26 -0
- package/dist/agent/run-store.d.ts.map +1 -0
- package/dist/agent/run-store.js +145 -0
- package/dist/agent/run-store.js.map +1 -0
- package/dist/agent/thread-data-builder.d.ts +30 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -0
- package/dist/agent/thread-data-builder.js +88 -0
- package/dist/agent/thread-data-builder.js.map +1 -0
- package/dist/agent/types.d.ts +52 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/application-state/emitter.d.ts +3 -2
- package/dist/application-state/emitter.d.ts.map +1 -1
- package/dist/application-state/emitter.js +14 -4
- package/dist/application-state/emitter.js.map +1 -1
- package/dist/application-state/handlers.d.ts.map +1 -1
- package/dist/application-state/handlers.js +13 -16
- package/dist/application-state/handlers.js.map +1 -1
- package/dist/application-state/script-helpers.d.ts +1 -1
- package/dist/application-state/script-helpers.d.ts.map +1 -1
- package/dist/application-state/script-helpers.js +15 -5
- package/dist/application-state/script-helpers.js.map +1 -1
- package/dist/application-state/store.d.ts +4 -3
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +31 -59
- package/dist/application-state/store.js.map +1 -1
- package/dist/chat-threads/emitter.d.ts +9 -0
- package/dist/chat-threads/emitter.d.ts.map +1 -0
- package/dist/chat-threads/emitter.js +14 -0
- package/dist/chat-threads/emitter.js.map +1 -0
- package/dist/chat-threads/store.d.ts +28 -0
- package/dist/chat-threads/store.d.ts.map +1 -0
- package/dist/chat-threads/store.js +124 -0
- package/dist/chat-threads/store.js.map +1 -0
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +4 -18
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +30 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup-agents.d.ts +11 -0
- package/dist/cli/setup-agents.d.ts.map +1 -0
- package/dist/cli/setup-agents.js +123 -0
- package/dist/cli/setup-agents.js.map +1 -0
- package/dist/client/AgentPanel.d.ts +9 -2
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +466 -29
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +25 -3
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +613 -83
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ClientOnly.d.ts +14 -0
- package/dist/client/ClientOnly.d.ts.map +1 -0
- package/dist/client/ClientOnly.js +17 -0
- package/dist/client/ClientOnly.js.map +1 -0
- package/dist/client/CommandMenu.d.ts +71 -0
- package/dist/client/CommandMenu.d.ts.map +1 -0
- package/dist/client/CommandMenu.js +257 -0
- package/dist/client/CommandMenu.js.map +1 -0
- package/dist/client/DefaultSpinner.d.ts +7 -0
- package/dist/client/DefaultSpinner.d.ts.map +1 -0
- package/dist/client/DefaultSpinner.js +28 -0
- package/dist/client/DefaultSpinner.js.map +1 -0
- package/dist/client/MultiTabAssistantChat.d.ts +34 -2
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +346 -57
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/PoweredByBadge.d.ts.map +1 -1
- package/dist/client/PoweredByBadge.js +2 -1
- package/dist/client/PoweredByBadge.js.map +1 -1
- package/dist/client/active-run-state.d.ts +10 -0
- package/dist/client/active-run-state.d.ts.map +1 -0
- package/dist/client/active-run-state.js +32 -0
- package/dist/client/active-run-state.js.map +1 -0
- package/dist/client/agent-chat-adapter.d.ts +2 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +83 -129
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-chat.js +2 -2
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/components/ApiKeySettings.d.ts +2 -2
- package/dist/client/components/ApiKeySettings.js +4 -4
- package/dist/client/components/ApiKeySettings.js.map +1 -1
- package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -1
- package/dist/client/components/CodeRequiredDialog.js +4 -3
- package/dist/client/components/CodeRequiredDialog.js.map +1 -1
- package/dist/client/composer/MentionPopover.d.ts +26 -0
- package/dist/client/composer/MentionPopover.d.ts.map +1 -0
- package/dist/client/composer/MentionPopover.js +130 -0
- package/dist/client/composer/MentionPopover.js.map +1 -0
- package/dist/client/composer/TiptapComposer.d.ts +19 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -0
- package/dist/client/composer/TiptapComposer.js +415 -0
- package/dist/client/composer/TiptapComposer.js.map +1 -0
- package/dist/client/composer/extensions/FileReference.d.ts +3 -0
- package/dist/client/composer/extensions/FileReference.d.ts.map +1 -0
- package/dist/client/composer/extensions/FileReference.js +36 -0
- package/dist/client/composer/extensions/FileReference.js.map +1 -0
- package/dist/client/composer/extensions/MentionReference.d.ts +3 -0
- package/dist/client/composer/extensions/MentionReference.d.ts.map +1 -0
- package/dist/client/composer/extensions/MentionReference.js +63 -0
- package/dist/client/composer/extensions/MentionReference.js.map +1 -0
- package/dist/client/composer/extensions/SkillReference.d.ts +3 -0
- package/dist/client/composer/extensions/SkillReference.d.ts.map +1 -0
- package/dist/client/composer/extensions/SkillReference.js +40 -0
- package/dist/client/composer/extensions/SkillReference.js.map +1 -0
- package/dist/client/composer/index.d.ts +8 -0
- package/dist/client/composer/index.d.ts.map +1 -0
- package/dist/client/composer/index.js +7 -0
- package/dist/client/composer/index.js.map +1 -0
- package/dist/client/composer/types.d.ts +32 -0
- package/dist/client/composer/types.d.ts.map +1 -0
- package/dist/client/composer/types.js +2 -0
- package/dist/client/composer/types.js.map +1 -0
- package/dist/client/composer/use-file-search.d.ts +6 -0
- package/dist/client/composer/use-file-search.d.ts.map +1 -0
- package/dist/client/composer/use-file-search.js +40 -0
- package/dist/client/composer/use-file-search.js.map +1 -0
- package/dist/client/composer/use-mention-search.d.ts +6 -0
- package/dist/client/composer/use-mention-search.d.ts.map +1 -0
- package/dist/client/composer/use-mention-search.js +39 -0
- package/dist/client/composer/use-mention-search.js.map +1 -0
- package/dist/client/composer/use-skills.d.ts +7 -0
- package/dist/client/composer/use-skills.d.ts.map +1 -0
- package/dist/client/composer/use-skills.js +38 -0
- package/dist/client/composer/use-skills.js.map +1 -0
- package/dist/client/index.d.ts +9 -4
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +8 -3
- package/dist/client/index.js.map +1 -1
- package/dist/client/resources/ResourceEditor.d.ts +7 -0
- package/dist/client/resources/ResourceEditor.d.ts.map +1 -0
- package/dist/client/resources/ResourceEditor.js +851 -0
- package/dist/client/resources/ResourceEditor.js.map +1 -0
- package/dist/client/resources/ResourceTree.d.ts +13 -0
- package/dist/client/resources/ResourceTree.d.ts.map +1 -0
- package/dist/client/resources/ResourceTree.js +122 -0
- package/dist/client/resources/ResourceTree.js.map +1 -0
- package/dist/client/resources/ResourcesPanel.d.ts +2 -0
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -0
- package/dist/client/resources/ResourcesPanel.js +341 -0
- package/dist/client/resources/ResourcesPanel.js.map +1 -0
- package/dist/client/resources/index.d.ts +5 -0
- package/dist/client/resources/index.d.ts.map +1 -0
- package/dist/client/resources/index.js +5 -0
- package/dist/client/resources/index.js.map +1 -0
- package/dist/client/resources/use-resources.d.ts +45 -0
- package/dist/client/resources/use-resources.d.ts.map +1 -0
- package/dist/client/resources/use-resources.js +102 -0
- package/dist/client/resources/use-resources.js.map +1 -0
- package/dist/client/sse-event-processor.d.ts +50 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -0
- package/dist/client/sse-event-processor.js +267 -0
- package/dist/client/sse-event-processor.js.map +1 -0
- package/dist/client/terminal/AgentTerminal.d.ts +1 -1
- package/dist/client/terminal/AgentTerminal.d.ts.map +1 -1
- package/dist/client/terminal/AgentTerminal.js +11 -6
- package/dist/client/terminal/AgentTerminal.js.map +1 -1
- package/dist/client/use-agent-chat.d.ts +1 -1
- package/dist/client/use-agent-chat.d.ts.map +1 -1
- package/dist/client/use-agent-chat.js +3 -3
- package/dist/client/use-agent-chat.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts +36 -0
- package/dist/client/use-chat-threads.d.ts.map +1 -0
- package/dist/client/use-chat-threads.js +175 -0
- package/dist/client/use-chat-threads.js.map +1 -0
- package/dist/client/use-db-sync.d.ts +35 -0
- package/dist/client/use-db-sync.d.ts.map +1 -0
- package/dist/client/use-db-sync.js +74 -0
- package/dist/client/use-db-sync.js.map +1 -0
- package/dist/client/use-dev-mode.d.ts +4 -2
- package/dist/client/use-dev-mode.d.ts.map +1 -1
- package/dist/client/use-dev-mode.js +39 -12
- package/dist/client/use-dev-mode.js.map +1 -1
- package/dist/client/use-file-sync-status.d.ts +1 -1
- package/dist/client/use-file-sync-status.js +3 -3
- package/dist/client/use-file-sync-status.js.map +1 -1
- package/dist/client/use-session.d.ts +1 -1
- package/dist/client/use-session.js +2 -2
- package/dist/client/use-session.js.map +1 -1
- package/dist/client/useProductionAgent.d.ts +1 -1
- package/dist/client/useProductionAgent.d.ts.map +1 -1
- package/dist/client/useProductionAgent.js +38 -3
- package/dist/client/useProductionAgent.js.map +1 -1
- package/dist/credentials/index.d.ts +18 -0
- package/dist/credentials/index.d.ts.map +1 -0
- package/dist/credentials/index.js +32 -0
- package/dist/credentials/index.js.map +1 -0
- package/dist/db/client.d.ts +35 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +248 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +103 -16
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/db/index.d.ts +10 -6
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +10 -4
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +31 -30
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/schema.d.ts +45 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +61 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/deploy/build.js +35 -6
- package/dist/deploy/build.js.map +1 -1
- package/dist/deploy/route-discovery.d.ts +9 -0
- package/dist/deploy/route-discovery.d.ts.map +1 -1
- package/dist/deploy/route-discovery.js +30 -1
- package/dist/deploy/route-discovery.js.map +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/oauth-tokens/store.d.ts.map +1 -1
- package/dist/oauth-tokens/store.js +43 -81
- package/dist/oauth-tokens/store.js.map +1 -1
- package/dist/resources/emitter.d.ts +13 -0
- package/dist/resources/emitter.d.ts.map +1 -0
- package/dist/resources/emitter.js +32 -0
- package/dist/resources/emitter.js.map +1 -0
- package/dist/resources/handlers.d.ts +45 -0
- package/dist/resources/handlers.d.ts.map +1 -0
- package/dist/resources/handlers.js +219 -0
- package/dist/resources/handlers.js.map +1 -0
- package/dist/resources/index.d.ts +5 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +5 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/script-helpers.d.ts +24 -0
- package/dist/resources/script-helpers.d.ts.map +1 -0
- package/dist/resources/script-helpers.js +36 -0
- package/dist/resources/script-helpers.js.map +1 -0
- package/dist/resources/store.d.ts +35 -0
- package/dist/resources/store.d.ts.map +1 -0
- package/dist/resources/store.js +453 -0
- package/dist/resources/store.js.map +1 -0
- package/dist/scripts/call-agent.d.ts +5 -0
- package/dist/scripts/call-agent.d.ts.map +1 -0
- package/dist/scripts/call-agent.js +107 -0
- package/dist/scripts/call-agent.js.map +1 -0
- package/dist/scripts/core-scripts.d.ts.map +1 -1
- package/dist/scripts/core-scripts.js +2 -0
- package/dist/scripts/core-scripts.js.map +1 -1
- package/dist/scripts/db/exec.d.ts +6 -2
- package/dist/scripts/db/exec.d.ts.map +1 -1
- package/dist/scripts/db/exec.js +127 -36
- package/dist/scripts/db/exec.js.map +1 -1
- package/dist/scripts/db/query.d.ts +7 -2
- package/dist/scripts/db/query.d.ts.map +1 -1
- package/dist/scripts/db/query.js +89 -45
- package/dist/scripts/db/query.js.map +1 -1
- package/dist/scripts/db/schema.d.ts +2 -2
- package/dist/scripts/db/schema.d.ts.map +1 -1
- package/dist/scripts/db/schema.js +145 -6
- package/dist/scripts/db/schema.js.map +1 -1
- package/dist/scripts/db/scoping.d.ts +36 -0
- package/dist/scripts/db/scoping.d.ts.map +1 -0
- package/dist/scripts/db/scoping.js +198 -0
- package/dist/scripts/db/scoping.js.map +1 -0
- package/dist/scripts/dev/index.d.ts +2 -2
- package/dist/scripts/dev/index.js +1 -1
- package/dist/scripts/dev/list-files.d.ts +2 -2
- package/dist/scripts/dev/read-file.d.ts +2 -2
- package/dist/scripts/dev/read-file.js +1 -1
- package/dist/scripts/dev/read-file.js.map +1 -1
- package/dist/scripts/dev/search-files.d.ts +2 -2
- package/dist/scripts/dev/search-files.js +1 -1
- package/dist/scripts/dev/search-files.js.map +1 -1
- package/dist/scripts/dev/shell.d.ts +2 -2
- package/dist/scripts/dev/shell.js +1 -1
- package/dist/scripts/dev/shell.js.map +1 -1
- package/dist/scripts/dev/write-file.d.ts +2 -2
- package/dist/scripts/dev/write-file.js +1 -1
- package/dist/scripts/dev/write-file.js.map +1 -1
- package/dist/scripts/resources/delete.d.ts +10 -0
- package/dist/scripts/resources/delete.d.ts.map +1 -0
- package/dist/scripts/resources/delete.js +38 -0
- package/dist/scripts/resources/delete.js.map +1 -0
- package/dist/scripts/resources/index.d.ts +2 -0
- package/dist/scripts/resources/index.d.ts.map +1 -0
- package/dist/scripts/resources/index.js +8 -0
- package/dist/scripts/resources/index.js.map +1 -0
- package/dist/scripts/resources/list.d.ts +10 -0
- package/dist/scripts/resources/list.d.ts.map +1 -0
- package/dist/scripts/resources/list.js +57 -0
- package/dist/scripts/resources/list.js.map +1 -0
- package/dist/scripts/resources/migrate-learnings.d.ts +10 -0
- package/dist/scripts/resources/migrate-learnings.d.ts.map +1 -0
- package/dist/scripts/resources/migrate-learnings.js +23 -0
- package/dist/scripts/resources/migrate-learnings.js.map +1 -0
- package/dist/scripts/resources/read.d.ts +10 -0
- package/dist/scripts/resources/read.d.ts.map +1 -0
- package/dist/scripts/resources/read.js +59 -0
- package/dist/scripts/resources/read.js.map +1 -0
- package/dist/scripts/resources/write.d.ts +10 -0
- package/dist/scripts/resources/write.d.ts.map +1 -0
- package/dist/scripts/resources/write.js +67 -0
- package/dist/scripts/resources/write.js.map +1 -0
- package/dist/scripts/runner.d.ts +7 -7
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +68 -27
- package/dist/scripts/runner.js.map +1 -1
- package/dist/scripts/utils.d.ts +4 -1
- package/dist/scripts/utils.d.ts.map +1 -1
- package/dist/scripts/utils.js +5 -3
- package/dist/scripts/utils.js.map +1 -1
- package/dist/server/action-discovery.d.ts +40 -0
- package/dist/server/action-discovery.d.ts.map +1 -0
- package/dist/server/action-discovery.js +189 -0
- package/dist/server/action-discovery.js.map +1 -0
- package/dist/server/agent-chat-plugin.d.ts +12 -23
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +1087 -36
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts +16 -0
- package/dist/server/agent-discovery.d.ts.map +1 -0
- package/dist/server/agent-discovery.js +136 -0
- package/dist/server/agent-discovery.js.map +1 -0
- package/dist/server/auth-plugin.d.ts +5 -0
- package/dist/server/auth-plugin.d.ts.map +1 -1
- package/dist/server/auth-plugin.js +12 -1
- package/dist/server/auth-plugin.js.map +1 -1
- package/dist/server/auth.d.ts +3 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +576 -117
- package/dist/server/auth.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +57 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -0
- package/dist/server/core-routes-plugin.js +125 -0
- package/dist/server/core-routes-plugin.js.map +1 -0
- package/dist/server/create-server.d.ts +4 -4
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +5 -5
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/default-watcher.d.ts +9 -3
- package/dist/server/default-watcher.d.ts.map +1 -1
- package/dist/server/default-watcher.js +26 -6
- package/dist/server/default-watcher.js.map +1 -1
- package/dist/server/google-auth-plugin.js +3 -3
- package/dist/server/google-auth-plugin.js.map +1 -1
- package/dist/server/google-oauth.d.ts +72 -0
- package/dist/server/google-oauth.d.ts.map +1 -0
- package/dist/server/google-oauth.js +187 -0
- package/dist/server/google-oauth.js.map +1 -0
- package/dist/server/index.d.ts +9 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +8 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/oauth-helpers.d.ts +16 -0
- package/dist/server/oauth-helpers.d.ts.map +1 -0
- package/dist/server/oauth-helpers.js +25 -0
- package/dist/server/oauth-helpers.js.map +1 -0
- package/dist/server/poll.d.ts +40 -0
- package/dist/server/poll.d.ts.map +1 -0
- package/dist/server/poll.js +49 -0
- package/dist/server/poll.js.map +1 -0
- package/dist/server/resources-plugin.d.ts +27 -0
- package/dist/server/resources-plugin.d.ts.map +1 -0
- package/dist/server/resources-plugin.js +74 -0
- package/dist/server/resources-plugin.js.map +1 -0
- package/dist/server/script-discovery.d.ts +6 -0
- package/dist/server/script-discovery.d.ts.map +1 -0
- package/dist/server/script-discovery.js +6 -0
- package/dist/server/script-discovery.js.map +1 -0
- package/dist/server/sse.d.ts +1 -1
- package/dist/server/sse.js +1 -1
- package/dist/settings/handlers.d.ts +3 -3
- package/dist/settings/handlers.d.ts.map +1 -1
- package/dist/settings/handlers.js +8 -6
- package/dist/settings/handlers.js.map +1 -1
- package/dist/settings/index.d.ts +1 -1
- package/dist/settings/index.d.ts.map +1 -1
- package/dist/settings/index.js.map +1 -1
- package/dist/settings/store.d.ts +6 -2
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +26 -63
- package/dist/settings/store.js.map +1 -1
- package/dist/settings/user-settings.d.ts +3 -2
- package/dist/settings/user-settings.d.ts.map +1 -1
- package/dist/settings/user-settings.js +5 -5
- package/dist/settings/user-settings.js.map +1 -1
- package/dist/tailwind.preset.d.ts +7 -6
- package/dist/tailwind.preset.d.ts.map +1 -1
- package/dist/tailwind.preset.js +18 -1
- package/dist/tailwind.preset.js.map +1 -1
- package/dist/terminal/cli-registry.d.ts +1 -1
- package/dist/terminal/cli-registry.js +3 -3
- package/dist/terminal/cli-registry.js.map +1 -1
- package/dist/terminal/pty-server.d.ts.map +1 -1
- package/dist/terminal/pty-server.js +65 -11
- package/dist/terminal/pty-server.js.map +1 -1
- package/dist/terminal/terminal-plugin.d.ts +2 -2
- package/dist/terminal/terminal-plugin.d.ts.map +1 -1
- package/dist/terminal/terminal-plugin.js +27 -21
- package/dist/terminal/terminal-plugin.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +114 -8
- package/dist/vite/client.js.map +1 -1
- package/dist/vite/dev-api-server.d.ts +1 -1
- package/dist/vite/dev-api-server.d.ts.map +1 -1
- package/dist/vite/dev-api-server.js +105 -22
- package/dist/vite/dev-api-server.js.map +1 -1
- package/package.json +22 -6
- package/src/templates/default/.agents/skills/actions/SKILL.md +136 -0
- package/src/templates/default/.agents/skills/create-skill/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/files-as-database/SKILL.md +2 -2
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +112 -0
- package/src/templates/default/AGENTS.md +56 -164
- package/src/templates/default/DEVELOPING.md +117 -0
- package/src/templates/default/{scripts → actions}/hello.ts +1 -1
- package/src/templates/default/actions/navigate.ts +53 -0
- package/src/templates/default/actions/view-screen.ts +39 -0
- package/src/templates/default/app/global.css +2 -2
- package/src/templates/default/app/root.tsx +19 -16
- package/src/templates/default/app/routes/_index.tsx +1 -1
- package/src/templates/default/package.json +4 -0
- package/src/templates/default/server/plugins/.gitkeep +0 -0
- package/dist/a2a/middleware.d.ts +0 -3
- package/dist/a2a/middleware.d.ts.map +0 -1
- package/dist/a2a/middleware.js +0 -36
- package/dist/a2a/middleware.js.map +0 -1
- package/dist/client/use-file-watcher.d.ts +0 -23
- package/dist/client/use-file-watcher.d.ts.map +0 -1
- package/dist/client/use-file-watcher.js +0 -50
- package/dist/client/use-file-watcher.js.map +0 -1
- package/src/templates/default/.agents/skills/scripts/SKILL.md +0 -121
- package/src/templates/default/.agents/skills/sse-file-watcher/SKILL.md +0 -80
- package/src/templates/default/server/plugins/agent-chat.ts +0 -1
- package/src/templates/default/server/plugins/auth.ts +0 -1
- package/src/templates/default/server/plugins/file-sync.ts +0 -1
- package/src/templates/default/server/plugins/terminal.ts +0 -1
- package/src/templates/default/server/routes/api/events.get.ts +0 -3
- package/src/templates/default/server/routes/api/file-sync/status.get.ts +0 -4
- /package/src/templates/default/{scripts → actions}/run.ts +0 -0
package/dist/server/auth.js
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { defineEventHandler, readBody, getMethod, setResponseHeader, setResponseStatus, getCookie, setCookie, deleteCookie, } from "h3";
|
|
5
|
-
import { createClient } from "@libsql/client";
|
|
2
|
+
import { defineEventHandler, readBody, getMethod, getQuery, getRequestIP, setResponseHeader, setResponseStatus, getCookie, setCookie, deleteCookie, } from "h3";
|
|
3
|
+
import { getDbExec, isPostgres, intType } from "../db/client.js";
|
|
6
4
|
// ---------------------------------------------------------------------------
|
|
7
5
|
// Constants
|
|
8
6
|
// ---------------------------------------------------------------------------
|
|
9
7
|
const COOKIE_NAME = "an_session";
|
|
10
8
|
const DEFAULT_MAX_AGE = 60 * 60 * 24 * 30; // 30 days
|
|
9
|
+
const RATE_LIMIT_WINDOW = 15 * 60 * 1000; // 15 minutes
|
|
10
|
+
const RATE_LIMIT_MAX = 10; // max attempts per window
|
|
11
|
+
const rateLimitMap = new Map();
|
|
12
|
+
// Prune stale entries every 5 minutes to prevent unbounded growth
|
|
13
|
+
setInterval(() => {
|
|
14
|
+
const now = Date.now();
|
|
15
|
+
for (const [key, entry] of rateLimitMap) {
|
|
16
|
+
if (now > entry.resetAt)
|
|
17
|
+
rateLimitMap.delete(key);
|
|
18
|
+
}
|
|
19
|
+
}, 5 * 60 * 1000).unref();
|
|
20
|
+
function getClientIp(event) {
|
|
21
|
+
return getRequestIP(event, { xForwardedFor: true }) ?? "unknown";
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check rate limit for a given key (typically IP + route).
|
|
25
|
+
* Returns null if allowed, or a response object if blocked.
|
|
26
|
+
*/
|
|
27
|
+
function checkRateLimit(event, key) {
|
|
28
|
+
const now = Date.now();
|
|
29
|
+
const entry = rateLimitMap.get(key);
|
|
30
|
+
if (!entry || now > entry.resetAt) {
|
|
31
|
+
rateLimitMap.set(key, { count: 1, resetAt: now + RATE_LIMIT_WINDOW });
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
entry.count++;
|
|
35
|
+
if (entry.count > RATE_LIMIT_MAX) {
|
|
36
|
+
const retryAfter = Math.ceil((entry.resetAt - now) / 1000);
|
|
37
|
+
setResponseStatus(event, 429);
|
|
38
|
+
setResponseHeader(event, "Retry-After", retryAfter);
|
|
39
|
+
return {
|
|
40
|
+
error: "Too many attempts. Please try again later.",
|
|
41
|
+
retryAfter,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
/** Reset rate limit on successful auth (so valid users aren't penalized). */
|
|
47
|
+
function resetRateLimit(key) {
|
|
48
|
+
rateLimitMap.delete(key);
|
|
49
|
+
}
|
|
11
50
|
// ---------------------------------------------------------------------------
|
|
12
51
|
// Session store — SQL-backed
|
|
13
52
|
// ---------------------------------------------------------------------------
|
|
14
|
-
let
|
|
15
|
-
let _sessionTableReady = false;
|
|
53
|
+
let _sessionInitPromise;
|
|
16
54
|
let sessionMaxAge = DEFAULT_MAX_AGE;
|
|
17
|
-
function
|
|
18
|
-
if (!
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
const r = await d1
|
|
32
|
-
.prepare(sql.sql)
|
|
33
|
-
.bind(...sql.args)
|
|
34
|
-
.all();
|
|
35
|
-
return { rows: r.results || [], rowsAffected: r.meta?.changes ?? 0 };
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
return _sessionClient;
|
|
39
|
-
}
|
|
40
|
-
// Fall back to libsql
|
|
41
|
-
const url = process.env.DATABASE_URL || "file:./data/app.db";
|
|
42
|
-
if (url.startsWith("file:")) {
|
|
55
|
+
async function ensureSessionTable() {
|
|
56
|
+
if (!_sessionInitPromise) {
|
|
57
|
+
_sessionInitPromise = (async () => {
|
|
58
|
+
const client = getDbExec();
|
|
59
|
+
await client.execute(`
|
|
60
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
61
|
+
token TEXT PRIMARY KEY,
|
|
62
|
+
email TEXT,
|
|
63
|
+
created_at ${intType()} NOT NULL
|
|
64
|
+
)
|
|
65
|
+
`);
|
|
66
|
+
// Migration: add email column to existing tables that lack it
|
|
43
67
|
try {
|
|
44
|
-
|
|
68
|
+
await client.execute(`ALTER TABLE sessions ADD COLUMN email TEXT`);
|
|
45
69
|
}
|
|
46
70
|
catch {
|
|
47
|
-
//
|
|
71
|
+
// Column already exists — ignore
|
|
48
72
|
}
|
|
49
|
-
}
|
|
50
|
-
_sessionClient = createClient({
|
|
51
|
-
url,
|
|
52
|
-
authToken: process.env.DATABASE_AUTH_TOKEN,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
return _sessionClient;
|
|
56
|
-
}
|
|
57
|
-
async function ensureSessionTable() {
|
|
58
|
-
if (_sessionTableReady)
|
|
59
|
-
return;
|
|
60
|
-
const client = getSessionClient();
|
|
61
|
-
await client.execute(`
|
|
62
|
-
CREATE TABLE IF NOT EXISTS sessions (
|
|
63
|
-
token TEXT PRIMARY KEY,
|
|
64
|
-
email TEXT,
|
|
65
|
-
created_at INTEGER NOT NULL
|
|
66
|
-
)
|
|
67
|
-
`);
|
|
68
|
-
// Migration: add email column to existing tables that lack it
|
|
69
|
-
try {
|
|
70
|
-
await client.execute(`ALTER TABLE sessions ADD COLUMN email TEXT`);
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
// Column already exists — ignore
|
|
73
|
+
})();
|
|
74
74
|
}
|
|
75
|
-
|
|
75
|
+
return _sessionInitPromise;
|
|
76
76
|
}
|
|
77
77
|
async function pruneExpiredSessions() {
|
|
78
78
|
await ensureSessionTable();
|
|
79
|
-
const client =
|
|
79
|
+
const client = getDbExec();
|
|
80
80
|
const cutoff = Date.now() - sessionMaxAge * 1000;
|
|
81
81
|
await client.execute({
|
|
82
82
|
sql: `DELETE FROM sessions WHERE created_at < ?`,
|
|
@@ -89,16 +89,18 @@ async function pruneExpiredSessions() {
|
|
|
89
89
|
*/
|
|
90
90
|
export async function addSession(token, email) {
|
|
91
91
|
await ensureSessionTable();
|
|
92
|
-
const client =
|
|
92
|
+
const client = getDbExec();
|
|
93
93
|
await client.execute({
|
|
94
|
-
sql:
|
|
94
|
+
sql: isPostgres()
|
|
95
|
+
? `INSERT INTO sessions (token, email, created_at) VALUES (?, ?, ?) ON CONFLICT (token) DO UPDATE SET email=EXCLUDED.email, created_at=EXCLUDED.created_at`
|
|
96
|
+
: `INSERT OR REPLACE INTO sessions (token, email, created_at) VALUES (?, ?, ?)`,
|
|
95
97
|
args: [token, email ?? null, Date.now()],
|
|
96
98
|
});
|
|
97
99
|
}
|
|
98
100
|
/** Remove a session by token. */
|
|
99
101
|
export async function removeSession(token) {
|
|
100
102
|
await ensureSessionTable();
|
|
101
|
-
const client =
|
|
103
|
+
const client = getDbExec();
|
|
102
104
|
await client.execute({
|
|
103
105
|
sql: `DELETE FROM sessions WHERE token = ?`,
|
|
104
106
|
args: [token],
|
|
@@ -110,7 +112,7 @@ export async function removeSession(token) {
|
|
|
110
112
|
*/
|
|
111
113
|
export async function getSessionEmail(token) {
|
|
112
114
|
await ensureSessionTable();
|
|
113
|
-
const client =
|
|
115
|
+
const client = getDbExec();
|
|
114
116
|
const { rows } = await client.execute({
|
|
115
117
|
sql: `SELECT email, created_at FROM sessions WHERE token = ?`,
|
|
116
118
|
args: [token],
|
|
@@ -129,7 +131,7 @@ export async function getSessionEmail(token) {
|
|
|
129
131
|
}
|
|
130
132
|
async function hasSession(token) {
|
|
131
133
|
await ensureSessionTable();
|
|
132
|
-
const client =
|
|
134
|
+
const client = getDbExec();
|
|
133
135
|
const { rows } = await client.execute({
|
|
134
136
|
sql: `SELECT created_at FROM sessions WHERE token = ?`,
|
|
135
137
|
args: [token],
|
|
@@ -182,20 +184,61 @@ const DEV_SESSION = { email: "local@localhost" };
|
|
|
182
184
|
/**
|
|
183
185
|
* Get the current auth session for a request.
|
|
184
186
|
*
|
|
185
|
-
* - In dev mode:
|
|
187
|
+
* - In dev mode: checks for a session cookie first (e.g. from Google OAuth),
|
|
188
|
+
* so the real email is used when sharing a DB with production.
|
|
189
|
+
* Falls back to { email: "local@localhost" } if no session cookie.
|
|
186
190
|
* - In production with built-in auth: returns session if cookie is valid
|
|
187
191
|
* - With custom auth (BYOA): delegates to the custom getSession
|
|
188
192
|
*/
|
|
189
193
|
export async function getSession(event) {
|
|
190
|
-
if (isDevMode())
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
if (isDevMode() || authDisabledMode) {
|
|
195
|
+
// Check for a real session cookie (created by Google OAuth callback)
|
|
196
|
+
// so dev and prod share the same identity on the same DB
|
|
197
|
+
try {
|
|
198
|
+
const cookie = getCookie(event, COOKIE_NAME);
|
|
199
|
+
if (cookie) {
|
|
200
|
+
const email = await getSessionEmail(cookie);
|
|
201
|
+
if (email)
|
|
202
|
+
return { email, token: cookie };
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// DB not ready yet — fall back to dev session
|
|
207
|
+
}
|
|
193
208
|
return DEV_SESSION;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
209
|
+
}
|
|
210
|
+
if (customGetSession) {
|
|
211
|
+
const session = await customGetSession(event);
|
|
212
|
+
if (session)
|
|
213
|
+
return session;
|
|
214
|
+
// Fall through to _session query param check (mobile WebView bridge)
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
const cookie = getCookie(event, COOKIE_NAME);
|
|
218
|
+
if (cookie) {
|
|
219
|
+
const email = await getSessionEmail(cookie);
|
|
220
|
+
if (email)
|
|
221
|
+
return { email, token: cookie };
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Mobile WebViews have a separate cookie jar from Safari, so after OAuth
|
|
225
|
+
// completes in Safari the WebView won't have the session cookie. The mobile
|
|
226
|
+
// app passes the token as a query parameter; if it's valid we promote it to
|
|
227
|
+
// an httpOnly cookie so subsequent requests work normally.
|
|
228
|
+
// This MUST run even with custom auth providers (e.g. createGoogleAuthPlugin).
|
|
229
|
+
const qToken = getQuery(event)?._session;
|
|
230
|
+
if (qToken) {
|
|
231
|
+
const email = await getSessionEmail(qToken);
|
|
232
|
+
if (email) {
|
|
233
|
+
setCookie(event, COOKIE_NAME, qToken, {
|
|
234
|
+
httpOnly: true,
|
|
235
|
+
secure: process.env.NODE_ENV === "production",
|
|
236
|
+
sameSite: "lax",
|
|
237
|
+
path: "/",
|
|
238
|
+
maxAge: sessionMaxAge,
|
|
239
|
+
});
|
|
240
|
+
return { email, token: qToken };
|
|
241
|
+
}
|
|
199
242
|
}
|
|
200
243
|
return null;
|
|
201
244
|
}
|
|
@@ -214,6 +257,102 @@ function safeTokenMatch(input, tokens) {
|
|
|
214
257
|
return false;
|
|
215
258
|
}
|
|
216
259
|
// ---------------------------------------------------------------------------
|
|
260
|
+
// Password hashing — Web Crypto PBKDF2 (works on Node.js + CF Workers)
|
|
261
|
+
// ---------------------------------------------------------------------------
|
|
262
|
+
const PBKDF2_ITERATIONS = 100_000;
|
|
263
|
+
function toHex(buf) {
|
|
264
|
+
return Array.from(buf)
|
|
265
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
266
|
+
.join("");
|
|
267
|
+
}
|
|
268
|
+
function fromHex(hex) {
|
|
269
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
270
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
271
|
+
bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
|
|
272
|
+
}
|
|
273
|
+
return bytes;
|
|
274
|
+
}
|
|
275
|
+
async function hashPassword(password) {
|
|
276
|
+
const salt = crypto.getRandomValues(new Uint8Array(16));
|
|
277
|
+
const encoded = new TextEncoder().encode(password);
|
|
278
|
+
const keyMaterial = await globalThis.crypto.subtle.importKey("raw", encoded.buffer, "PBKDF2", false, ["deriveBits"]);
|
|
279
|
+
const derived = await globalThis.crypto.subtle.deriveBits({
|
|
280
|
+
name: "PBKDF2",
|
|
281
|
+
salt: salt.buffer,
|
|
282
|
+
iterations: PBKDF2_ITERATIONS,
|
|
283
|
+
hash: "SHA-256",
|
|
284
|
+
}, keyMaterial, 256);
|
|
285
|
+
return `${PBKDF2_ITERATIONS}:${toHex(salt)}:${toHex(new Uint8Array(derived))}`;
|
|
286
|
+
}
|
|
287
|
+
async function verifyPassword(password, stored) {
|
|
288
|
+
const [iterStr, saltHex, hashHex] = stored.split(":");
|
|
289
|
+
const iterations = parseInt(iterStr, 10);
|
|
290
|
+
const salt = fromHex(saltHex);
|
|
291
|
+
const expectedHash = fromHex(hashHex);
|
|
292
|
+
const encoded = new TextEncoder().encode(password);
|
|
293
|
+
const keyMaterial = await globalThis.crypto.subtle.importKey("raw", encoded.buffer, "PBKDF2", false, ["deriveBits"]);
|
|
294
|
+
const derived = new Uint8Array(await globalThis.crypto.subtle.deriveBits({
|
|
295
|
+
name: "PBKDF2",
|
|
296
|
+
salt: salt.buffer,
|
|
297
|
+
iterations,
|
|
298
|
+
hash: "SHA-256",
|
|
299
|
+
}, keyMaterial, 256));
|
|
300
|
+
if (derived.length !== expectedHash.length)
|
|
301
|
+
return false;
|
|
302
|
+
// Constant-time comparison
|
|
303
|
+
let diff = 0;
|
|
304
|
+
for (let i = 0; i < derived.length; i++) {
|
|
305
|
+
diff |= derived[i] ^ expectedHash[i];
|
|
306
|
+
}
|
|
307
|
+
return diff === 0;
|
|
308
|
+
}
|
|
309
|
+
// ---------------------------------------------------------------------------
|
|
310
|
+
// Users table — email/password accounts
|
|
311
|
+
// ---------------------------------------------------------------------------
|
|
312
|
+
let _usersTableReady = false;
|
|
313
|
+
async function ensureUsersTable() {
|
|
314
|
+
if (_usersTableReady)
|
|
315
|
+
return;
|
|
316
|
+
const client = getDbExec();
|
|
317
|
+
await client.execute(`
|
|
318
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
319
|
+
email TEXT PRIMARY KEY,
|
|
320
|
+
password_hash TEXT NOT NULL,
|
|
321
|
+
created_at ${intType()} NOT NULL
|
|
322
|
+
)
|
|
323
|
+
`);
|
|
324
|
+
_usersTableReady = true;
|
|
325
|
+
}
|
|
326
|
+
async function createUser(email, password) {
|
|
327
|
+
await ensureUsersTable();
|
|
328
|
+
const client = getDbExec();
|
|
329
|
+
// Check if user already exists
|
|
330
|
+
const { rows } = await client.execute({
|
|
331
|
+
sql: `SELECT email FROM users WHERE email = ?`,
|
|
332
|
+
args: [email],
|
|
333
|
+
});
|
|
334
|
+
if (rows.length > 0) {
|
|
335
|
+
return { ok: false, error: "An account with this email already exists" };
|
|
336
|
+
}
|
|
337
|
+
const passwordHash = await hashPassword(password);
|
|
338
|
+
await client.execute({
|
|
339
|
+
sql: `INSERT INTO users (email, password_hash, created_at) VALUES (?, ?, ?)`,
|
|
340
|
+
args: [email, passwordHash, Date.now()],
|
|
341
|
+
});
|
|
342
|
+
return { ok: true };
|
|
343
|
+
}
|
|
344
|
+
async function authenticateUser(email, password) {
|
|
345
|
+
await ensureUsersTable();
|
|
346
|
+
const client = getDbExec();
|
|
347
|
+
const { rows } = await client.execute({
|
|
348
|
+
sql: `SELECT password_hash FROM users WHERE email = ?`,
|
|
349
|
+
args: [email],
|
|
350
|
+
});
|
|
351
|
+
if (rows.length === 0)
|
|
352
|
+
return false;
|
|
353
|
+
return verifyPassword(password, rows[0].password_hash);
|
|
354
|
+
}
|
|
355
|
+
// ---------------------------------------------------------------------------
|
|
217
356
|
// Login page HTML
|
|
218
357
|
// ---------------------------------------------------------------------------
|
|
219
358
|
const LOGIN_HTML = `<!DOCTYPE html>
|
|
@@ -287,7 +426,7 @@ const LOGIN_HTML = `<!DOCTYPE html>
|
|
|
287
426
|
document.getElementById('form').addEventListener('submit', async (e) => {
|
|
288
427
|
e.preventDefault();
|
|
289
428
|
const token = document.getElementById('token').value;
|
|
290
|
-
const res = await fetch('/
|
|
429
|
+
const res = await fetch('/_agent-native/auth/login', {
|
|
291
430
|
method: 'POST',
|
|
292
431
|
headers: { 'Content-Type': 'application/json' },
|
|
293
432
|
body: JSON.stringify({ token }),
|
|
@@ -302,6 +441,327 @@ const LOGIN_HTML = `<!DOCTYPE html>
|
|
|
302
441
|
</body>
|
|
303
442
|
</html>`;
|
|
304
443
|
// ---------------------------------------------------------------------------
|
|
444
|
+
// Email/password auth HTML — combined login + register page
|
|
445
|
+
// ---------------------------------------------------------------------------
|
|
446
|
+
const EMAIL_AUTH_HTML = `<!DOCTYPE html>
|
|
447
|
+
<html lang="en">
|
|
448
|
+
<head>
|
|
449
|
+
<meta charset="UTF-8">
|
|
450
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
451
|
+
<title>Sign in</title>
|
|
452
|
+
<style>
|
|
453
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
454
|
+
body {
|
|
455
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
456
|
+
background: #0a0a0a;
|
|
457
|
+
color: #e5e5e5;
|
|
458
|
+
display: flex;
|
|
459
|
+
align-items: center;
|
|
460
|
+
justify-content: center;
|
|
461
|
+
min-height: 100vh;
|
|
462
|
+
}
|
|
463
|
+
.card {
|
|
464
|
+
width: 100%;
|
|
465
|
+
max-width: 380px;
|
|
466
|
+
padding: 2rem;
|
|
467
|
+
background: #141414;
|
|
468
|
+
border: 1px solid rgba(255,255,255,0.08);
|
|
469
|
+
border-radius: 12px;
|
|
470
|
+
}
|
|
471
|
+
.tabs {
|
|
472
|
+
display: inline-flex;
|
|
473
|
+
width: 100%;
|
|
474
|
+
padding: 4px;
|
|
475
|
+
margin-bottom: 1.5rem;
|
|
476
|
+
background: rgba(255,255,255,0.06);
|
|
477
|
+
border-radius: 8px;
|
|
478
|
+
}
|
|
479
|
+
.tab {
|
|
480
|
+
flex: 1;
|
|
481
|
+
padding: 0.5rem 0.75rem;
|
|
482
|
+
background: none;
|
|
483
|
+
border: none;
|
|
484
|
+
color: #888;
|
|
485
|
+
font-size: 0.8125rem;
|
|
486
|
+
font-weight: 500;
|
|
487
|
+
cursor: pointer;
|
|
488
|
+
border-radius: 6px;
|
|
489
|
+
}
|
|
490
|
+
.tab.active {
|
|
491
|
+
background: #1e1e1e;
|
|
492
|
+
color: #fff;
|
|
493
|
+
box-shadow: 0 1px 2px rgba(0,0,0,0.3);
|
|
494
|
+
}
|
|
495
|
+
.tab:hover:not(.active) { color: #bbb; }
|
|
496
|
+
.form { display: none; }
|
|
497
|
+
.form.active { display: block; }
|
|
498
|
+
label { display: block; font-size: 0.8125rem; color: #888; margin-bottom: 0.375rem; }
|
|
499
|
+
input {
|
|
500
|
+
width: 100%;
|
|
501
|
+
padding: 0.5rem 0.75rem;
|
|
502
|
+
background: transparent;
|
|
503
|
+
border: 1px solid rgba(255,255,255,0.12);
|
|
504
|
+
border-radius: 6px;
|
|
505
|
+
color: #e5e5e5;
|
|
506
|
+
font-size: 0.875rem;
|
|
507
|
+
outline: none;
|
|
508
|
+
margin-bottom: 0.875rem;
|
|
509
|
+
}
|
|
510
|
+
input:focus { border-color: rgba(255,255,255,0.3); box-shadow: 0 0 0 1px rgba(255,255,255,0.1); }
|
|
511
|
+
input::placeholder { color: #555; }
|
|
512
|
+
button[type="submit"] {
|
|
513
|
+
width: 100%;
|
|
514
|
+
margin-top: 0.25rem;
|
|
515
|
+
padding: 0.5rem;
|
|
516
|
+
background: #fff;
|
|
517
|
+
color: #000;
|
|
518
|
+
border: none;
|
|
519
|
+
border-radius: 6px;
|
|
520
|
+
font-size: 0.875rem;
|
|
521
|
+
font-weight: 500;
|
|
522
|
+
cursor: pointer;
|
|
523
|
+
}
|
|
524
|
+
button[type="submit"]:hover { background: #e5e5e5; }
|
|
525
|
+
button[type="submit"]:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
526
|
+
.msg { margin-top: 0.75rem; font-size: 0.8125rem; display: none; }
|
|
527
|
+
.msg.error { color: #f87171; }
|
|
528
|
+
.msg.success { color: #4ade80; }
|
|
529
|
+
.msg.show { display: block; }
|
|
530
|
+
</style>
|
|
531
|
+
</head>
|
|
532
|
+
<body>
|
|
533
|
+
<div class="card">
|
|
534
|
+
<div class="tabs">
|
|
535
|
+
<button class="tab active" data-tab="login">Sign in</button>
|
|
536
|
+
<button class="tab" data-tab="register">Create account</button>
|
|
537
|
+
</div>
|
|
538
|
+
<form id="login-form" class="form active">
|
|
539
|
+
<label for="l-email">Email</label>
|
|
540
|
+
<input id="l-email" type="email" autocomplete="email" autofocus placeholder="you@example.com" required />
|
|
541
|
+
<label for="l-pass">Password</label>
|
|
542
|
+
<input id="l-pass" type="password" autocomplete="current-password" placeholder="Enter password" required />
|
|
543
|
+
<button type="submit">Sign in</button>
|
|
544
|
+
<p class="msg error" id="l-err"></p>
|
|
545
|
+
</form>
|
|
546
|
+
<form id="register-form" class="form">
|
|
547
|
+
<label for="r-email">Email</label>
|
|
548
|
+
<input id="r-email" type="email" autocomplete="email" placeholder="you@example.com" required />
|
|
549
|
+
<label for="r-pass">Password</label>
|
|
550
|
+
<input id="r-pass" type="password" autocomplete="new-password" placeholder="At least 8 characters" required minlength="8" />
|
|
551
|
+
<label for="r-pass2">Confirm password</label>
|
|
552
|
+
<input id="r-pass2" type="password" autocomplete="new-password" placeholder="Confirm password" required minlength="8" />
|
|
553
|
+
<button type="submit">Create account</button>
|
|
554
|
+
<p class="msg" id="r-msg"></p>
|
|
555
|
+
</form>
|
|
556
|
+
</div>
|
|
557
|
+
<script>
|
|
558
|
+
const tabs = document.querySelectorAll('.tab');
|
|
559
|
+
const forms = document.querySelectorAll('.form');
|
|
560
|
+
tabs.forEach(t => t.addEventListener('click', () => {
|
|
561
|
+
tabs.forEach(x => x.classList.remove('active'));
|
|
562
|
+
forms.forEach(x => x.classList.remove('active'));
|
|
563
|
+
t.classList.add('active');
|
|
564
|
+
document.getElementById(t.dataset.tab + '-form').classList.add('active');
|
|
565
|
+
}));
|
|
566
|
+
|
|
567
|
+
document.getElementById('login-form').addEventListener('submit', async (e) => {
|
|
568
|
+
e.preventDefault();
|
|
569
|
+
const err = document.getElementById('l-err');
|
|
570
|
+
err.classList.remove('show');
|
|
571
|
+
const res = await fetch('/_agent-native/auth/login', {
|
|
572
|
+
method: 'POST',
|
|
573
|
+
headers: { 'Content-Type': 'application/json' },
|
|
574
|
+
body: JSON.stringify({
|
|
575
|
+
email: document.getElementById('l-email').value,
|
|
576
|
+
password: document.getElementById('l-pass').value,
|
|
577
|
+
}),
|
|
578
|
+
});
|
|
579
|
+
if (res.ok) {
|
|
580
|
+
window.location.reload();
|
|
581
|
+
} else {
|
|
582
|
+
const data = await res.json().catch(() => ({}));
|
|
583
|
+
err.textContent = data.error || 'Invalid email or password';
|
|
584
|
+
err.classList.add('show');
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
document.getElementById('register-form').addEventListener('submit', async (e) => {
|
|
589
|
+
e.preventDefault();
|
|
590
|
+
const msg = document.getElementById('r-msg');
|
|
591
|
+
msg.classList.remove('show', 'error', 'success');
|
|
592
|
+
const pass = document.getElementById('r-pass').value;
|
|
593
|
+
const pass2 = document.getElementById('r-pass2').value;
|
|
594
|
+
if (pass !== pass2) {
|
|
595
|
+
msg.textContent = 'Passwords do not match';
|
|
596
|
+
msg.classList.add('show', 'error');
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
const res = await fetch('/_agent-native/auth/register', {
|
|
600
|
+
method: 'POST',
|
|
601
|
+
headers: { 'Content-Type': 'application/json' },
|
|
602
|
+
body: JSON.stringify({
|
|
603
|
+
email: document.getElementById('r-email').value,
|
|
604
|
+
password: pass,
|
|
605
|
+
}),
|
|
606
|
+
});
|
|
607
|
+
const data = await res.json().catch(() => ({}));
|
|
608
|
+
if (res.ok) {
|
|
609
|
+
msg.textContent = 'Account created — signing you in...';
|
|
610
|
+
msg.classList.add('show', 'success');
|
|
611
|
+
// Auto-login after registration
|
|
612
|
+
const loginRes = await fetch('/_agent-native/auth/login', {
|
|
613
|
+
method: 'POST',
|
|
614
|
+
headers: { 'Content-Type': 'application/json' },
|
|
615
|
+
body: JSON.stringify({
|
|
616
|
+
email: document.getElementById('r-email').value,
|
|
617
|
+
password: pass,
|
|
618
|
+
}),
|
|
619
|
+
});
|
|
620
|
+
if (loginRes.ok) {
|
|
621
|
+
window.location.reload();
|
|
622
|
+
}
|
|
623
|
+
} else {
|
|
624
|
+
msg.textContent = data.error || 'Registration failed';
|
|
625
|
+
msg.classList.add('show', 'error');
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
</script>
|
|
629
|
+
</body>
|
|
630
|
+
</html>`;
|
|
631
|
+
// ---------------------------------------------------------------------------
|
|
632
|
+
// mountEmailAuthRoutes — email/password registration + login
|
|
633
|
+
// ---------------------------------------------------------------------------
|
|
634
|
+
function mountEmailAuthRoutes(app, publicPaths = []) {
|
|
635
|
+
// Also support ACCESS_TOKEN login for backward compat (API callers, scripts)
|
|
636
|
+
const accessTokens = getAccessTokens();
|
|
637
|
+
// POST /_agent-native/auth/register
|
|
638
|
+
app.use("/_agent-native/auth/register", defineEventHandler(async (event) => {
|
|
639
|
+
if (getMethod(event) !== "POST") {
|
|
640
|
+
setResponseStatus(event, 405);
|
|
641
|
+
return { error: "Method not allowed" };
|
|
642
|
+
}
|
|
643
|
+
const ip = getClientIp(event);
|
|
644
|
+
const limited = checkRateLimit(event, `register:${ip}`);
|
|
645
|
+
if (limited)
|
|
646
|
+
return limited;
|
|
647
|
+
const body = await readBody(event);
|
|
648
|
+
const email = body?.email?.trim?.()?.toLowerCase?.();
|
|
649
|
+
const password = body?.password;
|
|
650
|
+
if (!email || typeof email !== "string" || !email.includes("@")) {
|
|
651
|
+
setResponseStatus(event, 400);
|
|
652
|
+
return { error: "Valid email is required" };
|
|
653
|
+
}
|
|
654
|
+
if (!password || typeof password !== "string" || password.length < 8) {
|
|
655
|
+
setResponseStatus(event, 400);
|
|
656
|
+
return { error: "Password must be at least 8 characters" };
|
|
657
|
+
}
|
|
658
|
+
const result = await createUser(email, password);
|
|
659
|
+
if (!result.ok) {
|
|
660
|
+
setResponseStatus(event, 409);
|
|
661
|
+
return { error: result.error };
|
|
662
|
+
}
|
|
663
|
+
resetRateLimit(`register:${ip}`);
|
|
664
|
+
return { ok: true };
|
|
665
|
+
}));
|
|
666
|
+
// POST /_agent-native/auth/login — email/password or legacy ACCESS_TOKEN
|
|
667
|
+
app.use("/_agent-native/auth/login", defineEventHandler(async (event) => {
|
|
668
|
+
if (getMethod(event) !== "POST") {
|
|
669
|
+
setResponseStatus(event, 405);
|
|
670
|
+
return { error: "Method not allowed" };
|
|
671
|
+
}
|
|
672
|
+
const ip = getClientIp(event);
|
|
673
|
+
const rateLimitKey = `login:${ip}`;
|
|
674
|
+
const limited = checkRateLimit(event, rateLimitKey);
|
|
675
|
+
if (limited)
|
|
676
|
+
return limited;
|
|
677
|
+
const body = await readBody(event);
|
|
678
|
+
// Legacy: ACCESS_TOKEN login (for API callers, scripts)
|
|
679
|
+
if (body?.token &&
|
|
680
|
+
typeof body.token === "string" &&
|
|
681
|
+
accessTokens.length > 0) {
|
|
682
|
+
if (!safeTokenMatch(body.token, accessTokens)) {
|
|
683
|
+
setResponseStatus(event, 401);
|
|
684
|
+
return { error: "Invalid token" };
|
|
685
|
+
}
|
|
686
|
+
const sessionToken = crypto.randomBytes(32).toString("hex");
|
|
687
|
+
await addSession(sessionToken, "user");
|
|
688
|
+
setCookie(event, COOKIE_NAME, sessionToken, {
|
|
689
|
+
httpOnly: true,
|
|
690
|
+
secure: process.env.NODE_ENV === "production",
|
|
691
|
+
sameSite: "lax",
|
|
692
|
+
path: "/",
|
|
693
|
+
maxAge: sessionMaxAge,
|
|
694
|
+
});
|
|
695
|
+
resetRateLimit(rateLimitKey);
|
|
696
|
+
return { ok: true };
|
|
697
|
+
}
|
|
698
|
+
// Email/password login
|
|
699
|
+
const email = body?.email?.trim?.()?.toLowerCase?.();
|
|
700
|
+
const password = body?.password;
|
|
701
|
+
if (!email || !password) {
|
|
702
|
+
setResponseStatus(event, 400);
|
|
703
|
+
return { error: "Email and password are required" };
|
|
704
|
+
}
|
|
705
|
+
const valid = await authenticateUser(email, password);
|
|
706
|
+
if (!valid) {
|
|
707
|
+
setResponseStatus(event, 401);
|
|
708
|
+
return { error: "Invalid email or password" };
|
|
709
|
+
}
|
|
710
|
+
const sessionToken = crypto.randomBytes(32).toString("hex");
|
|
711
|
+
await addSession(sessionToken, email);
|
|
712
|
+
setCookie(event, COOKIE_NAME, sessionToken, {
|
|
713
|
+
httpOnly: true,
|
|
714
|
+
secure: process.env.NODE_ENV === "production",
|
|
715
|
+
sameSite: "lax",
|
|
716
|
+
path: "/",
|
|
717
|
+
maxAge: sessionMaxAge,
|
|
718
|
+
});
|
|
719
|
+
resetRateLimit(rateLimitKey);
|
|
720
|
+
return { ok: true };
|
|
721
|
+
}));
|
|
722
|
+
// POST /_agent-native/auth/logout
|
|
723
|
+
app.use("/_agent-native/auth/logout", defineEventHandler(async (event) => {
|
|
724
|
+
const cookie = getCookie(event, COOKIE_NAME);
|
|
725
|
+
if (cookie)
|
|
726
|
+
await removeSession(cookie);
|
|
727
|
+
deleteCookie(event, COOKIE_NAME, { path: "/" });
|
|
728
|
+
return { ok: true };
|
|
729
|
+
}));
|
|
730
|
+
// GET /_agent-native/auth/session
|
|
731
|
+
app.use("/_agent-native/auth/session", defineEventHandler(async (event) => {
|
|
732
|
+
if (getMethod(event) !== "GET") {
|
|
733
|
+
setResponseStatus(event, 405);
|
|
734
|
+
return { error: "Method not allowed" };
|
|
735
|
+
}
|
|
736
|
+
const session = await getSession(event);
|
|
737
|
+
return session ?? { error: "Not authenticated" };
|
|
738
|
+
}));
|
|
739
|
+
// Auth guard
|
|
740
|
+
const loginHtml = EMAIL_AUTH_HTML;
|
|
741
|
+
app.use(defineEventHandler(async (event) => {
|
|
742
|
+
const url = event.node?.req?.url ?? event.path ?? "/";
|
|
743
|
+
const p = url.split("?")[0];
|
|
744
|
+
if (p === "/_agent-native/auth/login" ||
|
|
745
|
+
p === "/_agent-native/auth/logout" ||
|
|
746
|
+
p === "/_agent-native/auth/session" ||
|
|
747
|
+
p === "/_agent-native/auth/register") {
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
if (isPublicPath(url, publicPaths))
|
|
751
|
+
return;
|
|
752
|
+
const session = await getSession(event);
|
|
753
|
+
if (session)
|
|
754
|
+
return;
|
|
755
|
+
if (p.startsWith("/api/") || p.startsWith("/_agent-native/")) {
|
|
756
|
+
setResponseStatus(event, 401);
|
|
757
|
+
return { error: "Unauthorized" };
|
|
758
|
+
}
|
|
759
|
+
setResponseStatus(event, 200);
|
|
760
|
+
setResponseHeader(event, "Content-Type", "text/html");
|
|
761
|
+
return loginHtml;
|
|
762
|
+
}));
|
|
763
|
+
}
|
|
764
|
+
// ---------------------------------------------------------------------------
|
|
305
765
|
// mountAuthMiddleware — mounts login/logout/session routes + auth guard
|
|
306
766
|
// ---------------------------------------------------------------------------
|
|
307
767
|
/**
|
|
@@ -319,12 +779,17 @@ function isPublicPath(url, publicPaths) {
|
|
|
319
779
|
return publicPaths.some((pp) => p === pp || p.startsWith(pp + "/"));
|
|
320
780
|
}
|
|
321
781
|
function mountAuthRoutes(app, accessTokens, publicPaths = []) {
|
|
322
|
-
// POST /
|
|
323
|
-
app.use("/
|
|
782
|
+
// POST /_agent-native/auth/login
|
|
783
|
+
app.use("/_agent-native/auth/login", defineEventHandler(async (event) => {
|
|
324
784
|
if (getMethod(event) !== "POST") {
|
|
325
785
|
setResponseStatus(event, 405);
|
|
326
786
|
return { error: "Method not allowed" };
|
|
327
787
|
}
|
|
788
|
+
const ip = getClientIp(event);
|
|
789
|
+
const rateLimitKey = `login:${ip}`;
|
|
790
|
+
const limited = checkRateLimit(event, rateLimitKey);
|
|
791
|
+
if (limited)
|
|
792
|
+
return limited;
|
|
328
793
|
const body = await readBody(event);
|
|
329
794
|
if (!body?.token ||
|
|
330
795
|
typeof body.token !== "string" ||
|
|
@@ -333,26 +798,27 @@ function mountAuthRoutes(app, accessTokens, publicPaths = []) {
|
|
|
333
798
|
return { error: "Invalid token" };
|
|
334
799
|
}
|
|
335
800
|
const sessionToken = crypto.randomBytes(32).toString("hex");
|
|
336
|
-
await addSession(sessionToken);
|
|
801
|
+
await addSession(sessionToken, "user");
|
|
337
802
|
setCookie(event, COOKIE_NAME, sessionToken, {
|
|
338
803
|
httpOnly: true,
|
|
339
|
-
secure:
|
|
804
|
+
secure: process.env.NODE_ENV === "production",
|
|
340
805
|
sameSite: "lax",
|
|
341
806
|
path: "/",
|
|
342
807
|
maxAge: sessionMaxAge,
|
|
343
808
|
});
|
|
809
|
+
resetRateLimit(rateLimitKey);
|
|
344
810
|
return { ok: true };
|
|
345
811
|
}));
|
|
346
|
-
// POST /
|
|
347
|
-
app.use("/
|
|
812
|
+
// POST /_agent-native/auth/logout
|
|
813
|
+
app.use("/_agent-native/auth/logout", defineEventHandler(async (event) => {
|
|
348
814
|
const cookie = getCookie(event, COOKIE_NAME);
|
|
349
815
|
if (cookie)
|
|
350
816
|
await removeSession(cookie);
|
|
351
817
|
deleteCookie(event, COOKIE_NAME, { path: "/" });
|
|
352
818
|
return { ok: true };
|
|
353
819
|
}));
|
|
354
|
-
// GET /
|
|
355
|
-
app.use("/
|
|
820
|
+
// GET /_agent-native/auth/session — client session check
|
|
821
|
+
app.use("/_agent-native/auth/session", defineEventHandler(async (event) => {
|
|
356
822
|
if (getMethod(event) !== "GET") {
|
|
357
823
|
setResponseStatus(event, 405);
|
|
358
824
|
return { error: "Method not allowed" };
|
|
@@ -365,9 +831,9 @@ function mountAuthRoutes(app, accessTokens, publicPaths = []) {
|
|
|
365
831
|
const url = event.node?.req?.url ?? event.path ?? "/";
|
|
366
832
|
const p = url.split("?")[0];
|
|
367
833
|
// Skip auth routes
|
|
368
|
-
if (p === "/
|
|
369
|
-
p === "/
|
|
370
|
-
p === "/
|
|
834
|
+
if (p === "/_agent-native/auth/login" ||
|
|
835
|
+
p === "/_agent-native/auth/logout" ||
|
|
836
|
+
p === "/_agent-native/auth/session") {
|
|
371
837
|
return;
|
|
372
838
|
}
|
|
373
839
|
// Skip public paths
|
|
@@ -380,7 +846,7 @@ function mountAuthRoutes(app, accessTokens, publicPaths = []) {
|
|
|
380
846
|
return; // Authenticated
|
|
381
847
|
}
|
|
382
848
|
// Unauthenticated
|
|
383
|
-
if (p.startsWith("/api/")) {
|
|
849
|
+
if (p.startsWith("/api/") || p.startsWith("/_agent-native/")) {
|
|
384
850
|
setResponseStatus(event, 401);
|
|
385
851
|
return { error: "Unauthorized" };
|
|
386
852
|
}
|
|
@@ -431,23 +897,23 @@ export function autoMountAuth(app, options = {}) {
|
|
|
431
897
|
}
|
|
432
898
|
// Dev mode — skip auth entirely
|
|
433
899
|
if (isDevMode()) {
|
|
434
|
-
// Mount a session endpoint that
|
|
435
|
-
app.use("/
|
|
900
|
+
// Mount a session endpoint that checks for a real session first
|
|
901
|
+
app.use("/_agent-native/auth/session", defineEventHandler(async (event) => {
|
|
436
902
|
if (getMethod(event) !== "GET") {
|
|
437
903
|
setResponseStatus(event, 405);
|
|
438
904
|
return { error: "Method not allowed" };
|
|
439
905
|
}
|
|
440
|
-
return
|
|
906
|
+
return await getSession(event);
|
|
441
907
|
}));
|
|
442
908
|
// Mount no-op login/logout so client code doesn't break
|
|
443
|
-
app.use("/
|
|
444
|
-
app.use("/
|
|
909
|
+
app.use("/_agent-native/auth/login", defineEventHandler(() => ({ ok: true })));
|
|
910
|
+
app.use("/_agent-native/auth/logout", defineEventHandler(() => ({ ok: true })));
|
|
445
911
|
return false;
|
|
446
912
|
}
|
|
447
913
|
// BYOA with custom getSession — skip token check, mount session/guard routes
|
|
448
914
|
if (customGetSession) {
|
|
449
915
|
// Mount session endpoint
|
|
450
|
-
app.use("/
|
|
916
|
+
app.use("/_agent-native/auth/session", defineEventHandler(async (event) => {
|
|
451
917
|
if (getMethod(event) !== "GET") {
|
|
452
918
|
setResponseStatus(event, 405);
|
|
453
919
|
return { error: "Method not allowed" };
|
|
@@ -455,8 +921,8 @@ export function autoMountAuth(app, options = {}) {
|
|
|
455
921
|
const session = await getSession(event);
|
|
456
922
|
return session ?? { error: "Not authenticated" };
|
|
457
923
|
}));
|
|
458
|
-
app.use("/
|
|
459
|
-
app.use("/
|
|
924
|
+
app.use("/_agent-native/auth/login", defineEventHandler(() => ({ ok: true })));
|
|
925
|
+
app.use("/_agent-native/auth/logout", defineEventHandler(async (event) => {
|
|
460
926
|
const cookie = getCookie(event, COOKIE_NAME);
|
|
461
927
|
if (cookie)
|
|
462
928
|
await removeSession(cookie);
|
|
@@ -469,9 +935,9 @@ export function autoMountAuth(app, options = {}) {
|
|
|
469
935
|
// Use H3's getRequestURL for cross-platform compat (Node + Workers)
|
|
470
936
|
const url = event.node?.req?.url ?? event.path ?? "/";
|
|
471
937
|
const p = url.split("?")[0];
|
|
472
|
-
if (p === "/
|
|
473
|
-
p === "/
|
|
474
|
-
p === "/
|
|
938
|
+
if (p === "/_agent-native/auth/login" ||
|
|
939
|
+
p === "/_agent-native/auth/logout" ||
|
|
940
|
+
p === "/_agent-native/auth/session") {
|
|
475
941
|
return;
|
|
476
942
|
}
|
|
477
943
|
// Skip public paths
|
|
@@ -481,7 +947,7 @@ export function autoMountAuth(app, options = {}) {
|
|
|
481
947
|
const session = await getSession(event);
|
|
482
948
|
if (session)
|
|
483
949
|
return;
|
|
484
|
-
if (p.startsWith("/api/")) {
|
|
950
|
+
if (p.startsWith("/api/") || p.startsWith("/_agent-native/")) {
|
|
485
951
|
setResponseStatus(event, 401);
|
|
486
952
|
return { error: "Unauthorized" };
|
|
487
953
|
}
|
|
@@ -500,30 +966,23 @@ export function autoMountAuth(app, options = {}) {
|
|
|
500
966
|
authDisabledMode = true;
|
|
501
967
|
console.warn("[agent-native] AUTH_DISABLED=true — running in production without auth. " +
|
|
502
968
|
"Ensure this app is behind infrastructure-level auth (Cloudflare Access, VPN, etc.).");
|
|
503
|
-
// Mount session endpoint
|
|
504
|
-
app.use("/
|
|
969
|
+
// Mount session endpoint
|
|
970
|
+
app.use("/_agent-native/auth/session", defineEventHandler(async (event) => {
|
|
505
971
|
if (getMethod(event) !== "GET") {
|
|
506
972
|
setResponseStatus(event, 405);
|
|
507
973
|
return { error: "Method not allowed" };
|
|
508
974
|
}
|
|
509
|
-
return
|
|
975
|
+
return await getSession(event);
|
|
510
976
|
}));
|
|
511
|
-
app.use("/
|
|
512
|
-
app.use("/
|
|
977
|
+
app.use("/_agent-native/auth/login", defineEventHandler(() => ({ ok: true })));
|
|
978
|
+
app.use("/_agent-native/auth/logout", defineEventHandler(() => ({ ok: true })));
|
|
513
979
|
return false;
|
|
514
980
|
}
|
|
515
|
-
//
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
" Set ACCESS_TOKEN=<your-secret> to enable auth, or\n" +
|
|
521
|
-
" set AUTH_DISABLED=true if this app is behind infrastructure auth.\n\n" +
|
|
522
|
-
" For multi-user access: ACCESS_TOKENS=token1,token2,token3\n" +
|
|
523
|
-
"=".repeat(70) +
|
|
524
|
-
"\n";
|
|
525
|
-
console.error(msg);
|
|
526
|
-
process.exit(1);
|
|
981
|
+
// No access tokens set — enable email/password authentication
|
|
982
|
+
pruneExpiredSessions().catch(() => { });
|
|
983
|
+
mountEmailAuthRoutes(app, publicPaths);
|
|
984
|
+
console.log("[agent-native] Auth enabled — email/password authentication.");
|
|
985
|
+
return true;
|
|
527
986
|
}
|
|
528
987
|
// Production with tokens — mount auth
|
|
529
988
|
pruneExpiredSessions().catch(() => { });
|