@agent-native/core 0.4.4 → 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 +326 -107
- 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 -38
- 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 +42 -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 +14 -3
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +492 -21
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +27 -3
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +639 -57
- 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 -67
- 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.d.ts +2 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +2 -2
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/analytics.d.ts +16 -0
- package/dist/client/analytics.d.ts.map +1 -0
- package/dist/client/analytics.js +17 -0
- package/dist/client/analytics.js.map +1 -0
- 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 +13 -0
- package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -0
- package/dist/client/components/CodeRequiredDialog.js +160 -0
- package/dist/client/components/CodeRequiredDialog.js.map +1 -0
- 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 +13 -4
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +12 -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 +12 -7
- 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 +11 -0
- package/dist/client/use-dev-mode.d.ts.map +1 -0
- package/dist/client/use-dev-mode.js +71 -0
- package/dist/client/use-dev-mode.js.map +1 -0
- 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-send-to-agent-chat.d.ts +17 -0
- package/dist/client/use-send-to-agent-chat.d.ts.map +1 -0
- package/dist/client/use-send-to-agent-chat.js +40 -0
- package/dist/client/use-send-to-agent-chat.js.map +1 -0
- package/dist/client/use-session.d.ts +1 -1
- package/dist/client/use-session.d.ts.map +1 -1
- package/dist/client/use-session.js +13 -4
- 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 +108 -12
- 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 +52 -21
- 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.d.ts +16 -0
- package/dist/deploy/build.d.ts.map +1 -0
- package/dist/deploy/build.js +453 -0
- package/dist/deploy/build.js.map +1 -0
- package/dist/deploy/route-discovery.d.ts +43 -0
- package/dist/deploy/route-discovery.d.ts.map +1 -0
- package/dist/deploy/route-discovery.js +115 -0
- package/dist/deploy/route-discovery.js.map +1 -0
- 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/index.d.ts +1 -1
- package/dist/oauth-tokens/index.d.ts.map +1 -1
- package/dist/oauth-tokens/index.js +1 -1
- package/dist/oauth-tokens/index.js.map +1 -1
- package/dist/oauth-tokens/store.d.ts +18 -1
- package/dist/oauth-tokens/store.d.ts.map +1 -1
- package/dist/oauth-tokens/store.js +81 -40
- 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 +1102 -39
- 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/analytics.d.ts +19 -0
- package/dist/server/analytics.d.ts.map +1 -0
- package/dist/server/analytics.js +61 -0
- package/dist/server/analytics.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 +598 -104
- 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.d.ts.map +1 -1
- package/dist/server/google-auth-plugin.js +4 -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 +10 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +9 -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 -36
- package/dist/settings/store.js.map +1 -1
- package/dist/settings/user-settings.d.ts +6 -10
- package/dist/settings/user-settings.d.ts.map +1 -1
- package/dist/settings/user-settings.js +9 -18
- 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 +3 -1
- package/dist/terminal/cli-registry.d.ts.map +1 -1
- package/dist/terminal/cli-registry.js +10 -5
- 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 -8
- 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 +23 -7
- 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/entry.server.tsx +2 -1
- package/src/templates/default/app/global.css +2 -2
- package/src/templates/default/app/root.tsx +27 -15
- package/src/templates/default/app/routes/_index.tsx +1 -1
- package/src/templates/default/package.json +4 -0
- package/src/templates/default/public/icon-180.svg +4 -0
- package/src/templates/default/public/icon-192.svg +4 -0
- package/src/templates/default/public/icon-512.svg +4 -0
- package/src/templates/default/public/manifest.json +13 -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,55 +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 getSessionClient() {
|
|
18
|
-
if (!_sessionClient) {
|
|
19
|
-
const url = process.env.DATABASE_URL || "file:./data/app.db";
|
|
20
|
-
if (url.startsWith("file:")) {
|
|
21
|
-
fs.mkdirSync(path.join(process.cwd(), "data"), { recursive: true });
|
|
22
|
-
}
|
|
23
|
-
_sessionClient = createClient({
|
|
24
|
-
url,
|
|
25
|
-
authToken: process.env.DATABASE_AUTH_TOKEN,
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
return _sessionClient;
|
|
29
|
-
}
|
|
30
55
|
async function ensureSessionTable() {
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
67
|
+
try {
|
|
68
|
+
await client.execute(`ALTER TABLE sessions ADD COLUMN email TEXT`);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Column already exists — ignore
|
|
72
|
+
}
|
|
73
|
+
})();
|
|
47
74
|
}
|
|
48
|
-
|
|
75
|
+
return _sessionInitPromise;
|
|
49
76
|
}
|
|
50
77
|
async function pruneExpiredSessions() {
|
|
51
78
|
await ensureSessionTable();
|
|
52
|
-
const client =
|
|
79
|
+
const client = getDbExec();
|
|
53
80
|
const cutoff = Date.now() - sessionMaxAge * 1000;
|
|
54
81
|
await client.execute({
|
|
55
82
|
sql: `DELETE FROM sessions WHERE created_at < ?`,
|
|
@@ -62,16 +89,18 @@ async function pruneExpiredSessions() {
|
|
|
62
89
|
*/
|
|
63
90
|
export async function addSession(token, email) {
|
|
64
91
|
await ensureSessionTable();
|
|
65
|
-
const client =
|
|
92
|
+
const client = getDbExec();
|
|
66
93
|
await client.execute({
|
|
67
|
-
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 (?, ?, ?)`,
|
|
68
97
|
args: [token, email ?? null, Date.now()],
|
|
69
98
|
});
|
|
70
99
|
}
|
|
71
100
|
/** Remove a session by token. */
|
|
72
101
|
export async function removeSession(token) {
|
|
73
102
|
await ensureSessionTable();
|
|
74
|
-
const client =
|
|
103
|
+
const client = getDbExec();
|
|
75
104
|
await client.execute({
|
|
76
105
|
sql: `DELETE FROM sessions WHERE token = ?`,
|
|
77
106
|
args: [token],
|
|
@@ -83,7 +112,7 @@ export async function removeSession(token) {
|
|
|
83
112
|
*/
|
|
84
113
|
export async function getSessionEmail(token) {
|
|
85
114
|
await ensureSessionTable();
|
|
86
|
-
const client =
|
|
115
|
+
const client = getDbExec();
|
|
87
116
|
const { rows } = await client.execute({
|
|
88
117
|
sql: `SELECT email, created_at FROM sessions WHERE token = ?`,
|
|
89
118
|
args: [token],
|
|
@@ -102,7 +131,7 @@ export async function getSessionEmail(token) {
|
|
|
102
131
|
}
|
|
103
132
|
async function hasSession(token) {
|
|
104
133
|
await ensureSessionTable();
|
|
105
|
-
const client =
|
|
134
|
+
const client = getDbExec();
|
|
106
135
|
const { rows } = await client.execute({
|
|
107
136
|
sql: `SELECT created_at FROM sessions WHERE token = ?`,
|
|
108
137
|
args: [token],
|
|
@@ -141,7 +170,10 @@ function getAccessTokens() {
|
|
|
141
170
|
// Dev mode detection
|
|
142
171
|
// ---------------------------------------------------------------------------
|
|
143
172
|
function isDevMode() {
|
|
144
|
-
|
|
173
|
+
// On edge runtimes (e.g. CF Workers), NODE_ENV may not be set.
|
|
174
|
+
// Treat undefined as production — dev mode must be explicitly opted in.
|
|
175
|
+
const env = process.env.NODE_ENV;
|
|
176
|
+
return env === "development" || env === "test";
|
|
145
177
|
}
|
|
146
178
|
// ---------------------------------------------------------------------------
|
|
147
179
|
// getSession — the auth contract
|
|
@@ -152,20 +184,61 @@ const DEV_SESSION = { email: "local@localhost" };
|
|
|
152
184
|
/**
|
|
153
185
|
* Get the current auth session for a request.
|
|
154
186
|
*
|
|
155
|
-
* - 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.
|
|
156
190
|
* - In production with built-in auth: returns session if cookie is valid
|
|
157
191
|
* - With custom auth (BYOA): delegates to the custom getSession
|
|
158
192
|
*/
|
|
159
193
|
export async function getSession(event) {
|
|
160
|
-
if (isDevMode())
|
|
161
|
-
|
|
162
|
-
|
|
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
|
+
}
|
|
163
208
|
return DEV_SESSION;
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
+
}
|
|
169
242
|
}
|
|
170
243
|
return null;
|
|
171
244
|
}
|
|
@@ -184,6 +257,102 @@ function safeTokenMatch(input, tokens) {
|
|
|
184
257
|
return false;
|
|
185
258
|
}
|
|
186
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
|
+
// ---------------------------------------------------------------------------
|
|
187
356
|
// Login page HTML
|
|
188
357
|
// ---------------------------------------------------------------------------
|
|
189
358
|
const LOGIN_HTML = `<!DOCTYPE html>
|
|
@@ -257,7 +426,7 @@ const LOGIN_HTML = `<!DOCTYPE html>
|
|
|
257
426
|
document.getElementById('form').addEventListener('submit', async (e) => {
|
|
258
427
|
e.preventDefault();
|
|
259
428
|
const token = document.getElementById('token').value;
|
|
260
|
-
const res = await fetch('/
|
|
429
|
+
const res = await fetch('/_agent-native/auth/login', {
|
|
261
430
|
method: 'POST',
|
|
262
431
|
headers: { 'Content-Type': 'application/json' },
|
|
263
432
|
body: JSON.stringify({ token }),
|
|
@@ -272,6 +441,327 @@ const LOGIN_HTML = `<!DOCTYPE html>
|
|
|
272
441
|
</body>
|
|
273
442
|
</html>`;
|
|
274
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
|
+
// ---------------------------------------------------------------------------
|
|
275
765
|
// mountAuthMiddleware — mounts login/logout/session routes + auth guard
|
|
276
766
|
// ---------------------------------------------------------------------------
|
|
277
767
|
/**
|
|
@@ -289,12 +779,17 @@ function isPublicPath(url, publicPaths) {
|
|
|
289
779
|
return publicPaths.some((pp) => p === pp || p.startsWith(pp + "/"));
|
|
290
780
|
}
|
|
291
781
|
function mountAuthRoutes(app, accessTokens, publicPaths = []) {
|
|
292
|
-
// POST /
|
|
293
|
-
app.use("/
|
|
782
|
+
// POST /_agent-native/auth/login
|
|
783
|
+
app.use("/_agent-native/auth/login", defineEventHandler(async (event) => {
|
|
294
784
|
if (getMethod(event) !== "POST") {
|
|
295
785
|
setResponseStatus(event, 405);
|
|
296
786
|
return { error: "Method not allowed" };
|
|
297
787
|
}
|
|
788
|
+
const ip = getClientIp(event);
|
|
789
|
+
const rateLimitKey = `login:${ip}`;
|
|
790
|
+
const limited = checkRateLimit(event, rateLimitKey);
|
|
791
|
+
if (limited)
|
|
792
|
+
return limited;
|
|
298
793
|
const body = await readBody(event);
|
|
299
794
|
if (!body?.token ||
|
|
300
795
|
typeof body.token !== "string" ||
|
|
@@ -303,26 +798,27 @@ function mountAuthRoutes(app, accessTokens, publicPaths = []) {
|
|
|
303
798
|
return { error: "Invalid token" };
|
|
304
799
|
}
|
|
305
800
|
const sessionToken = crypto.randomBytes(32).toString("hex");
|
|
306
|
-
await addSession(sessionToken);
|
|
801
|
+
await addSession(sessionToken, "user");
|
|
307
802
|
setCookie(event, COOKIE_NAME, sessionToken, {
|
|
308
803
|
httpOnly: true,
|
|
309
|
-
secure:
|
|
804
|
+
secure: process.env.NODE_ENV === "production",
|
|
310
805
|
sameSite: "lax",
|
|
311
806
|
path: "/",
|
|
312
807
|
maxAge: sessionMaxAge,
|
|
313
808
|
});
|
|
809
|
+
resetRateLimit(rateLimitKey);
|
|
314
810
|
return { ok: true };
|
|
315
811
|
}));
|
|
316
|
-
// POST /
|
|
317
|
-
app.use("/
|
|
812
|
+
// POST /_agent-native/auth/logout
|
|
813
|
+
app.use("/_agent-native/auth/logout", defineEventHandler(async (event) => {
|
|
318
814
|
const cookie = getCookie(event, COOKIE_NAME);
|
|
319
815
|
if (cookie)
|
|
320
816
|
await removeSession(cookie);
|
|
321
817
|
deleteCookie(event, COOKIE_NAME, { path: "/" });
|
|
322
818
|
return { ok: true };
|
|
323
819
|
}));
|
|
324
|
-
// GET /
|
|
325
|
-
app.use("/
|
|
820
|
+
// GET /_agent-native/auth/session — client session check
|
|
821
|
+
app.use("/_agent-native/auth/session", defineEventHandler(async (event) => {
|
|
326
822
|
if (getMethod(event) !== "GET") {
|
|
327
823
|
setResponseStatus(event, 405);
|
|
328
824
|
return { error: "Method not allowed" };
|
|
@@ -332,12 +828,12 @@ function mountAuthRoutes(app, accessTokens, publicPaths = []) {
|
|
|
332
828
|
}));
|
|
333
829
|
// Auth guard — runs before all other handlers
|
|
334
830
|
app.use(defineEventHandler(async (event) => {
|
|
335
|
-
const url = event.node
|
|
831
|
+
const url = event.node?.req?.url ?? event.path ?? "/";
|
|
336
832
|
const p = url.split("?")[0];
|
|
337
833
|
// Skip auth routes
|
|
338
|
-
if (p === "/
|
|
339
|
-
p === "/
|
|
340
|
-
p === "/
|
|
834
|
+
if (p === "/_agent-native/auth/login" ||
|
|
835
|
+
p === "/_agent-native/auth/logout" ||
|
|
836
|
+
p === "/_agent-native/auth/session") {
|
|
341
837
|
return;
|
|
342
838
|
}
|
|
343
839
|
// Skip public paths
|
|
@@ -350,14 +846,13 @@ function mountAuthRoutes(app, accessTokens, publicPaths = []) {
|
|
|
350
846
|
return; // Authenticated
|
|
351
847
|
}
|
|
352
848
|
// Unauthenticated
|
|
353
|
-
if (p.startsWith("/api/")) {
|
|
849
|
+
if (p.startsWith("/api/") || p.startsWith("/_agent-native/")) {
|
|
354
850
|
setResponseStatus(event, 401);
|
|
355
|
-
|
|
356
|
-
event.node.res.end(JSON.stringify({ error: "Unauthorized" }));
|
|
357
|
-
return;
|
|
851
|
+
return { error: "Unauthorized" };
|
|
358
852
|
}
|
|
853
|
+
setResponseStatus(event, 200);
|
|
359
854
|
setResponseHeader(event, "Content-Type", "text/html");
|
|
360
|
-
|
|
855
|
+
return LOGIN_HTML;
|
|
361
856
|
}));
|
|
362
857
|
}
|
|
363
858
|
// ---------------------------------------------------------------------------
|
|
@@ -402,23 +897,23 @@ export function autoMountAuth(app, options = {}) {
|
|
|
402
897
|
}
|
|
403
898
|
// Dev mode — skip auth entirely
|
|
404
899
|
if (isDevMode()) {
|
|
405
|
-
// Mount a session endpoint that
|
|
406
|
-
app.use("/
|
|
900
|
+
// Mount a session endpoint that checks for a real session first
|
|
901
|
+
app.use("/_agent-native/auth/session", defineEventHandler(async (event) => {
|
|
407
902
|
if (getMethod(event) !== "GET") {
|
|
408
903
|
setResponseStatus(event, 405);
|
|
409
904
|
return { error: "Method not allowed" };
|
|
410
905
|
}
|
|
411
|
-
return
|
|
906
|
+
return await getSession(event);
|
|
412
907
|
}));
|
|
413
908
|
// Mount no-op login/logout so client code doesn't break
|
|
414
|
-
app.use("/
|
|
415
|
-
app.use("/
|
|
909
|
+
app.use("/_agent-native/auth/login", defineEventHandler(() => ({ ok: true })));
|
|
910
|
+
app.use("/_agent-native/auth/logout", defineEventHandler(() => ({ ok: true })));
|
|
416
911
|
return false;
|
|
417
912
|
}
|
|
418
913
|
// BYOA with custom getSession — skip token check, mount session/guard routes
|
|
419
914
|
if (customGetSession) {
|
|
420
915
|
// Mount session endpoint
|
|
421
|
-
app.use("/
|
|
916
|
+
app.use("/_agent-native/auth/session", defineEventHandler(async (event) => {
|
|
422
917
|
if (getMethod(event) !== "GET") {
|
|
423
918
|
setResponseStatus(event, 405);
|
|
424
919
|
return { error: "Method not allowed" };
|
|
@@ -426,16 +921,23 @@ export function autoMountAuth(app, options = {}) {
|
|
|
426
921
|
const session = await getSession(event);
|
|
427
922
|
return session ?? { error: "Not authenticated" };
|
|
428
923
|
}));
|
|
429
|
-
app.use("/
|
|
430
|
-
app.use("/
|
|
924
|
+
app.use("/_agent-native/auth/login", defineEventHandler(() => ({ ok: true })));
|
|
925
|
+
app.use("/_agent-native/auth/logout", defineEventHandler(async (event) => {
|
|
926
|
+
const cookie = getCookie(event, COOKIE_NAME);
|
|
927
|
+
if (cookie)
|
|
928
|
+
await removeSession(cookie);
|
|
929
|
+
deleteCookie(event, COOKIE_NAME, { path: "/" });
|
|
930
|
+
return { ok: true };
|
|
931
|
+
}));
|
|
431
932
|
// Mount auth guard that delegates to custom getSession
|
|
432
933
|
const byoaLoginHtml = options.loginHtml ?? LOGIN_HTML;
|
|
433
934
|
app.use(defineEventHandler(async (event) => {
|
|
434
|
-
|
|
935
|
+
// Use H3's getRequestURL for cross-platform compat (Node + Workers)
|
|
936
|
+
const url = event.node?.req?.url ?? event.path ?? "/";
|
|
435
937
|
const p = url.split("?")[0];
|
|
436
|
-
if (p === "/
|
|
437
|
-
p === "/
|
|
438
|
-
p === "/
|
|
938
|
+
if (p === "/_agent-native/auth/login" ||
|
|
939
|
+
p === "/_agent-native/auth/logout" ||
|
|
940
|
+
p === "/_agent-native/auth/session") {
|
|
439
941
|
return;
|
|
440
942
|
}
|
|
441
943
|
// Skip public paths
|
|
@@ -445,14 +947,13 @@ export function autoMountAuth(app, options = {}) {
|
|
|
445
947
|
const session = await getSession(event);
|
|
446
948
|
if (session)
|
|
447
949
|
return;
|
|
448
|
-
if (p.startsWith("/api/")) {
|
|
950
|
+
if (p.startsWith("/api/") || p.startsWith("/_agent-native/")) {
|
|
449
951
|
setResponseStatus(event, 401);
|
|
450
|
-
|
|
451
|
-
event.node.res.end(JSON.stringify({ error: "Unauthorized" }));
|
|
452
|
-
return;
|
|
952
|
+
return { error: "Unauthorized" };
|
|
453
953
|
}
|
|
954
|
+
setResponseStatus(event, 200);
|
|
454
955
|
setResponseHeader(event, "Content-Type", "text/html");
|
|
455
|
-
|
|
956
|
+
return byoaLoginHtml;
|
|
456
957
|
}));
|
|
457
958
|
console.log("[agent-native] Auth enabled — custom getSession provider.");
|
|
458
959
|
return true;
|
|
@@ -465,30 +966,23 @@ export function autoMountAuth(app, options = {}) {
|
|
|
465
966
|
authDisabledMode = true;
|
|
466
967
|
console.warn("[agent-native] AUTH_DISABLED=true — running in production without auth. " +
|
|
467
968
|
"Ensure this app is behind infrastructure-level auth (Cloudflare Access, VPN, etc.).");
|
|
468
|
-
// Mount session endpoint
|
|
469
|
-
app.use("/
|
|
969
|
+
// Mount session endpoint
|
|
970
|
+
app.use("/_agent-native/auth/session", defineEventHandler(async (event) => {
|
|
470
971
|
if (getMethod(event) !== "GET") {
|
|
471
972
|
setResponseStatus(event, 405);
|
|
472
973
|
return { error: "Method not allowed" };
|
|
473
974
|
}
|
|
474
|
-
return
|
|
975
|
+
return await getSession(event);
|
|
475
976
|
}));
|
|
476
|
-
app.use("/
|
|
477
|
-
app.use("/
|
|
977
|
+
app.use("/_agent-native/auth/login", defineEventHandler(() => ({ ok: true })));
|
|
978
|
+
app.use("/_agent-native/auth/logout", defineEventHandler(() => ({ ok: true })));
|
|
478
979
|
return false;
|
|
479
980
|
}
|
|
480
|
-
//
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
" Set ACCESS_TOKEN=<your-secret> to enable auth, or\n" +
|
|
486
|
-
" set AUTH_DISABLED=true if this app is behind infrastructure auth.\n\n" +
|
|
487
|
-
" For multi-user access: ACCESS_TOKENS=token1,token2,token3\n" +
|
|
488
|
-
"=".repeat(70) +
|
|
489
|
-
"\n";
|
|
490
|
-
console.error(msg);
|
|
491
|
-
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;
|
|
492
986
|
}
|
|
493
987
|
// Production with tokens — mount auth
|
|
494
988
|
pruneExpiredSessions().catch(() => { });
|