@agent-native/core 0.15.13 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/agent/app-model-defaults.d.ts +37 -0
- package/dist/agent/app-model-defaults.d.ts.map +1 -0
- package/dist/agent/app-model-defaults.js +136 -0
- package/dist/agent/app-model-defaults.js.map +1 -0
- package/dist/agent/engine/registry.d.ts +12 -7
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +28 -8
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/production-agent.d.ts +2 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +3 -1
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/browser-sessions/actions.d.ts +7 -0
- package/dist/browser-sessions/actions.d.ts.map +1 -0
- package/dist/browser-sessions/actions.js +223 -0
- package/dist/browser-sessions/actions.js.map +1 -0
- package/dist/browser-sessions/routes.d.ts +7 -0
- package/dist/browser-sessions/routes.d.ts.map +1 -0
- package/dist/browser-sessions/routes.js +159 -0
- package/dist/browser-sessions/routes.js.map +1 -0
- package/dist/browser-sessions/store.d.ts +33 -0
- package/dist/browser-sessions/store.d.ts.map +1 -0
- package/dist/browser-sessions/store.js +506 -0
- package/dist/browser-sessions/store.js.map +1 -0
- package/dist/browser-sessions/types.d.ts +68 -0
- package/dist/browser-sessions/types.d.ts.map +1 -0
- package/dist/browser-sessions/types.js +2 -0
- package/dist/browser-sessions/types.js.map +1 -0
- package/dist/cli/code-agent-commands.d.ts +36 -0
- package/dist/cli/code-agent-commands.d.ts.map +1 -0
- package/dist/cli/code-agent-commands.js +192 -0
- package/dist/cli/code-agent-commands.js.map +1 -0
- package/dist/cli/code-agent-connector.d.ts +17 -0
- package/dist/cli/code-agent-connector.d.ts.map +1 -0
- package/dist/cli/code-agent-connector.js +724 -0
- package/dist/cli/code-agent-connector.js.map +1 -0
- package/dist/cli/code-agent-executor.d.ts +31 -0
- package/dist/cli/code-agent-executor.d.ts.map +1 -0
- package/dist/cli/code-agent-executor.js +921 -0
- package/dist/cli/code-agent-executor.js.map +1 -0
- package/dist/cli/code-agent-runs.d.ts +102 -0
- package/dist/cli/code-agent-runs.d.ts.map +1 -0
- package/dist/cli/code-agent-runs.js +277 -0
- package/dist/cli/code-agent-runs.js.map +1 -0
- package/dist/cli/code.d.ts +66 -0
- package/dist/cli/code.d.ts.map +1 -0
- package/dist/cli/code.js +1306 -0
- package/dist/cli/code.js.map +1 -0
- package/dist/cli/create.d.ts +2 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +11 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +26 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.d.ts +27 -0
- package/dist/cli/migrate.d.ts.map +1 -1
- package/dist/cli/migrate.js +1328 -20
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +26 -2
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/cli/workspacify.d.ts +2 -0
- package/dist/cli/workspacify.d.ts.map +1 -1
- package/dist/cli/workspacify.js +2 -1
- package/dist/cli/workspacify.js.map +1 -1
- package/dist/client/AgentNative.d.ts +32 -0
- package/dist/client/AgentNative.d.ts.map +1 -0
- package/dist/client/AgentNative.js +79 -0
- package/dist/client/AgentNative.js.map +1 -0
- package/dist/client/AgentNativeEmbedded.d.ts +47 -0
- package/dist/client/AgentNativeEmbedded.d.ts.map +1 -0
- package/dist/client/AgentNativeEmbedded.js +148 -0
- package/dist/client/AgentNativeEmbedded.js.map +1 -0
- package/dist/client/AgentNativeFrame.d.ts +25 -0
- package/dist/client/AgentNativeFrame.d.ts.map +1 -0
- package/dist/client/AgentNativeFrame.js +68 -0
- package/dist/client/AgentNativeFrame.js.map +1 -0
- package/dist/client/AgentPanel.d.ts +19 -2
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +15 -4
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +79 -48
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +2 -1
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.js +3 -2
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
- package/dist/client/browser-session-bridge.d.ts +44 -0
- package/dist/client/browser-session-bridge.d.ts.map +1 -0
- package/dist/client/browser-session-bridge.js +339 -0
- package/dist/client/browser-session-bridge.js.map +1 -0
- package/dist/client/client-action.d.ts +7 -0
- package/dist/client/client-action.d.ts.map +1 -0
- package/dist/client/client-action.js +4 -0
- package/dist/client/client-action.js.map +1 -0
- package/dist/client/components/ui/tooltip.d.ts.map +1 -1
- package/dist/client/components/ui/tooltip.js +1 -1
- package/dist/client/components/ui/tooltip.js.map +1 -1
- package/dist/client/composer/AgentComposerFrame.d.ts +17 -0
- package/dist/client/composer/AgentComposerFrame.d.ts.map +1 -0
- package/dist/client/composer/AgentComposerFrame.js +14 -0
- package/dist/client/composer/AgentComposerFrame.js.map +1 -0
- package/dist/client/composer/MentionPopover.d.ts.map +1 -1
- package/dist/client/composer/MentionPopover.js +2 -2
- package/dist/client/composer/MentionPopover.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts +35 -2
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +31 -17
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +20 -2
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +112 -22
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/index.d.ts +3 -2
- package/dist/client/composer/index.d.ts.map +1 -1
- package/dist/client/composer/index.js +1 -0
- package/dist/client/composer/index.js.map +1 -1
- package/dist/client/composer/types.d.ts +1 -0
- package/dist/client/composer/types.d.ts.map +1 -1
- package/dist/client/composer/types.js.map +1 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.d.ts +58 -0
- package/dist/client/extensions/AgentNativeExtensionFrame.d.ts.map +1 -0
- package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.d.ts +2 -0
- package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.d.ts.map +1 -0
- package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.js +110 -0
- package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.js.map +1 -0
- package/dist/client/extensions/AgentNativeExtensionFrame.js +354 -0
- package/dist/client/extensions/AgentNativeExtensionFrame.js.map +1 -0
- package/dist/client/extensions/AgentNativeExtensionFrame.spec.d.ts +2 -0
- package/dist/client/extensions/AgentNativeExtensionFrame.spec.d.ts.map +1 -0
- package/dist/client/extensions/AgentNativeExtensionFrame.spec.js +68 -0
- package/dist/client/extensions/AgentNativeExtensionFrame.spec.js.map +1 -0
- package/dist/client/extensions/agent-native-extension-runtime.d.ts +69 -0
- package/dist/client/extensions/agent-native-extension-runtime.d.ts.map +1 -0
- package/dist/client/extensions/agent-native-extension-runtime.js +348 -0
- package/dist/client/extensions/agent-native-extension-runtime.js.map +1 -0
- package/dist/client/extensions/index.d.ts +2 -0
- package/dist/client/extensions/index.d.ts.map +1 -1
- package/dist/client/extensions/index.js +2 -0
- package/dist/client/extensions/index.js.map +1 -1
- package/dist/client/extensions/portable-extension.d.ts +86 -0
- package/dist/client/extensions/portable-extension.d.ts.map +1 -0
- package/dist/client/extensions/portable-extension.js +480 -0
- package/dist/client/extensions/portable-extension.js.map +1 -0
- package/dist/client/host-bridge.d.ts +266 -0
- package/dist/client/host-bridge.d.ts.map +1 -0
- package/dist/client/host-bridge.js +745 -0
- package/dist/client/host-bridge.js.map +1 -0
- package/dist/client/host-tools.d.ts +40 -0
- package/dist/client/host-tools.d.ts.map +1 -0
- package/dist/client/host-tools.js +94 -0
- package/dist/client/host-tools.js.map +1 -0
- package/dist/client/index.d.ts +13 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +11 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/resources/BuiltinCapabilityDetail.d.ts +10 -0
- package/dist/client/resources/BuiltinCapabilityDetail.d.ts.map +1 -0
- package/dist/client/resources/BuiltinCapabilityDetail.js +51 -0
- package/dist/client/resources/BuiltinCapabilityDetail.js.map +1 -0
- package/dist/client/resources/ResourceEditor.d.ts +3 -1
- package/dist/client/resources/ResourceEditor.d.ts.map +1 -1
- package/dist/client/resources/ResourceEditor.js +40 -17
- package/dist/client/resources/ResourceEditor.js.map +1 -1
- package/dist/client/resources/ResourceTree.d.ts.map +1 -1
- package/dist/client/resources/ResourceTree.js +23 -2
- package/dist/client/resources/ResourceTree.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +77 -17
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/resources/index.d.ts +1 -0
- package/dist/client/resources/index.d.ts.map +1 -1
- package/dist/client/resources/index.js +1 -0
- package/dist/client/resources/index.js.map +1 -1
- package/dist/client/resources/use-builtin-capabilities.d.ts +62 -0
- package/dist/client/resources/use-builtin-capabilities.d.ts.map +1 -0
- package/dist/client/resources/use-builtin-capabilities.js +54 -0
- package/dist/client/resources/use-builtin-capabilities.js.map +1 -0
- package/dist/client/resources/use-resources.d.ts +30 -2
- package/dist/client/resources/use-resources.d.ts.map +1 -1
- package/dist/client/resources/use-resources.js +42 -1
- package/dist/client/resources/use-resources.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +151 -2
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/use-chat-models.d.ts.map +1 -1
- package/dist/client/use-chat-models.js +20 -0
- package/dist/client/use-chat-models.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +46 -2
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/use-chat-threads.spec.js +77 -0
- package/dist/client/use-chat-threads.spec.js.map +1 -1
- package/dist/code-agents/index.d.ts +4 -0
- package/dist/code-agents/index.d.ts.map +1 -0
- package/dist/code-agents/index.js +4 -0
- package/dist/code-agents/index.js.map +1 -0
- package/dist/connections/catalog.d.ts +134 -0
- package/dist/connections/catalog.d.ts.map +1 -0
- package/dist/connections/catalog.js +180 -0
- package/dist/connections/catalog.js.map +1 -0
- package/dist/connections/index.d.ts +2 -0
- package/dist/connections/index.d.ts.map +1 -0
- package/dist/connections/index.js +2 -0
- package/dist/connections/index.js.map +1 -0
- package/dist/extensions/change-marker.d.ts +10 -0
- package/dist/extensions/change-marker.d.ts.map +1 -0
- package/dist/extensions/change-marker.js +42 -0
- package/dist/extensions/change-marker.js.map +1 -0
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +1 -7
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/schema.d.ts +1 -0
- package/dist/extensions/schema.d.ts.map +1 -1
- package/dist/extensions/schema.js +1 -0
- package/dist/extensions/schema.js.map +1 -1
- package/dist/extensions/slots/routes.js +1 -1
- package/dist/extensions/slots/routes.js.map +1 -1
- package/dist/extensions/store.d.ts +3 -0
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +112 -4
- package/dist/extensions/store.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/adapters/telegram.d.ts.map +1 -1
- package/dist/integrations/adapters/telegram.js +1 -0
- package/dist/integrations/adapters/telegram.js.map +1 -1
- package/dist/integrations/index.d.ts +5 -1
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +4 -1
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/plugin.d.ts +8 -0
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +760 -32
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/remote-commands-store.d.ts +36 -0
- package/dist/integrations/remote-commands-store.d.ts.map +1 -0
- package/dist/integrations/remote-commands-store.js +273 -0
- package/dist/integrations/remote-commands-store.js.map +1 -0
- package/dist/integrations/remote-devices-store.d.ts +43 -0
- package/dist/integrations/remote-devices-store.d.ts.map +1 -0
- package/dist/integrations/remote-devices-store.js +315 -0
- package/dist/integrations/remote-devices-store.js.map +1 -0
- package/dist/integrations/remote-push-store.d.ts +37 -0
- package/dist/integrations/remote-push-store.d.ts.map +1 -0
- package/dist/integrations/remote-push-store.js +299 -0
- package/dist/integrations/remote-push-store.js.map +1 -0
- package/dist/integrations/remote-retry-job.d.ts +7 -0
- package/dist/integrations/remote-retry-job.d.ts.map +1 -0
- package/dist/integrations/remote-retry-job.js +45 -0
- package/dist/integrations/remote-retry-job.js.map +1 -0
- package/dist/integrations/remote-run-events-store.d.ts +18 -0
- package/dist/integrations/remote-run-events-store.d.ts.map +1 -0
- package/dist/integrations/remote-run-events-store.js +82 -0
- package/dist/integrations/remote-run-events-store.js.map +1 -0
- package/dist/integrations/remote-types.d.ts +101 -0
- package/dist/integrations/remote-types.d.ts.map +1 -0
- package/dist/integrations/remote-types.js +2 -0
- package/dist/integrations/remote-types.js.map +1 -0
- package/dist/integrations/webhook-handler.d.ts +2 -0
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +4 -1
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/jobs/scheduler.d.ts +4 -2
- package/dist/jobs/scheduler.d.ts.map +1 -1
- package/dist/jobs/scheduler.js +9 -3
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/mcp-client/builtin-capabilities.d.ts +20 -0
- package/dist/mcp-client/builtin-capabilities.d.ts.map +1 -0
- package/dist/mcp-client/builtin-capabilities.js +75 -0
- package/dist/mcp-client/builtin-capabilities.js.map +1 -0
- package/dist/mcp-client/builtin-store.d.ts +10 -0
- package/dist/mcp-client/builtin-store.d.ts.map +1 -0
- package/dist/mcp-client/builtin-store.js +55 -0
- package/dist/mcp-client/builtin-store.js.map +1 -0
- package/dist/mcp-client/index.d.ts +3 -1
- package/dist/mcp-client/index.d.ts.map +1 -1
- package/dist/mcp-client/index.js +3 -1
- package/dist/mcp-client/index.js.map +1 -1
- package/dist/mcp-client/routes.d.ts +28 -0
- package/dist/mcp-client/routes.d.ts.map +1 -1
- package/dist/mcp-client/routes.js +195 -1
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +34 -0
- package/dist/org/context.js.map +1 -1
- package/dist/resources/handlers.d.ts +4 -0
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +46 -7
- package/dist/resources/handlers.js.map +1 -1
- package/dist/resources/script-helpers.d.ts +8 -1
- package/dist/resources/script-helpers.d.ts.map +1 -1
- package/dist/resources/script-helpers.js +18 -8
- package/dist/resources/script-helpers.js.map +1 -1
- package/dist/resources/store.d.ts +19 -0
- package/dist/resources/store.d.ts.map +1 -1
- package/dist/resources/store.js +86 -3
- package/dist/resources/store.js.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +18 -7
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/agent-engines/manage-agent-engine.d.ts.map +1 -1
- package/dist/scripts/agent-engines/manage-agent-engine.js +100 -7
- package/dist/scripts/agent-engines/manage-agent-engine.js.map +1 -1
- package/dist/scripts/resources/delete.d.ts.map +1 -1
- package/dist/scripts/resources/delete.js +4 -1
- package/dist/scripts/resources/delete.js.map +1 -1
- package/dist/scripts/resources/effective.d.ts +11 -0
- package/dist/scripts/resources/effective.d.ts.map +1 -0
- package/dist/scripts/resources/effective.js +54 -0
- package/dist/scripts/resources/effective.js.map +1 -0
- package/dist/scripts/resources/index.d.ts.map +1 -1
- package/dist/scripts/resources/index.js +1 -0
- package/dist/scripts/resources/index.js.map +1 -1
- package/dist/scripts/resources/list.d.ts +1 -1
- package/dist/scripts/resources/list.d.ts.map +1 -1
- package/dist/scripts/resources/list.js +17 -5
- package/dist/scripts/resources/list.js.map +1 -1
- package/dist/scripts/resources/read.d.ts +1 -1
- package/dist/scripts/resources/read.d.ts.map +1 -1
- package/dist/scripts/resources/read.js +20 -5
- package/dist/scripts/resources/read.js.map +1 -1
- package/dist/scripts/resources/write.d.ts.map +1 -1
- package/dist/scripts/resources/write.js +4 -1
- package/dist/scripts/resources/write.js.map +1 -1
- package/dist/scripts/runner.d.ts +11 -1
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +75 -27
- package/dist/scripts/runner.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +5 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +24 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +608 -54
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +2 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/embedded.d.ts +72 -0
- package/dist/server/embedded.d.ts.map +1 -0
- package/dist/server/embedded.js +119 -0
- package/dist/server/embedded.js.map +1 -0
- package/dist/server/index.d.ts +8 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +7 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +184 -13
- package/dist/server/poll.js.map +1 -1
- package/dist/server/resources-plugin.d.ts.map +1 -1
- package/dist/server/resources-plugin.js +11 -2
- package/dist/server/resources-plugin.js.map +1 -1
- package/dist/sharing/actions/extension-change.d.ts +4 -0
- package/dist/sharing/actions/extension-change.d.ts.map +1 -0
- package/dist/sharing/actions/extension-change.js +13 -0
- package/dist/sharing/actions/extension-change.js.map +1 -0
- package/dist/sharing/actions/set-resource-visibility.d.ts.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.js +3 -0
- package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
- package/dist/sharing/actions/share-resource.d.ts.map +1 -1
- package/dist/sharing/actions/share-resource.js +4 -0
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/sharing/actions/unshare-resource.d.ts.map +1 -1
- package/dist/sharing/actions/unshare-resource.js +3 -0
- package/dist/sharing/actions/unshare-resource.js.map +1 -1
- package/dist/templates/default/AGENTS.md +3 -3
- package/dist/templates/workspace-core/AGENTS.md +7 -0
- package/dist/templates/workspace-root/AGENTS.md +7 -0
- package/dist/templates/workspace-root/README.md +25 -0
- package/dist/triggers/dispatcher.d.ts +3 -1
- package/dist/triggers/dispatcher.d.ts.map +1 -1
- package/dist/triggers/dispatcher.js +9 -3
- package/dist/triggers/dispatcher.js.map +1 -1
- package/dist/workspace-connections/index.d.ts +2 -0
- package/dist/workspace-connections/index.d.ts.map +1 -0
- package/dist/workspace-connections/index.js +2 -0
- package/dist/workspace-connections/index.js.map +1 -0
- package/dist/workspace-connections/store.d.ts +229 -0
- package/dist/workspace-connections/store.d.ts.map +1 -0
- package/dist/workspace-connections/store.js +938 -0
- package/dist/workspace-connections/store.js.map +1 -0
- package/docs/content/agent-teams.md +6 -0
- package/docs/content/cloneable-saas.md +1 -0
- package/docs/content/code-agents-ui.md +261 -0
- package/docs/content/dispatch.md +40 -3
- package/docs/content/embedding-sdk.md +459 -0
- package/docs/content/faq.md +1 -0
- package/docs/content/getting-started.md +1 -0
- package/docs/content/mcp-clients.md +41 -3
- package/docs/content/migration-workbench.md +237 -54
- package/docs/content/multi-app-workspace.md +41 -0
- package/docs/content/multi-tenancy.md +1 -1
- package/docs/content/template-brain.md +418 -0
- package/docs/content/template-dispatch.md +30 -0
- package/docs/content/workspace-connections.md +509 -0
- package/docs/content/workspace-management.md +12 -12
- package/docs/content/workspace.md +180 -40
- package/package.json +7 -2
- package/src/templates/default/AGENTS.md +3 -3
- package/src/templates/workspace-core/AGENTS.md +7 -0
- package/src/templates/workspace-root/AGENTS.md +7 -0
- package/src/templates/workspace-root/README.md +25 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-devices-store.js","sourceRoot":"","sources":["../../src/integrations/remote-devices-store.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getDbExec,\n intType,\n isPostgres,\n retryOnDdlRace,\n} from \"../db/client.js\";\nimport type { PublicRemoteDevice, RemoteDevice } from \"./remote-types.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n await retryOnDdlRace(() =>\n client.execute(`\n CREATE TABLE IF NOT EXISTS integration_remote_devices (\n id TEXT PRIMARY KEY,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n label TEXT NOT NULL,\n platform TEXT,\n app_version TEXT,\n host_name TEXT,\n metadata_json TEXT,\n device_token_hash TEXT NOT NULL,\n last_seen_at ${intType()},\n status TEXT NOT NULL,\n revoked_at ${intType()},\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL\n )\n `),\n );\n await addColumnIfMissing(\"platform\", \"TEXT\");\n await addColumnIfMissing(\"app_version\", \"TEXT\");\n await addColumnIfMissing(\"host_name\", \"TEXT\");\n await addColumnIfMissing(\"metadata_json\", \"TEXT\");\n await addColumnIfMissing(\"revoked_at\", intType());\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_remote_devices_token_hash ON integration_remote_devices(device_token_hash)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_remote_devices_owner ON integration_remote_devices(owner_email, org_id)`,\n ),\n );\n })();\n }\n return _initPromise;\n}\n\nasync function addColumnIfMissing(\n name: string,\n definition: string,\n): Promise<void> {\n const sql = isPostgres()\n ? `ALTER TABLE integration_remote_devices ADD COLUMN IF NOT EXISTS ${name} ${definition}`\n : `ALTER TABLE integration_remote_devices ADD COLUMN ${name} ${definition}`;\n try {\n await retryOnDdlRace(() => getDbExec().execute(sql));\n } catch (err) {\n if (isDuplicateColumnError(err)) return;\n throw err;\n }\n}\n\nfunction isDuplicateColumnError(err: unknown): boolean {\n const code = String((err as { code?: unknown })?.code ?? \"\");\n const message = String((err as { message?: unknown })?.message ?? err)\n .toLowerCase()\n .trim();\n return (\n code === \"42701\" ||\n message.includes(\"duplicate column\") ||\n message.includes(\"already exists\")\n );\n}\n\nfunction rowToDevice(row: Record<string, unknown>): RemoteDevice {\n return {\n id: row.id as string,\n ownerEmail: row.owner_email as string,\n orgId: (row.org_id as string | null) ?? null,\n label: row.label as string,\n platform: (row.platform as string | null) ?? null,\n appVersion: (row.app_version as string | null) ?? null,\n hostName: (row.host_name as string | null) ?? null,\n metadata: parseJson(row.metadata_json, null) as Record<\n string,\n unknown\n > | null,\n deviceTokenHash: row.device_token_hash as string,\n lastSeenAt:\n row.last_seen_at == null ? null : Number(row.last_seen_at as number),\n status: row.status as RemoteDevice[\"status\"],\n revokedAt: row.revoked_at == null ? null : Number(row.revoked_at as number),\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n };\n}\n\nexport function toPublicRemoteDevice(device: RemoteDevice): PublicRemoteDevice {\n return {\n id: device.id,\n ownerEmail: device.ownerEmail,\n orgId: device.orgId,\n label: device.label,\n platform: device.platform,\n appVersion: device.appVersion,\n hostName: device.hostName,\n metadata: device.metadata,\n lastSeenAt: device.lastSeenAt,\n status: device.status,\n revokedAt: device.revokedAt,\n createdAt: device.createdAt,\n updatedAt: device.updatedAt,\n };\n}\n\nexport async function createRemoteDevice(input: {\n ownerEmail: string;\n orgId?: string | null;\n label: string;\n platform?: string | null;\n appVersion?: string | null;\n hostName?: string | null;\n metadata?: Record<string, unknown> | null;\n}): Promise<{ device: RemoteDevice; token: string }> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const id = `remote-device-${now}-${randomHex(8)}`;\n const token = `anr_${randomHex(32)}`;\n const tokenHash = await hashRemoteDeviceToken(token);\n\n await client.execute({\n sql: `INSERT INTO integration_remote_devices\n (id, owner_email, org_id, label, platform, app_version, host_name, metadata_json,\n device_token_hash, last_seen_at, status, revoked_at, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n input.ownerEmail,\n input.orgId ?? null,\n input.label.trim() || \"Remote device\",\n sanitizeOptionalString(input.platform, 80),\n sanitizeOptionalString(input.appVersion, 120),\n sanitizeOptionalString(input.hostName, 200),\n input.metadata ? JSON.stringify(input.metadata) : null,\n tokenHash,\n now,\n \"active\",\n null,\n now,\n now,\n ],\n });\n\n const device = await getRemoteDevice(id);\n if (!device) throw new Error(\"remote device insert failed\");\n return { device, token };\n}\n\nexport async function getRemoteDevice(\n id: string,\n): Promise<RemoteDevice | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_devices WHERE id = ? LIMIT 1`,\n args: [id],\n });\n return rows[0] ? rowToDevice(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function getRemoteDeviceForOwner(input: {\n id: string;\n ownerEmail: string;\n orgId?: string | null;\n}): Promise<RemoteDevice | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_devices\n WHERE id = ?\n AND owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)\n LIMIT 1`,\n args: [\n input.id,\n input.ownerEmail,\n input.orgId ?? null,\n input.orgId ?? null,\n ],\n });\n return rows[0] ? rowToDevice(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function listRemoteDevicesForOwner(input: {\n ownerEmail: string;\n orgId?: string | null;\n status?: RemoteDevice[\"status\"];\n limit?: number;\n}): Promise<RemoteDevice[]> {\n await ensureTable();\n const limit = Math.max(1, Math.min(input.limit ?? 50, 100));\n const statusClause = input.status ? \" AND status = ?\" : \"\";\n if (!Object.prototype.hasOwnProperty.call(input, \"orgId\")) {\n const args: Array<string | number> = [input.ownerEmail];\n if (input.status) args.push(input.status);\n args.push(limit);\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_devices\n WHERE owner_email = ?${statusClause}\n ORDER BY COALESCE(last_seen_at, updated_at) DESC\n LIMIT ?`,\n args,\n });\n return rows.map((row) => rowToDevice(row as Record<string, unknown>));\n }\n const args: Array<string | number | null> = [\n input.ownerEmail,\n input.orgId ?? null,\n input.orgId ?? null,\n ];\n if (input.status) args.push(input.status);\n args.push(limit);\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_devices\n WHERE owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)${statusClause}\n ORDER BY COALESCE(last_seen_at, updated_at) DESC\n LIMIT ?`,\n args,\n });\n return rows.map((row) => rowToDevice(row as Record<string, unknown>));\n}\n\nexport async function authenticateRemoteDeviceToken(\n rawToken: string | null | undefined,\n): Promise<RemoteDevice | null> {\n if (!rawToken) return null;\n await ensureTable();\n const tokenHash = await hashRemoteDeviceToken(rawToken);\n const now = Date.now();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM integration_remote_devices\n WHERE device_token_hash = ? AND status = 'active'\n LIMIT 1`,\n args: [tokenHash],\n });\n if (!rows[0]) return null;\n const device = rowToDevice(rows[0] as Record<string, unknown>);\n await client.execute({\n sql: `UPDATE integration_remote_devices\n SET last_seen_at = ?, updated_at = ?\n WHERE id = ?`,\n args: [now, now, device.id],\n });\n return { ...device, lastSeenAt: now, updatedAt: now };\n}\n\nexport async function updateRemoteDeviceDetails(input: {\n id: string;\n label?: string | null;\n platform?: string | null;\n appVersion?: string | null;\n hostName?: string | null;\n metadata?: Record<string, unknown> | null;\n}): Promise<RemoteDevice | null> {\n await ensureTable();\n const now = Date.now();\n const updates: string[] = [];\n const args: Array<string | number | null> = [];\n if (input.label !== undefined) {\n updates.push(\"label = ?\");\n args.push(sanitizeOptionalString(input.label, 200) ?? \"Remote device\");\n }\n if (input.platform !== undefined) {\n updates.push(\"platform = ?\");\n args.push(sanitizeOptionalString(input.platform, 80));\n }\n if (input.appVersion !== undefined) {\n updates.push(\"app_version = ?\");\n args.push(sanitizeOptionalString(input.appVersion, 120));\n }\n if (input.hostName !== undefined) {\n updates.push(\"host_name = ?\");\n args.push(sanitizeOptionalString(input.hostName, 200));\n }\n if (input.metadata !== undefined) {\n updates.push(\"metadata_json = ?\");\n args.push(input.metadata ? JSON.stringify(input.metadata) : null);\n }\n if (updates.length === 0) return getRemoteDevice(input.id);\n\n updates.push(\"updated_at = ?\");\n args.push(now, input.id);\n await getDbExec().execute({\n sql: `UPDATE integration_remote_devices\n SET ${updates.join(\", \")}\n WHERE id = ? AND status = 'active'`,\n args,\n });\n return getRemoteDevice(input.id);\n}\n\nexport async function revokeRemoteDeviceForOwner(input: {\n id: string;\n ownerEmail: string;\n orgId?: string | null;\n}): Promise<RemoteDevice | null> {\n await ensureTable();\n const now = Date.now();\n await getDbExec().execute({\n sql: `UPDATE integration_remote_devices\n SET status = 'inactive',\n revoked_at = COALESCE(revoked_at, ?),\n updated_at = ?\n WHERE id = ?\n AND owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)`,\n args: [\n now,\n now,\n input.id,\n input.ownerEmail,\n input.orgId ?? null,\n input.orgId ?? null,\n ],\n });\n return getRemoteDeviceForOwner(input);\n}\n\nexport async function unregisterRemoteDevice(id: string): Promise<boolean> {\n await ensureTable();\n const now = Date.now();\n const result = await getDbExec().execute({\n sql: `UPDATE integration_remote_devices\n SET status = 'inactive',\n revoked_at = COALESCE(revoked_at, ?),\n updated_at = ?\n WHERE id = ? AND status = 'active'`,\n args: [now, now, id],\n });\n return (result.rowsAffected ?? (result as any).rowCount ?? 0) > 0;\n}\n\nexport async function hashRemoteDeviceToken(token: string): Promise<string> {\n const bytes = new TextEncoder().encode(token);\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", bytes);\n return bytesToHex(new Uint8Array(digest));\n}\n\nfunction sanitizeOptionalString(\n value: string | null | undefined,\n max: number,\n): string | null {\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, max) : null;\n}\n\nfunction parseJson(value: unknown, fallback: unknown): unknown {\n if (value == null) return fallback;\n try {\n return JSON.parse(String(value));\n } catch {\n return fallback;\n }\n}\n\nfunction randomHex(byteLength: number): string {\n const bytes = new Uint8Array(byteLength);\n globalThis.crypto.getRandomValues(bytes);\n return bytesToHex(bytes);\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PublicRemotePushRegistration, RemotePushNotification, RemotePushRegistration } from "./remote-types.js";
|
|
2
|
+
export declare function toPublicRemotePushRegistration(registration: RemotePushRegistration): PublicRemotePushRegistration;
|
|
3
|
+
export declare function upsertRemotePushRegistration(input: {
|
|
4
|
+
ownerEmail: string;
|
|
5
|
+
orgId?: string | null;
|
|
6
|
+
provider: string;
|
|
7
|
+
token: string;
|
|
8
|
+
platform?: string | null;
|
|
9
|
+
clientDeviceId?: string | null;
|
|
10
|
+
label?: string | null;
|
|
11
|
+
}): Promise<RemotePushRegistration>;
|
|
12
|
+
export declare function listRemotePushRegistrationsForOwner(input: {
|
|
13
|
+
ownerEmail: string;
|
|
14
|
+
orgId?: string | null;
|
|
15
|
+
includeInactive?: boolean;
|
|
16
|
+
limit?: number;
|
|
17
|
+
}): Promise<RemotePushRegistration[]>;
|
|
18
|
+
export declare function unregisterRemotePushRegistrationForOwner(input: {
|
|
19
|
+
ownerEmail: string;
|
|
20
|
+
orgId?: string | null;
|
|
21
|
+
id?: string | null;
|
|
22
|
+
token?: string | null;
|
|
23
|
+
}): Promise<boolean>;
|
|
24
|
+
export declare function queueRemotePushNotifications(input: {
|
|
25
|
+
ownerEmail: string;
|
|
26
|
+
orgId?: string | null;
|
|
27
|
+
payload: unknown;
|
|
28
|
+
}): Promise<{
|
|
29
|
+
queued: number;
|
|
30
|
+
}>;
|
|
31
|
+
export declare function listRemotePushNotificationsForOwner(input: {
|
|
32
|
+
ownerEmail: string;
|
|
33
|
+
orgId?: string | null;
|
|
34
|
+
status?: RemotePushNotification["status"];
|
|
35
|
+
limit?: number;
|
|
36
|
+
}): Promise<RemotePushNotification[]>;
|
|
37
|
+
//# sourceMappingURL=remote-push-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-push-store.d.ts","sourceRoot":"","sources":["../../src/integrations/remote-push-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,4BAA4B,EAC5B,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAoG3B,wBAAgB,8BAA8B,CAC5C,YAAY,EAAE,sBAAsB,GACnC,4BAA4B,CAc9B;AAED,wBAAsB,4BAA4B,CAAC,KAAK,EAAE;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAoElC;AAED,wBAAsB,mCAAmC,CAAC,KAAK,EAAE;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAuBpC;AAED,wBAAsB,wCAAwC,CAAC,KAAK,EAAE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,GAAG,OAAO,CAAC,OAAO,CAAC,CAuBnB;AAED,wBAAsB,4BAA4B,CAAC,KAAK,EAAE;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAgC9B;AAED,wBAAsB,mCAAmC,CAAC,KAAK,EAAE;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAoBpC"}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { getDbExec, intType, retryOnDdlRace } from "../db/client.js";
|
|
2
|
+
let _initPromise;
|
|
3
|
+
async function ensureTables() {
|
|
4
|
+
if (!_initPromise) {
|
|
5
|
+
_initPromise = (async () => {
|
|
6
|
+
const client = getDbExec();
|
|
7
|
+
await retryOnDdlRace(() => client.execute(`
|
|
8
|
+
CREATE TABLE IF NOT EXISTS integration_remote_push_registrations (
|
|
9
|
+
id TEXT PRIMARY KEY,
|
|
10
|
+
owner_email TEXT NOT NULL,
|
|
11
|
+
org_id TEXT,
|
|
12
|
+
provider TEXT NOT NULL,
|
|
13
|
+
platform TEXT,
|
|
14
|
+
client_device_id TEXT,
|
|
15
|
+
label TEXT,
|
|
16
|
+
token TEXT NOT NULL,
|
|
17
|
+
token_hash TEXT NOT NULL,
|
|
18
|
+
status TEXT NOT NULL,
|
|
19
|
+
last_seen_at ${intType()},
|
|
20
|
+
created_at ${intType()} NOT NULL,
|
|
21
|
+
updated_at ${intType()} NOT NULL
|
|
22
|
+
)
|
|
23
|
+
`));
|
|
24
|
+
await retryOnDdlRace(() => client.execute(`CREATE UNIQUE INDEX IF NOT EXISTS idx_remote_push_token_hash ON integration_remote_push_registrations(token_hash)`));
|
|
25
|
+
await retryOnDdlRace(() => client.execute(`CREATE INDEX IF NOT EXISTS idx_remote_push_owner ON integration_remote_push_registrations(owner_email, org_id, status)`));
|
|
26
|
+
await retryOnDdlRace(() => client.execute(`
|
|
27
|
+
CREATE TABLE IF NOT EXISTS integration_remote_push_notifications (
|
|
28
|
+
id TEXT PRIMARY KEY,
|
|
29
|
+
owner_email TEXT NOT NULL,
|
|
30
|
+
org_id TEXT,
|
|
31
|
+
registration_id TEXT NOT NULL,
|
|
32
|
+
payload_json TEXT NOT NULL,
|
|
33
|
+
status TEXT NOT NULL,
|
|
34
|
+
attempts ${intType()} NOT NULL DEFAULT 0,
|
|
35
|
+
created_at ${intType()} NOT NULL,
|
|
36
|
+
updated_at ${intType()} NOT NULL
|
|
37
|
+
)
|
|
38
|
+
`));
|
|
39
|
+
await retryOnDdlRace(() => client.execute(`CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_owner ON integration_remote_push_notifications(owner_email, org_id, status, created_at)`));
|
|
40
|
+
})();
|
|
41
|
+
}
|
|
42
|
+
return _initPromise;
|
|
43
|
+
}
|
|
44
|
+
function rowToRegistration(row) {
|
|
45
|
+
return {
|
|
46
|
+
id: row.id,
|
|
47
|
+
ownerEmail: row.owner_email,
|
|
48
|
+
orgId: row.org_id ?? null,
|
|
49
|
+
provider: row.provider,
|
|
50
|
+
platform: row.platform ?? null,
|
|
51
|
+
clientDeviceId: row.client_device_id ?? null,
|
|
52
|
+
label: row.label ?? null,
|
|
53
|
+
token: row.token,
|
|
54
|
+
tokenHash: row.token_hash,
|
|
55
|
+
status: row.status,
|
|
56
|
+
lastSeenAt: row.last_seen_at == null ? null : Number(row.last_seen_at),
|
|
57
|
+
createdAt: Number(row.created_at ?? 0),
|
|
58
|
+
updatedAt: Number(row.updated_at ?? 0),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function rowToNotification(row) {
|
|
62
|
+
return {
|
|
63
|
+
id: row.id,
|
|
64
|
+
ownerEmail: row.owner_email,
|
|
65
|
+
orgId: row.org_id ?? null,
|
|
66
|
+
registrationId: row.registration_id,
|
|
67
|
+
payload: parseJson(row.payload_json, null),
|
|
68
|
+
status: row.status,
|
|
69
|
+
attempts: Number(row.attempts ?? 0),
|
|
70
|
+
createdAt: Number(row.created_at ?? 0),
|
|
71
|
+
updatedAt: Number(row.updated_at ?? 0),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export function toPublicRemotePushRegistration(registration) {
|
|
75
|
+
return {
|
|
76
|
+
id: registration.id,
|
|
77
|
+
ownerEmail: registration.ownerEmail,
|
|
78
|
+
orgId: registration.orgId,
|
|
79
|
+
provider: registration.provider,
|
|
80
|
+
platform: registration.platform,
|
|
81
|
+
clientDeviceId: registration.clientDeviceId,
|
|
82
|
+
label: registration.label,
|
|
83
|
+
status: registration.status,
|
|
84
|
+
lastSeenAt: registration.lastSeenAt,
|
|
85
|
+
createdAt: registration.createdAt,
|
|
86
|
+
updatedAt: registration.updatedAt,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export async function upsertRemotePushRegistration(input) {
|
|
90
|
+
await ensureTables();
|
|
91
|
+
const client = getDbExec();
|
|
92
|
+
const now = Date.now();
|
|
93
|
+
const tokenHash = await hashToken(input.token);
|
|
94
|
+
const provider = sanitizeString(input.provider, 80) ?? "unknown";
|
|
95
|
+
const platform = sanitizeString(input.platform, 80);
|
|
96
|
+
const clientDeviceId = sanitizeString(input.clientDeviceId, 200);
|
|
97
|
+
const label = sanitizeString(input.label, 200);
|
|
98
|
+
const existing = await getRemotePushRegistrationByTokenHash(tokenHash);
|
|
99
|
+
if (existing) {
|
|
100
|
+
await client.execute({
|
|
101
|
+
sql: `UPDATE integration_remote_push_registrations
|
|
102
|
+
SET owner_email = ?,
|
|
103
|
+
org_id = ?,
|
|
104
|
+
provider = ?,
|
|
105
|
+
platform = ?,
|
|
106
|
+
client_device_id = ?,
|
|
107
|
+
label = ?,
|
|
108
|
+
token = ?,
|
|
109
|
+
status = 'active',
|
|
110
|
+
last_seen_at = ?,
|
|
111
|
+
updated_at = ?
|
|
112
|
+
WHERE token_hash = ?`,
|
|
113
|
+
args: [
|
|
114
|
+
input.ownerEmail,
|
|
115
|
+
input.orgId ?? null,
|
|
116
|
+
provider,
|
|
117
|
+
platform,
|
|
118
|
+
clientDeviceId,
|
|
119
|
+
label,
|
|
120
|
+
input.token,
|
|
121
|
+
now,
|
|
122
|
+
now,
|
|
123
|
+
tokenHash,
|
|
124
|
+
],
|
|
125
|
+
});
|
|
126
|
+
const updated = await getRemotePushRegistrationByTokenHash(tokenHash);
|
|
127
|
+
if (!updated)
|
|
128
|
+
throw new Error("remote push registration update failed");
|
|
129
|
+
return updated;
|
|
130
|
+
}
|
|
131
|
+
const id = `remote-push-${now}-${randomHex(8)}`;
|
|
132
|
+
await client.execute({
|
|
133
|
+
sql: `INSERT INTO integration_remote_push_registrations
|
|
134
|
+
(id, owner_email, org_id, provider, platform, client_device_id, label,
|
|
135
|
+
token, token_hash, status, last_seen_at, created_at, updated_at)
|
|
136
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
137
|
+
args: [
|
|
138
|
+
id,
|
|
139
|
+
input.ownerEmail,
|
|
140
|
+
input.orgId ?? null,
|
|
141
|
+
provider,
|
|
142
|
+
platform,
|
|
143
|
+
clientDeviceId,
|
|
144
|
+
label,
|
|
145
|
+
input.token,
|
|
146
|
+
tokenHash,
|
|
147
|
+
"active",
|
|
148
|
+
now,
|
|
149
|
+
now,
|
|
150
|
+
now,
|
|
151
|
+
],
|
|
152
|
+
});
|
|
153
|
+
const registration = await getRemotePushRegistrationByTokenHash(tokenHash);
|
|
154
|
+
if (!registration)
|
|
155
|
+
throw new Error("remote push registration insert failed");
|
|
156
|
+
return registration;
|
|
157
|
+
}
|
|
158
|
+
export async function listRemotePushRegistrationsForOwner(input) {
|
|
159
|
+
await ensureTables();
|
|
160
|
+
const limit = Math.max(1, Math.min(input.limit ?? 50, 100));
|
|
161
|
+
const statusClause = input.includeInactive ? "" : " AND status = 'active'";
|
|
162
|
+
if (!Object.prototype.hasOwnProperty.call(input, "orgId")) {
|
|
163
|
+
const { rows } = await getDbExec().execute({
|
|
164
|
+
sql: `SELECT * FROM integration_remote_push_registrations
|
|
165
|
+
WHERE owner_email = ?${statusClause}
|
|
166
|
+
ORDER BY COALESCE(last_seen_at, updated_at) DESC
|
|
167
|
+
LIMIT ?`,
|
|
168
|
+
args: [input.ownerEmail, limit],
|
|
169
|
+
});
|
|
170
|
+
return rows.map((row) => rowToRegistration(row));
|
|
171
|
+
}
|
|
172
|
+
const { rows } = await getDbExec().execute({
|
|
173
|
+
sql: `SELECT * FROM integration_remote_push_registrations
|
|
174
|
+
WHERE owner_email = ?
|
|
175
|
+
AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)${statusClause}
|
|
176
|
+
ORDER BY COALESCE(last_seen_at, updated_at) DESC
|
|
177
|
+
LIMIT ?`,
|
|
178
|
+
args: [input.ownerEmail, input.orgId ?? null, input.orgId ?? null, limit],
|
|
179
|
+
});
|
|
180
|
+
return rows.map((row) => rowToRegistration(row));
|
|
181
|
+
}
|
|
182
|
+
export async function unregisterRemotePushRegistrationForOwner(input) {
|
|
183
|
+
await ensureTables();
|
|
184
|
+
const tokenHash = input.token ? await hashToken(input.token) : null;
|
|
185
|
+
if (!input.id && !tokenHash)
|
|
186
|
+
return false;
|
|
187
|
+
const now = Date.now();
|
|
188
|
+
const result = await getDbExec().execute({
|
|
189
|
+
sql: `UPDATE integration_remote_push_registrations
|
|
190
|
+
SET status = 'inactive', updated_at = ?
|
|
191
|
+
WHERE owner_email = ?
|
|
192
|
+
AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)
|
|
193
|
+
AND (${input.id ? "id = ?" : "0 = 1"} OR ${tokenHash ? "token_hash = ?" : "0 = 1"})`,
|
|
194
|
+
args: [
|
|
195
|
+
now,
|
|
196
|
+
input.ownerEmail,
|
|
197
|
+
input.orgId ?? null,
|
|
198
|
+
input.orgId ?? null,
|
|
199
|
+
...(input.id ? [input.id] : []),
|
|
200
|
+
...(tokenHash ? [tokenHash] : []),
|
|
201
|
+
],
|
|
202
|
+
});
|
|
203
|
+
return (result.rowsAffected ?? result.rowCount ?? 0) > 0;
|
|
204
|
+
}
|
|
205
|
+
export async function queueRemotePushNotifications(input) {
|
|
206
|
+
await ensureTables();
|
|
207
|
+
const registrations = await listRemotePushRegistrationsForOwner({
|
|
208
|
+
ownerEmail: input.ownerEmail,
|
|
209
|
+
orgId: input.orgId ?? null,
|
|
210
|
+
limit: 100,
|
|
211
|
+
});
|
|
212
|
+
const client = getDbExec();
|
|
213
|
+
const now = Date.now();
|
|
214
|
+
let queued = 0;
|
|
215
|
+
for (const registration of registrations) {
|
|
216
|
+
const id = `remote-push-notification-${now}-${randomHex(8)}`;
|
|
217
|
+
const result = await client.execute({
|
|
218
|
+
sql: `INSERT INTO integration_remote_push_notifications
|
|
219
|
+
(id, owner_email, org_id, registration_id, payload_json, status,
|
|
220
|
+
attempts, created_at, updated_at)
|
|
221
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
222
|
+
args: [
|
|
223
|
+
id,
|
|
224
|
+
input.ownerEmail,
|
|
225
|
+
input.orgId ?? null,
|
|
226
|
+
registration.id,
|
|
227
|
+
JSON.stringify(input.payload ?? null),
|
|
228
|
+
"pending",
|
|
229
|
+
0,
|
|
230
|
+
now,
|
|
231
|
+
now,
|
|
232
|
+
],
|
|
233
|
+
});
|
|
234
|
+
queued += result.rowsAffected ?? result.rowCount ?? 0;
|
|
235
|
+
}
|
|
236
|
+
return { queued };
|
|
237
|
+
}
|
|
238
|
+
export async function listRemotePushNotificationsForOwner(input) {
|
|
239
|
+
await ensureTables();
|
|
240
|
+
const limit = Math.max(1, Math.min(input.limit ?? 50, 100));
|
|
241
|
+
const statusClause = input.status ? " AND status = ?" : "";
|
|
242
|
+
const args = [
|
|
243
|
+
input.ownerEmail,
|
|
244
|
+
input.orgId ?? null,
|
|
245
|
+
input.orgId ?? null,
|
|
246
|
+
];
|
|
247
|
+
if (input.status)
|
|
248
|
+
args.push(input.status);
|
|
249
|
+
args.push(limit);
|
|
250
|
+
const { rows } = await getDbExec().execute({
|
|
251
|
+
sql: `SELECT * FROM integration_remote_push_notifications
|
|
252
|
+
WHERE owner_email = ?
|
|
253
|
+
AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)${statusClause}
|
|
254
|
+
ORDER BY created_at DESC
|
|
255
|
+
LIMIT ?`,
|
|
256
|
+
args,
|
|
257
|
+
});
|
|
258
|
+
return rows.map((row) => rowToNotification(row));
|
|
259
|
+
}
|
|
260
|
+
async function getRemotePushRegistrationByTokenHash(tokenHash) {
|
|
261
|
+
const { rows } = await getDbExec().execute({
|
|
262
|
+
sql: `SELECT * FROM integration_remote_push_registrations
|
|
263
|
+
WHERE token_hash = ?
|
|
264
|
+
LIMIT 1`,
|
|
265
|
+
args: [tokenHash],
|
|
266
|
+
});
|
|
267
|
+
return rows[0] ? rowToRegistration(rows[0]) : null;
|
|
268
|
+
}
|
|
269
|
+
async function hashToken(token) {
|
|
270
|
+
const bytes = new TextEncoder().encode(token);
|
|
271
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
|
|
272
|
+
return Array.from(new Uint8Array(digest))
|
|
273
|
+
.map((byte) => byte.toString(16).padStart(2, "0"))
|
|
274
|
+
.join("");
|
|
275
|
+
}
|
|
276
|
+
function randomHex(byteLength) {
|
|
277
|
+
const bytes = new Uint8Array(byteLength);
|
|
278
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
279
|
+
return Array.from(bytes)
|
|
280
|
+
.map((byte) => byte.toString(16).padStart(2, "0"))
|
|
281
|
+
.join("");
|
|
282
|
+
}
|
|
283
|
+
function sanitizeString(value, max) {
|
|
284
|
+
if (typeof value !== "string")
|
|
285
|
+
return null;
|
|
286
|
+
const trimmed = value.trim();
|
|
287
|
+
return trimmed ? trimmed.slice(0, max) : null;
|
|
288
|
+
}
|
|
289
|
+
function parseJson(value, fallback) {
|
|
290
|
+
if (value == null)
|
|
291
|
+
return fallback;
|
|
292
|
+
try {
|
|
293
|
+
return JSON.parse(String(value));
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
return fallback;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=remote-push-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-push-store.js","sourceRoot":"","sources":["../../src/integrations/remote-push-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { getDbExec, intType, retryOnDdlRace } from \"../db/client.js\";\nimport type {\n PublicRemotePushRegistration,\n RemotePushNotification,\n RemotePushRegistration,\n} from \"./remote-types.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\nasync function ensureTables(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n await retryOnDdlRace(() =>\n client.execute(`\n CREATE TABLE IF NOT EXISTS integration_remote_push_registrations (\n id TEXT PRIMARY KEY,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n provider TEXT NOT NULL,\n platform TEXT,\n client_device_id TEXT,\n label TEXT,\n token TEXT NOT NULL,\n token_hash TEXT NOT NULL,\n status TEXT NOT NULL,\n last_seen_at ${intType()},\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL\n )\n `),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_remote_push_token_hash ON integration_remote_push_registrations(token_hash)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_remote_push_owner ON integration_remote_push_registrations(owner_email, org_id, status)`,\n ),\n );\n\n await retryOnDdlRace(() =>\n client.execute(`\n CREATE TABLE IF NOT EXISTS integration_remote_push_notifications (\n id TEXT PRIMARY KEY,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n registration_id TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n status TEXT NOT NULL,\n attempts ${intType()} NOT NULL DEFAULT 0,\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL\n )\n `),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_owner ON integration_remote_push_notifications(owner_email, org_id, status, created_at)`,\n ),\n );\n })();\n }\n return _initPromise;\n}\n\nfunction rowToRegistration(\n row: Record<string, unknown>,\n): RemotePushRegistration {\n return {\n id: row.id as string,\n ownerEmail: row.owner_email as string,\n orgId: (row.org_id as string | null) ?? null,\n provider: row.provider as string,\n platform: (row.platform as string | null) ?? null,\n clientDeviceId: (row.client_device_id as string | null) ?? null,\n label: (row.label as string | null) ?? null,\n token: row.token as string,\n tokenHash: row.token_hash as string,\n status: row.status as RemotePushRegistration[\"status\"],\n lastSeenAt:\n row.last_seen_at == null ? null : Number(row.last_seen_at as number),\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n };\n}\n\nfunction rowToNotification(\n row: Record<string, unknown>,\n): RemotePushNotification {\n return {\n id: row.id as string,\n ownerEmail: row.owner_email as string,\n orgId: (row.org_id as string | null) ?? null,\n registrationId: row.registration_id as string,\n payload: parseJson(row.payload_json, null),\n status: row.status as RemotePushNotification[\"status\"],\n attempts: Number(row.attempts ?? 0),\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n };\n}\n\nexport function toPublicRemotePushRegistration(\n registration: RemotePushRegistration,\n): PublicRemotePushRegistration {\n return {\n id: registration.id,\n ownerEmail: registration.ownerEmail,\n orgId: registration.orgId,\n provider: registration.provider,\n platform: registration.platform,\n clientDeviceId: registration.clientDeviceId,\n label: registration.label,\n status: registration.status,\n lastSeenAt: registration.lastSeenAt,\n createdAt: registration.createdAt,\n updatedAt: registration.updatedAt,\n };\n}\n\nexport async function upsertRemotePushRegistration(input: {\n ownerEmail: string;\n orgId?: string | null;\n provider: string;\n token: string;\n platform?: string | null;\n clientDeviceId?: string | null;\n label?: string | null;\n}): Promise<RemotePushRegistration> {\n await ensureTables();\n const client = getDbExec();\n const now = Date.now();\n const tokenHash = await hashToken(input.token);\n const provider = sanitizeString(input.provider, 80) ?? \"unknown\";\n const platform = sanitizeString(input.platform, 80);\n const clientDeviceId = sanitizeString(input.clientDeviceId, 200);\n const label = sanitizeString(input.label, 200);\n\n const existing = await getRemotePushRegistrationByTokenHash(tokenHash);\n if (existing) {\n await client.execute({\n sql: `UPDATE integration_remote_push_registrations\n SET owner_email = ?,\n org_id = ?,\n provider = ?,\n platform = ?,\n client_device_id = ?,\n label = ?,\n token = ?,\n status = 'active',\n last_seen_at = ?,\n updated_at = ?\n WHERE token_hash = ?`,\n args: [\n input.ownerEmail,\n input.orgId ?? null,\n provider,\n platform,\n clientDeviceId,\n label,\n input.token,\n now,\n now,\n tokenHash,\n ],\n });\n const updated = await getRemotePushRegistrationByTokenHash(tokenHash);\n if (!updated) throw new Error(\"remote push registration update failed\");\n return updated;\n }\n\n const id = `remote-push-${now}-${randomHex(8)}`;\n await client.execute({\n sql: `INSERT INTO integration_remote_push_registrations\n (id, owner_email, org_id, provider, platform, client_device_id, label,\n token, token_hash, status, last_seen_at, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n input.ownerEmail,\n input.orgId ?? null,\n provider,\n platform,\n clientDeviceId,\n label,\n input.token,\n tokenHash,\n \"active\",\n now,\n now,\n now,\n ],\n });\n const registration = await getRemotePushRegistrationByTokenHash(tokenHash);\n if (!registration) throw new Error(\"remote push registration insert failed\");\n return registration;\n}\n\nexport async function listRemotePushRegistrationsForOwner(input: {\n ownerEmail: string;\n orgId?: string | null;\n includeInactive?: boolean;\n limit?: number;\n}): Promise<RemotePushRegistration[]> {\n await ensureTables();\n const limit = Math.max(1, Math.min(input.limit ?? 50, 100));\n const statusClause = input.includeInactive ? \"\" : \" AND status = 'active'\";\n if (!Object.prototype.hasOwnProperty.call(input, \"orgId\")) {\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_registrations\n WHERE owner_email = ?${statusClause}\n ORDER BY COALESCE(last_seen_at, updated_at) DESC\n LIMIT ?`,\n args: [input.ownerEmail, limit],\n });\n return rows.map((row) => rowToRegistration(row as Record<string, unknown>));\n }\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_registrations\n WHERE owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)${statusClause}\n ORDER BY COALESCE(last_seen_at, updated_at) DESC\n LIMIT ?`,\n args: [input.ownerEmail, input.orgId ?? null, input.orgId ?? null, limit],\n });\n return rows.map((row) => rowToRegistration(row as Record<string, unknown>));\n}\n\nexport async function unregisterRemotePushRegistrationForOwner(input: {\n ownerEmail: string;\n orgId?: string | null;\n id?: string | null;\n token?: string | null;\n}): Promise<boolean> {\n await ensureTables();\n const tokenHash = input.token ? await hashToken(input.token) : null;\n if (!input.id && !tokenHash) return false;\n const now = Date.now();\n const result = await getDbExec().execute({\n sql: `UPDATE integration_remote_push_registrations\n SET status = 'inactive', updated_at = ?\n WHERE owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)\n AND (${input.id ? \"id = ?\" : \"0 = 1\"} OR ${\n tokenHash ? \"token_hash = ?\" : \"0 = 1\"\n })`,\n args: [\n now,\n input.ownerEmail,\n input.orgId ?? null,\n input.orgId ?? null,\n ...(input.id ? [input.id] : []),\n ...(tokenHash ? [tokenHash] : []),\n ],\n });\n return (result.rowsAffected ?? (result as any).rowCount ?? 0) > 0;\n}\n\nexport async function queueRemotePushNotifications(input: {\n ownerEmail: string;\n orgId?: string | null;\n payload: unknown;\n}): Promise<{ queued: number }> {\n await ensureTables();\n const registrations = await listRemotePushRegistrationsForOwner({\n ownerEmail: input.ownerEmail,\n orgId: input.orgId ?? null,\n limit: 100,\n });\n const client = getDbExec();\n const now = Date.now();\n let queued = 0;\n for (const registration of registrations) {\n const id = `remote-push-notification-${now}-${randomHex(8)}`;\n const result = await client.execute({\n sql: `INSERT INTO integration_remote_push_notifications\n (id, owner_email, org_id, registration_id, payload_json, status,\n attempts, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n input.ownerEmail,\n input.orgId ?? null,\n registration.id,\n JSON.stringify(input.payload ?? null),\n \"pending\",\n 0,\n now,\n now,\n ],\n });\n queued += result.rowsAffected ?? (result as any).rowCount ?? 0;\n }\n return { queued };\n}\n\nexport async function listRemotePushNotificationsForOwner(input: {\n ownerEmail: string;\n orgId?: string | null;\n status?: RemotePushNotification[\"status\"];\n limit?: number;\n}): Promise<RemotePushNotification[]> {\n await ensureTables();\n const limit = Math.max(1, Math.min(input.limit ?? 50, 100));\n const statusClause = input.status ? \" AND status = ?\" : \"\";\n const args: Array<string | number | null> = [\n input.ownerEmail,\n input.orgId ?? null,\n input.orgId ?? null,\n ];\n if (input.status) args.push(input.status);\n args.push(limit);\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_notifications\n WHERE owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)${statusClause}\n ORDER BY created_at DESC\n LIMIT ?`,\n args,\n });\n return rows.map((row) => rowToNotification(row as Record<string, unknown>));\n}\n\nasync function getRemotePushRegistrationByTokenHash(\n tokenHash: string,\n): Promise<RemotePushRegistration | null> {\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_registrations\n WHERE token_hash = ?\n LIMIT 1`,\n args: [tokenHash],\n });\n return rows[0] ? rowToRegistration(rows[0] as Record<string, unknown>) : null;\n}\n\nasync function hashToken(token: string): Promise<string> {\n const bytes = new TextEncoder().encode(token);\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", bytes);\n return Array.from(new Uint8Array(digest))\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nfunction randomHex(byteLength: number): string {\n const bytes = new Uint8Array(byteLength);\n globalThis.crypto.getRandomValues(bytes);\n return Array.from(bytes)\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nfunction sanitizeString(\n value: string | null | undefined,\n max: number,\n): string | null {\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, max) : null;\n}\n\nfunction parseJson(value: unknown, fallback: unknown): unknown {\n if (value == null) return fallback;\n try {\n return JSON.parse(String(value));\n } catch {\n return fallback;\n }\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function retryRemoteCommands(): Promise<{
|
|
2
|
+
retried: number;
|
|
3
|
+
failed: number;
|
|
4
|
+
}>;
|
|
5
|
+
export declare function startRemoteCommandsRetryJob(): void;
|
|
6
|
+
export declare function stopRemoteCommandsRetryJob(): void;
|
|
7
|
+
//# sourceMappingURL=remote-retry-job.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-retry-job.d.ts","sourceRoot":"","sources":["../../src/integrations/remote-retry-job.ts"],"names":[],"mappings":"AAOA,wBAAsB,mBAAmB,IAAI,OAAO,CAAC;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAWD;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAgBlD;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CASjD"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { retryStaleRemoteCommands } from "./remote-commands-store.js";
|
|
2
|
+
const RETRY_INTERVAL_MS = 60_000;
|
|
3
|
+
let retryInterval = null;
|
|
4
|
+
let initialTimer = null;
|
|
5
|
+
export async function retryRemoteCommands() {
|
|
6
|
+
try {
|
|
7
|
+
return await retryStaleRemoteCommands();
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
if (process.env.DEBUG) {
|
|
11
|
+
console.log("[integrations] remote command retry job: tables not ready, skipping");
|
|
12
|
+
}
|
|
13
|
+
return { retried: 0, failed: 0 };
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function startRemoteCommandsRetryJob() {
|
|
17
|
+
if (retryInterval)
|
|
18
|
+
return;
|
|
19
|
+
initialTimer = setTimeout(() => {
|
|
20
|
+
void retryRemoteCommands().catch((err) => {
|
|
21
|
+
console.error("[integrations] Remote command retry job error:", err);
|
|
22
|
+
});
|
|
23
|
+
}, 10_000);
|
|
24
|
+
unrefTimer(initialTimer);
|
|
25
|
+
retryInterval = setInterval(() => {
|
|
26
|
+
void retryRemoteCommands().catch((err) => {
|
|
27
|
+
console.error("[integrations] Remote command retry job error:", err);
|
|
28
|
+
});
|
|
29
|
+
}, RETRY_INTERVAL_MS);
|
|
30
|
+
unrefTimer(retryInterval);
|
|
31
|
+
}
|
|
32
|
+
export function stopRemoteCommandsRetryJob() {
|
|
33
|
+
if (initialTimer) {
|
|
34
|
+
clearTimeout(initialTimer);
|
|
35
|
+
initialTimer = null;
|
|
36
|
+
}
|
|
37
|
+
if (retryInterval) {
|
|
38
|
+
clearInterval(retryInterval);
|
|
39
|
+
retryInterval = null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function unrefTimer(timer) {
|
|
43
|
+
timer.unref?.();
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=remote-retry-job.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-retry-job.js","sourceRoot":"","sources":["../../src/integrations/remote-retry-job.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAEjC,IAAI,aAAa,GAA0C,IAAI,CAAC;AAChE,IAAI,YAAY,GAAyC,IAAI,CAAC;AAE9D,MAAM,CAAC,KAAK,UAAU,mBAAmB;IAIvC,IAAI,CAAC;QACH,OAAO,MAAM,wBAAwB,EAAE,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CACT,qEAAqE,CACtE,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACnC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,IAAI,aAAa;QAAE,OAAO;IAE1B,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE;QAC7B,KAAK,mBAAmB,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACvC,OAAO,CAAC,KAAK,CAAC,gDAAgD,EAAE,GAAG,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,MAAM,CAAC,CAAC;IACX,UAAU,CAAC,YAAY,CAAC,CAAC;IAEzB,aAAa,GAAG,WAAW,CAAC,GAAG,EAAE;QAC/B,KAAK,mBAAmB,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACvC,OAAO,CAAC,KAAK,CAAC,gDAAgD,EAAE,GAAG,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACtB,UAAU,CAAC,aAAa,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,IAAI,YAAY,EAAE,CAAC;QACjB,YAAY,CAAC,YAAY,CAAC,CAAC;QAC3B,YAAY,GAAG,IAAI,CAAC;IACtB,CAAC;IACD,IAAI,aAAa,EAAE,CAAC;QAClB,aAAa,CAAC,aAAa,CAAC,CAAC;QAC7B,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,KAAqC;IACtD,KAA2C,CAAC,KAAK,EAAE,EAAE,CAAC;AACzD,CAAC","sourcesContent":["import { retryStaleRemoteCommands } from \"./remote-commands-store.js\";\n\nconst RETRY_INTERVAL_MS = 60_000;\n\nlet retryInterval: ReturnType<typeof setInterval> | null = null;\nlet initialTimer: ReturnType<typeof setTimeout> | null = null;\n\nexport async function retryRemoteCommands(): Promise<{\n retried: number;\n failed: number;\n}> {\n try {\n return await retryStaleRemoteCommands();\n } catch (err) {\n if (process.env.DEBUG) {\n console.log(\n \"[integrations] remote command retry job: tables not ready, skipping\",\n );\n }\n return { retried: 0, failed: 0 };\n }\n}\n\nexport function startRemoteCommandsRetryJob(): void {\n if (retryInterval) return;\n\n initialTimer = setTimeout(() => {\n void retryRemoteCommands().catch((err) => {\n console.error(\"[integrations] Remote command retry job error:\", err);\n });\n }, 10_000);\n unrefTimer(initialTimer);\n\n retryInterval = setInterval(() => {\n void retryRemoteCommands().catch((err) => {\n console.error(\"[integrations] Remote command retry job error:\", err);\n });\n }, RETRY_INTERVAL_MS);\n unrefTimer(retryInterval);\n}\n\nexport function stopRemoteCommandsRetryJob(): void {\n if (initialTimer) {\n clearTimeout(initialTimer);\n initialTimer = null;\n }\n if (retryInterval) {\n clearInterval(retryInterval);\n retryInterval = null;\n }\n}\n\nfunction unrefTimer(timer: ReturnType<typeof setInterval>): void {\n (timer as unknown as { unref?: () => void }).unref?.();\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RemoteRunEvent } from "./remote-types.js";
|
|
2
|
+
export declare function insertRemoteRunEvents(input: {
|
|
3
|
+
deviceId: string;
|
|
4
|
+
remoteRunId: string;
|
|
5
|
+
events: Array<{
|
|
6
|
+
seq: number;
|
|
7
|
+
event: unknown;
|
|
8
|
+
}>;
|
|
9
|
+
}): Promise<{
|
|
10
|
+
inserted: number;
|
|
11
|
+
}>;
|
|
12
|
+
export declare function listRemoteRunEvents(input: {
|
|
13
|
+
deviceId: string;
|
|
14
|
+
remoteRunId: string;
|
|
15
|
+
afterSeq?: number;
|
|
16
|
+
limit?: number;
|
|
17
|
+
}): Promise<RemoteRunEvent[]>;
|
|
18
|
+
//# sourceMappingURL=remote-run-events-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-run-events-store.d.ts","sourceRoot":"","sources":["../../src/integrations/remote-run-events-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AA4CxD,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAChD,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBhC;AAED,wBAAsB,mBAAmB,CAAC,KAAK,EAAE;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAiB5B"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { getDbExec, intType, retryOnDdlRace } from "../db/client.js";
|
|
2
|
+
let _initPromise;
|
|
3
|
+
async function ensureTable() {
|
|
4
|
+
if (!_initPromise) {
|
|
5
|
+
_initPromise = (async () => {
|
|
6
|
+
const client = getDbExec();
|
|
7
|
+
await retryOnDdlRace(() => client.execute(`
|
|
8
|
+
CREATE TABLE IF NOT EXISTS integration_remote_run_events (
|
|
9
|
+
device_id TEXT NOT NULL,
|
|
10
|
+
remote_run_id TEXT NOT NULL,
|
|
11
|
+
seq ${intType()} NOT NULL,
|
|
12
|
+
event_json TEXT NOT NULL,
|
|
13
|
+
created_at ${intType()} NOT NULL
|
|
14
|
+
)
|
|
15
|
+
`));
|
|
16
|
+
await retryOnDdlRace(() => client.execute(`CREATE UNIQUE INDEX IF NOT EXISTS idx_remote_run_events_unique ON integration_remote_run_events(device_id, remote_run_id, seq)`));
|
|
17
|
+
await retryOnDdlRace(() => client.execute(`CREATE INDEX IF NOT EXISTS idx_remote_run_events_run ON integration_remote_run_events(device_id, remote_run_id, seq)`));
|
|
18
|
+
})();
|
|
19
|
+
}
|
|
20
|
+
return _initPromise;
|
|
21
|
+
}
|
|
22
|
+
function rowToRunEvent(row) {
|
|
23
|
+
return {
|
|
24
|
+
deviceId: row.device_id,
|
|
25
|
+
remoteRunId: row.remote_run_id,
|
|
26
|
+
seq: Number(row.seq ?? 0),
|
|
27
|
+
event: parseJson(row.event_json, null),
|
|
28
|
+
createdAt: Number(row.created_at ?? 0),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export async function insertRemoteRunEvents(input) {
|
|
32
|
+
await ensureTable();
|
|
33
|
+
const client = getDbExec();
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
let inserted = 0;
|
|
36
|
+
for (const event of input.events) {
|
|
37
|
+
const result = await client.execute({
|
|
38
|
+
sql: `INSERT INTO integration_remote_run_events
|
|
39
|
+
(device_id, remote_run_id, seq, event_json, created_at)
|
|
40
|
+
VALUES (?, ?, ?, ?, ?)
|
|
41
|
+
ON CONFLICT(device_id, remote_run_id, seq) DO NOTHING`,
|
|
42
|
+
args: [
|
|
43
|
+
input.deviceId,
|
|
44
|
+
input.remoteRunId,
|
|
45
|
+
event.seq,
|
|
46
|
+
JSON.stringify(event.event ?? null),
|
|
47
|
+
now,
|
|
48
|
+
],
|
|
49
|
+
});
|
|
50
|
+
inserted += result.rowsAffected ?? result.rowCount ?? 0;
|
|
51
|
+
}
|
|
52
|
+
return { inserted };
|
|
53
|
+
}
|
|
54
|
+
export async function listRemoteRunEvents(input) {
|
|
55
|
+
await ensureTable();
|
|
56
|
+
const { rows } = await getDbExec().execute({
|
|
57
|
+
sql: `SELECT * FROM integration_remote_run_events
|
|
58
|
+
WHERE device_id = ?
|
|
59
|
+
AND remote_run_id = ?
|
|
60
|
+
AND seq > ?
|
|
61
|
+
ORDER BY seq ASC
|
|
62
|
+
LIMIT ?`,
|
|
63
|
+
args: [
|
|
64
|
+
input.deviceId,
|
|
65
|
+
input.remoteRunId,
|
|
66
|
+
input.afterSeq ?? -1,
|
|
67
|
+
input.limit ?? 500,
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
return rows.map((row) => rowToRunEvent(row));
|
|
71
|
+
}
|
|
72
|
+
function parseJson(value, fallback) {
|
|
73
|
+
if (value == null)
|
|
74
|
+
return fallback;
|
|
75
|
+
try {
|
|
76
|
+
return JSON.parse(String(value));
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return fallback;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=remote-run-events-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-run-events-store.js","sourceRoot":"","sources":["../../src/integrations/remote-run-events-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { getDbExec, intType, retryOnDdlRace } from \"../db/client.js\";\nimport type { RemoteRunEvent } from \"./remote-types.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n await retryOnDdlRace(() =>\n client.execute(`\n CREATE TABLE IF NOT EXISTS integration_remote_run_events (\n device_id TEXT NOT NULL,\n remote_run_id TEXT NOT NULL,\n seq ${intType()} NOT NULL,\n event_json TEXT NOT NULL,\n created_at ${intType()} NOT NULL\n )\n `),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_remote_run_events_unique ON integration_remote_run_events(device_id, remote_run_id, seq)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_remote_run_events_run ON integration_remote_run_events(device_id, remote_run_id, seq)`,\n ),\n );\n })();\n }\n return _initPromise;\n}\n\nfunction rowToRunEvent(row: Record<string, unknown>): RemoteRunEvent {\n return {\n deviceId: row.device_id as string,\n remoteRunId: row.remote_run_id as string,\n seq: Number(row.seq ?? 0),\n event: parseJson(row.event_json, null),\n createdAt: Number(row.created_at ?? 0),\n };\n}\n\nexport async function insertRemoteRunEvents(input: {\n deviceId: string;\n remoteRunId: string;\n events: Array<{ seq: number; event: unknown }>;\n}): Promise<{ inserted: number }> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n let inserted = 0;\n\n for (const event of input.events) {\n const result = await client.execute({\n sql: `INSERT INTO integration_remote_run_events\n (device_id, remote_run_id, seq, event_json, created_at)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(device_id, remote_run_id, seq) DO NOTHING`,\n args: [\n input.deviceId,\n input.remoteRunId,\n event.seq,\n JSON.stringify(event.event ?? null),\n now,\n ],\n });\n inserted += result.rowsAffected ?? (result as any).rowCount ?? 0;\n }\n\n return { inserted };\n}\n\nexport async function listRemoteRunEvents(input: {\n deviceId: string;\n remoteRunId: string;\n afterSeq?: number;\n limit?: number;\n}): Promise<RemoteRunEvent[]> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_run_events\n WHERE device_id = ?\n AND remote_run_id = ?\n AND seq > ?\n ORDER BY seq ASC\n LIMIT ?`,\n args: [\n input.deviceId,\n input.remoteRunId,\n input.afterSeq ?? -1,\n input.limit ?? 500,\n ],\n });\n return rows.map((row) => rowToRunEvent(row as Record<string, unknown>));\n}\n\nfunction parseJson(value: unknown, fallback: unknown): unknown {\n if (value == null) return fallback;\n try {\n return JSON.parse(String(value));\n } catch {\n return fallback;\n }\n}\n"]}
|