whale-code 6.5.6 → 6.5.7
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 +1 -1
- package/bin/whale-code.js +23 -0
- package/dist/cli/__tests__/print-mode-streaming.test.js +270 -0
- package/dist/cli/__tests__/print-mode.basic-output.test.js +230 -0
- package/dist/cli/__tests__/print-mode.session-errors.test.js +252 -0
- package/dist/cli/__tests__/print-mode.test.js +273 -0
- package/dist/cli/__tests__/serve-mode-messages.test.js +338 -0
- package/dist/cli/__tests__/serve-mode.messages.part2.test.js +266 -0
- package/dist/cli/__tests__/serve-mode.messages.test.js +277 -0
- package/dist/cli/__tests__/serve-mode.startup-http.test.js +279 -0
- package/dist/cli/__tests__/serve-mode.test.js +345 -0
- package/dist/cli/app.d.ts +1 -0
- package/dist/cli/app.js +8 -2
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/chat/ChatApp.d.ts +8 -36
- package/dist/cli/chat/ChatApp.js +135 -450
- package/dist/cli/chat/ChatApp.js.map +1 -1
- package/dist/cli/chat/ChatInput.d.ts +3 -2
- package/dist/cli/chat/ChatInput.js +37 -14
- package/dist/cli/chat/ChatInput.js.map +1 -1
- package/dist/cli/chat/ImsgManager.d.ts +20 -0
- package/dist/cli/chat/ImsgManager.js +341 -0
- package/dist/cli/chat/ImsgManager.js.map +1 -0
- package/dist/cli/chat/MarkdownText.d.ts +2 -1
- package/dist/cli/chat/MarkdownText.js +12 -8
- package/dist/cli/chat/MarkdownText.js.map +1 -1
- package/dist/cli/chat/MemoryManager.js +3 -2
- package/dist/cli/chat/MemoryManager.js.map +1 -1
- package/dist/cli/chat/MessageList.d.ts +1 -1
- package/dist/cli/chat/MessageList.js +119 -114
- package/dist/cli/chat/MessageList.js.map +1 -1
- package/dist/cli/chat/NodeManager.js +57 -170
- package/dist/cli/chat/NodeManager.js.map +1 -1
- package/dist/cli/chat/OverlayContext.d.ts +27 -0
- package/dist/cli/chat/OverlayContext.js +2 -0
- package/dist/cli/chat/OverlayContext.js.map +1 -0
- package/dist/cli/chat/PlanApproval.js +3 -2
- package/dist/cli/chat/PlanApproval.js.map +1 -1
- package/dist/cli/chat/RewindConfirmation.d.ts +12 -0
- package/dist/cli/chat/RewindConfirmation.js +243 -0
- package/dist/cli/chat/RewindConfirmation.js.map +1 -0
- package/dist/cli/chat/RewindViewer.js +5 -4
- package/dist/cli/chat/RewindViewer.js.map +1 -1
- package/dist/cli/chat/SessionManager.js +3 -2
- package/dist/cli/chat/SessionManager.js.map +1 -1
- package/dist/cli/chat/SlashMenu.d.ts +7 -24
- package/dist/cli/chat/SlashMenu.js +14 -183
- package/dist/cli/chat/SlashMenu.js.map +1 -1
- package/dist/cli/chat/StatusBar.d.ts +5 -2
- package/dist/cli/chat/StatusBar.js +80 -65
- package/dist/cli/chat/StatusBar.js.map +1 -1
- package/dist/cli/chat/StreamingText.d.ts +2 -1
- package/dist/cli/chat/StreamingText.js +2 -2
- package/dist/cli/chat/StreamingText.js.map +1 -1
- package/dist/cli/chat/SubagentPanel.d.ts +6 -6
- package/dist/cli/chat/SubagentPanel.js +159 -537
- package/dist/cli/chat/SubagentPanel.js.map +1 -1
- package/dist/cli/chat/TeamPanel.js +2 -30
- package/dist/cli/chat/TeamPanel.js.map +1 -1
- package/dist/cli/chat/ToolIndicator.d.ts +7 -23
- package/dist/cli/chat/ToolIndicator.js +543 -1443
- package/dist/cli/chat/ToolIndicator.js.map +1 -1
- package/dist/cli/chat/chat-input-menu-handler.d.ts +32 -0
- package/dist/cli/chat/components/LiveArea.d.ts +12 -0
- package/dist/cli/chat/components/LiveArea.js +252 -0
- package/dist/cli/chat/components/LiveArea.js.map +1 -0
- package/dist/cli/chat/components/OverlayRouter.d.ts +13 -0
- package/dist/cli/chat/components/OverlayRouter.js +257 -0
- package/dist/cli/chat/components/OverlayRouter.js.map +1 -0
- package/dist/cli/chat/components/StaticMessages.d.ts +9 -0
- package/dist/cli/chat/components/StaticMessages.js +132 -0
- package/dist/cli/chat/components/StaticMessages.js.map +1 -0
- package/dist/cli/chat/hooks/agent-loop-events.d.ts +77 -0
- package/dist/cli/chat/hooks/agent-loop-events.js +171 -0
- package/dist/cli/chat/hooks/agent-loop-events.js.map +1 -0
- package/dist/cli/chat/hooks/slash-command-config-system.d.ts +11 -0
- package/dist/cli/chat/hooks/slash-command-config-system.js +177 -0
- package/dist/cli/chat/hooks/slash-command-config-system.js.map +1 -0
- package/dist/cli/chat/hooks/slash-command-handlers-system.d.ts +12 -0
- package/dist/cli/chat/hooks/slash-command-handlers-system.js +127 -0
- package/dist/cli/chat/hooks/slash-command-handlers-system.js.map +1 -0
- package/dist/cli/chat/hooks/slash-command-handlers.d.ts +21 -0
- package/dist/cli/chat/hooks/slash-command-handlers.js +222 -0
- package/dist/cli/chat/hooks/slash-command-handlers.js.map +1 -0
- package/dist/cli/chat/hooks/slash-imsg-handlers.js +148 -0
- package/dist/cli/chat/hooks/slash-imsg-handlers.js.map +1 -0
- package/dist/cli/chat/hooks/slash-node-handlers.d.ts +26 -0
- package/dist/cli/chat/hooks/slash-node-handlers.js +226 -0
- package/dist/cli/chat/hooks/slash-node-handlers.js.map +1 -0
- package/dist/cli/chat/hooks/useAgentLoop.d.ts +2 -21
- package/dist/cli/chat/hooks/useAgentLoop.js +258 -401
- package/dist/cli/chat/hooks/useAgentLoop.js.map +1 -1
- package/dist/cli/chat/hooks/useElapsedClock.d.ts +19 -0
- package/dist/cli/chat/hooks/useElapsedClock.js +80 -0
- package/dist/cli/chat/hooks/useElapsedClock.js.map +1 -0
- package/dist/cli/chat/hooks/useOverlayHandlers.d.ts +23 -0
- package/dist/cli/chat/hooks/useOverlayHandlers.js +125 -0
- package/dist/cli/chat/hooks/useOverlayHandlers.js.map +1 -0
- package/dist/cli/chat/hooks/useSlashCommands.d.ts +14 -22
- package/dist/cli/chat/hooks/useSlashCommands.js +99 -720
- package/dist/cli/chat/hooks/useSlashCommands.js.map +1 -1
- package/dist/cli/chat/hooks/useStreamingReducer.d.ts +66 -0
- package/dist/cli/chat/imsg-manager-render.d.ts +29 -0
- package/dist/cli/chat/imsg-manager-render.js +294 -0
- package/dist/cli/chat/imsg-manager-render.js.map +1 -0
- package/dist/cli/chat/slash-commands.d.ts +37 -0
- package/dist/cli/chat/slash-commands.js +194 -0
- package/dist/cli/chat/slash-commands.js.map +1 -0
- package/dist/cli/chat/store.d.ts +115 -0
- package/dist/cli/chat/store.js +177 -0
- package/dist/cli/chat/store.js.map +1 -0
- package/dist/cli/chat/tool-indicator-helpers.d.ts +14 -0
- package/dist/cli/chat/tool-indicator-helpers.js +167 -0
- package/dist/cli/chat/tool-indicator-helpers.js.map +1 -0
- package/dist/cli/chat/tool-indicator-summary.d.ts +6 -0
- package/dist/cli/chat/tool-indicator-summary.js +103 -0
- package/dist/cli/chat/tool-indicator-summary.js.map +1 -0
- package/dist/cli/chat/tool-indicator-types.d.ts +66 -0
- package/dist/cli/chat/tool-indicator-types.js +177 -0
- package/dist/cli/chat/tool-indicator-types.js.map +1 -0
- package/dist/cli/commands/__tests__/config-cmd.test.js +270 -0
- package/dist/cli/commands/__tests__/doctor.test.js +257 -0
- package/dist/cli/commands/__tests__/imsg-node-bridge.test.js +99 -0
- package/dist/cli/commands/__tests__/imsg-utils.test.js +73 -0
- package/dist/cli/commands/__tests__/init.test.js +214 -0
- package/dist/cli/commands/__tests__/mcp.test.js +287 -0
- package/dist/cli/commands/imsg-config.d.ts +31 -0
- package/dist/cli/commands/imsg-config.js +104 -0
- package/dist/cli/commands/imsg-config.js.map +1 -0
- package/dist/cli/commands/imsg-node-bridge.d.ts +25 -0
- package/dist/cli/commands/imsg-node-bridge.js +229 -0
- package/dist/cli/commands/imsg-node-bridge.js.map +1 -0
- package/dist/cli/commands/imsg-utils.d.ts +14 -0
- package/dist/cli/commands/imsg-utils.js +42 -0
- package/dist/cli/commands/imsg-utils.js.map +1 -0
- package/dist/cli/commands/imsg-watcher-helpers.d.ts +40 -0
- package/dist/cli/commands/imsg-watcher-helpers.js +184 -0
- package/dist/cli/commands/imsg-watcher-helpers.js.map +1 -0
- package/dist/cli/commands/imsg-watcher.d.ts +11 -0
- package/dist/cli/commands/imsg-watcher.js +230 -0
- package/dist/cli/commands/imsg-watcher.js.map +1 -0
- package/dist/cli/commands/imsg.d.ts +14 -0
- package/dist/cli/commands/imsg.js +181 -0
- package/dist/cli/commands/imsg.js.map +1 -0
- package/dist/cli/commands/sessions.d.ts +9 -0
- package/dist/cli/commands/sessions.js +93 -0
- package/dist/cli/commands/sessions.js.map +1 -0
- package/dist/cli/login/LoginApp.js +3 -0
- package/dist/cli/login/LoginApp.js.map +1 -1
- package/dist/cli/serve-mode-persistence.d.ts +18 -0
- package/dist/cli/serve-mode-persistence.js +157 -0
- package/dist/cli/serve-mode-persistence.js.map +1 -0
- package/dist/cli/serve-mode-query.d.ts +9 -0
- package/dist/cli/serve-mode-query.js +247 -0
- package/dist/cli/serve-mode-query.js.map +1 -0
- package/dist/cli/serve-mode-types.d.ts +29 -0
- package/dist/cli/serve-mode-types.js +56 -0
- package/dist/cli/serve-mode-types.js.map +1 -0
- package/dist/cli/services/__tests__/agent-definitions.test.js +153 -0
- package/dist/cli/services/__tests__/agent-events-global.test.js +39 -0
- package/dist/cli/services/__tests__/agent-events.part2.test.js +113 -0
- package/dist/cli/services/__tests__/agent-events.test.js +157 -0
- package/dist/cli/services/__tests__/agent-loop-auth.test.js +392 -0
- package/dist/cli/services/__tests__/agent-loop-budget.test.js +389 -0
- package/dist/cli/services/__tests__/agent-loop-tools-lifecycle.test.js +430 -0
- package/dist/cli/services/__tests__/agent-loop-tools-maxturns.test.js +486 -0
- package/dist/cli/services/__tests__/agent-loop-utils-execution.test.js +528 -0
- package/dist/cli/services/__tests__/agent-loop-utils-helpers.test.js +466 -0
- package/dist/cli/services/__tests__/agent-worker-base-execute.test.js +257 -0
- package/dist/cli/services/__tests__/agent-worker-base-helpers.test.js +198 -0
- package/dist/cli/services/__tests__/agent-worker-base.test.js +278 -0
- package/dist/cli/services/__tests__/auth-service-exports.test.js +41 -0
- package/dist/cli/services/__tests__/auth-service.part2.test.js +169 -0
- package/dist/cli/services/__tests__/auth-service.test.js +242 -0
- package/dist/cli/services/__tests__/background-processes.test.js +282 -0
- package/dist/cli/services/__tests__/claude-md-loader.test.js +134 -0
- package/dist/cli/services/__tests__/config-store.test.js +247 -0
- package/dist/cli/services/__tests__/debug-log.test.js +199 -0
- package/dist/cli/services/__tests__/edge-cases-caching.test.js +174 -0
- package/dist/cli/services/__tests__/edge-cases-compaction-core.test.js +226 -0
- package/dist/cli/services/__tests__/edge-cases-compaction-openai.test.js +152 -0
- package/dist/cli/services/__tests__/edge-cases-compaction-shapes.test.js +53 -0
- package/dist/cli/services/__tests__/edge-cases-compaction-thinking.test.js +226 -0
- package/dist/cli/services/__tests__/edge-cases-compaction.test.js +131 -0
- package/dist/cli/services/__tests__/edge-cases-paths.test.js +86 -0
- package/dist/cli/services/__tests__/error-logger-messages.test.js +81 -0
- package/dist/cli/services/__tests__/error-logger-transport.test.js +119 -0
- package/dist/cli/services/__tests__/error-logger.test.js +264 -0
- package/dist/cli/services/__tests__/file-history.test.js +136 -0
- package/dist/cli/services/__tests__/git-context-cache-reset.test.js +223 -0
- package/dist/cli/services/__tests__/git-context.test.js +241 -0
- package/dist/cli/services/__tests__/interactive-tools-execute.test.js +166 -0
- package/dist/cli/services/__tests__/interactive-tools-plan.test.js +197 -0
- package/dist/cli/services/__tests__/interactive-tools.part2.test.js +168 -0
- package/dist/cli/services/__tests__/interactive-tools.test.js +179 -0
- package/dist/cli/services/__tests__/keybinding-manager.test.js +205 -0
- package/dist/cli/services/__tests__/local-tools-dispatch.test.js +404 -0
- package/dist/cli/services/__tests__/local-tools.test.js +238 -0
- package/dist/cli/services/__tests__/lsp-manager.test.js +364 -0
- package/dist/cli/services/__tests__/mcp-client-connect-disconnect.test.js +310 -0
- package/dist/cli/services/__tests__/mcp-client.test.js +93 -0
- package/dist/cli/services/__tests__/memory-manager.test.js +154 -0
- package/dist/cli/services/__tests__/model-manager-utils.test.js +154 -0
- package/dist/cli/services/__tests__/model-manager.test.js +175 -0
- package/dist/cli/services/__tests__/permission-modes.test.js +222 -0
- package/dist/cli/services/__tests__/ripgrep.test.js +328 -0
- package/dist/cli/services/__tests__/server-tools-execute.test.js +317 -0
- package/dist/cli/services/__tests__/server-tools.test.js +272 -0
- package/dist/cli/services/__tests__/session-persistence.test.js +245 -0
- package/dist/cli/services/__tests__/subagent-basic.test.js +489 -0
- package/dist/cli/services/__tests__/subagent-edge.test.js +545 -0
- package/dist/cli/services/__tests__/subagent-prompts.test.js +558 -0
- package/dist/cli/services/__tests__/subagent-worker-errors.test.js +255 -0
- package/dist/cli/services/__tests__/subagent-worker.test.js +242 -0
- package/dist/cli/services/__tests__/system-prompt.test.js +210 -0
- package/dist/cli/services/__tests__/team-lead-comms-messaging.test.js +250 -0
- package/dist/cli/services/__tests__/team-lead-comms-result.test.js +232 -0
- package/dist/cli/services/__tests__/team-lead-comms-stop.test.js +344 -0
- package/dist/cli/services/__tests__/team-lead-comms.test.js +285 -0
- package/dist/cli/services/__tests__/team-lead-create.test.js +327 -0
- package/dist/cli/services/__tests__/team-lead-run.test.js +318 -0
- package/dist/cli/services/__tests__/team-lead-stop.test.js +199 -0
- package/dist/cli/services/__tests__/team-state-comms.test.js +240 -0
- package/dist/cli/services/__tests__/team-state-core.test.js +230 -0
- package/dist/cli/services/__tests__/team-state-tasks-complete-fail-available.test.js +224 -0
- package/dist/cli/services/__tests__/team-state-tasks.test.js +184 -0
- package/dist/cli/services/__tests__/telemetry-ai-metadata.test.js +116 -0
- package/dist/cli/services/__tests__/telemetry.part2.test.js +195 -0
- package/dist/cli/services/__tests__/telemetry.test.js +176 -0
- package/dist/cli/services/agent-event-types.d.ts +148 -0
- package/dist/cli/services/agent-event-types.js +2 -0
- package/dist/cli/services/agent-event-types.js.map +1 -0
- package/dist/cli/services/agent-loop-iteration.d.ts +13 -0
- package/dist/cli/services/agent-loop-setup.d.ts +32 -0
- package/dist/cli/services/agent-loop-shell-summarize.d.ts +11 -0
- package/dist/cli/services/agent-loop-shell-summarize.js +94 -0
- package/dist/cli/services/agent-loop-shell-summarize.js.map +1 -0
- package/dist/cli/services/agent-loop-tools.d.ts +37 -0
- package/dist/cli/services/agent-loop-tools.js +243 -0
- package/dist/cli/services/agent-loop-tools.js.map +1 -0
- package/dist/cli/services/agent-loop-types.d.ts +52 -0
- package/dist/cli/services/agent-loop-types.js +25 -0
- package/dist/cli/services/agent-loop-types.js.map +1 -0
- package/dist/cli/services/agent-loop.d.ts +2 -2
- package/dist/cli/services/agent-loop.js +162 -17
- package/dist/cli/services/agent-loop.js.map +1 -1
- package/dist/cli/services/agent-worker-base-api.d.ts +19 -0
- package/dist/cli/services/agent-worker-base-helpers.d.ts +27 -0
- package/dist/cli/services/agent-worker-base-tools.d.ts +16 -0
- package/dist/cli/services/agent-worker-base-types.d.ts +81 -0
- package/dist/cli/services/agent-worker-base.js +1 -1
- package/dist/cli/services/agent-worker-base.js.map +1 -1
- package/dist/cli/services/auth-service.js +19 -19
- package/dist/cli/services/auth-service.js.map +1 -1
- package/dist/cli/services/background-agents.d.ts +26 -0
- package/dist/cli/services/background-processes-ops.d.ts +24 -0
- package/dist/cli/services/background-processes.d.ts +2 -1
- package/dist/cli/services/background-processes.js +7 -3
- package/dist/cli/services/background-processes.js.map +1 -1
- package/dist/cli/services/background-tool-defs.d.ts +50 -0
- package/dist/cli/services/cli-agent-loop.d.ts +41 -0
- package/dist/cli/services/cli-agent-loop.js +104 -0
- package/dist/cli/services/cli-agent-loop.js.map +1 -0
- package/dist/cli/services/config-modules-model.test.js +133 -0
- package/dist/cli/services/config-modules-permission.test.js +85 -0
- package/dist/cli/services/config-modules-permissions.test.js +85 -0
- package/dist/cli/services/config-modules-session.test.js +297 -0
- package/dist/cli/services/config-store.d.ts +5 -0
- package/dist/cli/services/config-store.js +90 -5
- package/dist/cli/services/config-store.js.map +1 -1
- package/dist/cli/services/error-logger-internals.d.ts +25 -0
- package/dist/cli/services/error-logger-internals.js +111 -0
- package/dist/cli/services/error-logger-internals.js.map +1 -0
- package/dist/cli/services/format-server-response-columns.test.js +265 -0
- package/dist/cli/services/format-server-response-fallback.test.js +65 -0
- package/dist/cli/services/format-server-response-formatters.d.ts +18 -0
- package/dist/cli/services/format-server-response-formatters.js +195 -0
- package/dist/cli/services/format-server-response-formatters.js.map +1 -0
- package/dist/cli/services/format-server-response-primitives-basic.test.js +261 -0
- package/dist/cli/services/format-server-response-primitives-nested.test.js +188 -0
- package/dist/cli/services/format-server-response-primitives.test.js +300 -0
- package/dist/cli/services/format-server-response-realworld.test.js +248 -0
- package/dist/cli/services/format-server-response-values.test.js +247 -0
- package/dist/cli/services/format-server-response.js +5 -3
- package/dist/cli/services/format-server-response.js.map +1 -1
- package/dist/cli/services/hooks-execute.d.ts +47 -0
- package/dist/cli/services/hooks-execute.js +181 -0
- package/dist/cli/services/hooks-execute.js.map +1 -0
- package/dist/cli/services/hooks-runners.test.js +184 -0
- package/dist/cli/services/hooks.glob-load.test.js +233 -0
- package/dist/cli/services/hooks.run-hooks.test.js +184 -0
- package/dist/cli/services/hooks.test.js +233 -0
- package/dist/cli/services/interactive-tool-defs.d.ts +80 -0
- package/dist/cli/services/interactive-tools.d.ts +5 -2
- package/dist/cli/services/interactive-tools.js +47 -33
- package/dist/cli/services/interactive-tools.js.map +1 -1
- package/dist/cli/services/keybinding-manager.d.ts +2 -0
- package/dist/cli/services/keybinding-manager.js +5 -0
- package/dist/cli/services/keybinding-manager.js.map +1 -1
- package/dist/cli/services/local-tools-agent-defs-tasks.d.ts +6 -0
- package/dist/cli/services/local-tools-agent-defs-tasks.js +245 -0
- package/dist/cli/services/local-tools-agent-defs-tasks.js.map +1 -0
- package/dist/cli/services/local-tools-agent-defs-utils.d.ts +6 -0
- package/dist/cli/services/local-tools-agent-defs-utils.js +198 -0
- package/dist/cli/services/local-tools-agent-defs-utils.js.map +1 -0
- package/dist/cli/services/local-tools-agent-defs.d.ts +10 -0
- package/dist/cli/services/local-tools-agent-defs.js +13 -0
- package/dist/cli/services/local-tools-agent-defs.js.map +1 -0
- package/dist/cli/services/local-tools-definitions.d.ts +6 -0
- package/dist/cli/services/local-tools-files.test.js +256 -0
- package/dist/cli/services/local-tools-read-many.d.ts +6 -0
- package/dist/cli/services/local-tools.js +7 -9
- package/dist/cli/services/local-tools.js.map +1 -1
- package/dist/cli/services/lsp-config.d.ts +13 -0
- package/dist/cli/services/lsp-config.js +72 -0
- package/dist/cli/services/lsp-config.js.map +1 -0
- package/dist/cli/services/lsp-formatters.d.ts +11 -0
- package/dist/cli/services/lsp-formatters.js +209 -0
- package/dist/cli/services/lsp-formatters.js.map +1 -0
- package/dist/cli/services/lsp-protocol.d.ts +9 -0
- package/dist/cli/services/lsp-protocol.js +40 -0
- package/dist/cli/services/lsp-protocol.js.map +1 -0
- package/dist/cli/services/lsp-server-docs.d.ts +8 -0
- package/dist/cli/services/lsp-server-docs.js +132 -0
- package/dist/cli/services/lsp-server-docs.js.map +1 -0
- package/dist/cli/services/lsp-server-documents.d.ts +8 -0
- package/dist/cli/services/lsp-server-documents.js +132 -0
- package/dist/cli/services/lsp-server-documents.js.map +1 -0
- package/dist/cli/services/lsp-server.d.ts +40 -0
- package/dist/cli/services/lsp-server.js +270 -0
- package/dist/cli/services/lsp-server.js.map +1 -0
- package/dist/cli/services/model-router.test.js +245 -0
- package/dist/cli/services/permission-modes.js +16 -3
- package/dist/cli/services/permission-modes.js.map +1 -1
- package/dist/cli/services/project-index.d.ts +41 -0
- package/dist/cli/services/project-index.js +286 -0
- package/dist/cli/services/project-index.js.map +1 -0
- package/dist/cli/services/rewind-rewindTo.test.js +202 -0
- package/dist/cli/services/rewind.test.js +175 -0
- package/dist/cli/services/sandbox.test.js +198 -0
- package/dist/cli/services/server-tools-client.d.ts +46 -0
- package/dist/cli/services/server-tools-client.js +211 -0
- package/dist/cli/services/server-tools-client.js.map +1 -0
- package/dist/cli/services/server-tools-media.d.ts +21 -0
- package/dist/cli/services/server-tools-media.js +163 -0
- package/dist/cli/services/server-tools-media.js.map +1 -0
- package/dist/cli/services/server-tools-preprocess.d.ts +23 -0
- package/dist/cli/services/server-tools-preprocess.js +386 -0
- package/dist/cli/services/server-tools-preprocess.js.map +1 -0
- package/dist/cli/services/server-tools.d.ts +2 -0
- package/dist/cli/services/server-tools.js +40 -15
- package/dist/cli/services/server-tools.js.map +1 -1
- package/dist/cli/services/session-client.d.ts +78 -0
- package/dist/cli/services/session-client.js +197 -0
- package/dist/cli/services/session-client.js.map +1 -0
- package/dist/cli/services/session-persistence.d.ts +3 -0
- package/dist/cli/services/session-persistence.js +12 -0
- package/dist/cli/services/session-persistence.js.map +1 -1
- package/dist/cli/services/subagent-execution.d.ts +12 -0
- package/dist/cli/services/subagent-loop-v2.d.ts +36 -0
- package/dist/cli/services/subagent-loop-v2.js +238 -0
- package/dist/cli/services/subagent-loop-v2.js.map +1 -0
- package/dist/cli/services/subagent-tools.d.ts +10 -0
- package/dist/cli/services/subagent-tools.js +96 -0
- package/dist/cli/services/subagent-tools.js.map +1 -0
- package/dist/cli/services/subagent-types.d.ts +57 -0
- package/dist/cli/services/subagent-types.js +218 -0
- package/dist/cli/services/subagent-types.js.map +1 -0
- package/dist/cli/services/subagent.js +3 -2
- package/dist/cli/services/subagent.js.map +1 -1
- package/dist/cli/services/system-prompt.js +26 -3
- package/dist/cli/services/system-prompt.js.map +1 -1
- package/dist/cli/services/team-lead-auto.d.ts +11 -0
- package/dist/cli/services/team-lead-execution.d.ts +28 -0
- package/dist/cli/services/team-lead-types.d.ts +37 -0
- package/dist/cli/services/team-lead-types.js +2 -0
- package/dist/cli/services/team-lead-types.js.map +1 -0
- package/dist/cli/services/team-lead.d.ts +60 -0
- package/dist/cli/services/team-lead.js +148 -11
- package/dist/cli/services/team-lead.js.map +1 -1
- package/dist/cli/services/team-state-members.d.ts +11 -0
- package/dist/cli/services/team-state-members.js +185 -0
- package/dist/cli/services/team-state-members.js.map +1 -0
- package/dist/cli/services/team-state-messaging.d.ts +16 -0
- package/dist/cli/services/team-state-messaging.js +90 -0
- package/dist/cli/services/team-state-messaging.js.map +1 -0
- package/dist/cli/services/team-state-tasks.d.ts +12 -0
- package/dist/cli/services/team-state-tasks.js +23 -0
- package/dist/cli/services/team-state-tasks.js.map +1 -0
- package/dist/cli/services/team-state-types.d.ts +54 -0
- package/dist/cli/services/team-state-types.js +129 -0
- package/dist/cli/services/team-state-types.js.map +1 -0
- package/dist/cli/services/team-state.d.ts +5 -0
- package/dist/cli/services/team-state.js +29 -0
- package/dist/cli/services/team-state.js.map +1 -1
- package/dist/cli/services/teammate-loop.js +557 -0
- package/dist/cli/services/teammate-loop.js.map +1 -0
- package/dist/cli/services/teammate-prompt.d.ts +2 -0
- package/dist/cli/services/teammate-prompt.js +68 -0
- package/dist/cli/services/teammate-prompt.js.map +1 -0
- package/dist/cli/services/teammate-tools.d.ts +6 -0
- package/dist/cli/services/teammate-tools.js +158 -0
- package/dist/cli/services/teammate-tools.js.map +1 -0
- package/dist/cli/services/teammate-types.d.ts +36 -0
- package/dist/cli/services/teammate-types.js +43 -0
- package/dist/cli/services/teammate-types.js.map +1 -0
- package/dist/cli/services/teammate-worker-helpers.d.ts +71 -0
- package/dist/cli/services/teammate-worker-helpers.js +183 -0
- package/dist/cli/services/teammate-worker-helpers.js.map +1 -0
- package/dist/cli/services/teammate-worker-task-cleanup.d.ts +27 -0
- package/dist/cli/services/teammate-worker-task-cleanup.js +91 -0
- package/dist/cli/services/teammate-worker-task-cleanup.js.map +1 -0
- package/dist/cli/services/teammate-worker-task-loop.d.ts +35 -0
- package/dist/cli/services/teammate-worker-task-loop.js +273 -0
- package/dist/cli/services/teammate-worker-task-loop.js.map +1 -0
- package/dist/cli/services/teammate-worker.d.ts +13 -0
- package/dist/cli/services/teammate-worker.js +294 -0
- package/dist/cli/services/teammate-worker.js.map +1 -0
- package/dist/cli/services/telemetry-spans.d.ts +17 -0
- package/dist/cli/services/telemetry-spans.js +172 -0
- package/dist/cli/services/telemetry-spans.js.map +1 -0
- package/dist/cli/services/tools/__tests__/agent-tools-tasks-teams.test.js +250 -0
- package/dist/cli/services/tools/__tests__/agent-tools-teams.test.js +200 -0
- package/dist/cli/services/tools/__tests__/agent-tools.test.js +340 -0
- package/dist/cli/services/tools/__tests__/file-ops-cache.test.js +152 -0
- package/dist/cli/services/tools/__tests__/file-ops-notebook.test.js +249 -0
- package/dist/cli/services/tools/__tests__/file-ops-read.test.js +261 -0
- package/dist/cli/services/tools/__tests__/file-ops-write.test.js +292 -0
- package/dist/cli/services/tools/__tests__/search-tools-rg.test.js +92 -0
- package/dist/cli/services/tools/__tests__/search-tools.part2.test.js +174 -0
- package/dist/cli/services/tools/__tests__/search-tools.test.js +227 -0
- package/dist/cli/services/tools/__tests__/shell-exec-allowed-core.test.js +163 -0
- package/dist/cli/services/tools/__tests__/shell-exec-allowed-extended.test.js +220 -0
- package/dist/cli/services/tools/__tests__/shell-exec-allowed.part2.test.js +215 -0
- package/dist/cli/services/tools/__tests__/shell-exec-allowed.test.js +154 -0
- package/dist/cli/services/tools/__tests__/shell-exec-blocked.test.js +132 -0
- package/dist/cli/services/tools/__tests__/shell-exec-execution.test.js +245 -0
- package/dist/cli/services/tools/__tests__/task-manager-create.test.js +110 -0
- package/dist/cli/services/tools/__tests__/task-manager-crud.test.js +339 -0
- package/dist/cli/services/tools/__tests__/task-manager-list-get.test.js +343 -0
- package/dist/cli/services/tools/__tests__/task-manager-query.test.js +346 -0
- package/dist/cli/services/tools/__tests__/task-manager-routing.test.js +58 -0
- package/dist/cli/services/tools/__tests__/task-manager-update.test.js +224 -0
- package/dist/cli/services/tools/__tests__/task-manager.test.js +159 -0
- package/dist/cli/services/tools/__tests__/web-tools-html-search.test.js +227 -0
- package/dist/cli/services/tools/__tests__/web-tools.test.js +285 -0
- package/dist/cli/services/tools/agent-tools-tasks.d.ts +10 -0
- package/dist/cli/services/tools/agent-tools-tasks.js +216 -0
- package/dist/cli/services/tools/agent-tools-tasks.js.map +1 -0
- package/dist/cli/services/tools/agent-tools-team.d.ts +8 -0
- package/dist/cli/services/tools/agent-tools-team.js +101 -0
- package/dist/cli/services/tools/agent-tools-team.js.map +1 -0
- package/dist/cli/services/tools/agent-tools.js +115 -42
- package/dist/cli/services/tools/agent-tools.js.map +1 -1
- package/dist/cli/services/tools/file-ops-notebook.d.ts +9 -0
- package/dist/cli/services/tools/file-ops-notebook.js +186 -0
- package/dist/cli/services/tools/file-ops-notebook.js.map +1 -0
- package/dist/cli/services/tools/file-ops-read.d.ts +11 -0
- package/dist/cli/services/tools/file-ops-read.js +237 -0
- package/dist/cli/services/tools/file-ops-read.js.map +1 -0
- package/dist/cli/services/tools/file-ops-write.d.ts +8 -0
- package/dist/cli/services/tools/file-ops-write.js +260 -0
- package/dist/cli/services/tools/file-ops-write.js.map +1 -0
- package/dist/cli/services/tools/file-ops.d.ts +1 -0
- package/dist/cli/services/tools/file-ops.js +167 -0
- package/dist/cli/services/tools/file-ops.js.map +1 -1
- package/dist/cli/services/tools/html-to-text.d.ts +6 -0
- package/dist/cli/services/tools/html-to-text.js +118 -0
- package/dist/cli/services/tools/html-to-text.js.map +1 -0
- package/dist/cli/services/tools/shell-exec.test.js +148 -0
- package/dist/cli/services/tools/ssrf-guard.d.ts +6 -0
- package/dist/cli/services/tools/ssrf-guard.js +80 -0
- package/dist/cli/services/tools/ssrf-guard.js.map +1 -0
- package/dist/cli/setup/SetupComponents.d.ts +10 -0
- package/dist/cli/setup/SetupComponents.js +144 -0
- package/dist/cli/setup/SetupComponents.js.map +1 -0
- package/dist/cli/setup/setup-cli-targets.d.ts +9 -0
- package/dist/cli/setup/setup-cli-targets.js +49 -0
- package/dist/cli/setup/setup-cli-targets.js.map +1 -0
- package/dist/cli/shared/InlineErrorBoundary.d.ts +22 -0
- package/dist/cli/shared/InlineErrorBoundary.js +35 -0
- package/dist/cli/shared/InlineErrorBoundary.js.map +1 -0
- package/dist/cli/shared/MatrixIntro.js +2 -1
- package/dist/cli/shared/MatrixIntro.js.map +1 -1
- package/dist/cli/shared/SharedTick.d.ts +10 -0
- package/dist/cli/shared/SpinnerSlot.d.ts +16 -8
- package/dist/cli/shared/SpinnerSlot.js +122 -29
- package/dist/cli/shared/SpinnerSlot.js.map +1 -1
- package/dist/cli/shared/WhaleBanner.js +3 -2
- package/dist/cli/shared/WhaleBanner.js.map +1 -1
- package/dist/cli/shared/__tests__/markdown.test.js +188 -0
- package/dist/cli/shared/format-utils.d.ts +16 -0
- package/dist/cli/shared/format-utils.js +121 -0
- package/dist/cli/shared/format-utils.js.map +1 -0
- package/dist/cli/shared/markdown-chart.d.ts +8 -0
- package/dist/cli/shared/markdown-chart.js +92 -0
- package/dist/cli/shared/markdown-chart.js.map +1 -0
- package/dist/cli/shared/markdown-diff.d.ts +15 -0
- package/dist/cli/shared/markdown-diff.js +205 -0
- package/dist/cli/shared/markdown-diff.js.map +1 -0
- package/dist/cli/shared/markdown-helpers.d.ts +33 -0
- package/dist/cli/shared/markdown-helpers.js +129 -0
- package/dist/cli/shared/markdown-helpers.js.map +1 -0
- package/dist/cli/shared/markdown-table.d.ts +10 -0
- package/dist/cli/shared/markdown-table.js +227 -0
- package/dist/cli/shared/markdown-table.js.map +1 -0
- package/dist/cli/shared/markdown.d.ts +2 -6
- package/dist/cli/shared/markdown.js +8 -115
- package/dist/cli/shared/markdown.js.map +1 -1
- package/dist/cli/shared/useLatestRef.d.ts +11 -0
- package/dist/cli/shared/useLatestRef.js +34 -0
- package/dist/cli/shared/useLatestRef.js.map +1 -0
- package/dist/cli/shared/useSyncState.d.ts +11 -0
- package/dist/cli/shared/useSyncState.js +39 -0
- package/dist/cli/shared/useSyncState.js.map +1 -0
- package/dist/cli/stores/StoreApp.js +3 -1
- package/dist/cli/stores/StoreApp.js.map +1 -1
- package/dist/index-agent.d.ts +11 -0
- package/dist/index-agent.js +83 -0
- package/dist/index-agent.js.map +1 -0
- package/dist/index-auth.d.ts +22 -0
- package/dist/index-auth.js +114 -0
- package/dist/index-auth.js.map +1 -0
- package/dist/index-handlers.d.ts +25 -0
- package/dist/index-handlers.js +164 -0
- package/dist/index-handlers.js.map +1 -0
- package/dist/index-tools.d.ts +22 -0
- package/dist/index-tools.js +115 -0
- package/dist/index-tools.js.map +1 -0
- package/dist/local-agent/__tests__/connection-disconnect.test.js +201 -0
- package/dist/local-agent/__tests__/connection-lifecycle.test.js +289 -0
- package/dist/local-agent/__tests__/connection-msghandling.test.js +311 -0
- package/dist/local-agent/__tests__/connection-reconnect.test.js +230 -0
- package/dist/local-agent/__tests__/connection-toolexec.test.js +253 -0
- package/dist/local-agent/__tests__/discovery.test.js +328 -0
- package/dist/local-agent/__tests__/executor-background.test.js +219 -0
- package/dist/local-agent/__tests__/executor-exec.test.js +221 -0
- package/dist/local-agent/__tests__/executor-jobs-sessions.test.js +220 -0
- package/dist/local-agent/__tests__/executor-system-info.test.js +133 -0
- package/dist/local-agent/__tests__/executor-systeminfo.test.js +109 -0
- package/dist/local-agent/__tests__/executor.test.js +235 -0
- package/dist/local-agent/__tests__/index.test.js +139 -0
- package/dist/local-agent/connection-handlers.d.ts +8 -0
- package/dist/local-agent/connection-handlers.js +112 -0
- package/dist/local-agent/connection-handlers.js.map +1 -0
- package/dist/local-agent/connection-tools.d.ts +8 -0
- package/dist/local-agent/connection-tools.js +111 -0
- package/dist/local-agent/connection-tools.js.map +1 -0
- package/dist/local-agent/executor-jobs.d.ts +12 -0
- package/dist/local-agent/executor-jobs.js +143 -0
- package/dist/local-agent/executor-jobs.js.map +1 -0
- package/dist/local-agent/executor.d.ts +3 -0
- package/dist/local-agent/executor.js +2 -2
- package/dist/local-agent/executor.js.map +1 -1
- package/dist/node/__tests__/cli-channels.test.js +293 -0
- package/dist/node/__tests__/cli-config-edge.test.js +154 -0
- package/dist/node/__tests__/cli-config.test.js +215 -0
- package/dist/node/__tests__/config.test.js +292 -0
- package/dist/node/__tests__/runtime-heartbeat.test.js +153 -0
- package/dist/node/__tests__/runtime-lifecycle-init.test.js +263 -0
- package/dist/node/__tests__/runtime-lifecycle-stats.test.js +180 -0
- package/dist/node/__tests__/runtime-lifecycle.test.js +305 -0
- package/dist/node/__tests__/runtime-relay.test.js +341 -0
- package/dist/node/adapters/__tests__/base.test.js +286 -0
- package/dist/node/adapters/__tests__/discord.test.js +284 -0
- package/dist/node/adapters/__tests__/email-send.test.js +295 -0
- package/dist/node/adapters/__tests__/email.inbound-send.test.js +217 -0
- package/dist/node/adapters/__tests__/email.lifecycle.test.js +211 -0
- package/dist/node/adapters/__tests__/email.test.js +290 -0
- package/dist/node/adapters/__tests__/email.webhook-send.test.js +251 -0
- package/dist/node/adapters/__tests__/imessage-filter.test.js +183 -0
- package/dist/node/adapters/__tests__/imessage-lifecycle.test.js +215 -0
- package/dist/node/adapters/__tests__/imessage-send-restart.test.js +227 -0
- package/dist/node/adapters/__tests__/slack.part2.test.js +135 -0
- package/dist/node/adapters/__tests__/slack.test.js +241 -0
- package/dist/node/adapters/__tests__/sms-extras.test.js +108 -0
- package/dist/node/adapters/__tests__/sms-lifecycle.test.js +203 -0
- package/dist/node/adapters/__tests__/sms-messaging.test.js +266 -0
- package/dist/node/adapters/__tests__/sms.part2.test.js +174 -0
- package/dist/node/adapters/__tests__/sms.test.js +253 -0
- package/dist/node/adapters/__tests__/telegram-polling.test.js +256 -0
- package/dist/node/adapters/__tests__/telegram-send.test.js +166 -0
- package/dist/node/adapters/__tests__/webchat-inbound.test.js +188 -0
- package/dist/node/adapters/__tests__/webchat-outbound.test.js +178 -0
- package/dist/node/adapters/__tests__/whatsapp-inbound.test.js +200 -0
- package/dist/node/adapters/__tests__/whatsapp-send.test.js +212 -0
- package/dist/node/adapters/__tests__/whatsapp.test.js +280 -0
- package/dist/node/adapters/discord-gateway.d.ts +42 -0
- package/dist/node/adapters/discord-gateway.js +169 -0
- package/dist/node/adapters/discord-gateway.js.map +1 -0
- package/dist/node/adapters/imessage.d.ts +11 -0
- package/dist/node/adapters/imessage.js +23 -6
- package/dist/node/adapters/imessage.js.map +1 -1
- package/dist/node/cli-channels.d.ts +6 -0
- package/dist/node/cli-channels.js +229 -0
- package/dist/node/cli-channels.js.map +1 -0
- package/dist/node/cli-node.d.ts +9 -0
- package/dist/node/cli-node.js +186 -0
- package/dist/node/cli-node.js.map +1 -0
- package/dist/node/cli-portal.d.ts +11 -0
- package/dist/node/cli-portal.js +503 -0
- package/dist/node/cli-portal.js.map +1 -0
- package/dist/node/portal/portal-target.d.ts +16 -0
- package/dist/node/portal/portal-target.js +102 -0
- package/dist/node/portal/portal-target.js.map +1 -0
- package/dist/node/portal/protocol-frames.d.ts +33 -0
- package/dist/node/portal/protocol-frames.js +170 -0
- package/dist/node/portal/protocol-frames.js.map +1 -0
- package/dist/node/runtime-network.d.ts +25 -0
- package/dist/node/runtime-network.js +226 -0
- package/dist/node/runtime-network.js.map +1 -0
- package/dist/node/runtime-utils.d.ts +27 -0
- package/dist/node/runtime-utils.js +99 -0
- package/dist/node/runtime-utils.js.map +1 -0
- package/dist/node/runtime.d.ts +1 -0
- package/dist/node/runtime.js +71 -1
- package/dist/node/runtime.js.map +1 -1
- package/dist/node/task-runner.d.ts +33 -0
- package/dist/node/task-runner.js +276 -0
- package/dist/node/task-runner.js.map +1 -0
- package/dist/server/__tests__/gateway-fast-fail.test.js +160 -0
- package/dist/server/__tests__/local-agent-gateway.test.js +186 -0
- package/dist/server/__tests__/proxy-handlers-delegation.test.js +240 -0
- package/dist/server/__tests__/proxy-handlers-validation.test.js +211 -0
- package/dist/server/__tests__/proxy-handlers.part2.test.js +240 -0
- package/dist/server/__tests__/proxy-handlers.test.js +213 -0
- package/dist/server/__tests__/strip-base64-e2e.test.js +303 -0
- package/dist/server/__tests__/strip-base64.test.js +256 -0
- package/dist/server/__tests__/tool-router-agent-tools.test.js +324 -0
- package/dist/server/__tests__/tool-router-execute-core.test.js +357 -0
- package/dist/server/__tests__/tool-router-execute-permissions.test.js +332 -0
- package/dist/server/__tests__/tool-router-execute.test.js +348 -0
- package/dist/server/__tests__/tool-router-load.test.js +432 -0
- package/dist/server/__tests__/tool-router-permissions.test.js +359 -0
- package/dist/server/__tests__/tool-router-registry-cache.test.js +383 -0
- package/dist/server/__tests__/tool-router-registry-handlers.test.js +272 -0
- package/dist/server/__tests__/tool-router-registry.test.js +331 -0
- package/dist/server/__tests__/validation-inventory.test.js +250 -0
- package/dist/server/__tests__/validation-misc.test.js +243 -0
- package/dist/server/__tests__/validation-supply-chain.test.js +188 -0
- package/dist/server/__tests__/worker.test.js +265 -0
- package/dist/server/handlers/__test-utils__/test-db.d.ts +2 -0
- package/dist/server/handlers/__test-utils__/test-db.js +14 -1
- package/dist/server/handlers/__test-utils__/test-db.js.map +1 -1
- package/dist/server/handlers/__tests__/conversation-lock.test.js +117 -0
- package/dist/server/handlers/__tests__/e2e/auth-cross-platform-login.e2e.test.js +268 -0
- package/dist/server/handlers/__tests__/e2e/auth-cross-platform-tokens.e2e.test.js +264 -0
- package/dist/server/handlers/__tests__/e2e/email-pipeline-send.e2e.test.js +214 -0
- package/dist/server/handlers/__tests__/e2e/email-pipeline-threads.e2e.test.js +168 -0
- package/dist/server/handlers/__tests__/e2e/error-logging-pipeline-dedup.e2e.test.js +229 -0
- package/dist/server/handlers/__tests__/e2e/error-logging-pipeline.e2e.test.js +239 -0
- package/dist/server/handlers/__tests__/e2e/error-logging-rate-limit.e2e.test.js +150 -0
- package/dist/server/handlers/__tests__/e2e/inventory-sync-guards.e2e.test.js +177 -0
- package/dist/server/handlers/__tests__/e2e/inventory-sync.e2e.test.js +228 -0
- package/dist/server/handlers/__tests__/e2e/inventory-sync.part2.e2e.test.js +188 -0
- package/dist/server/handlers/__tests__/e2e/order-lifecycle-fulfillment.e2e.test.js +295 -0
- package/dist/server/handlers/__tests__/e2e/order-lifecycle.e2e.test.js +277 -0
- package/dist/server/handlers/__tests__/e2e/order-lifecycle.fulfillment.e2e.test.js +307 -0
- package/dist/server/handlers/__tests__/e2e/order-lifecycle.setup.e2e.test.js +177 -0
- package/dist/server/handlers/__tests__/e2e/storefront-checkout-cart.e2e.test.js +255 -0
- package/dist/server/handlers/__tests__/e2e/storefront-checkout-webhook.e2e.test.js +231 -0
- package/dist/server/handlers/__tests__/e2e/workflow-execution-failures.e2e.test.js +235 -0
- package/dist/server/handlers/__tests__/e2e/workflow-execution.e2e.test.js +294 -0
- package/dist/server/handlers/__tests__/e2e/workflow-security.e2e.test.js +311 -0
- package/dist/server/handlers/__tests__/e2e/workflow-security.part2.e2e.test.js +267 -0
- package/dist/server/handlers/__tests__/workflow-cache.test.js +237 -0
- package/dist/server/handlers/analytics-errors-edge.test.js +173 -0
- package/dist/server/handlers/analytics.js +88 -1
- package/dist/server/handlers/analytics.js.map +1 -1
- package/dist/server/handlers/analytics.test.js +280 -0
- package/dist/server/handlers/api-docs-examples-ext.d.ts +9 -0
- package/dist/server/handlers/api-docs-examples-ext.js +278 -0
- package/dist/server/handlers/api-docs-examples-ext.js.map +1 -0
- package/dist/server/handlers/api-docs-examples.d.ts +8 -0
- package/dist/server/handlers/api-docs-examples.js +221 -0
- package/dist/server/handlers/api-docs-examples.js.map +1 -0
- package/dist/server/handlers/api-docs-sections-ext.d.ts +2 -0
- package/dist/server/handlers/api-docs-sections-ext.js +497 -0
- package/dist/server/handlers/api-docs-sections-ext.js.map +1 -0
- package/dist/server/handlers/api-docs-sections.d.ts +21 -0
- package/dist/server/handlers/api-docs-sections.js +293 -0
- package/dist/server/handlers/api-docs-sections.js.map +1 -0
- package/dist/server/handlers/api-docs.d.ts +2 -0
- package/dist/server/handlers/api-docs.js +177 -0
- package/dist/server/handlers/api-docs.js.map +1 -1
- package/dist/server/handlers/api-keys.part2.test.js +157 -0
- package/dist/server/handlers/api-keys.test.js +161 -0
- package/dist/server/handlers/billing-core.d.ts +28 -0
- package/dist/server/handlers/billing-core.js +126 -0
- package/dist/server/handlers/billing-core.js.map +1 -0
- package/dist/server/handlers/billing-routes.d.ts +9 -0
- package/dist/server/handlers/billing-routes.js +243 -0
- package/dist/server/handlers/billing-routes.js.map +1 -0
- package/dist/server/handlers/billing-routes.test.js +123 -0
- package/dist/server/handlers/billing.test.js +215 -0
- package/dist/server/handlers/browser-actions-errors.test.js +94 -0
- package/dist/server/handlers/browser-actions.d.ts +35 -0
- package/dist/server/handlers/browser-actions.js +171 -0
- package/dist/server/handlers/browser-actions.js.map +1 -0
- package/dist/server/handlers/browser-actions.part2.test.js +190 -0
- package/dist/server/handlers/browser-actions.test.js +190 -0
- package/dist/server/handlers/browser-captcha.d.ts +6 -0
- package/dist/server/handlers/browser-captcha.js +172 -0
- package/dist/server/handlers/browser-captcha.js.map +1 -0
- package/dist/server/handlers/browser-lifecycle.d.ts +9 -0
- package/dist/server/handlers/browser-lifecycle.js +142 -0
- package/dist/server/handlers/browser-lifecycle.js.map +1 -0
- package/dist/server/handlers/browser-validation.test.js +257 -0
- package/dist/server/handlers/catalog-advanced.d.ts +9 -0
- package/dist/server/handlers/catalog-advanced.js +352 -0
- package/dist/server/handlers/catalog-advanced.js.map +1 -0
- package/dist/server/handlers/catalog-categories.d.ts +5 -0
- package/dist/server/handlers/catalog-categories.js +181 -0
- package/dist/server/handlers/catalog-categories.js.map +1 -0
- package/dist/server/handlers/catalog-products.d.ts +5 -0
- package/dist/server/handlers/catalog-products.js +404 -0
- package/dist/server/handlers/catalog-products.js.map +1 -0
- package/dist/server/handlers/catalog-schemas.d.ts +5 -0
- package/dist/server/handlers/catalog-schemas.js +426 -0
- package/dist/server/handlers/catalog-schemas.js.map +1 -0
- package/dist/server/handlers/catalog.test.js +297 -0
- package/dist/server/handlers/comms-documents-advanced.d.ts +8 -0
- package/dist/server/handlers/comms-documents-advanced.js +159 -0
- package/dist/server/handlers/comms-documents-advanced.js.map +1 -0
- package/dist/server/handlers/comms-documents.d.ts +10 -0
- package/dist/server/handlers/comms-documents.js +445 -0
- package/dist/server/handlers/comms-documents.js.map +1 -0
- package/dist/server/handlers/comms-email.d.ts +10 -0
- package/dist/server/handlers/comms-email.js +492 -0
- package/dist/server/handlers/comms-email.js.map +1 -0
- package/dist/server/handlers/comms-pdf-generation.d.ts +8 -0
- package/dist/server/handlers/comms-pdf-generation.js +327 -0
- package/dist/server/handlers/comms-pdf-generation.js.map +1 -0
- package/dist/server/handlers/comms-pdf-helpers.d.ts +9 -0
- package/dist/server/handlers/comms-pdf-helpers.js +126 -0
- package/dist/server/handlers/comms-pdf-helpers.js.map +1 -0
- package/dist/server/handlers/comms-shared.d.ts +3 -0
- package/dist/server/handlers/comms-shared.js +28 -0
- package/dist/server/handlers/comms-shared.js.map +1 -0
- package/dist/server/handlers/comms.test.js +289 -0
- package/dist/server/handlers/creations-actions.d.ts +21 -0
- package/dist/server/handlers/creations-actions.js +250 -0
- package/dist/server/handlers/creations-actions.js.map +1 -0
- package/dist/server/handlers/creations-advanced-collections.test.js +214 -0
- package/dist/server/handlers/creations-advanced-generate.test.js +142 -0
- package/dist/server/handlers/creations-advanced.test.js +171 -0
- package/dist/server/handlers/creations-collections-preview.test.js +214 -0
- package/dist/server/handlers/creations-crud.d.ts +35 -0
- package/dist/server/handlers/creations-crud.js +248 -0
- package/dist/server/handlers/creations-crud.js.map +1 -0
- package/dist/server/handlers/creations-crud.test.js +260 -0
- package/dist/server/handlers/creations-generate.d.ts +21 -0
- package/dist/server/handlers/creations-generate.js +256 -0
- package/dist/server/handlers/creations-generate.js.map +1 -0
- package/dist/server/handlers/creations-mutations.test.js +197 -0
- package/dist/server/handlers/crm-customers-read.d.ts +58 -0
- package/dist/server/handlers/crm-customers-read.js +208 -0
- package/dist/server/handlers/crm-customers-read.js.map +1 -0
- package/dist/server/handlers/crm-customers-write.d.ts +54 -0
- package/dist/server/handlers/crm-customers-write.js +414 -0
- package/dist/server/handlers/crm-customers-write.js.map +1 -0
- package/dist/server/handlers/crm-utils.d.ts +6 -0
- package/dist/server/handlers/crm-utils.js +19 -0
- package/dist/server/handlers/crm-utils.js.map +1 -0
- package/dist/server/handlers/crm.test.js +179 -0
- package/dist/server/handlers/discovery-advertise.d.ts +18 -0
- package/dist/server/handlers/discovery-advertise.js +101 -0
- package/dist/server/handlers/discovery-advertise.js.map +1 -0
- package/dist/server/handlers/discovery-advertise.test.js +185 -0
- package/dist/server/handlers/discovery-scan.d.ts +19 -0
- package/dist/server/handlers/discovery-scan.js +107 -0
- package/dist/server/handlers/discovery-scan.js.map +1 -0
- package/dist/server/handlers/discovery-scan.test.js +233 -0
- package/dist/server/handlers/embeddings-embed-search.test.js +196 -0
- package/dist/server/handlers/embeddings-index-delete-stats.test.js +140 -0
- package/dist/server/handlers/embeddings-search.test.js +221 -0
- package/dist/server/handlers/embeddings.test.js +137 -0
- package/dist/server/handlers/enrichment-breach.d.ts +8 -0
- package/dist/server/handlers/enrichment-breach.js +266 -0
- package/dist/server/handlers/enrichment-breach.js.map +1 -0
- package/dist/server/handlers/enrichment-data.d.ts +13 -0
- package/dist/server/handlers/enrichment-data.js +145 -0
- package/dist/server/handlers/enrichment-data.js.map +1 -0
- package/dist/server/handlers/enrichment-enrich.d.ts +6 -0
- package/dist/server/handlers/enrichment-enrich.js +235 -0
- package/dist/server/handlers/enrichment-enrich.js.map +1 -0
- package/dist/server/handlers/enrichment-helpers.d.ts +10 -0
- package/dist/server/handlers/enrichment-helpers.js +17 -0
- package/dist/server/handlers/enrichment-helpers.js.map +1 -0
- package/dist/server/handlers/enrichment-mutations.test.js +240 -0
- package/dist/server/handlers/enrichment-queries.test.js +181 -0
- package/dist/server/handlers/enrichment-validation.test.js +177 -0
- package/dist/server/handlers/enrichment-writes.d.ts +16 -0
- package/dist/server/handlers/enrichment-writes.js +226 -0
- package/dist/server/handlers/enrichment-writes.js.map +1 -0
- package/dist/server/handlers/image-gen-actions.d.ts +18 -0
- package/dist/server/handlers/image-gen-actions.js +183 -0
- package/dist/server/handlers/image-gen-actions.js.map +1 -0
- package/dist/server/handlers/image-gen-providers.d.ts +29 -0
- package/dist/server/handlers/image-gen-providers.js +161 -0
- package/dist/server/handlers/image-gen-providers.js.map +1 -0
- package/dist/server/handlers/image-gen.test.js +205 -0
- package/dist/server/handlers/inventory-audit.d.ts +10 -0
- package/dist/server/handlers/inventory-audit.js +90 -0
- package/dist/server/handlers/inventory-audit.js.map +1 -0
- package/dist/server/handlers/inventory-helpers.d.ts +8 -0
- package/dist/server/handlers/inventory-helpers.js +19 -0
- package/dist/server/handlers/inventory-helpers.js.map +1 -0
- package/dist/server/handlers/inventory-query.d.ts +67 -0
- package/dist/server/handlers/inventory-query.js +299 -0
- package/dist/server/handlers/inventory-query.js.map +1 -0
- package/dist/server/handlers/inventory.test.js +380 -0
- package/dist/server/handlers/kali-background.test.js +222 -0
- package/dist/server/handlers/kali-errors.test.js +92 -0
- package/dist/server/handlers/kali-validation.test.js +234 -0
- package/dist/server/handlers/llm-providers-actions.test.js +220 -0
- package/dist/server/handlers/llm-providers-anthropic.test.js +239 -0
- package/dist/server/handlers/llm-providers-clients.d.ts +6 -0
- package/dist/server/handlers/llm-providers-clients.js +296 -0
- package/dist/server/handlers/llm-providers-clients.js.map +1 -0
- package/dist/server/handlers/llm-providers-credentials.d.ts +3 -0
- package/dist/server/handlers/llm-providers-credentials.js +109 -0
- package/dist/server/handlers/llm-providers-credentials.js.map +1 -0
- package/dist/server/handlers/llm-providers-failover.test.js +232 -0
- package/dist/server/handlers/llm-providers-models.d.ts +67 -0
- package/dist/server/handlers/llm-providers-models.js +213 -0
- package/dist/server/handlers/llm-providers-models.js.map +1 -0
- package/dist/server/handlers/llm-providers-providers.test.js +300 -0
- package/dist/server/handlers/llm-providers-validation.test.js +239 -0
- package/dist/server/handlers/local-agent-tools.test.js +224 -0
- package/dist/server/handlers/local-agent.test.js +198 -0
- package/dist/server/handlers/local-agent.tools-status.test.js +204 -0
- package/dist/server/handlers/local-agent.validation-exec.test.js +182 -0
- package/dist/server/handlers/media-actions.d.ts +14 -0
- package/dist/server/handlers/media-actions.js +398 -0
- package/dist/server/handlers/media-actions.js.map +1 -0
- package/dist/server/handlers/media-crud.d.ts +9 -0
- package/dist/server/handlers/media-crud.js +365 -0
- package/dist/server/handlers/media-crud.js.map +1 -0
- package/dist/server/handlers/media-upload.d.ts +4 -0
- package/dist/server/handlers/media-upload.js +179 -0
- package/dist/server/handlers/media-upload.js.map +1 -0
- package/dist/server/handlers/media-utils.d.ts +14 -0
- package/dist/server/handlers/media-utils.js +33 -0
- package/dist/server/handlers/media-utils.js.map +1 -0
- package/dist/server/handlers/meta-ads-advanced.d.ts +46 -0
- package/dist/server/handlers/meta-ads-advanced.js +222 -0
- package/dist/server/handlers/meta-ads-advanced.js.map +1 -0
- package/dist/server/handlers/meta-ads-audience-rules.test.js +243 -0
- package/dist/server/handlers/meta-ads-audience-targeting.test.js +205 -0
- package/dist/server/handlers/meta-ads-audiences-targeting.test.js +383 -0
- package/dist/server/handlers/meta-ads-audiences.d.ts +48 -0
- package/dist/server/handlers/meta-ads-audiences.js +214 -0
- package/dist/server/handlers/meta-ads-audiences.js.map +1 -0
- package/dist/server/handlers/meta-ads-crud-ads.test.js +136 -0
- package/dist/server/handlers/meta-ads-crud-campaigns.test.js +189 -0
- package/dist/server/handlers/meta-ads-crud-create.test.js +303 -0
- package/dist/server/handlers/meta-ads-crud-list-update.test.js +259 -0
- package/dist/server/handlers/meta-ads-crud-read.d.ts +78 -0
- package/dist/server/handlers/meta-ads-crud-read.js +204 -0
- package/dist/server/handlers/meta-ads-crud-read.js.map +1 -0
- package/dist/server/handlers/meta-ads-crud-write.d.ts +105 -0
- package/dist/server/handlers/meta-ads-crud-write.js +390 -0
- package/dist/server/handlers/meta-ads-crud-write.js.map +1 -0
- package/dist/server/handlers/meta-ads-crud.d.ts +9 -0
- package/dist/server/handlers/meta-ads-crud.js +12 -0
- package/dist/server/handlers/meta-ads-crud.js.map +1 -0
- package/dist/server/handlers/meta-ads-delete-publish-sync.test.js +282 -0
- package/dist/server/handlers/meta-ads-graph-api.d.ts +25 -0
- package/dist/server/handlers/meta-ads-graph-api.js +155 -0
- package/dist/server/handlers/meta-ads-graph-api.js.map +1 -0
- package/dist/server/handlers/meta-ads-insights.test.js +80 -0
- package/dist/server/handlers/meta-ads-list-get.test.js +237 -0
- package/dist/server/handlers/meta-ads-media.d.ts +16 -0
- package/dist/server/handlers/meta-ads-media.js +205 -0
- package/dist/server/handlers/meta-ads-media.js.map +1 -0
- package/dist/server/handlers/meta-ads-pixels-rules.d.ts +127 -0
- package/dist/server/handlers/meta-ads-pixels-rules.js +463 -0
- package/dist/server/handlers/meta-ads-pixels-rules.js.map +1 -0
- package/dist/server/handlers/meta-ads-publish-ad.d.ts +11 -0
- package/dist/server/handlers/meta-ads-publish-ad.js +229 -0
- package/dist/server/handlers/meta-ads-publish-ad.js.map +1 -0
- package/dist/server/handlers/meta-ads-publish-delete.test.js +254 -0
- package/dist/server/handlers/meta-ads-publish-helpers.js +117 -0
- package/dist/server/handlers/meta-ads-publish-helpers.js.map +1 -0
- package/dist/server/handlers/meta-ads-publish-sync.test.js +205 -0
- package/dist/server/handlers/meta-ads-publish.d.ts +14 -0
- package/dist/server/handlers/meta-ads-publish.js +194 -0
- package/dist/server/handlers/meta-ads-publish.js.map +1 -0
- package/dist/server/handlers/meta-ads-publish.test.js +254 -0
- package/dist/server/handlers/meta-ads-sync-insights.test.js +184 -0
- package/dist/server/handlers/meta-ads-targeting.d.ts +27 -0
- package/dist/server/handlers/meta-ads-targeting.js +323 -0
- package/dist/server/handlers/meta-ads-targeting.js.map +1 -0
- package/dist/server/handlers/meta-ads-types.d.ts +49 -0
- package/dist/server/handlers/meta-ads-types.js +59 -0
- package/dist/server/handlers/meta-ads-types.js.map +1 -0
- package/dist/server/handlers/meta-ads-update.test.js +117 -0
- package/dist/server/handlers/meta-ads.d.ts +25 -0
- package/dist/server/handlers/meta-ads.js +392 -3
- package/dist/server/handlers/meta-ads.js.map +1 -1
- package/dist/server/handlers/nodes-channels.test.js +413 -0
- package/dist/server/handlers/nodes-events.test.js +131 -0
- package/dist/server/handlers/nodes-handlers-channels-messages.d.ts +20 -0
- package/dist/server/handlers/nodes-handlers-channels-messages.js +314 -0
- package/dist/server/handlers/nodes-handlers-channels-messages.js.map +1 -0
- package/dist/server/handlers/nodes-handlers-channels.d.ts +19 -0
- package/dist/server/handlers/nodes-handlers-channels.js +225 -0
- package/dist/server/handlers/nodes-handlers-channels.js.map +1 -0
- package/dist/server/handlers/nodes-handlers-mgmt.d.ts +33 -0
- package/dist/server/handlers/nodes-handlers-mgmt.js +418 -0
- package/dist/server/handlers/nodes-handlers-mgmt.js.map +1 -0
- package/dist/server/handlers/nodes-list-delete.test.js +171 -0
- package/dist/server/handlers/nodes-messages-delivery.test.js +208 -0
- package/dist/server/handlers/nodes-messages.test.js +211 -0
- package/dist/server/handlers/nodes-register.test.js +277 -0
- package/dist/server/handlers/nodes-routes-channels.d.ts +9 -0
- package/dist/server/handlers/nodes-routes-channels.js +217 -0
- package/dist/server/handlers/nodes-routes-channels.js.map +1 -0
- package/dist/server/handlers/nodes-routes-crud.d.ts +9 -0
- package/dist/server/handlers/nodes-routes-crud.js +290 -0
- package/dist/server/handlers/nodes-routes-crud.js.map +1 -0
- package/dist/server/handlers/nodes-routes-delivery.d.ts +9 -0
- package/dist/server/handlers/nodes-routes-delivery.js +226 -0
- package/dist/server/handlers/nodes-routes-delivery.js.map +1 -0
- package/dist/server/handlers/nodes-routes-messages.d.ts +9 -0
- package/dist/server/handlers/nodes-routes-messages.js +218 -0
- package/dist/server/handlers/nodes-routes-messages.js.map +1 -0
- package/dist/server/handlers/nodes-routes-register.d.ts +9 -0
- package/dist/server/handlers/nodes-routes-register.js +239 -0
- package/dist/server/handlers/nodes-routes-register.js.map +1 -0
- package/dist/server/handlers/nodes-types.d.ts +82 -0
- package/dist/server/handlers/nodes-types.js +220 -0
- package/dist/server/handlers/nodes-types.js.map +1 -0
- package/dist/server/handlers/nodes-utils.d.ts +70 -0
- package/dist/server/handlers/nodes-utils.js +214 -0
- package/dist/server/handlers/nodes-utils.js.map +1 -0
- package/dist/server/handlers/nodes.test.js +353 -0
- package/dist/server/handlers/operations.test.js +136 -0
- package/dist/server/handlers/platform-telemetry.d.ts +10 -0
- package/dist/server/handlers/platform-telemetry.js +372 -0
- package/dist/server/handlers/platform-telemetry.js.map +1 -0
- package/dist/server/handlers/platform-telemetry.test.js +200 -0
- package/dist/server/handlers/platform-websearch.test.js +160 -0
- package/dist/server/handlers/sessions-handlers.d.ts +23 -0
- package/dist/server/handlers/sessions-handlers.js +374 -0
- package/dist/server/handlers/sessions-handlers.js.map +1 -0
- package/dist/server/handlers/storefront-cart.d.ts +31 -0
- package/dist/server/handlers/storefront-cart.js +381 -0
- package/dist/server/handlers/storefront-cart.js.map +1 -0
- package/dist/server/handlers/storefront.test.js +329 -0
- package/dist/server/handlers/supply-chain-transfers.d.ts +10 -0
- package/dist/server/handlers/supply-chain-transfers.js +214 -0
- package/dist/server/handlers/supply-chain-transfers.js.map +1 -0
- package/dist/server/handlers/supply-chain-utils.d.ts +2 -0
- package/dist/server/handlers/supply-chain-utils.js +21 -0
- package/dist/server/handlers/supply-chain-utils.js.map +1 -0
- package/dist/server/handlers/supply-chain.test.js +347 -0
- package/dist/server/handlers/transcription.test.js +118 -0
- package/dist/server/handlers/video-gen-providers.d.ts +30 -0
- package/dist/server/handlers/video-gen-providers.js +205 -0
- package/dist/server/handlers/video-gen-providers.js.map +1 -0
- package/dist/server/handlers/video-gen-sora.d.ts +5 -0
- package/dist/server/handlers/video-gen-sora.js +87 -0
- package/dist/server/handlers/video-gen-sora.js.map +1 -0
- package/dist/server/handlers/video-gen-veo.js +114 -0
- package/dist/server/handlers/video-gen-veo.js.map +1 -0
- package/dist/server/handlers/video-gen.test.js +146 -0
- package/dist/server/handlers/voice-handlers-audio.d.ts +9 -0
- package/dist/server/handlers/voice-handlers-audio.js +229 -0
- package/dist/server/handlers/voice-handlers-audio.js.map +1 -0
- package/dist/server/handlers/voice-handlers-music.d.ts +5 -0
- package/dist/server/handlers/voice-handlers-music.js +124 -0
- package/dist/server/handlers/voice-handlers-music.js.map +1 -0
- package/dist/server/handlers/voice-handlers-pvc.d.ts +8 -0
- package/dist/server/handlers/voice-handlers-pvc.js +345 -0
- package/dist/server/handlers/voice-handlers-pvc.js.map +1 -0
- package/dist/server/handlers/voice-handlers-tts.d.ts +5 -0
- package/dist/server/handlers/voice-handlers-tts.js +142 -0
- package/dist/server/handlers/voice-handlers-tts.js.map +1 -0
- package/dist/server/handlers/voice-handlers-voices.d.ts +8 -0
- package/dist/server/handlers/voice-handlers-voices.js +321 -0
- package/dist/server/handlers/voice-handlers-voices.js.map +1 -0
- package/dist/server/handlers/voice-utils.d.ts +32 -0
- package/dist/server/handlers/voice-utils.js +281 -0
- package/dist/server/handlers/voice-utils.js.map +1 -0
- package/dist/server/handlers/voice.test.js +153 -0
- package/dist/server/handlers/workflow-crud-advanced.d.ts +8 -0
- package/dist/server/handlers/workflow-crud-advanced.js +275 -0
- package/dist/server/handlers/workflow-crud-advanced.js.map +1 -0
- package/dist/server/handlers/workflow-crud-core.d.ts +8 -0
- package/dist/server/handlers/workflow-crud-core.js +286 -0
- package/dist/server/handlers/workflow-crud-core.js.map +1 -0
- package/dist/server/handlers/workflow-crud-events.d.ts +8 -0
- package/dist/server/handlers/workflow-crud-events.js +483 -0
- package/dist/server/handlers/workflow-crud-events.js.map +1 -0
- package/dist/server/handlers/workflow-crud-runs-lifecycle.d.ts +8 -0
- package/dist/server/handlers/workflow-crud-runs-lifecycle.js +231 -0
- package/dist/server/handlers/workflow-crud-runs-lifecycle.js.map +1 -0
- package/dist/server/handlers/workflow-crud-runs-versioning.d.ts +8 -0
- package/dist/server/handlers/workflow-crud-runs-versioning.js +319 -0
- package/dist/server/handlers/workflow-crud-runs-versioning.js.map +1 -0
- package/dist/server/handlers/workflow-crud-runs.d.ts +8 -0
- package/dist/server/handlers/workflow-crud-runs.js +18 -0
- package/dist/server/handlers/workflow-crud-runs.js.map +1 -0
- package/dist/server/handlers/workflow-steps-advancement.d.ts +13 -0
- package/dist/server/handlers/workflow-steps-advancement.js +197 -0
- package/dist/server/handlers/workflow-steps-advancement.js.map +1 -0
- package/dist/server/handlers/workflow-steps-circuit-breaker.d.ts +7 -0
- package/dist/server/handlers/workflow-steps-circuit-breaker.js +131 -0
- package/dist/server/handlers/workflow-steps-circuit-breaker.js.map +1 -0
- package/dist/server/handlers/workflow-steps-completion.d.ts +5 -0
- package/dist/server/handlers/workflow-steps-completion.js +254 -0
- package/dist/server/handlers/workflow-steps-completion.js.map +1 -0
- package/dist/server/handlers/workflow-steps-cron.d.ts +4 -0
- package/dist/server/handlers/workflow-steps-cron.js +259 -0
- package/dist/server/handlers/workflow-steps-cron.js.map +1 -0
- package/dist/server/handlers/workflow-steps-engine-execute.d.ts +3 -0
- package/dist/server/handlers/workflow-steps-engine-execute.js +388 -0
- package/dist/server/handlers/workflow-steps-engine-execute.js.map +1 -0
- package/dist/server/handlers/workflow-steps-engine-inline.d.ts +2 -0
- package/dist/server/handlers/workflow-steps-engine-inline.js +91 -0
- package/dist/server/handlers/workflow-steps-engine-inline.js.map +1 -0
- package/dist/server/handlers/workflow-steps-engine-persist.d.ts +5 -0
- package/dist/server/handlers/workflow-steps-engine-persist.js +192 -0
- package/dist/server/handlers/workflow-steps-engine-persist.js.map +1 -0
- package/dist/server/handlers/workflow-steps-engine-process.d.ts +7 -0
- package/dist/server/handlers/workflow-steps-engine-process.js +290 -0
- package/dist/server/handlers/workflow-steps-engine-process.js.map +1 -0
- package/dist/server/handlers/workflow-steps-engine.d.ts +3 -0
- package/dist/server/handlers/workflow-steps-engine.js +10 -0
- package/dist/server/handlers/workflow-steps-engine.js.map +1 -0
- package/dist/server/handlers/workflow-steps-executors-llm.d.ts +7 -0
- package/dist/server/handlers/workflow-steps-executors-llm.js +265 -0
- package/dist/server/handlers/workflow-steps-executors-llm.js.map +1 -0
- package/dist/server/handlers/workflow-steps-executors.d.ts +9 -0
- package/dist/server/handlers/workflow-steps-executors.js +188 -0
- package/dist/server/handlers/workflow-steps-executors.js.map +1 -0
- package/dist/server/handlers/workflow-steps-maintenance.d.ts +4 -0
- package/dist/server/handlers/workflow-steps-maintenance.js +256 -0
- package/dist/server/handlers/workflow-steps-maintenance.js.map +1 -0
- package/dist/server/handlers/workflow-steps-types.d.ts +84 -0
- package/dist/server/handlers/workflow-steps-types.js +179 -0
- package/dist/server/handlers/workflow-steps-types.js.map +1 -0
- package/dist/server/handlers/workflow-steps-webhook.d.ts +5 -0
- package/dist/server/handlers/workflow-steps-webhook.js +179 -0
- package/dist/server/handlers/workflow-steps-webhook.js.map +1 -0
- package/dist/server/handlers/workflow-steps.test.js +330 -0
- package/dist/server/handlers/workflows-extras.test.js +65 -0
- package/dist/server/handlers/workflows.part2.test.js +170 -0
- package/dist/server/handlers/workflows.test.js +281 -0
- package/dist/server/index.js +81 -1720
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/__tests__/batch-client-conversion-jsonl.test.js +171 -0
- package/dist/server/lib/__tests__/batch-client-polling.test.js +292 -0
- package/dist/server/lib/__tests__/batch-client-queue.test.js +270 -0
- package/dist/server/lib/__tests__/clickhouse-buffer.test.js +236 -0
- package/dist/server/lib/__tests__/code-worker-edge-cases.test.js +118 -0
- package/dist/server/lib/__tests__/code-worker-pool-execute.test.js +193 -0
- package/dist/server/lib/__tests__/code-worker-pool-execution.test.js +165 -0
- package/dist/server/lib/__tests__/code-worker-pool-init.test.js +131 -0
- package/dist/server/lib/__tests__/code-worker-pool.test.js +194 -0
- package/dist/server/lib/__tests__/code-worker-sandbox-ops.test.js +123 -0
- package/dist/server/lib/__tests__/code-worker-sandbox.test.js +217 -0
- package/dist/server/lib/__tests__/code-worker.test.js +179 -0
- package/dist/server/lib/__tests__/compaction-service-generate.test.js +229 -0
- package/dist/server/lib/__tests__/compaction-service.test.js +319 -0
- package/dist/server/lib/__tests__/otel.test.js +146 -0
- package/dist/server/lib/__tests__/prompt-sanitizer-validation.test.js +165 -0
- package/dist/server/lib/__tests__/prompt-sanitizer.sanitize.test.js +343 -0
- package/dist/server/lib/__tests__/prompt-sanitizer.test.js +328 -0
- package/dist/server/lib/__tests__/prompt-sanitizer.validate-tool.test.js +145 -0
- package/dist/server/lib/__tests__/provider-capabilities.test.js +263 -0
- package/dist/server/lib/__tests__/provider-failover-routing.test.js +145 -0
- package/dist/server/lib/__tests__/provider-failover-state.test.js +131 -0
- package/dist/server/lib/__tests__/rate-limiter-budgets.test.js +216 -0
- package/dist/server/lib/__tests__/rate-limiter.budgets-tools.test.js +113 -0
- package/dist/server/lib/__tests__/rate-limiter.check-request.test.js +141 -0
- package/dist/server/lib/__tests__/rate-limiter.stats-lifecycle.test.js +135 -0
- package/dist/server/lib/__tests__/rate-limiter.test.js +207 -0
- package/dist/server/lib/__tests__/server-agent-loop-abort-conditions.test.js +544 -0
- package/dist/server/lib/__tests__/server-agent-loop-abort.part2.test.js +504 -0
- package/dist/server/lib/__tests__/server-agent-loop-abort.test.js +396 -0
- package/dist/server/lib/__tests__/server-agent-loop-compaction.test.js +397 -0
- package/dist/server/lib/__tests__/server-agent-loop-failover.test.js +356 -0
- package/dist/server/lib/__tests__/server-agent-loop-features-caching.test.js +519 -0
- package/dist/server/lib/__tests__/server-agent-loop-features-edges.test.js +512 -0
- package/dist/server/lib/__tests__/server-subagent-bailout.test.js +194 -0
- package/dist/server/lib/__tests__/server-subagent-basics.test.js +348 -0
- package/dist/server/lib/__tests__/server-subagent-errors-abort.test.js +319 -0
- package/dist/server/lib/__tests__/server-subagent-errors-progress.test.js +253 -0
- package/dist/server/lib/__tests__/server-subagent-errors.part2.test.js +253 -0
- package/dist/server/lib/__tests__/server-subagent-errors.test.js +319 -0
- package/dist/server/lib/__tests__/session-checkpoint-load.test.js +275 -0
- package/dist/server/lib/__tests__/session-checkpoint-save.test.js +159 -0
- package/dist/server/lib/__tests__/ssrf-guard.test.js +93 -0
- package/dist/server/lib/__tests__/supabase-client.test.js +111 -0
- package/dist/server/lib/__tests__/template-resolver.test.js +317 -0
- package/dist/server/lib/__tests__/utils-timeout.test.js +49 -0
- package/dist/server/lib/__tests__/utils.test.js +322 -0
- package/dist/server/lib/agent-loop-executor.d.ts +7 -0
- package/dist/server/lib/agent-loop-executor.js +224 -0
- package/dist/server/lib/agent-loop-executor.js.map +1 -0
- package/dist/server/lib/agent-loop-turn.d.ts +53 -0
- package/dist/server/lib/agent-loop-turn.js +166 -0
- package/dist/server/lib/agent-loop-turn.js.map +1 -0
- package/dist/server/lib/agent-loop-types.d.ts +118 -0
- package/dist/server/lib/agent-loop-types.js +53 -0
- package/dist/server/lib/agent-loop-types.js.map +1 -0
- package/dist/server/lib/batch-client-anthropic.d.ts +10 -0
- package/dist/server/lib/batch-client-anthropic.js +144 -0
- package/dist/server/lib/batch-client-anthropic.js.map +1 -0
- package/dist/server/lib/batch-client-openai.d.ts +10 -0
- package/dist/server/lib/batch-client-openai.js +172 -0
- package/dist/server/lib/batch-client-openai.js.map +1 -0
- package/dist/server/lib/batch-client-types.d.ts +54 -0
- package/dist/server/lib/batch-client-types.js +27 -0
- package/dist/server/lib/batch-client-types.js.map +1 -0
- package/dist/server/lib/coa-renderer-components.d.ts +15 -0
- package/dist/server/lib/coa-renderer-components.js +361 -0
- package/dist/server/lib/coa-renderer-components.js.map +1 -0
- package/dist/server/lib/coa-renderer-pages.d.ts +15 -0
- package/dist/server/lib/coa-renderer-pages.js +467 -0
- package/dist/server/lib/coa-renderer-pages.js.map +1 -0
- package/dist/server/lib/coa-renderer-styles.d.ts +525 -0
- package/dist/server/lib/coa-renderer-styles.js +540 -0
- package/dist/server/lib/coa-renderer-styles.js.map +1 -0
- package/dist/server/lib/coa-renderer-tokens.d.ts +107 -0
- package/dist/server/lib/coa-renderer-tokens.js +46 -0
- package/dist/server/lib/coa-renderer-tokens.js.map +1 -0
- package/dist/server/lib/pdf-renderer-calc.d.ts +7 -0
- package/dist/server/lib/pdf-renderer-calc.js +272 -0
- package/dist/server/lib/pdf-renderer-calc.js.map +1 -0
- package/dist/server/lib/pdf-renderer-generation.d.ts +73 -0
- package/dist/server/lib/pdf-renderer-generation.js +298 -0
- package/dist/server/lib/pdf-renderer-generation.js.map +1 -0
- package/dist/server/lib/pdf-renderer-layout.d.ts +2 -0
- package/dist/server/lib/pdf-renderer-layout.js +144 -0
- package/dist/server/lib/pdf-renderer-layout.js.map +1 -0
- package/dist/server/lib/pdf-renderer-validation.d.ts +14 -0
- package/dist/server/lib/pdf-renderer-validation.js +220 -0
- package/dist/server/lib/pdf-renderer-validation.js.map +1 -0
- package/dist/server/lib/react-pdf-layout-elements.d.ts +8 -0
- package/dist/server/lib/react-pdf-layout-elements.js +366 -0
- package/dist/server/lib/react-pdf-layout-elements.js.map +1 -0
- package/dist/server/lib/react-pdf-layout-labels.d.ts +38 -0
- package/dist/server/lib/react-pdf-layout-labels.js +217 -0
- package/dist/server/lib/react-pdf-layout-labels.js.map +1 -0
- package/dist/server/lib/server-agent-loop-init.d.ts +28 -0
- package/dist/server/lib/server-agent-loop-init.js +138 -0
- package/dist/server/lib/server-agent-loop-init.js.map +1 -0
- package/dist/server/lib/server-agent-loop-v2.d.ts +110 -0
- package/dist/server/lib/server-agent-loop-v2.js +340 -0
- package/dist/server/lib/server-agent-loop-v2.js.map +1 -0
- package/dist/server/lib/server-agent-loop.js +2 -1
- package/dist/server/lib/server-agent-loop.js.map +1 -1
- package/dist/server/lib/server-subagent-loop.d.ts +3 -0
- package/dist/server/lib/server-subagent-loop.js +267 -0
- package/dist/server/lib/server-subagent-loop.js.map +1 -0
- package/dist/server/lib/session-types.d.ts +106 -0
- package/dist/server/lib/session-types.js +2 -0
- package/dist/server/lib/session-types.js.map +1 -0
- package/dist/server/local-agent-gateway-api.d.ts +34 -0
- package/dist/server/local-agent-gateway-api.js +156 -0
- package/dist/server/local-agent-gateway-api.js.map +1 -0
- package/dist/server/local-agent-gateway-handler.d.ts +3 -0
- package/dist/server/local-agent-gateway-handler.js +292 -0
- package/dist/server/local-agent-gateway-handler.js.map +1 -0
- package/dist/server/local-agent-gateway-init.d.ts +21 -0
- package/dist/server/local-agent-gateway-init.js +143 -0
- package/dist/server/local-agent-gateway-init.js.map +1 -0
- package/dist/server/local-agent-gateway-messages.d.ts +12 -0
- package/dist/server/local-agent-gateway-messages.js +108 -0
- package/dist/server/local-agent-gateway-messages.js.map +1 -0
- package/dist/server/local-agent-gateway-stats.d.ts +53 -0
- package/dist/server/local-agent-gateway-stats.js +129 -0
- package/dist/server/local-agent-gateway-stats.js.map +1 -0
- package/dist/server/local-agent-gateway-types.d.ts +94 -0
- package/dist/server/local-agent-gateway-types.js +78 -0
- package/dist/server/local-agent-gateway-types.js.map +1 -0
- package/dist/server/local-agent-gateway.d.ts +6 -0
- package/dist/server/local-agent-gateway.js +40 -0
- package/dist/server/local-agent-gateway.js.map +1 -1
- package/dist/server/providers/__tests__/anthropic-adapter.test.js +228 -0
- package/dist/server/providers/__tests__/anthropic-betas-toolchoice.test.js +257 -0
- package/dist/server/providers/__tests__/anthropic-errors.test.js +262 -0
- package/dist/server/providers/__tests__/anthropic-stream-core.test.js +275 -0
- package/dist/server/providers/__tests__/anthropic-streaming-betas.test.js +247 -0
- package/dist/server/providers/__tests__/anthropic-streaming-core.test.js +275 -0
- package/dist/server/providers/__tests__/bedrock-config.test.js +177 -0
- package/dist/server/providers/__tests__/bedrock-stream-behavior-streaming.test.js +272 -0
- package/dist/server/providers/__tests__/bedrock-stream-behavior-toolchoice.test.js +214 -0
- package/dist/server/providers/__tests__/bedrock-stream-behavior.part2.test.js +165 -0
- package/dist/server/providers/__tests__/bedrock-stream-behavior.test.js +309 -0
- package/dist/server/providers/__tests__/bedrock-stream-body-credentials.test.js +170 -0
- package/dist/server/providers/__tests__/bedrock-stream-body-extras.test.js +183 -0
- package/dist/server/providers/__tests__/bedrock-stream-body-request.test.js +305 -0
- package/dist/server/providers/__tests__/bedrock-stream-body.part2.test.js +305 -0
- package/dist/server/providers/__tests__/bedrock-stream-body.test.js +175 -0
- package/dist/server/providers/__tests__/bedrock-stream-errors.test.js +165 -0
- package/dist/server/providers/__tests__/gemini-config-methods.test.js +182 -0
- package/dist/server/providers/__tests__/gemini-config-streaming.test.js +257 -0
- package/dist/server/providers/__tests__/gemini-conversion-messages.test.js +247 -0
- package/dist/server/providers/__tests__/gemini-conversion-schema.test.js +365 -0
- package/dist/server/providers/__tests__/gemini-tools-choice.test.js +221 -0
- package/dist/server/providers/__tests__/gemini-tools-fn.test.js +252 -0
- package/dist/server/providers/__tests__/openai-config.test.js +194 -0
- package/dist/server/providers/__tests__/openai-conversion.test.js +276 -0
- package/dist/server/providers/__tests__/openai-messages.test.js +261 -0
- package/dist/server/providers/__tests__/openai-streaming.test.js +394 -0
- package/dist/server/providers/__tests__/openai-tools-cache.test.js +227 -0
- package/dist/server/providers/__tests__/registry.test.js +183 -0
- package/dist/server/providers/__tests__/shared.test.js +297 -0
- package/dist/server/providers/gemini-conversion.d.ts +17 -0
- package/dist/server/providers/gemini-conversion.js +185 -0
- package/dist/server/providers/gemini-conversion.js.map +1 -0
- package/dist/server/providers/gemini-streaming.d.ts +18 -0
- package/dist/server/providers/gemini-streaming.js +187 -0
- package/dist/server/providers/gemini-streaming.js.map +1 -0
- package/dist/server/providers/openai-adapter.d.ts +15 -0
- package/dist/server/providers/openai-adapter.js +423 -0
- package/dist/server/providers/openai-adapter.js.map +1 -0
- package/dist/server/providers/openai-conversion.d.ts +21 -0
- package/dist/server/providers/openai-conversion.js +191 -0
- package/dist/server/providers/openai-conversion.js.map +1 -0
- package/dist/server/server-agent.d.ts +21 -0
- package/dist/server/server-agent.js +162 -0
- package/dist/server/server-agent.js.map +1 -0
- package/dist/server/server-chat.d.ts +6 -0
- package/dist/server/server-chat.js +210 -0
- package/dist/server/server-chat.js.map +1 -0
- package/dist/server/server-cost-guard.d.ts +16 -0
- package/dist/server/server-cost-guard.js +141 -0
- package/dist/server/server-cost-guard.js.map +1 -0
- package/dist/server/server-executors.d.ts +10 -0
- package/dist/server/server-executors.js +110 -0
- package/dist/server/server-executors.js.map +1 -0
- package/dist/server/server-helpers.d.ts +49 -0
- package/dist/server/server-helpers.js +210 -0
- package/dist/server/server-helpers.js.map +1 -0
- package/dist/server/server-persist.d.ts +43 -0
- package/dist/server/server-persist.js +249 -0
- package/dist/server/server-persist.js.map +1 -0
- package/dist/server/server-rate-limit.d.ts +9 -0
- package/dist/server/server-rate-limit.js +77 -0
- package/dist/server/server-rate-limit.js.map +1 -0
- package/dist/server/server-routes-approvals.d.ts +4 -0
- package/dist/server/server-routes-approvals.js +238 -0
- package/dist/server/server-routes-approvals.js.map +1 -0
- package/dist/server/server-routes-auth.d.ts +7 -0
- package/dist/server/server-routes-auth.js +532 -0
- package/dist/server/server-routes-auth.js.map +1 -0
- package/dist/server/server-routes-events.d.ts +4 -0
- package/dist/server/server-routes-events.js +167 -0
- package/dist/server/server-routes-events.js.map +1 -0
- package/dist/server/server-routes-public.d.ts +24 -0
- package/dist/server/server-routes-public.js +453 -0
- package/dist/server/server-routes-public.js.map +1 -0
- package/dist/server/server-routes-waitpoints.d.ts +4 -0
- package/dist/server/server-routes-waitpoints.js +190 -0
- package/dist/server/server-routes-waitpoints.js.map +1 -0
- package/dist/server/server-routes-webchat.d.ts +14 -0
- package/dist/server/server-routes-webchat.js +307 -0
- package/dist/server/server-routes-webchat.js.map +1 -0
- package/dist/server/server-routes-workflows.d.ts +5 -0
- package/dist/server/server-routes-workflows.js +289 -0
- package/dist/server/server-routes-workflows.js.map +1 -0
- package/dist/server/server-sse.d.ts +13 -0
- package/dist/server/server-sse.js +197 -0
- package/dist/server/server-sse.js.map +1 -0
- package/dist/server/server-store-circuit-breaker.d.ts +32 -0
- package/dist/server/server-store-circuit-breaker.js +211 -0
- package/dist/server/server-store-circuit-breaker.js.map +1 -0
- package/dist/server/server-store.d.ts +5 -0
- package/dist/server/server-store.js +71 -0
- package/dist/server/server-store.js.map +1 -0
- package/dist/server/server-trace.d.ts +41 -0
- package/dist/server/server-trace.js +133 -0
- package/dist/server/server-trace.js.map +1 -0
- package/dist/server/server-worker.d.ts +4 -0
- package/dist/server/server-worker.js +127 -0
- package/dist/server/server-worker.js.map +1 -0
- package/dist/server/session-events.d.ts +27 -0
- package/dist/server/session-events.js +69 -0
- package/dist/server/session-events.js.map +1 -0
- package/dist/server/session-manager.d.ts +52 -0
- package/dist/server/session-manager.js +502 -0
- package/dist/server/session-manager.js.map +1 -0
- package/dist/server/tool-router-discovery.d.ts +33 -0
- package/dist/server/tool-router-discovery.js +218 -0
- package/dist/server/tool-router-discovery.js.map +1 -0
- package/dist/server/tool-router-types.d.ts +91 -0
- package/dist/server/tool-router-types.js +336 -0
- package/dist/server/tool-router-types.js.map +1 -0
- package/dist/server/tool-router-user-tools.d.ts +16 -0
- package/dist/server/tool-router-user-tools.js +269 -0
- package/dist/server/tool-router-user-tools.js.map +1 -0
- package/dist/server/validation-schemas.d.ts +12 -0
- package/dist/server/validation-schemas.js +251 -0
- package/dist/server/validation-schemas.js.map +1 -0
- package/dist/shared/agent-core-config.d.ts +12 -0
- package/dist/shared/agent-core-config.js +77 -0
- package/dist/shared/agent-core-config.js.map +1 -0
- package/dist/shared/agent-core-config.test.js +132 -0
- package/dist/shared/agent-core-context-thinking.test.js +293 -0
- package/dist/shared/agent-core-loop-calls.test.js +174 -0
- package/dist/shared/agent-core-loop-detector-bail.test.js +201 -0
- package/dist/shared/agent-core-loop-detector.test.js +195 -0
- package/dist/shared/agent-core-loop-errors.test.js +258 -0
- package/dist/shared/agent-core-loop.d.ts +53 -0
- package/dist/shared/agent-core-loop.js +251 -0
- package/dist/shared/agent-core-loop.js.map +1 -0
- package/dist/shared/agent-core-pricing.test.js +191 -0
- package/dist/shared/agent-core-sanitize-retry.test.js +129 -0
- package/dist/shared/agent-core-tools.d.ts +32 -0
- package/dist/shared/agent-core-tools.js +323 -0
- package/dist/shared/agent-core-tools.js.map +1 -0
- package/dist/shared/agent-core-types.d.ts +182 -0
- package/dist/shared/agent-core-types.js +265 -0
- package/dist/shared/agent-core-types.js.map +1 -0
- package/dist/shared/agent-core.js +1 -1
- package/dist/shared/agent-core.js.map +1 -1
- package/dist/shared/agent-loop-base.d.ts +130 -0
- package/dist/shared/agent-loop-base.js +347 -0
- package/dist/shared/agent-loop-base.js.map +1 -0
- package/dist/shared/api-client-build-request.test.js +228 -0
- package/dist/shared/api-client-build-system-caching.test.js +107 -0
- package/dist/shared/api-client-build.test.js +223 -0
- package/dist/shared/api-client-config.d.ts +21 -0
- package/dist/shared/api-client-helpers.d.ts +57 -0
- package/dist/shared/api-client-helpers.test.js +261 -0
- package/dist/shared/api-client-proxy-happy.test.js +255 -0
- package/dist/shared/api-client-proxy-retry.test.js +307 -0
- package/dist/shared/api-client-proxy.d.ts +26 -0
- package/dist/shared/api-client-proxy.test.js +255 -0
- package/dist/shared/api-client-retry.test.js +307 -0
- package/dist/shared/api-client-system-trimming.test.js +261 -0
- package/dist/shared/api-client-trimming.d.ts +36 -0
- package/dist/shared/api-client.js.map +1 -1
- package/dist/shared/api-client.test.js +228 -0
- package/dist/shared/compaction-thinking.test.js +315 -0
- package/dist/shared/compaction-trimming.test.js +223 -0
- package/dist/shared/exec-validator.d.ts +29 -0
- package/dist/shared/exec-validator.js +106 -0
- package/dist/shared/exec-validator.js.map +1 -0
- package/dist/shared/imsg-constants.d.ts +8 -0
- package/dist/shared/imsg-constants.js +13 -0
- package/dist/shared/imsg-constants.js.map +1 -0
- package/dist/shared/sse-parser-callbacks.test.js +422 -0
- package/dist/shared/sse-parser-collect.test.js +252 -0
- package/dist/shared/sse-parser-e2e.test.js +558 -0
- package/dist/shared/sse-parser-parse.test.js +253 -0
- package/dist/shared/tool-dispatch-advanced-batch-build.test.js +405 -0
- package/dist/shared/tool-dispatch-advanced.test.js +320 -0
- package/dist/shared/tool-dispatch-basic.test.js +278 -0
- package/dist/shared/tool-dispatch-content.d.ts +14 -0
- package/dist/shared/tool-dispatch-parallel.test.js +378 -0
- package/dist/shared/tool-dispatch.js +1 -1
- package/dist/shared/tool-dispatch.js.map +1 -1
- package/dist/webchat/__tests__/widget-messaging.test.js +323 -0
- package/dist/webchat/__tests__/widget.test.js +273 -0
- package/dist/webchat/widget-styles.d.ts +7 -0
- package/dist/webchat/widget-styles.js +11 -0
- package/dist/webchat/widget-styles.js.map +1 -0
- package/package.json +5 -4
- package/src/cli/services/builtin-skills/verify.md +72 -0
- package/vendor/ink/build/ink.js +33 -10
- package/vendor/ink/build/log-update.js +11 -4
package/dist/server/index.js
CHANGED
|
@@ -5,27 +5,36 @@
|
|
|
5
5
|
// Shares agent-core with CLI via src/shared/agent-core.ts
|
|
6
6
|
|
|
7
7
|
import http from "node:http";
|
|
8
|
-
import { randomUUID
|
|
8
|
+
import { randomUUID } from "node:crypto";
|
|
9
9
|
import Anthropic from "@anthropic-ai/sdk";
|
|
10
10
|
import { createLogger } from "./lib/logger.js";
|
|
11
11
|
const log = createLogger("server");
|
|
12
|
-
import { sanitizeError
|
|
13
|
-
import { MODELS } from "../shared/constants.js";
|
|
12
|
+
import { sanitizeError } from "../shared/agent-core.js";
|
|
14
13
|
import { handleProxy } from "./proxy-handlers.js";
|
|
15
14
|
import { handleNodeRoutes, setNodeAgentInvoker } from "./handlers/nodes.js";
|
|
16
15
|
import { handleTranscribe } from "./handlers/transcription.js";
|
|
17
16
|
import { handleBillingRoutes, incrementUsage, checkPlanLimits } from "./handlers/billing.js";
|
|
17
|
+
import { handleSessionRoutes } from "./handlers/sessions-handlers.js";
|
|
18
18
|
import { generateCompaction } from "./lib/compaction-service.js";
|
|
19
19
|
import { initLocalAgentGateway, shutdownGateway as shutdownAgentGateway, getGatewayStats } from "./local-agent-gateway.js";
|
|
20
20
|
import { initSupabase, getServiceClient } from "./lib/supabase-client.js";
|
|
21
21
|
import { loadCheckpoint, markOrphaned } from "./lib/session-checkpoint.js";
|
|
22
22
|
import { rateLimiter } from "./lib/rate-limiter.js";
|
|
23
23
|
import { sanitizeAndLog } from "./lib/prompt-sanitizer.js";
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import { queueSpan, auditRowToSpan
|
|
28
|
-
|
|
24
|
+
import { generateOpenApiSpec } from "./handlers/api-docs.js";
|
|
25
|
+
import { processWorkflowSteps, handleWebhookIngestion, executeInlineChain, initWorkerPool, getPoolStats, shutdownPool, verifyGuestApprovalSignature } from "./handlers/workflows.js";
|
|
26
|
+
import { loadUserTools, executeTool, flushSpans } from "./tool-router.js";
|
|
27
|
+
import { queueSpan, auditRowToSpan } from "./lib/clickhouse-buffer.js";
|
|
28
|
+
|
|
29
|
+
// Extracted modules — single source of truth (no inline duplicates)
|
|
30
|
+
import { safeCompare, getCorsHeaders, jsonResponse, readBody } from "./server-helpers.js";
|
|
31
|
+
import { sendIpRateLimit } from "./server-rate-limit.js";
|
|
32
|
+
import { resolveAndValidateStoreId } from "./server-store.js";
|
|
33
|
+
import { getSseClients, safeSseWrite, sendWorkflowSSE, getTotalSseClients, sseCleanupInterval, MAX_SSE_CLIENTS_PER_RUN, MAX_SSE_TOTAL_CLIENTS, setupPgListen, closePgClient, pgListenReady } from "./server-sse.js";
|
|
34
|
+
import { handleAgentChat } from "./server-chat.js";
|
|
35
|
+
import { wireToolExecutor, wireAgentExecutor, wireBroadcasters, invokeAgentForChannel } from "./server-executors.js";
|
|
36
|
+
import { startWorkerLoop, stopWorkerLoop } from "./server-worker.js";
|
|
37
|
+
import { getCircuitBreakerStats } from "./server-store-circuit-breaker.js";
|
|
29
38
|
|
|
30
39
|
// ============================================================================
|
|
31
40
|
// PROCESS ERROR HANDLERS
|
|
@@ -52,7 +61,6 @@ const SUPABASE_URL = process.env.SUPABASE_URL;
|
|
|
52
61
|
const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
53
62
|
const SERVICE_ROLE_JWT = process.env.SERVICE_ROLE_JWT || "";
|
|
54
63
|
const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
|
|
55
|
-
const ALLOWED_ORIGINS = (process.env.ALLOWED_ORIGINS || "http://localhost:3000,http://127.0.0.1:3000").split(",").map(s => s.trim());
|
|
56
64
|
const FLY_INTERNAL_SECRET = process.env.FLY_INTERNAL_SECRET || "";
|
|
57
65
|
if (!FLY_INTERNAL_SECRET) {
|
|
58
66
|
console.warn("[SECURITY] FLY_INTERNAL_SECRET is not set — internal endpoints are unprotected");
|
|
@@ -62,7 +70,6 @@ if (!FLY_INTERNAL_SECRET) {
|
|
|
62
70
|
// READINESS STATE
|
|
63
71
|
// ============================================================================
|
|
64
72
|
|
|
65
|
-
let pgListenReady = false;
|
|
66
73
|
let workerPoolReady = false;
|
|
67
74
|
function isReady() {
|
|
68
75
|
return workerPoolReady; // PG listen is optional (SSE only)
|
|
@@ -71,1311 +78,6 @@ function isReady() {
|
|
|
71
78
|
// Webchat agent invoker — set later to avoid circular deps (same as node agent invoker)
|
|
72
79
|
let webchatAgentInvoker = null;
|
|
73
80
|
|
|
74
|
-
// ============================================================================
|
|
75
|
-
// RATE LIMITING — Phase 7.2 token-bucket (see lib/rate-limiter.ts)
|
|
76
|
-
// ============================================================================
|
|
77
|
-
|
|
78
|
-
/** Check IP rate limit and send 429 with proper headers if exceeded */
|
|
79
|
-
function sendIpRateLimit(res, ip, headers) {
|
|
80
|
-
const result = rateLimiter.checkRequest(`ip:${ip}`, "unauthenticated");
|
|
81
|
-
if (result.allowed) return false; // not rate-limited
|
|
82
|
-
res.writeHead(429, {
|
|
83
|
-
"Retry-After": String(Math.ceil(result.retryAfterMs / 1000) || 1),
|
|
84
|
-
"X-RateLimit-Remaining": "0",
|
|
85
|
-
"Content-Type": "application/json",
|
|
86
|
-
...headers
|
|
87
|
-
});
|
|
88
|
-
res.end(JSON.stringify({
|
|
89
|
-
error: "Too many requests"
|
|
90
|
-
}));
|
|
91
|
-
return true; // was rate-limited
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Agent chat rate limiting — per-store + global concurrent cap
|
|
95
|
-
const agentChatLimiter = new Map();
|
|
96
|
-
const AGENT_CHAT_MAX_PER_MIN = 60;
|
|
97
|
-
const AGENT_CHAT_MAX_CONCURRENT = 10;
|
|
98
|
-
let agentChatConcurrent = 0;
|
|
99
|
-
|
|
100
|
-
// Periodically clean up stale entries from agentChatLimiter to prevent unbounded Map growth
|
|
101
|
-
setInterval(() => {
|
|
102
|
-
const now = Date.now();
|
|
103
|
-
for (const [key, entry] of agentChatLimiter) {
|
|
104
|
-
if (now - entry.windowStart > 120_000) {
|
|
105
|
-
agentChatLimiter.delete(key);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}, 60_000);
|
|
109
|
-
function checkAgentChatRateLimit(storeId) {
|
|
110
|
-
// Concurrent check
|
|
111
|
-
if (agentChatConcurrent >= AGENT_CHAT_MAX_CONCURRENT) {
|
|
112
|
-
return {
|
|
113
|
-
allowed: false,
|
|
114
|
-
error: "Too many concurrent agent sessions. Please wait."
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Per-store per-minute check
|
|
119
|
-
const now = Date.now();
|
|
120
|
-
let entry = agentChatLimiter.get(storeId);
|
|
121
|
-
if (!entry || now - entry.windowStart > 60_000) {
|
|
122
|
-
entry = {
|
|
123
|
-
count: 0,
|
|
124
|
-
windowStart: now
|
|
125
|
-
};
|
|
126
|
-
agentChatLimiter.set(storeId, entry);
|
|
127
|
-
}
|
|
128
|
-
entry.count++;
|
|
129
|
-
if (entry.count > AGENT_CHAT_MAX_PER_MIN) {
|
|
130
|
-
return {
|
|
131
|
-
allowed: false,
|
|
132
|
-
error: `Rate limit exceeded: ${AGENT_CHAT_MAX_PER_MIN}/min for agent chat`
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
return {
|
|
136
|
-
allowed: true
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Timing-safe secret comparison to prevent timing attacks
|
|
141
|
-
// Hash both values to fixed length before comparing — avoids leaking secret length
|
|
142
|
-
function safeCompare(a, b) {
|
|
143
|
-
if (!a || !b) return false;
|
|
144
|
-
const hashA = createHash("sha256").update(a).digest();
|
|
145
|
-
const hashB = createHash("sha256").update(b).digest();
|
|
146
|
-
return timingSafeEqual(hashA, hashB);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// ============================================================================
|
|
150
|
-
// TYPES
|
|
151
|
-
// ============================================================================
|
|
152
|
-
|
|
153
|
-
// Tool registry, user tools, executor, and agent loader are in ./tool-router.ts
|
|
154
|
-
|
|
155
|
-
// ============================================================================
|
|
156
|
-
// STORE CONTEXT — Server-derived store resolution (Apple-style)
|
|
157
|
-
// The server NEVER blindly trusts a client-supplied storeId. Instead it:
|
|
158
|
-
// 1. Resolves the user's stores from the `users` table via auth.uid()
|
|
159
|
-
// 2. Validates the client hint against the resolved set
|
|
160
|
-
// 3. Falls back to the user's first store if no hint provided
|
|
161
|
-
// 4. Returns null if no store can be resolved (caller must fail closed)
|
|
162
|
-
// ============================================================================
|
|
163
|
-
|
|
164
|
-
async function resolveAndValidateStoreId(supabase, clientStoreId, user, isServiceRole, _token, requestUserId) {
|
|
165
|
-
// Service-role callers: trusted ONLY for internal server-to-server calls
|
|
166
|
-
// (workflows, cron jobs) that have NO associated user. When a userId is
|
|
167
|
-
// present (e.g. MCP CLI using env-var service role key), we MUST still
|
|
168
|
-
// validate store membership to prevent cross-tenant access.
|
|
169
|
-
if (isServiceRole) {
|
|
170
|
-
const srUserId = user?.id || requestUserId;
|
|
171
|
-
if (!srUserId) return clientStoreId || null; // true internal call — pass through
|
|
172
|
-
if (!clientStoreId) return null; // user-context call without store hint
|
|
173
|
-
|
|
174
|
-
// Validate the user actually belongs to the requested store
|
|
175
|
-
const {
|
|
176
|
-
data: membership
|
|
177
|
-
} = await supabase.from("store_members").select("id").eq("store_id", clientStoreId).eq("user_id", srUserId).limit(1).maybeSingle();
|
|
178
|
-
if (membership) return clientStoreId;
|
|
179
|
-
|
|
180
|
-
// Fallback: check users table (legacy single-store pattern)
|
|
181
|
-
const {
|
|
182
|
-
data: userRow
|
|
183
|
-
} = await supabase.from("users").select("store_id").eq("auth_user_id", srUserId).eq("store_id", clientStoreId).maybeSingle();
|
|
184
|
-
if (userRow) return clientStoreId;
|
|
185
|
-
log.warn({
|
|
186
|
-
userId: srUserId,
|
|
187
|
-
clientStoreId
|
|
188
|
-
}, "resolveStoreId: service-role caller userId not authorized for store");
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
if (!user?.id) return null;
|
|
192
|
-
|
|
193
|
-
// Resolve user's actual stores from the `users` table (auth_user_id = auth.uid())
|
|
194
|
-
const {
|
|
195
|
-
data: userStores,
|
|
196
|
-
error
|
|
197
|
-
} = await supabase.from("users").select("store_id").eq("auth_user_id", user.id).not("store_id", "is", null);
|
|
198
|
-
if (error || !userStores?.length) {
|
|
199
|
-
log.warn({
|
|
200
|
-
userId: user.id,
|
|
201
|
-
error
|
|
202
|
-
}, "resolveStoreId: user has no stores");
|
|
203
|
-
return null;
|
|
204
|
-
}
|
|
205
|
-
const storeIds = userStores.map(r => r.store_id);
|
|
206
|
-
|
|
207
|
-
// If client provided a hint, validate it's in the user's set
|
|
208
|
-
if (clientStoreId) {
|
|
209
|
-
if (storeIds.includes(clientStoreId)) {
|
|
210
|
-
return clientStoreId;
|
|
211
|
-
}
|
|
212
|
-
log.warn({
|
|
213
|
-
userId: user.id,
|
|
214
|
-
clientStoreId,
|
|
215
|
-
userStores: storeIds
|
|
216
|
-
}, "resolveStoreId: client storeId not in user's stores");
|
|
217
|
-
return null; // Reject — don't silently fall back
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// No client hint — use first store (single-store users), or require explicit selection
|
|
221
|
-
if (storeIds.length === 1) {
|
|
222
|
-
return storeIds[0];
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Multi-store user without a hint — can't guess
|
|
226
|
-
log.warn({
|
|
227
|
-
userId: user.id,
|
|
228
|
-
storeCount: storeIds.length
|
|
229
|
-
}, "resolveStoreId: multi-store user must specify storeId");
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// ============================================================================
|
|
234
|
-
// CORS
|
|
235
|
-
// ============================================================================
|
|
236
|
-
|
|
237
|
-
function getCorsHeaders(origin) {
|
|
238
|
-
const headers = {
|
|
239
|
-
"X-Content-Type-Options": "nosniff",
|
|
240
|
-
"X-Frame-Options": "DENY",
|
|
241
|
-
"X-XSS-Protection": "0",
|
|
242
|
-
"Referrer-Policy": "strict-origin-when-cross-origin"
|
|
243
|
-
};
|
|
244
|
-
if (ALLOWED_ORIGINS.includes("*")) {
|
|
245
|
-
headers["Access-Control-Allow-Origin"] = "*";
|
|
246
|
-
} else if (origin && ALLOWED_ORIGINS.includes(origin)) {
|
|
247
|
-
headers["Access-Control-Allow-Origin"] = origin;
|
|
248
|
-
headers["Vary"] = "Origin";
|
|
249
|
-
}
|
|
250
|
-
// If origin doesn't match, no CORS header = browser blocks the request
|
|
251
|
-
|
|
252
|
-
headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS";
|
|
253
|
-
headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization, X-Store-Id";
|
|
254
|
-
return headers;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// ============================================================================
|
|
258
|
-
// PHASE 3: SSE STREAMING — real-time workflow run progress
|
|
259
|
-
// ============================================================================
|
|
260
|
-
|
|
261
|
-
// Map<runId, Set<ServerResponse>> for multiplexing SSE clients
|
|
262
|
-
const sseClients = new Map();
|
|
263
|
-
const MAX_SSE_CLIENTS_PER_RUN = 10;
|
|
264
|
-
const MAX_SSE_TOTAL_CLIENTS = 100;
|
|
265
|
-
|
|
266
|
-
/** Safe SSE write — returns false and calls cleanup if the connection is dead */
|
|
267
|
-
function safeSseWrite(res, data, cleanup) {
|
|
268
|
-
try {
|
|
269
|
-
if (res.destroyed || res.writableEnded) {
|
|
270
|
-
cleanup();
|
|
271
|
-
return false;
|
|
272
|
-
}
|
|
273
|
-
res.write(data);
|
|
274
|
-
return true;
|
|
275
|
-
} catch {
|
|
276
|
-
cleanup();
|
|
277
|
-
return false;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
function sendWorkflowSSE(res, data) {
|
|
281
|
-
try {
|
|
282
|
-
if (res.destroyed || res.writableEnded) return;
|
|
283
|
-
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
284
|
-
} catch {/* client disconnected — benign */}
|
|
285
|
-
}
|
|
286
|
-
function broadcastToRun(runId, data) {
|
|
287
|
-
const clients = sseClients.get(runId);
|
|
288
|
-
if (!clients?.size) return;
|
|
289
|
-
// H6 FIX: Prune dead connections during broadcast
|
|
290
|
-
for (const res of clients) {
|
|
291
|
-
if (res.destroyed || res.writableEnded) {
|
|
292
|
-
clients.delete(res);
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
sendWorkflowSSE(res, data);
|
|
296
|
-
}
|
|
297
|
-
if (clients.size === 0) sseClients.delete(runId);
|
|
298
|
-
}
|
|
299
|
-
function getTotalSseClients() {
|
|
300
|
-
let total = 0;
|
|
301
|
-
for (const clients of sseClients.values()) total += clients.size;
|
|
302
|
-
return total;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// H6 FIX: Periodic stale connection cleanup (every 60s)
|
|
306
|
-
const sseCleanupInterval = setInterval(() => {
|
|
307
|
-
for (const [rid, clients] of sseClients) {
|
|
308
|
-
for (const res of clients) {
|
|
309
|
-
if (res.destroyed || res.writableEnded) {
|
|
310
|
-
clients.delete(res);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
if (clients.size === 0) sseClients.delete(rid);
|
|
314
|
-
}
|
|
315
|
-
}, 60_000);
|
|
316
|
-
|
|
317
|
-
// pg LISTEN for real-time notifications
|
|
318
|
-
const DATABASE_URL = process.env.DATABASE_URL || "";
|
|
319
|
-
let pgClient = null;
|
|
320
|
-
let pgReconnectAttempts = 0;
|
|
321
|
-
const MAX_PG_RECONNECT_DELAY = 10_000; // 10s max — keep SSE reconnect snappy
|
|
322
|
-
|
|
323
|
-
async function setupPgListen() {
|
|
324
|
-
if (!DATABASE_URL) {
|
|
325
|
-
log.info("DATABASE_URL not set — SSE streaming disabled, using worker-only mode");
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
try {
|
|
329
|
-
// Strip sslmode from URL (pg v8 treats sslmode=require as verify-full) and set ssl manually
|
|
330
|
-
const cleanUrl = DATABASE_URL.replace(/[?&]sslmode=[^&]*/g, "").replace(/\?$/, "");
|
|
331
|
-
pgClient = new pg.Client({
|
|
332
|
-
connectionString: cleanUrl,
|
|
333
|
-
ssl: {
|
|
334
|
-
rejectUnauthorized: false
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
await pgClient.connect();
|
|
338
|
-
await pgClient.query("LISTEN workflow_step_event");
|
|
339
|
-
await pgClient.query("LISTEN workflow_run_event");
|
|
340
|
-
await pgClient.query("LISTEN workflow_step_pending");
|
|
341
|
-
await pgClient.query("LISTEN workflow_event");
|
|
342
|
-
await pgClient.query("LISTEN automation_event");
|
|
343
|
-
|
|
344
|
-
// Reset reconnect counter on successful connection
|
|
345
|
-
pgReconnectAttempts = 0;
|
|
346
|
-
pgListenReady = true;
|
|
347
|
-
|
|
348
|
-
// Debounced event trigger processing — fires at most once per 100ms
|
|
349
|
-
let eventTriggerTimer = null;
|
|
350
|
-
function debouncedEventProcess() {
|
|
351
|
-
if (eventTriggerTimer) return;
|
|
352
|
-
eventTriggerTimer = setTimeout(async () => {
|
|
353
|
-
eventTriggerTimer = null;
|
|
354
|
-
try {
|
|
355
|
-
const sb = getServiceClient();
|
|
356
|
-
const count = await processEventTriggers(sb);
|
|
357
|
-
if (count > 0) log.info({
|
|
358
|
-
count
|
|
359
|
-
}, "instant event processing");
|
|
360
|
-
} catch (err) {
|
|
361
|
-
log.error({
|
|
362
|
-
err: err.message
|
|
363
|
-
}, "event trigger processing error");
|
|
364
|
-
}
|
|
365
|
-
}, 100);
|
|
366
|
-
}
|
|
367
|
-
pgClient.on("notification", msg => {
|
|
368
|
-
if (!msg.payload) return;
|
|
369
|
-
try {
|
|
370
|
-
const data = JSON.parse(msg.payload);
|
|
371
|
-
|
|
372
|
-
// Automation event — trigger immediate processing
|
|
373
|
-
if (msg.channel === "automation_event") {
|
|
374
|
-
debouncedEventProcess();
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
const runId = data.run_id;
|
|
378
|
-
if (!runId) return;
|
|
379
|
-
if (msg.channel === "workflow_step_event") {
|
|
380
|
-
broadcastToRun(runId, {
|
|
381
|
-
type: "step_update",
|
|
382
|
-
...data
|
|
383
|
-
});
|
|
384
|
-
} else if (msg.channel === "workflow_run_event") {
|
|
385
|
-
broadcastToRun(runId, {
|
|
386
|
-
type: "run_update",
|
|
387
|
-
...data
|
|
388
|
-
});
|
|
389
|
-
} else if (msg.channel === "workflow_event") {
|
|
390
|
-
broadcastToRun(runId, {
|
|
391
|
-
type: "event",
|
|
392
|
-
event_type: data.event_type,
|
|
393
|
-
...data
|
|
394
|
-
});
|
|
395
|
-
} else if (msg.channel === "workflow_step_pending") {
|
|
396
|
-
// Phase 3.1: NOTIFY-driven step execution — immediate pickup (~50ms vs 5s polling)
|
|
397
|
-
const sb = getServiceClient();
|
|
398
|
-
processWorkflowSteps(sb, 1).catch(err => {
|
|
399
|
-
log.error({
|
|
400
|
-
err: err.message,
|
|
401
|
-
runId
|
|
402
|
-
}, "NOTIFY-driven step processing failed");
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
} catch (err) {
|
|
406
|
-
log.error({
|
|
407
|
-
err: err.message
|
|
408
|
-
}, "failed to parse pg notification");
|
|
409
|
-
}
|
|
410
|
-
});
|
|
411
|
-
pgClient.on("error", err => {
|
|
412
|
-
log.error({
|
|
413
|
-
err: err.message
|
|
414
|
-
}, "pg-listen connection error");
|
|
415
|
-
pgClient = null;
|
|
416
|
-
// Reconnect with exponential backoff
|
|
417
|
-
pgReconnectAttempts++;
|
|
418
|
-
const delay = Math.min(1000 * Math.pow(2, pgReconnectAttempts - 1), MAX_PG_RECONNECT_DELAY);
|
|
419
|
-
log.warn({
|
|
420
|
-
delayMs: delay,
|
|
421
|
-
attempt: pgReconnectAttempts
|
|
422
|
-
}, "pg-listen reconnecting");
|
|
423
|
-
setTimeout(() => setupPgListen(), delay);
|
|
424
|
-
});
|
|
425
|
-
log.info("pg-listen active on workflow_step_event, workflow_run_event, workflow_step_pending, workflow_event, automation_event");
|
|
426
|
-
} catch (err) {
|
|
427
|
-
log.error({
|
|
428
|
-
err: err.message
|
|
429
|
-
}, "pg-listen failed to connect");
|
|
430
|
-
pgClient = null;
|
|
431
|
-
// Reconnect with exponential backoff on initial connection failure too
|
|
432
|
-
pgReconnectAttempts++;
|
|
433
|
-
const delay = Math.min(1000 * Math.pow(2, pgReconnectAttempts - 1), MAX_PG_RECONNECT_DELAY);
|
|
434
|
-
log.warn({
|
|
435
|
-
delayMs: delay,
|
|
436
|
-
attempt: pgReconnectAttempts
|
|
437
|
-
}, "pg-listen reconnecting");
|
|
438
|
-
setTimeout(() => setupPgListen(), delay);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// ============================================================================
|
|
443
|
-
// HELPERS
|
|
444
|
-
// ============================================================================
|
|
445
|
-
|
|
446
|
-
function getAnthropicClient(agent) {
|
|
447
|
-
const key = agent.api_key || ANTHROPIC_API_KEY;
|
|
448
|
-
return new Anthropic({
|
|
449
|
-
apiKey: key,
|
|
450
|
-
timeout: 15 * 60 * 1000
|
|
451
|
-
}); // 15 min for tool-heavy requests
|
|
452
|
-
}
|
|
453
|
-
function sendSSE(res, event) {
|
|
454
|
-
try {
|
|
455
|
-
if (res.destroyed || res.writableEnded) return;
|
|
456
|
-
res.write(`data: ${JSON.stringify(event)}\n\n`);
|
|
457
|
-
} catch {/* client disconnected — benign */}
|
|
458
|
-
}
|
|
459
|
-
function jsonResponse(res, status, data, corsHeaders) {
|
|
460
|
-
res.writeHead(status, {
|
|
461
|
-
"Content-Type": "application/json",
|
|
462
|
-
...corsHeaders
|
|
463
|
-
});
|
|
464
|
-
res.end(JSON.stringify(data));
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
/**
|
|
468
|
-
* Strip large base64 data fields from a JSON string up to `keepFrom` offset.
|
|
469
|
-
* Uses a linear indexOf scan — safe on strings of any size (no regex stack overflow).
|
|
470
|
-
* Handles both `"data":"<base64>"` (Anthropic image blocks) and
|
|
471
|
-
* `"__IMAGE__<mime>__<base64>"` text values (Read tool marker format).
|
|
472
|
-
*/
|
|
473
|
-
function stripLargeBase64Fields(raw, keepFrom) {
|
|
474
|
-
const MIN_DATA_LEN = 8_000;
|
|
475
|
-
|
|
476
|
-
// ── Pass 1: Strip "data":"<large base64>" fields (Anthropic image source blocks) ──
|
|
477
|
-
let result = raw;
|
|
478
|
-
{
|
|
479
|
-
const DATA_MARKER = '"data":"';
|
|
480
|
-
const parts = [];
|
|
481
|
-
let pos = 0;
|
|
482
|
-
while (pos < keepFrom) {
|
|
483
|
-
const idx = result.indexOf(DATA_MARKER, pos);
|
|
484
|
-
if (idx === -1 || idx >= keepFrom) {
|
|
485
|
-
parts.push(result.slice(pos, keepFrom));
|
|
486
|
-
pos = keepFrom;
|
|
487
|
-
break;
|
|
488
|
-
}
|
|
489
|
-
parts.push(result.slice(pos, idx + DATA_MARKER.length));
|
|
490
|
-
pos = idx + DATA_MARKER.length;
|
|
491
|
-
|
|
492
|
-
// Find closing quote (base64 has no backslashes, so simple scan is safe)
|
|
493
|
-
let end = pos;
|
|
494
|
-
while (end < result.length && result[end] !== '"') end++;
|
|
495
|
-
if (end - pos >= MIN_DATA_LEN && end <= keepFrom) {
|
|
496
|
-
// Large data field in the prune zone — replace with empty
|
|
497
|
-
parts.push('"');
|
|
498
|
-
pos = end + 1; // skip past the original closing quote (already replaced)
|
|
499
|
-
}
|
|
500
|
-
// else: small field or near keepFrom boundary — leave intact
|
|
501
|
-
}
|
|
502
|
-
parts.push(result.slice(keepFrom)); // always keep tail intact
|
|
503
|
-
result = parts.join("");
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// ── Pass 2: Strip __IMAGE__<mime>__<large base64> text markers ──
|
|
507
|
-
// If the client-side tool-dispatch regex failed to convert these to image
|
|
508
|
-
// content blocks, they stay as huge text strings in tool_result content.
|
|
509
|
-
// They appear in JSON as: "__IMAGE__image/png__iVBOR...very long..."
|
|
510
|
-
{
|
|
511
|
-
const IMG_MARKER = "__IMAGE__";
|
|
512
|
-
const adjustedKeepFrom = Math.min(keepFrom, result.length);
|
|
513
|
-
const parts = [];
|
|
514
|
-
let pos = 0;
|
|
515
|
-
while (pos < adjustedKeepFrom) {
|
|
516
|
-
const idx = result.indexOf(IMG_MARKER, pos);
|
|
517
|
-
if (idx === -1 || idx >= adjustedKeepFrom) {
|
|
518
|
-
parts.push(result.slice(pos, adjustedKeepFrom));
|
|
519
|
-
pos = adjustedKeepFrom;
|
|
520
|
-
break;
|
|
521
|
-
}
|
|
522
|
-
parts.push(result.slice(pos, idx));
|
|
523
|
-
|
|
524
|
-
// Find the end of this text value (closing quote of the JSON string)
|
|
525
|
-
let end = idx;
|
|
526
|
-
while (end < result.length && result[end] !== '"') end++;
|
|
527
|
-
if (end - idx >= MIN_DATA_LEN && end <= adjustedKeepFrom) {
|
|
528
|
-
// Large __IMAGE__ marker in the prune zone — replace with placeholder
|
|
529
|
-
parts.push("[image pruned]");
|
|
530
|
-
pos = end; // land on closing quote; next iteration emits it
|
|
531
|
-
} else {
|
|
532
|
-
// Small or near boundary — keep intact
|
|
533
|
-
parts.push(result.slice(idx, idx + IMG_MARKER.length));
|
|
534
|
-
pos = idx + IMG_MARKER.length;
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
parts.push(result.slice(adjustedKeepFrom));
|
|
538
|
-
result = parts.join("");
|
|
539
|
-
}
|
|
540
|
-
return result;
|
|
541
|
-
}
|
|
542
|
-
async function readBody(req) {
|
|
543
|
-
// 500MB hard limit — conversation history with many large images can be very large.
|
|
544
|
-
// For bodies over 10MB we prune old base64 image data from the raw string before
|
|
545
|
-
// JSON.parse, so subsequent requests in the same conversation stay bounded.
|
|
546
|
-
const MAX_BODY = 524_288_000; // 500MB
|
|
547
|
-
return new Promise((resolve, reject) => {
|
|
548
|
-
const chunks = [];
|
|
549
|
-
let size = 0;
|
|
550
|
-
let rejected = false;
|
|
551
|
-
req.on("data", chunk => {
|
|
552
|
-
size += chunk.length;
|
|
553
|
-
if (size > MAX_BODY && !rejected) {
|
|
554
|
-
rejected = true;
|
|
555
|
-
req.resume(); // drain to avoid Fly proxy 502
|
|
556
|
-
reject(new Error("Request body too large (max 500MB)"));
|
|
557
|
-
return;
|
|
558
|
-
}
|
|
559
|
-
if (!rejected) chunks.push(chunk);
|
|
560
|
-
});
|
|
561
|
-
req.on("end", () => {
|
|
562
|
-
if (rejected) return;
|
|
563
|
-
|
|
564
|
-
// Detect body truncation: if Content-Length was sent and we received less
|
|
565
|
-
const declaredLen = parseInt(req.headers["content-length"] || "0", 10);
|
|
566
|
-
if (declaredLen > 0 && size < declaredLen) {
|
|
567
|
-
log.error({
|
|
568
|
-
declaredLen,
|
|
569
|
-
receivedLen: size
|
|
570
|
-
}, "Request body truncated during transmission");
|
|
571
|
-
reject(new Error(`Body truncated: expected ${declaredLen} bytes, got ${size}`));
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
let raw = Buffer.concat(chunks).toString("utf8");
|
|
575
|
-
|
|
576
|
-
// Strip old base64 data from history when body is large.
|
|
577
|
-
// Threshold lowered to 1MB — image-heavy conversations (e.g. reading
|
|
578
|
-
// product photos) easily exceed 10MB with just a few images.
|
|
579
|
-
// Keep the last 1MB intact (current user message with fresh images).
|
|
580
|
-
// Uses a linear scan to avoid String.replace() stack overflow on huge strings.
|
|
581
|
-
if (raw.length > 1_000_000) {
|
|
582
|
-
const keepFrom = Math.max(0, raw.length - 1_048_576); // keep last 1MB
|
|
583
|
-
raw = stripLargeBase64Fields(raw, keepFrom);
|
|
584
|
-
log.info({
|
|
585
|
-
originalBytes: size,
|
|
586
|
-
prunedBytes: Buffer.byteLength(raw)
|
|
587
|
-
}, "Pruned old base64 data from request body");
|
|
588
|
-
}
|
|
589
|
-
resolve(raw);
|
|
590
|
-
});
|
|
591
|
-
req.on("error", reject);
|
|
592
|
-
});
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// ============================================================================
|
|
596
|
-
// HISTORY COMPACTION
|
|
597
|
-
// ============================================================================
|
|
598
|
-
|
|
599
|
-
/**
|
|
600
|
-
* Compact conversation history to fit within a total character budget.
|
|
601
|
-
*
|
|
602
|
-
* Does NOT truncate individual messages or tool results — Anthropic's
|
|
603
|
-
* context_management API handles clearing old tool uses (clear_tool_uses_20250919)
|
|
604
|
-
* and compacting context (compact_20260112) when the context window grows.
|
|
605
|
-
*
|
|
606
|
-
* This function only enforces a total budget by walking newest→oldest and
|
|
607
|
-
* dropping the oldest messages that don't fit.
|
|
608
|
-
*/
|
|
609
|
-
function compactHistory(history, maxHistoryChars) {
|
|
610
|
-
if (!history?.length) return [];
|
|
611
|
-
let totalChars = 0;
|
|
612
|
-
const compacted = [];
|
|
613
|
-
for (let i = history.length - 1; i >= 0; i--) {
|
|
614
|
-
const msg = history[i];
|
|
615
|
-
const msgChars = JSON.stringify(msg.content).length;
|
|
616
|
-
if (totalChars + msgChars > maxHistoryChars) break;
|
|
617
|
-
totalChars += msgChars;
|
|
618
|
-
compacted.unshift(msg);
|
|
619
|
-
}
|
|
620
|
-
// Ensure starts with user message
|
|
621
|
-
while (compacted.length > 0 && compacted[0].role !== "user") compacted.shift();
|
|
622
|
-
return compacted;
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
// ============================================================================
|
|
626
|
-
// SHARED AGENT HELPERS — used by both SSE chat and channel agent paths
|
|
627
|
-
// ============================================================================
|
|
628
|
-
|
|
629
|
-
/** Build the full system prompt for an agent. Both SSE chat and channel paths
|
|
630
|
-
* call this so the prompt logic is never duplicated. */
|
|
631
|
-
async function buildAgentSystemPrompt(supabase, agent, storeId, message, tools, opts) {
|
|
632
|
-
// --- STATIC portion (cache-friendly, same across conversations) ---
|
|
633
|
-
// Sanitize the DB-stored agent system prompt to prevent injection attacks
|
|
634
|
-
const rawAgentPrompt = agent.system_prompt || "You are a helpful assistant.";
|
|
635
|
-
let systemPrompt = sanitizeAndLog(rawAgentPrompt, "buildAgentSystemPrompt", {
|
|
636
|
-
agentId: agent.id
|
|
637
|
-
});
|
|
638
|
-
if (storeId) systemPrompt += `\n\nYou are operating for store_id: ${storeId}. Always include this in tool calls that require it.`;
|
|
639
|
-
if (!agent.can_modify) systemPrompt += "\n\nIMPORTANT: You have read-only access. Do not attempt to modify any data.";
|
|
640
|
-
if (agent.tone && agent.tone !== "professional") systemPrompt += `\n\nTone: Respond in a ${agent.tone} tone.`;
|
|
641
|
-
if (agent.verbosity === "concise") systemPrompt += "\n\nBe concise — short answers, minimal explanation.";else if (agent.verbosity === "verbose") systemPrompt += "\n\nBe thorough — provide detailed answers with full context.";
|
|
642
|
-
if (agent.context_config) {
|
|
643
|
-
const ctx = agent.context_config;
|
|
644
|
-
if (ctx.includeLocations && ctx.locationIds?.length) systemPrompt += `\n\nFocus on these locations: ${ctx.locationIds.join(", ")}`;
|
|
645
|
-
if (ctx.includeCustomers && ctx.customerSegments?.length) systemPrompt += `\n\nFocus on these customer segments: ${ctx.customerSegments.join(", ")}`;
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
// Tool manifest — core tools (full schemas already loaded)
|
|
649
|
-
const toolNames = tools.map(t => t.name);
|
|
650
|
-
systemPrompt += `\n\n## Available Tools\nYou have ${toolNames.length} core tools available in this session:\n${toolNames.join(", ")}\n\nFor local machine operations, use the \`local_agent\` tool (exec, tools, discover actions). For cloud security tools, use \`kali\`. Do NOT reference CLI-local tools like read_file, write_file, edit_file, glob, grep, run_command — those are not available in this environment.`;
|
|
651
|
-
|
|
652
|
-
// Extended tools index — names + one-line descriptions only (saves ~20K tokens)
|
|
653
|
-
const extendedTools = opts?.extendedTools || [];
|
|
654
|
-
if (extendedTools.length > 0) {
|
|
655
|
-
systemPrompt += `\n\n## Extended Tools (call discover_tools to activate)\nThese tools are available but not loaded yet. Call \`discover_tools\` with the tool name(s) before using them:\n`;
|
|
656
|
-
for (const t of extendedTools) {
|
|
657
|
-
// First sentence only for compact display
|
|
658
|
-
const shortDesc = t.description.split(".")[0];
|
|
659
|
-
systemPrompt += `- **${t.name}**: ${shortDesc}\n`;
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
// --- DYNAMIC portion (changes per conversation, prepended to user message) ---
|
|
664
|
-
const dynamicParts = [];
|
|
665
|
-
|
|
666
|
-
// Client-provided session context (SSE chat sends this from SwiftUI/web)
|
|
667
|
-
if (opts?.clientContext && typeof opts.clientContext === "object") {
|
|
668
|
-
const context = opts.clientContext;
|
|
669
|
-
const ctxParts = [];
|
|
670
|
-
if (context.storeName) ctxParts.push(`Store: ${context.storeName}`);
|
|
671
|
-
if (context.locationName) {
|
|
672
|
-
let loc = `Location: ${context.locationName}`;
|
|
673
|
-
if (context.locationAddress) loc += ` (${context.locationAddress})`;
|
|
674
|
-
if (context.locationType) loc += ` [${context.locationType}]`;
|
|
675
|
-
ctxParts.push(loc);
|
|
676
|
-
}
|
|
677
|
-
if (context.userName) {
|
|
678
|
-
ctxParts.push(`User: ${context.userName}${opts.userEmail ? ` (${opts.userEmail})` : ""}`);
|
|
679
|
-
} else if (opts.userEmail) {
|
|
680
|
-
ctxParts.push(`User: ${opts.userEmail}`);
|
|
681
|
-
}
|
|
682
|
-
if (context.conversationType) {
|
|
683
|
-
ctxParts.push(`Channel: ${context.conversationTitle || context.conversationType} (${context.conversationType})`);
|
|
684
|
-
}
|
|
685
|
-
if (ctxParts.length) {
|
|
686
|
-
dynamicParts.push(`## Current Session Context\n${ctxParts.join("\n")}`);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
// Parallel DB lookups: customer fetch + memory recall
|
|
691
|
-
const customerPromise = opts?.senderContext?.customerId && storeId ? Promise.resolve(supabase.from("v_store_customers").select("first_name, last_name, email, phone, loyalty_tier, total_orders, total_spent, lifetime_value").eq("id", opts.senderContext.customerId).eq("store_id", storeId).single()).then(({
|
|
692
|
-
data
|
|
693
|
-
}) => data).catch(() => null) : Promise.resolve(null);
|
|
694
|
-
const memoryPromise = storeId ? Promise.resolve(supabase.rpc("recall_memory", {
|
|
695
|
-
p_agent_id: agent.id,
|
|
696
|
-
p_query: message.substring(0, 200),
|
|
697
|
-
p_type: null,
|
|
698
|
-
p_limit: 5
|
|
699
|
-
})).then(({
|
|
700
|
-
data
|
|
701
|
-
}) => data).catch(err => {
|
|
702
|
-
log.warn({
|
|
703
|
-
err: err.message
|
|
704
|
-
}, "memory recall failed");
|
|
705
|
-
return null;
|
|
706
|
-
}) : Promise.resolve(null);
|
|
707
|
-
const [cust, memories] = await Promise.all([customerPromise, memoryPromise]);
|
|
708
|
-
|
|
709
|
-
// Channel-specific customer context injection
|
|
710
|
-
if (cust && opts?.senderContext?.customerId) {
|
|
711
|
-
dynamicParts.push(`## Current Customer\nName: ${cust.first_name} ${cust.last_name}\nEmail: ${cust.email || "N/A"}\nPhone: ${cust.phone || "N/A"}\nLoyalty: ${cust.loyalty_tier || "None"}\nOrders: ${cust.total_orders || 0}\nSpent: $${(cust.total_spent || 0).toFixed(2)}\nCustomer ID: ${opts.senderContext.customerId}`);
|
|
712
|
-
} else if (opts?.senderContext) {
|
|
713
|
-
const sc = opts.senderContext;
|
|
714
|
-
dynamicParts.push(`## Sender\nID: ${sc.senderId}\nName: ${sc.senderName || "Unknown"}\nChannel: ${sc.channelType || "unknown"}${sc.channelName ? ` (${sc.channelName})` : ""}\n(No customer record matched — use CRM tools to look them up if needed)`);
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
// Memory recall — inject relevant memories (capped at 5, 100 chars each)
|
|
718
|
-
if (memories?.length) {
|
|
719
|
-
const memBlock = memories.map(m => `- [${m.memory_type}] ${m.key}: ${JSON.stringify(m.value).substring(0, 100)}`).join("\n");
|
|
720
|
-
dynamicParts.push(`## Agent Memory\nRelevant memories from previous conversations:\n${memBlock}`);
|
|
721
|
-
}
|
|
722
|
-
const dynamicContext = dynamicParts.join("\n\n");
|
|
723
|
-
return {
|
|
724
|
-
systemPrompt,
|
|
725
|
-
dynamicContext
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
/** Persist everything after an agent turn — messages, audit, memory, cost.
|
|
730
|
-
* Called by both SSE chat and channel paths so nothing is ever missed. */
|
|
731
|
-
async function persistAgentTurn(supabase, agent, opts) {
|
|
732
|
-
const {
|
|
733
|
-
conversationId,
|
|
734
|
-
storeId,
|
|
735
|
-
agentId,
|
|
736
|
-
agentModel,
|
|
737
|
-
traceId,
|
|
738
|
-
message,
|
|
739
|
-
result,
|
|
740
|
-
source,
|
|
741
|
-
chatStartTime,
|
|
742
|
-
chatEndTime,
|
|
743
|
-
userId,
|
|
744
|
-
userEmail,
|
|
745
|
-
senderContext
|
|
746
|
-
} = opts;
|
|
747
|
-
|
|
748
|
-
// ── Persist user + assistant messages to ai_messages ──
|
|
749
|
-
try {
|
|
750
|
-
await supabase.from("ai_messages").insert([{
|
|
751
|
-
conversation_id: conversationId,
|
|
752
|
-
role: "user",
|
|
753
|
-
content: [{
|
|
754
|
-
type: "text",
|
|
755
|
-
text: message
|
|
756
|
-
}],
|
|
757
|
-
token_count: Math.ceil(message.length / 4)
|
|
758
|
-
}, {
|
|
759
|
-
conversation_id: conversationId,
|
|
760
|
-
role: "assistant",
|
|
761
|
-
content: [{
|
|
762
|
-
type: "text",
|
|
763
|
-
text: result.finalText || ""
|
|
764
|
-
}],
|
|
765
|
-
is_tool_use: result.toolCallCount > 0,
|
|
766
|
-
tool_names: result.toolsUsed?.length ? result.toolsUsed : null,
|
|
767
|
-
token_count: result.tokens.input + result.tokens.output
|
|
768
|
-
}]);
|
|
769
|
-
} catch (err) {
|
|
770
|
-
log.error({
|
|
771
|
-
err: err.message
|
|
772
|
-
}, "message persist failed");
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
// ── Update conversation metadata ──
|
|
776
|
-
try {
|
|
777
|
-
await supabase.from("ai_conversations").update({
|
|
778
|
-
metadata: {
|
|
779
|
-
agentName: agent.name,
|
|
780
|
-
source,
|
|
781
|
-
model: agentModel,
|
|
782
|
-
lastTurnTokens: result.tokens.input + result.tokens.output,
|
|
783
|
-
lastToolCalls: result.toolCallCount,
|
|
784
|
-
lastDurationMs: chatEndTime - chatStartTime,
|
|
785
|
-
// Channel-specific (null when SSE chat — that's fine, no clutter)
|
|
786
|
-
...(senderContext ? {
|
|
787
|
-
channel_type: senderContext.channelType || null,
|
|
788
|
-
channel_id: senderContext.channelId || null,
|
|
789
|
-
channel_name: senderContext.channelName || null,
|
|
790
|
-
sender_id: senderContext.senderId || null,
|
|
791
|
-
customer_id: senderContext.customerId || null,
|
|
792
|
-
customer_name: senderContext.customerName || null
|
|
793
|
-
} : {})
|
|
794
|
-
}
|
|
795
|
-
}).eq("id", conversationId);
|
|
796
|
-
} catch (err) {
|
|
797
|
-
log.error({
|
|
798
|
-
err: err.message
|
|
799
|
-
}, "conversation update failed");
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
// ── Telemetry: user message → ClickHouse ──
|
|
803
|
-
try {
|
|
804
|
-
queueSpan(auditRowToSpan({
|
|
805
|
-
action: "chat.user_message",
|
|
806
|
-
severity: "info",
|
|
807
|
-
store_id: storeId || null,
|
|
808
|
-
resource_type: "chat_message",
|
|
809
|
-
resource_id: agentId,
|
|
810
|
-
request_id: traceId,
|
|
811
|
-
conversation_id: conversationId,
|
|
812
|
-
user_id: userId || null,
|
|
813
|
-
user_email: userEmail || null,
|
|
814
|
-
source,
|
|
815
|
-
service_name: "agent-server",
|
|
816
|
-
span_kind: "INTERNAL",
|
|
817
|
-
status_code: "OK",
|
|
818
|
-
start_time: new Date().toISOString(),
|
|
819
|
-
end_time: new Date().toISOString(),
|
|
820
|
-
duration_ms: 0,
|
|
821
|
-
input_bytes: typeof message === "string" ? message.length : 0,
|
|
822
|
-
details: {
|
|
823
|
-
message_preview: message.substring(0, 200),
|
|
824
|
-
agent_id: agentId,
|
|
825
|
-
model: agentModel,
|
|
826
|
-
conversation_id: conversationId,
|
|
827
|
-
...(senderContext ? {
|
|
828
|
-
channel_type: senderContext.channelType || null,
|
|
829
|
-
sender_id: senderContext.senderId || null,
|
|
830
|
-
customer_id: senderContext.customerId || null
|
|
831
|
-
} : {})
|
|
832
|
-
}
|
|
833
|
-
}));
|
|
834
|
-
} catch (err) {
|
|
835
|
-
log.error({
|
|
836
|
-
err: err.message
|
|
837
|
-
}, "audit user_message failed");
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
// ── Telemetry: assistant response → ClickHouse ──
|
|
841
|
-
try {
|
|
842
|
-
queueSpan(auditRowToSpan({
|
|
843
|
-
action: "chat.assistant_response",
|
|
844
|
-
severity: "info",
|
|
845
|
-
store_id: storeId || null,
|
|
846
|
-
resource_type: "chat_message",
|
|
847
|
-
resource_id: agentId,
|
|
848
|
-
request_id: traceId,
|
|
849
|
-
conversation_id: conversationId,
|
|
850
|
-
duration_ms: chatEndTime - chatStartTime,
|
|
851
|
-
user_id: userId || null,
|
|
852
|
-
user_email: userEmail || null,
|
|
853
|
-
source,
|
|
854
|
-
input_tokens: result.tokens.input,
|
|
855
|
-
output_tokens: result.tokens.output,
|
|
856
|
-
total_cost: result.costUsd,
|
|
857
|
-
model: agentModel,
|
|
858
|
-
trace_id: traceId,
|
|
859
|
-
span_kind: "INTERNAL",
|
|
860
|
-
service_name: "agent-server",
|
|
861
|
-
status_code: "OK",
|
|
862
|
-
start_time: new Date(chatStartTime).toISOString(),
|
|
863
|
-
end_time: new Date(chatEndTime).toISOString(),
|
|
864
|
-
stop_reason: result.stopReason || undefined,
|
|
865
|
-
turn_number: result.turnCount || 1,
|
|
866
|
-
details: {
|
|
867
|
-
response_preview: (result.finalText || "").substring(0, 500),
|
|
868
|
-
agent_id: agentId,
|
|
869
|
-
model: agentModel,
|
|
870
|
-
"gen_ai.request.model": agentModel,
|
|
871
|
-
"gen_ai.usage.input_tokens": result.tokens.input,
|
|
872
|
-
"gen_ai.usage.output_tokens": result.tokens.output,
|
|
873
|
-
"gen_ai.usage.cache_creation_tokens": result.tokens.cacheCreation || 0,
|
|
874
|
-
"gen_ai.usage.cache_read_tokens": result.tokens.cacheRead || 0,
|
|
875
|
-
"gen_ai.usage.cost": result.costUsd,
|
|
876
|
-
turn_count: result.turnCount || 1,
|
|
877
|
-
tool_calls: result.toolCallCount,
|
|
878
|
-
tool_names: result.toolsUsed,
|
|
879
|
-
conversation_id: conversationId,
|
|
880
|
-
session_cost_usd: result.costUsd,
|
|
881
|
-
cache_creation_tokens: result.tokens.cacheCreation || 0,
|
|
882
|
-
cache_read_tokens: result.tokens.cacheRead || 0,
|
|
883
|
-
cache_hit_rate: result.tokens.input > 0 ? Math.round((result.tokens.cacheRead || 0) / ((result.tokens.cacheRead || 0) + result.tokens.input) * 10000) / 100 : 0,
|
|
884
|
-
cache_cost_savings_pct: result.tokens.input > 0 && (result.tokens.cacheRead || 0) > 0 ? Math.round((result.tokens.cacheRead || 0) * 0.9 / ((result.tokens.cacheRead || 0) + result.tokens.input) * 10000) / 100 : 0,
|
|
885
|
-
loop_detector_stats: result.loopDetectorStats || null,
|
|
886
|
-
turns: result.turns || [],
|
|
887
|
-
...(senderContext ? {
|
|
888
|
-
channel_type: senderContext.channelType || null,
|
|
889
|
-
channel_id: senderContext.channelId || null,
|
|
890
|
-
channel_name: senderContext.channelName || null,
|
|
891
|
-
sender_id: senderContext.senderId || null,
|
|
892
|
-
customer_id: senderContext.customerId || null,
|
|
893
|
-
customer_name: senderContext.customerName || null
|
|
894
|
-
} : {})
|
|
895
|
-
}
|
|
896
|
-
}));
|
|
897
|
-
} catch (err) {
|
|
898
|
-
log.error({
|
|
899
|
-
err: err.message
|
|
900
|
-
}, "audit assistant_response failed");
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
// ── Memory extraction — awaited with retry ──
|
|
904
|
-
if (storeId && result.finalText && result.finalText.length > 50) {
|
|
905
|
-
try {
|
|
906
|
-
await extractAndStoreMemories(supabase, getAnthropicClient(agent), agentId, storeId, message, result.finalText);
|
|
907
|
-
} catch (err1) {
|
|
908
|
-
// Retry once after 2s
|
|
909
|
-
try {
|
|
910
|
-
await new Promise(r => setTimeout(r, 2000));
|
|
911
|
-
await extractAndStoreMemories(supabase, getAnthropicClient(agent), agentId, storeId, message, result.finalText);
|
|
912
|
-
} catch (err2) {
|
|
913
|
-
log.error({
|
|
914
|
-
err: err2.message
|
|
915
|
-
}, "memory extract failed after retry");
|
|
916
|
-
queueSpan(auditRowToSpan({
|
|
917
|
-
action: "memory.extraction_failed",
|
|
918
|
-
severity: "warning",
|
|
919
|
-
store_id: storeId || null,
|
|
920
|
-
resource_type: "agent_memory",
|
|
921
|
-
resource_id: agentId,
|
|
922
|
-
conversation_id: conversationId,
|
|
923
|
-
user_id: userId || null,
|
|
924
|
-
user_email: userEmail || null,
|
|
925
|
-
error_type: classifyErrorType(err2.message) || undefined,
|
|
926
|
-
service_name: "agent-server",
|
|
927
|
-
span_kind: "INTERNAL",
|
|
928
|
-
status_code: "ERROR",
|
|
929
|
-
start_time: new Date().toISOString(),
|
|
930
|
-
end_time: new Date().toISOString(),
|
|
931
|
-
error_message: err2.message,
|
|
932
|
-
details: {
|
|
933
|
-
error: err2.message,
|
|
934
|
-
user_message_preview: message.substring(0, 100)
|
|
935
|
-
}
|
|
936
|
-
}));
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
// ── Cost budget tracking — awaited with retry ──
|
|
942
|
-
if (storeId && result.costUsd > 0) {
|
|
943
|
-
try {
|
|
944
|
-
await updateCostBudgets(supabase, storeId, agentId, result.costUsd);
|
|
945
|
-
} catch (err1) {
|
|
946
|
-
try {
|
|
947
|
-
await new Promise(r => setTimeout(r, 1000));
|
|
948
|
-
await updateCostBudgets(supabase, storeId, agentId, result.costUsd);
|
|
949
|
-
} catch (err2) {
|
|
950
|
-
log.error({
|
|
951
|
-
err: err2.message
|
|
952
|
-
}, "cost budget update failed after retry");
|
|
953
|
-
// Flag conversation metadata so budget sync can be reconciled later
|
|
954
|
-
await supabase.from("ai_conversations").update({
|
|
955
|
-
metadata: {
|
|
956
|
-
budget_sync_failed: true,
|
|
957
|
-
failed_cost_usd: result.costUsd
|
|
958
|
-
}
|
|
959
|
-
}).eq("id", conversationId).then(() => {});
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
// ============================================================================
|
|
966
|
-
// AGENT CHAT HANDLER
|
|
967
|
-
// ============================================================================
|
|
968
|
-
|
|
969
|
-
async function handleAgentChat(req, res, supabase, body, user, isServiceRole, token, corsHeaders) {
|
|
970
|
-
const {
|
|
971
|
-
agentId,
|
|
972
|
-
message,
|
|
973
|
-
conversationHistory,
|
|
974
|
-
source,
|
|
975
|
-
conversationId,
|
|
976
|
-
context,
|
|
977
|
-
attachments
|
|
978
|
-
} = body;
|
|
979
|
-
let storeId = body.storeId;
|
|
980
|
-
if (!agentId || !message) {
|
|
981
|
-
jsonResponse(res, 400, {
|
|
982
|
-
error: "agentId and message required"
|
|
983
|
-
}, corsHeaders);
|
|
984
|
-
return;
|
|
985
|
-
}
|
|
986
|
-
if (typeof message === "string" && message.length > 100_000) {
|
|
987
|
-
jsonResponse(res, 400, {
|
|
988
|
-
error: "Message too long (max 100K characters)"
|
|
989
|
-
}, corsHeaders);
|
|
990
|
-
return;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
// Server-derived store resolution — never trust client blindly
|
|
994
|
-
const resolvedStoreId = await resolveAndValidateStoreId(supabase, storeId, user, isServiceRole, token, body.userId);
|
|
995
|
-
|
|
996
|
-
// For service-role callers (workflows, internal), also try body.userId fallback
|
|
997
|
-
if (!resolvedStoreId && isServiceRole && body.userId) {
|
|
998
|
-
const {
|
|
999
|
-
data: srStores
|
|
1000
|
-
} = await supabase.from("users").select("store_id").eq("auth_user_id", body.userId).not("store_id", "is", null).limit(1);
|
|
1001
|
-
if (srStores?.length) {
|
|
1002
|
-
storeId = srStores[0].store_id;
|
|
1003
|
-
}
|
|
1004
|
-
} else {
|
|
1005
|
-
storeId = resolvedStoreId || undefined;
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
// Fail closed: non-service-role requests MUST have a resolved store
|
|
1009
|
-
if (!storeId && !isServiceRole) {
|
|
1010
|
-
jsonResponse(res, 400, {
|
|
1011
|
-
error: "storeId required for agent chat"
|
|
1012
|
-
}, corsHeaders);
|
|
1013
|
-
return;
|
|
1014
|
-
}
|
|
1015
|
-
log.info({
|
|
1016
|
-
storeId: storeId || "NONE",
|
|
1017
|
-
source: body.source || "unknown",
|
|
1018
|
-
isServiceRole,
|
|
1019
|
-
userId: user?.id || body.userId || "NONE"
|
|
1020
|
-
}, "agent-chat request");
|
|
1021
|
-
|
|
1022
|
-
// Agent chat rate limiting — per-store + concurrent cap
|
|
1023
|
-
const rateLimitStoreId = storeId || agentId; // fallback to agentId if no store
|
|
1024
|
-
const rateCheck = checkAgentChatRateLimit(rateLimitStoreId);
|
|
1025
|
-
if (!rateCheck.allowed) {
|
|
1026
|
-
res.writeHead(429, {
|
|
1027
|
-
"Content-Type": "application/json",
|
|
1028
|
-
...corsHeaders
|
|
1029
|
-
});
|
|
1030
|
-
res.end(JSON.stringify({
|
|
1031
|
-
error: rateCheck.error
|
|
1032
|
-
}));
|
|
1033
|
-
return;
|
|
1034
|
-
}
|
|
1035
|
-
agentChatConcurrent++;
|
|
1036
|
-
try {
|
|
1037
|
-
const userId = user?.id || body.userId || "";
|
|
1038
|
-
const userEmail = user?.email || body.userEmail || null;
|
|
1039
|
-
const agent = await loadAgentConfig(supabase, agentId, storeId);
|
|
1040
|
-
if (!agent) {
|
|
1041
|
-
jsonResponse(res, 404, {
|
|
1042
|
-
error: "Agent not found"
|
|
1043
|
-
}, corsHeaders);
|
|
1044
|
-
return;
|
|
1045
|
-
}
|
|
1046
|
-
const {
|
|
1047
|
-
core: coreTools,
|
|
1048
|
-
extended: extendedTools
|
|
1049
|
-
} = await loadTools(supabase);
|
|
1050
|
-
setExtendedToolsCache(extendedTools); // Populate discover_tools handler cache
|
|
1051
|
-
const {
|
|
1052
|
-
rows: userToolRows,
|
|
1053
|
-
defs: userToolDefs
|
|
1054
|
-
} = storeId ? await loadUserTools(supabase, storeId) : {
|
|
1055
|
-
rows: [],
|
|
1056
|
-
defs: []
|
|
1057
|
-
};
|
|
1058
|
-
const tools = getToolsForAgent(agent, coreTools, userToolDefs);
|
|
1059
|
-
const traceId = randomUUID();
|
|
1060
|
-
const agentModel = agent.model || MODELS.SONNET;
|
|
1061
|
-
|
|
1062
|
-
// Resolve or create conversation
|
|
1063
|
-
let activeConversationId;
|
|
1064
|
-
if (conversationId) {
|
|
1065
|
-
activeConversationId = conversationId;
|
|
1066
|
-
} else {
|
|
1067
|
-
let conv = await supabase.from("ai_conversations").insert({
|
|
1068
|
-
store_id: storeId || null,
|
|
1069
|
-
user_id: userId || null,
|
|
1070
|
-
agent_id: agentId,
|
|
1071
|
-
title: message.substring(0, 100),
|
|
1072
|
-
metadata: {
|
|
1073
|
-
agentName: agent.name,
|
|
1074
|
-
source: source || "whale_chat"
|
|
1075
|
-
}
|
|
1076
|
-
}).select("id").single();
|
|
1077
|
-
if (conv.error) {
|
|
1078
|
-
log.error({
|
|
1079
|
-
err: conv.error.message,
|
|
1080
|
-
details: conv.error.details,
|
|
1081
|
-
hint: conv.error.hint,
|
|
1082
|
-
storeId,
|
|
1083
|
-
userId,
|
|
1084
|
-
agentId
|
|
1085
|
-
}, "conversation create failed");
|
|
1086
|
-
// Retry without user_id (may be FK constraint)
|
|
1087
|
-
conv = await supabase.from("ai_conversations").insert({
|
|
1088
|
-
store_id: storeId || null,
|
|
1089
|
-
agent_id: agentId,
|
|
1090
|
-
title: message.substring(0, 100),
|
|
1091
|
-
metadata: {
|
|
1092
|
-
agentName: agent.name,
|
|
1093
|
-
source: source || "whale_chat",
|
|
1094
|
-
userId,
|
|
1095
|
-
userEmail
|
|
1096
|
-
}
|
|
1097
|
-
}).select("id").single();
|
|
1098
|
-
if (conv.error) {
|
|
1099
|
-
log.error({
|
|
1100
|
-
err: conv.error.message,
|
|
1101
|
-
details: conv.error.details,
|
|
1102
|
-
hint: conv.error.hint
|
|
1103
|
-
}, "conversation retry create failed");
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
activeConversationId = conv.data?.id || randomUUID();
|
|
1107
|
-
log.info({
|
|
1108
|
-
conversationId: activeConversationId,
|
|
1109
|
-
fromDb: !!conv.data?.id
|
|
1110
|
-
}, "conversation resolved");
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
// Build system prompt — shared helper ensures SSE chat + channel paths are identical
|
|
1114
|
-
const {
|
|
1115
|
-
systemPrompt,
|
|
1116
|
-
dynamicContext
|
|
1117
|
-
} = await buildAgentSystemPrompt(supabase, agent, storeId, message, tools, {
|
|
1118
|
-
clientContext: context,
|
|
1119
|
-
userId,
|
|
1120
|
-
userEmail,
|
|
1121
|
-
extendedTools: getExtendedToolsIndex()
|
|
1122
|
-
});
|
|
1123
|
-
const anthropic = getAnthropicClient(agent);
|
|
1124
|
-
|
|
1125
|
-
// Resolve all behavioral config from DB — single source of truth
|
|
1126
|
-
const resolved = resolveAgentLoopConfig(agent, "sse");
|
|
1127
|
-
if (resolved.defaultsUsed.length > 0) {
|
|
1128
|
-
log.info({
|
|
1129
|
-
agentId,
|
|
1130
|
-
defaults: resolved.defaultsUsed
|
|
1131
|
-
}, "agent config defaults applied");
|
|
1132
|
-
}
|
|
1133
|
-
const MAX_HISTORY_CHARS = resolved.maxHistoryChars;
|
|
1134
|
-
|
|
1135
|
-
// Build user message — multi-modal if image attachments present
|
|
1136
|
-
let userContent;
|
|
1137
|
-
if (attachments?.length) {
|
|
1138
|
-
const contentBlocks = [];
|
|
1139
|
-
for (const att of attachments) {
|
|
1140
|
-
if (att.type === "image" && att.media_type && att.data) {
|
|
1141
|
-
contentBlocks.push({
|
|
1142
|
-
type: "image",
|
|
1143
|
-
source: {
|
|
1144
|
-
type: "base64",
|
|
1145
|
-
media_type: att.media_type,
|
|
1146
|
-
data: att.data
|
|
1147
|
-
}
|
|
1148
|
-
});
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
contentBlocks.push({
|
|
1152
|
-
type: "text",
|
|
1153
|
-
text: message
|
|
1154
|
-
});
|
|
1155
|
-
userContent = contentBlocks;
|
|
1156
|
-
} else {
|
|
1157
|
-
userContent = message;
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
|
-
// Prepend dynamic context to user message to keep system prompt static (cache-friendly)
|
|
1161
|
-
const contextPrefix = dynamicContext ? `[Context]\n${dynamicContext}\n\n[User Message]\n` : "";
|
|
1162
|
-
const finalUserContent = typeof userContent === "string" ? contextPrefix + userContent : [...(contextPrefix ? [{
|
|
1163
|
-
type: "text",
|
|
1164
|
-
text: contextPrefix
|
|
1165
|
-
}] : []), ...userContent];
|
|
1166
|
-
const messages = [...compactHistory(conversationHistory || [], MAX_HISTORY_CHARS), {
|
|
1167
|
-
role: "user",
|
|
1168
|
-
content: finalUserContent
|
|
1169
|
-
}];
|
|
1170
|
-
|
|
1171
|
-
// Start SSE stream
|
|
1172
|
-
res.writeHead(200, {
|
|
1173
|
-
"Content-Type": "text/event-stream",
|
|
1174
|
-
"Cache-Control": "no-cache",
|
|
1175
|
-
Connection: "keep-alive",
|
|
1176
|
-
...corsHeaders
|
|
1177
|
-
});
|
|
1178
|
-
|
|
1179
|
-
// Client disconnect detection
|
|
1180
|
-
let clientDisconnected = false;
|
|
1181
|
-
req.on("close", () => {
|
|
1182
|
-
clientDisconnected = true;
|
|
1183
|
-
});
|
|
1184
|
-
const startedAt = Date.now();
|
|
1185
|
-
const chatStartTime = Date.now();
|
|
1186
|
-
try {
|
|
1187
|
-
const result = await runServerAgentLoop({
|
|
1188
|
-
anthropic,
|
|
1189
|
-
supabase,
|
|
1190
|
-
model: agentModel,
|
|
1191
|
-
systemPrompt,
|
|
1192
|
-
messages,
|
|
1193
|
-
tools,
|
|
1194
|
-
extendedTools,
|
|
1195
|
-
// All behavioral knobs from resolved config — DB is single source of truth
|
|
1196
|
-
maxTurns: resolved.maxTurns,
|
|
1197
|
-
temperature: resolved.temperature,
|
|
1198
|
-
maxTokens: resolved.maxTokens,
|
|
1199
|
-
maxConcurrentTools: resolved.maxConcurrentTools,
|
|
1200
|
-
enableDelegation: resolved.enableDelegation,
|
|
1201
|
-
enableModelRouting: resolved.enableModelRouting,
|
|
1202
|
-
contextOverrides: resolved.contextOverrides,
|
|
1203
|
-
subagentMaxTokens: resolved.subagentMaxTokens,
|
|
1204
|
-
subagentMaxTurns: resolved.subagentMaxTurns,
|
|
1205
|
-
subagentTemperature: resolved.subagentTemperature,
|
|
1206
|
-
// Loop detector thresholds from DB config
|
|
1207
|
-
loopDetectorConfig: {
|
|
1208
|
-
identicalCallLimit: resolved.loopIdenticalCallLimit,
|
|
1209
|
-
consecutiveErrorLimit: resolved.loopConsecutiveErrorLimit,
|
|
1210
|
-
turnErrorLimit: resolved.loopTurnErrorLimit,
|
|
1211
|
-
window: resolved.loopWindow,
|
|
1212
|
-
sessionToolErrorLimit: resolved.loopSessionToolErrorLimit,
|
|
1213
|
-
consecutiveFailedTurnLimit: resolved.loopConsecutiveFailedTurnLimit,
|
|
1214
|
-
fileReadLimit: resolved.loopFileReadLimit
|
|
1215
|
-
},
|
|
1216
|
-
batchErrorLimit: resolved.loopBatchErrorLimit,
|
|
1217
|
-
storeId,
|
|
1218
|
-
traceId,
|
|
1219
|
-
userId,
|
|
1220
|
-
userEmail,
|
|
1221
|
-
source,
|
|
1222
|
-
conversationId: activeConversationId,
|
|
1223
|
-
agentId,
|
|
1224
|
-
executeTool: async (toolName, args, sourceOverride, onToolProgress) => {
|
|
1225
|
-
const toolArgs = {
|
|
1226
|
-
...args
|
|
1227
|
-
};
|
|
1228
|
-
if (!toolArgs.store_id && storeId) toolArgs.store_id = storeId;
|
|
1229
|
-
return executeTool(supabase, toolName, toolArgs, storeId, traceId, userId, userEmail, sourceOverride || source, activeConversationId, userToolRows, agentId, onToolProgress, true);
|
|
1230
|
-
},
|
|
1231
|
-
onToolProgress: (name, progress) => sendSSE(res, {
|
|
1232
|
-
type: "tool_progress",
|
|
1233
|
-
name,
|
|
1234
|
-
progress
|
|
1235
|
-
}),
|
|
1236
|
-
onText: text => sendSSE(res, {
|
|
1237
|
-
type: "text",
|
|
1238
|
-
text
|
|
1239
|
-
}),
|
|
1240
|
-
onToolStart: (name, input) => {
|
|
1241
|
-
// Only send when input is available — deduplicates streaming double-fire
|
|
1242
|
-
// (sse-parser fires onToolStart twice: once on content_block_start without input,
|
|
1243
|
-
// once on content_block_stop with parsed input)
|
|
1244
|
-
if (input !== undefined) {
|
|
1245
|
-
sendSSE(res, {
|
|
1246
|
-
type: "tool_start",
|
|
1247
|
-
name,
|
|
1248
|
-
input
|
|
1249
|
-
});
|
|
1250
|
-
}
|
|
1251
|
-
},
|
|
1252
|
-
onToolResult: (name, success, r) => sendSSE(res, {
|
|
1253
|
-
type: "tool_result",
|
|
1254
|
-
name,
|
|
1255
|
-
success,
|
|
1256
|
-
result: r
|
|
1257
|
-
}),
|
|
1258
|
-
onSubagentProgress: evt => {
|
|
1259
|
-
sendSSE(res, {
|
|
1260
|
-
type: "subagent",
|
|
1261
|
-
subagentId: evt.subagentId,
|
|
1262
|
-
subagentEvent: evt.event,
|
|
1263
|
-
name: evt.toolName
|
|
1264
|
-
});
|
|
1265
|
-
},
|
|
1266
|
-
clientDisconnected: {
|
|
1267
|
-
get value() {
|
|
1268
|
-
return clientDisconnected;
|
|
1269
|
-
}
|
|
1270
|
-
},
|
|
1271
|
-
startedAt,
|
|
1272
|
-
maxDurationMs: resolved.maxDurationMs
|
|
1273
|
-
});
|
|
1274
|
-
|
|
1275
|
-
// Send usage SSE
|
|
1276
|
-
sendSSE(res, {
|
|
1277
|
-
type: "usage",
|
|
1278
|
-
usage: {
|
|
1279
|
-
input_tokens: result.tokens.input,
|
|
1280
|
-
output_tokens: result.tokens.output,
|
|
1281
|
-
cache_creation_tokens: result.tokens.cacheCreation,
|
|
1282
|
-
cache_read_tokens: result.tokens.cacheRead,
|
|
1283
|
-
cost_usd: result.costUsd
|
|
1284
|
-
}
|
|
1285
|
-
});
|
|
1286
|
-
|
|
1287
|
-
// Persist everything — shared helper ensures SSE chat + channel paths are identical
|
|
1288
|
-
await persistAgentTurn(supabase, agent, {
|
|
1289
|
-
conversationId: activeConversationId,
|
|
1290
|
-
storeId,
|
|
1291
|
-
agentId,
|
|
1292
|
-
agentModel,
|
|
1293
|
-
traceId,
|
|
1294
|
-
message,
|
|
1295
|
-
result,
|
|
1296
|
-
source: source || "whale_chat",
|
|
1297
|
-
chatStartTime,
|
|
1298
|
-
chatEndTime: Date.now(),
|
|
1299
|
-
userId,
|
|
1300
|
-
userEmail
|
|
1301
|
-
});
|
|
1302
|
-
sendSSE(res, {
|
|
1303
|
-
type: "done",
|
|
1304
|
-
conversationId: activeConversationId
|
|
1305
|
-
});
|
|
1306
|
-
} catch (err) {
|
|
1307
|
-
sendSSE(res, {
|
|
1308
|
-
type: "error",
|
|
1309
|
-
error: sanitizeError(err)
|
|
1310
|
-
});
|
|
1311
|
-
}
|
|
1312
|
-
res.end();
|
|
1313
|
-
} finally {
|
|
1314
|
-
agentChatConcurrent--;
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
// ============================================================================
|
|
1319
|
-
// MEMORY EXTRACTION — extract key facts after agent conversation
|
|
1320
|
-
// ============================================================================
|
|
1321
|
-
|
|
1322
|
-
async function extractAndStoreMemories(supabase, anthropic, agentId, storeId, userMessage, assistantResponse) {
|
|
1323
|
-
const extraction = await anthropic.messages.create({
|
|
1324
|
-
model: "claude-haiku-4-5-20251001",
|
|
1325
|
-
max_tokens: 500,
|
|
1326
|
-
system: `Extract key facts worth remembering from this conversation turn.
|
|
1327
|
-
Return JSON array: [{"key": "short_key", "value": {"detail": "..."}, "type": "short_term|long_term|entity"}]
|
|
1328
|
-
Rules:
|
|
1329
|
-
- Only extract genuinely useful facts (preferences, decisions, corrections, entities)
|
|
1330
|
-
- "entity" for people/businesses/products mentioned
|
|
1331
|
-
- "long_term" for preferences, patterns, decisions
|
|
1332
|
-
- "short_term" for context that may expire
|
|
1333
|
-
- Return [] if nothing worth remembering
|
|
1334
|
-
- Max 3 items per turn`,
|
|
1335
|
-
messages: [{
|
|
1336
|
-
role: "user",
|
|
1337
|
-
content: `User: ${userMessage.substring(0, 500)}\n\nAssistant: ${assistantResponse.substring(0, 1000)}`
|
|
1338
|
-
}]
|
|
1339
|
-
});
|
|
1340
|
-
const text = extraction.content.find(b => b.type === "text")?.text || "[]";
|
|
1341
|
-
const match = text.match(/\[[\s\S]*\]/);
|
|
1342
|
-
if (!match) return;
|
|
1343
|
-
let items;
|
|
1344
|
-
try {
|
|
1345
|
-
items = JSON.parse(match[0]);
|
|
1346
|
-
} catch {
|
|
1347
|
-
return; // Malformed JSON from extraction
|
|
1348
|
-
}
|
|
1349
|
-
for (const item of items.slice(0, 3)) {
|
|
1350
|
-
if (!item.key) continue;
|
|
1351
|
-
await supabase.rpc("store_memory", {
|
|
1352
|
-
p_agent_id: agentId,
|
|
1353
|
-
p_store_id: storeId,
|
|
1354
|
-
p_type: item.type || "short_term",
|
|
1355
|
-
p_key: item.key,
|
|
1356
|
-
p_value: item.value || {}
|
|
1357
|
-
});
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
|
-
// ============================================================================
|
|
1362
|
-
// COST BUDGET TRACKING — increment active budgets after each conversation
|
|
1363
|
-
// ============================================================================
|
|
1364
|
-
|
|
1365
|
-
// P0 FIX: Atomic cost budget increment via RPC (fixes TOCTOU race on concurrent updates)
|
|
1366
|
-
async function updateCostBudgets(supabase, storeId, agentId, costUsd) {
|
|
1367
|
-
const {
|
|
1368
|
-
error
|
|
1369
|
-
} = await supabase.rpc("increment_cost_budget", {
|
|
1370
|
-
p_store_id: storeId,
|
|
1371
|
-
p_agent_id: agentId,
|
|
1372
|
-
p_cost_usd: costUsd
|
|
1373
|
-
});
|
|
1374
|
-
if (error) {
|
|
1375
|
-
console.error("[cost-budget] increment_cost_budget RPC failed:", error.message);
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
81
|
// ============================================================================
|
|
1380
82
|
// HTTP SERVER
|
|
1381
83
|
// ============================================================================
|
|
@@ -1395,17 +97,31 @@ const server = http.createServer(async (req, res) => {
|
|
|
1395
97
|
const ready = isReady();
|
|
1396
98
|
const status = ready ? 200 : 503;
|
|
1397
99
|
const agentStats = getGatewayStats();
|
|
100
|
+
const cbStats = getCircuitBreakerStats();
|
|
1398
101
|
jsonResponse(res, status, {
|
|
1399
102
|
status: ready ? "ok" : "starting",
|
|
1400
103
|
version: process.env.npm_package_version || "6.4.0",
|
|
1401
104
|
uptime: Math.floor(process.uptime()),
|
|
1402
105
|
pg_listen: pgListenReady,
|
|
1403
106
|
worker_pool: workerPoolReady,
|
|
1404
|
-
local_agents: agentStats.total_agents
|
|
107
|
+
local_agents: agentStats.total_agents,
|
|
108
|
+
circuit_breakers: cbStats
|
|
1405
109
|
}, corsHeaders);
|
|
1406
110
|
return;
|
|
1407
111
|
}
|
|
1408
112
|
|
|
113
|
+
// OpenAPI spec — public, no auth required (for Scalar docs viewer)
|
|
114
|
+
if (req.method === "GET" && req.url === "/openapi.json") {
|
|
115
|
+
const spec = generateOpenApiSpec();
|
|
116
|
+
res.writeHead(200, {
|
|
117
|
+
...corsHeaders,
|
|
118
|
+
"Content-Type": "application/json",
|
|
119
|
+
"Cache-Control": "public, max-age=3600"
|
|
120
|
+
});
|
|
121
|
+
res.end(JSON.stringify(spec));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
1409
125
|
// CORS preflight
|
|
1410
126
|
if (req.method === "OPTIONS") {
|
|
1411
127
|
res.writeHead(204, corsHeaders);
|
|
@@ -1464,6 +180,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
1464
180
|
}
|
|
1465
181
|
|
|
1466
182
|
// H6 FIX: Enforce per-run and total client limits
|
|
183
|
+
const sseClients = getSseClients();
|
|
1467
184
|
const existingClients = sseClients.get(runId)?.size || 0;
|
|
1468
185
|
if (existingClients >= MAX_SSE_CLIENTS_PER_RUN) {
|
|
1469
186
|
jsonResponse(res, 429, {
|
|
@@ -1985,6 +702,43 @@ const server = http.createServer(async (req, res) => {
|
|
|
1985
702
|
}
|
|
1986
703
|
return;
|
|
1987
704
|
}
|
|
705
|
+
|
|
706
|
+
// ================================================================
|
|
707
|
+
// Session API routes (supports GET, POST)
|
|
708
|
+
// Must be before the method gate since GET /sessions is valid
|
|
709
|
+
// ================================================================
|
|
710
|
+
if (pathname.startsWith("/sessions")) {
|
|
711
|
+
const authHeader = req.headers.authorization;
|
|
712
|
+
const token = authHeader?.startsWith("Bearer ") ? authHeader.substring(7) : "";
|
|
713
|
+
if (!token) {
|
|
714
|
+
req.resume();
|
|
715
|
+
jsonResponse(res, 401, {
|
|
716
|
+
error: "Missing authorization"
|
|
717
|
+
}, corsHeaders);
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
const supabase = getServiceClient();
|
|
721
|
+
let userId;
|
|
722
|
+
const isServiceRole = safeCompare(token, SUPABASE_SERVICE_ROLE_KEY) || safeCompare(token, SERVICE_ROLE_JWT);
|
|
723
|
+
if (!isServiceRole) {
|
|
724
|
+
const {
|
|
725
|
+
data: {
|
|
726
|
+
user: authUser
|
|
727
|
+
}
|
|
728
|
+
} = await supabase.auth.getUser(token);
|
|
729
|
+
if (authUser) userId = authUser.id;
|
|
730
|
+
}
|
|
731
|
+
const handled = await handleSessionRoutes(req, res, pathname, url, corsHeaders, supabase, {
|
|
732
|
+
userId,
|
|
733
|
+
isServiceRole
|
|
734
|
+
});
|
|
735
|
+
if (!handled) {
|
|
736
|
+
jsonResponse(res, 404, {
|
|
737
|
+
error: `No route: ${req.method} ${pathname}`
|
|
738
|
+
}, corsHeaders);
|
|
739
|
+
}
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
1988
742
|
if (req.method !== "POST" && req.method !== "DELETE" && req.method !== "PUT") {
|
|
1989
743
|
jsonResponse(res, 405, {
|
|
1990
744
|
error: "Method not allowed"
|
|
@@ -2898,406 +1652,17 @@ const server = http.createServer(async (req, res) => {
|
|
|
2898
1652
|
}
|
|
2899
1653
|
});
|
|
2900
1654
|
|
|
2901
|
-
//
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
return Promise.resolve({
|
|
2906
|
-
success: false,
|
|
2907
|
-
error: "Store boundary violation: workflow cannot access other stores"
|
|
2908
|
-
});
|
|
2909
|
-
}
|
|
2910
|
-
args.store_id = storeId; // Force the workflow's store
|
|
2911
|
-
return executeTool(supabase, toolName, args, storeId, traceId, null, null, "workflow_engine");
|
|
2912
|
-
});
|
|
2913
|
-
|
|
2914
|
-
// Inject agent executor for "agent" step type in workflows
|
|
2915
|
-
setAgentExecutor(async (supabase, agentId, prompt, storeId, maxTurns = 5, onToken, traceId) => {
|
|
2916
|
-
const agent = await loadAgentConfig(supabase, agentId, storeId);
|
|
2917
|
-
if (!agent) return {
|
|
2918
|
-
success: false,
|
|
2919
|
-
error: `Agent ${agentId} not found`
|
|
2920
|
-
};
|
|
2921
|
-
|
|
2922
|
-
// Workflow agents get all tools (no lazy loading — they run headless)
|
|
2923
|
-
const {
|
|
2924
|
-
all: allTools
|
|
2925
|
-
} = await loadTools(supabase);
|
|
2926
|
-
const {
|
|
2927
|
-
rows: userToolRows,
|
|
2928
|
-
defs: userToolDefs
|
|
2929
|
-
} = await loadUserTools(supabase, storeId);
|
|
2930
|
-
const tools = getToolsForAgent(agent, allTools, userToolDefs);
|
|
2931
|
-
const agentModel = agent.model || MODELS.SONNET;
|
|
2932
|
-
|
|
2933
|
-
// Resolve all behavioral config from DB — workflow maxTurns caps agent config
|
|
2934
|
-
const resolved = resolveAgentLoopConfig(agent, "workflow", maxTurns);
|
|
2935
|
-
if (resolved.defaultsUsed.length > 0) {
|
|
2936
|
-
log.info({
|
|
2937
|
-
agentId,
|
|
2938
|
-
callPath: "workflow",
|
|
2939
|
-
defaults: resolved.defaultsUsed
|
|
2940
|
-
}, "workflow agent config defaults applied");
|
|
2941
|
-
}
|
|
2942
|
-
|
|
2943
|
-
// Build full system prompt — shared helper ensures workflow gets same context as SSE/channel
|
|
2944
|
-
// (previously hand-built, missing location/customer context)
|
|
2945
|
-
const {
|
|
2946
|
-
systemPrompt
|
|
2947
|
-
} = await buildAgentSystemPrompt(supabase, agent, storeId, prompt, tools);
|
|
2948
|
-
try {
|
|
2949
|
-
const result = await runServerAgentLoop({
|
|
2950
|
-
anthropic: getAnthropicClient(agent),
|
|
2951
|
-
supabase,
|
|
2952
|
-
model: agentModel,
|
|
2953
|
-
systemPrompt,
|
|
2954
|
-
messages: [{
|
|
2955
|
-
role: "user",
|
|
2956
|
-
content: prompt
|
|
2957
|
-
}],
|
|
2958
|
-
tools,
|
|
2959
|
-
// All behavioral knobs from resolved config — DB is single source of truth
|
|
2960
|
-
maxTurns: resolved.maxTurns,
|
|
2961
|
-
temperature: resolved.temperature,
|
|
2962
|
-
maxTokens: resolved.maxTokens,
|
|
2963
|
-
maxConcurrentTools: resolved.maxConcurrentTools,
|
|
2964
|
-
enableDelegation: resolved.enableDelegation,
|
|
2965
|
-
enableModelRouting: resolved.enableModelRouting,
|
|
2966
|
-
contextOverrides: resolved.contextOverrides,
|
|
2967
|
-
subagentMaxTokens: resolved.subagentMaxTokens,
|
|
2968
|
-
subagentMaxTurns: resolved.subagentMaxTurns,
|
|
2969
|
-
subagentTemperature: resolved.subagentTemperature,
|
|
2970
|
-
loopDetectorConfig: {
|
|
2971
|
-
identicalCallLimit: resolved.loopIdenticalCallLimit,
|
|
2972
|
-
consecutiveErrorLimit: resolved.loopConsecutiveErrorLimit,
|
|
2973
|
-
turnErrorLimit: resolved.loopTurnErrorLimit,
|
|
2974
|
-
window: resolved.loopWindow,
|
|
2975
|
-
sessionToolErrorLimit: resolved.loopSessionToolErrorLimit,
|
|
2976
|
-
consecutiveFailedTurnLimit: resolved.loopConsecutiveFailedTurnLimit,
|
|
2977
|
-
fileReadLimit: resolved.loopFileReadLimit
|
|
2978
|
-
},
|
|
2979
|
-
batchErrorLimit: resolved.loopBatchErrorLimit,
|
|
2980
|
-
storeId,
|
|
2981
|
-
source: "workflow_agent",
|
|
2982
|
-
agentId,
|
|
2983
|
-
traceId,
|
|
2984
|
-
executeTool: async (toolName, args) => {
|
|
2985
|
-
const toolArgs = {
|
|
2986
|
-
...args
|
|
2987
|
-
};
|
|
2988
|
-
if (!toolArgs.store_id) toolArgs.store_id = storeId;
|
|
2989
|
-
return executeTool(supabase, toolName, toolArgs, storeId, traceId, null, null, "workflow_agent", undefined, userToolRows, agentId, undefined, true);
|
|
2990
|
-
},
|
|
2991
|
-
enableStreaming: !!onToken,
|
|
2992
|
-
onText: onToken || undefined,
|
|
2993
|
-
maxDurationMs: resolved.maxDurationMs
|
|
2994
|
-
});
|
|
2995
|
-
return {
|
|
2996
|
-
success: true,
|
|
2997
|
-
response: result.finalText || "(no response)"
|
|
2998
|
-
};
|
|
2999
|
-
} catch (err) {
|
|
3000
|
-
return {
|
|
3001
|
-
success: false,
|
|
3002
|
-
error: sanitizeError(err)
|
|
3003
|
-
};
|
|
3004
|
-
}
|
|
3005
|
-
});
|
|
3006
|
-
|
|
3007
|
-
// Inject token broadcaster for real-time agent step streaming
|
|
3008
|
-
setTokenBroadcaster((runId, stepKey, token) => {
|
|
3009
|
-
broadcastToRun(runId, {
|
|
3010
|
-
type: "agent_token",
|
|
3011
|
-
run_id: runId,
|
|
3012
|
-
step_key: stepKey,
|
|
3013
|
-
token
|
|
3014
|
-
});
|
|
3015
|
-
});
|
|
3016
|
-
|
|
3017
|
-
// Inject step error broadcaster for real-time workflow error surfacing
|
|
3018
|
-
setStepErrorBroadcaster((runId, data) => {
|
|
3019
|
-
broadcastToRun(runId, data);
|
|
3020
|
-
});
|
|
3021
|
-
|
|
3022
|
-
// Shared agent invoker — used by channel messages, webchat, and any source
|
|
3023
|
-
// Uses shared helpers so it's IDENTICAL to CLI chat — same prompt, tools, memory, persistence, audit
|
|
3024
|
-
async function invokeAgentForChannel(supabase, agentId, message, storeId, conversationId, senderContext) {
|
|
3025
|
-
const agent = await loadAgentConfig(supabase, agentId, storeId);
|
|
3026
|
-
if (!agent) return {
|
|
3027
|
-
success: false,
|
|
3028
|
-
error: `Agent ${agentId} not found`
|
|
3029
|
-
};
|
|
3030
|
-
const {
|
|
3031
|
-
core: coreTools,
|
|
3032
|
-
extended: extendedTools
|
|
3033
|
-
} = await loadTools(supabase);
|
|
3034
|
-
setExtendedToolsCache(extendedTools);
|
|
3035
|
-
const {
|
|
3036
|
-
rows: userToolRows,
|
|
3037
|
-
defs: userToolDefs
|
|
3038
|
-
} = await loadUserTools(supabase, storeId);
|
|
3039
|
-
const tools = getToolsForAgent(agent, coreTools, userToolDefs);
|
|
3040
|
-
const agentModel = agent.model || MODELS.SONNET;
|
|
3041
|
-
|
|
3042
|
-
// Resolve all behavioral config from DB — channel has 15-turn safety cap built in
|
|
3043
|
-
const resolved = resolveAgentLoopConfig(agent, "channel");
|
|
3044
|
-
if (resolved.defaultsUsed.length > 0) {
|
|
3045
|
-
log.info({
|
|
3046
|
-
agentId,
|
|
3047
|
-
callPath: "channel",
|
|
3048
|
-
defaults: resolved.defaultsUsed
|
|
3049
|
-
}, "channel agent config defaults applied");
|
|
3050
|
-
}
|
|
3051
|
-
|
|
3052
|
-
// Build system prompt — shared helper, identical to SSE chat
|
|
3053
|
-
const {
|
|
3054
|
-
systemPrompt,
|
|
3055
|
-
dynamicContext
|
|
3056
|
-
} = await buildAgentSystemPrompt(supabase, agent, storeId, message, tools, {
|
|
3057
|
-
senderContext,
|
|
3058
|
-
extendedTools: getExtendedToolsIndex()
|
|
3059
|
-
});
|
|
3060
|
-
|
|
3061
|
-
// Update ai_conversations with agent_id (fire-and-forget)
|
|
3062
|
-
if (conversationId) {
|
|
3063
|
-
Promise.resolve(supabase.from("ai_conversations").update({
|
|
3064
|
-
agent_id: agentId
|
|
3065
|
-
}).eq("id", conversationId).is("agent_id", null)).catch(() => {});
|
|
3066
|
-
}
|
|
3067
|
-
|
|
3068
|
-
// Load conversation history with size-based compaction (same as SSE chat)
|
|
3069
|
-
const MAX_HISTORY_CHARS = resolved.maxHistoryChars;
|
|
3070
|
-
let loadedHistory = [];
|
|
3071
|
-
if (conversationId) {
|
|
3072
|
-
try {
|
|
3073
|
-
const {
|
|
3074
|
-
data: history
|
|
3075
|
-
} = await supabase.from("ai_messages").select("role, content").eq("conversation_id", conversationId).order("created_at", {
|
|
3076
|
-
ascending: true
|
|
3077
|
-
}).limit(50);
|
|
3078
|
-
if (history?.length) {
|
|
3079
|
-
const raw = [];
|
|
3080
|
-
for (const m of history) {
|
|
3081
|
-
if (m.role === "user" || m.role === "assistant") {
|
|
3082
|
-
raw.push({
|
|
3083
|
-
role: m.role,
|
|
3084
|
-
content: m.content
|
|
3085
|
-
});
|
|
3086
|
-
}
|
|
3087
|
-
}
|
|
3088
|
-
loadedHistory = compactHistory(raw, MAX_HISTORY_CHARS);
|
|
3089
|
-
}
|
|
3090
|
-
} catch {/* history not critical */}
|
|
3091
|
-
}
|
|
3092
|
-
// Prepend dynamic context to user message to keep system prompt static (cache-friendly)
|
|
3093
|
-
const contextPrefix = dynamicContext ? `[Context]\n${dynamicContext}\n\n[User Message]\n` : "";
|
|
3094
|
-
const finalMessage = contextPrefix + message;
|
|
3095
|
-
const messages = [...loadedHistory, {
|
|
3096
|
-
role: "user",
|
|
3097
|
-
content: finalMessage
|
|
3098
|
-
}];
|
|
3099
|
-
const traceId = randomUUID();
|
|
3100
|
-
const chatStartTime = Date.now();
|
|
3101
|
-
try {
|
|
3102
|
-
const result = await runServerAgentLoop({
|
|
3103
|
-
anthropic: getAnthropicClient(agent),
|
|
3104
|
-
supabase,
|
|
3105
|
-
model: agentModel,
|
|
3106
|
-
systemPrompt,
|
|
3107
|
-
messages,
|
|
3108
|
-
tools,
|
|
3109
|
-
extendedTools,
|
|
3110
|
-
// All behavioral knobs from resolved config — DB is single source of truth
|
|
3111
|
-
maxTurns: resolved.maxTurns,
|
|
3112
|
-
temperature: resolved.temperature,
|
|
3113
|
-
maxTokens: resolved.maxTokens,
|
|
3114
|
-
maxConcurrentTools: resolved.maxConcurrentTools,
|
|
3115
|
-
enableDelegation: resolved.enableDelegation,
|
|
3116
|
-
enableModelRouting: resolved.enableModelRouting,
|
|
3117
|
-
contextOverrides: resolved.contextOverrides,
|
|
3118
|
-
subagentMaxTokens: resolved.subagentMaxTokens,
|
|
3119
|
-
subagentMaxTurns: resolved.subagentMaxTurns,
|
|
3120
|
-
subagentTemperature: resolved.subagentTemperature,
|
|
3121
|
-
loopDetectorConfig: {
|
|
3122
|
-
identicalCallLimit: resolved.loopIdenticalCallLimit,
|
|
3123
|
-
consecutiveErrorLimit: resolved.loopConsecutiveErrorLimit,
|
|
3124
|
-
turnErrorLimit: resolved.loopTurnErrorLimit,
|
|
3125
|
-
window: resolved.loopWindow,
|
|
3126
|
-
sessionToolErrorLimit: resolved.loopSessionToolErrorLimit,
|
|
3127
|
-
consecutiveFailedTurnLimit: resolved.loopConsecutiveFailedTurnLimit,
|
|
3128
|
-
fileReadLimit: resolved.loopFileReadLimit
|
|
3129
|
-
},
|
|
3130
|
-
batchErrorLimit: resolved.loopBatchErrorLimit,
|
|
3131
|
-
storeId,
|
|
3132
|
-
source: "channel_agent",
|
|
3133
|
-
agentId,
|
|
3134
|
-
traceId,
|
|
3135
|
-
conversationId,
|
|
3136
|
-
executeTool: async (toolName, args) => {
|
|
3137
|
-
const toolArgs = {
|
|
3138
|
-
...args
|
|
3139
|
-
};
|
|
3140
|
-
if (!toolArgs.store_id) toolArgs.store_id = storeId;
|
|
3141
|
-
// Pass sender context as user identity so node-triggered tool calls aren't anonymous
|
|
3142
|
-
const senderUserId = senderContext?.customerId || null;
|
|
3143
|
-
const senderUserLabel = senderContext?.customerName || senderContext?.senderName || (senderContext?.senderId ? `${senderContext.channelType}:${senderContext.senderId}` : null);
|
|
3144
|
-
return executeTool(supabase, toolName, toolArgs, storeId, traceId, senderUserId, senderUserLabel, "channel_agent", conversationId, userToolRows, agentId, undefined, true);
|
|
3145
|
-
},
|
|
3146
|
-
enableStreaming: false,
|
|
3147
|
-
maxDurationMs: resolved.maxDurationMs
|
|
3148
|
-
});
|
|
3149
|
-
|
|
3150
|
-
// Persist everything — shared helper, identical to SSE chat
|
|
3151
|
-
await persistAgentTurn(supabase, agent, {
|
|
3152
|
-
conversationId,
|
|
3153
|
-
storeId,
|
|
3154
|
-
agentId,
|
|
3155
|
-
agentModel,
|
|
3156
|
-
traceId,
|
|
3157
|
-
message,
|
|
3158
|
-
result,
|
|
3159
|
-
source: "channel_agent",
|
|
3160
|
-
chatStartTime,
|
|
3161
|
-
chatEndTime: Date.now(),
|
|
3162
|
-
userId: senderContext?.customerId || undefined,
|
|
3163
|
-
userEmail: senderContext?.customerName || senderContext?.senderName || (senderContext?.senderId ? `${senderContext.channelType}:${senderContext.senderId}` : undefined),
|
|
3164
|
-
senderContext
|
|
3165
|
-
});
|
|
3166
|
-
return {
|
|
3167
|
-
success: true,
|
|
3168
|
-
response: result.finalText || "(no response)"
|
|
3169
|
-
};
|
|
3170
|
-
} catch (err) {
|
|
3171
|
-
return {
|
|
3172
|
-
success: false,
|
|
3173
|
-
error: err.message
|
|
3174
|
-
};
|
|
3175
|
-
}
|
|
3176
|
-
}
|
|
1655
|
+
// Wire executors into workflow engine (extracted modules — no inline duplicates)
|
|
1656
|
+
wireToolExecutor();
|
|
1657
|
+
wireAgentExecutor();
|
|
1658
|
+
wireBroadcasters();
|
|
3177
1659
|
|
|
3178
1660
|
// Wire both channel and webchat to the same invoker
|
|
3179
1661
|
setNodeAgentInvoker(invokeAgentForChannel);
|
|
3180
1662
|
webchatAgentInvoker = invokeAgentForChannel;
|
|
3181
1663
|
|
|
3182
|
-
//
|
|
3183
|
-
|
|
3184
|
-
// ============================================================================
|
|
3185
|
-
|
|
3186
|
-
async function enforceNodeOfflineStatus(supabase) {
|
|
3187
|
-
const threshold = new Date(Date.now() - 3 * 60_000).toISOString(); // 3 missed heartbeats (60s interval)
|
|
3188
|
-
const {
|
|
3189
|
-
data
|
|
3190
|
-
} = await supabase.from("nodes").update({
|
|
3191
|
-
status: "offline"
|
|
3192
|
-
}).eq("status", "online").lt("last_heartbeat", threshold).select("id");
|
|
3193
|
-
return data?.length || 0;
|
|
3194
|
-
}
|
|
3195
|
-
|
|
3196
|
-
// ============================================================================
|
|
3197
|
-
// PERSISTENT WORKFLOW WORKER LOOP (5-second interval)
|
|
3198
|
-
// ============================================================================
|
|
3199
|
-
|
|
3200
|
-
// Phase 3.1: Increased from 5s to 15s — NOTIFY-driven execution handles the fast path
|
|
3201
|
-
// Worker loop is now a safety net for missed notifications
|
|
3202
|
-
const BASE_WORKER_INTERVAL_MS = 15_000;
|
|
3203
|
-
const MAX_WORKER_INTERVAL_MS = 60_000;
|
|
3204
|
-
let workerRunning = false;
|
|
3205
|
-
let consecutiveErrors = 0;
|
|
3206
|
-
let currentWorkerInterval = BASE_WORKER_INTERVAL_MS;
|
|
3207
|
-
async function workflowWorkerLoop() {
|
|
3208
|
-
if (workerRunning) return; // Prevent concurrent runs
|
|
3209
|
-
workerRunning = true;
|
|
3210
|
-
try {
|
|
3211
|
-
const supabase = getServiceClient();
|
|
3212
|
-
const [stepResult, waitingResolved] = await Promise.all([processWorkflowSteps(supabase, 10), processWaitingSteps(supabase), Promise.resolve(supabase.rpc("expire_pending_waitpoints")).then(() => {}).catch(e => log.warn({
|
|
3213
|
-
err: e.message
|
|
3214
|
-
}, "expire_pending_waitpoints failed")) // Non-fatal
|
|
3215
|
-
]);
|
|
3216
|
-
|
|
3217
|
-
// Schedule triggers + timeout enforcement + event triggers + orphan cleanup + DLQ retries + node offline detection
|
|
3218
|
-
const [scheduled, timedOut, eventsProcessed, orphansCleaned, dlqRetried, nodesOfflined] = await Promise.all([processScheduleTriggers(supabase).catch(e => {
|
|
3219
|
-
log.warn({
|
|
3220
|
-
err: e.message
|
|
3221
|
-
}, "processScheduleTriggers failed");
|
|
3222
|
-
return 0;
|
|
3223
|
-
}), enforceWorkflowTimeouts(supabase).catch(e => {
|
|
3224
|
-
log.warn({
|
|
3225
|
-
err: e.message
|
|
3226
|
-
}, "enforceWorkflowTimeouts failed");
|
|
3227
|
-
return 0;
|
|
3228
|
-
}), processEventTriggers(supabase).catch(e => {
|
|
3229
|
-
log.warn({
|
|
3230
|
-
err: e.message
|
|
3231
|
-
}, "processEventTriggers failed");
|
|
3232
|
-
return 0;
|
|
3233
|
-
}), cleanupOrphanedSteps(supabase).catch(e => {
|
|
3234
|
-
log.warn({
|
|
3235
|
-
err: e.message
|
|
3236
|
-
}, "cleanupOrphanedSteps failed");
|
|
3237
|
-
return 0;
|
|
3238
|
-
}), processDlqRetries(supabase).catch(e => {
|
|
3239
|
-
log.warn({
|
|
3240
|
-
err: e.message
|
|
3241
|
-
}, "processDlqRetries failed");
|
|
3242
|
-
return 0;
|
|
3243
|
-
}), enforceNodeOfflineStatus(supabase).catch(e => {
|
|
3244
|
-
log.warn({
|
|
3245
|
-
err: e.message
|
|
3246
|
-
}, "enforceNodeOfflineStatus failed");
|
|
3247
|
-
return 0;
|
|
3248
|
-
})]);
|
|
3249
|
-
if (stepResult.processed > 0 || waitingResolved > 0 || scheduled > 0 || timedOut > 0 || eventsProcessed > 0 || stepResult.reclaimed > 0 || orphansCleaned > 0 || dlqRetried > 0 || nodesOfflined > 0) {
|
|
3250
|
-
log.info({
|
|
3251
|
-
processed: stepResult.processed,
|
|
3252
|
-
errors: stepResult.errors,
|
|
3253
|
-
reclaimed: stepResult.reclaimed || 0,
|
|
3254
|
-
waiting: waitingResolved,
|
|
3255
|
-
scheduled,
|
|
3256
|
-
timedOut,
|
|
3257
|
-
events: eventsProcessed,
|
|
3258
|
-
orphans: orphansCleaned,
|
|
3259
|
-
dlqRetries: dlqRetried,
|
|
3260
|
-
nodesOfflined
|
|
3261
|
-
}, "worker tick");
|
|
3262
|
-
}
|
|
3263
|
-
|
|
3264
|
-
// Reset backoff on success
|
|
3265
|
-
if (consecutiveErrors > 0) {
|
|
3266
|
-
consecutiveErrors = 0;
|
|
3267
|
-
if (currentWorkerInterval !== BASE_WORKER_INTERVAL_MS) {
|
|
3268
|
-
currentWorkerInterval = BASE_WORKER_INTERVAL_MS;
|
|
3269
|
-
clearInterval(workerInterval);
|
|
3270
|
-
workerInterval = setInterval(workflowWorkerLoop, currentWorkerInterval);
|
|
3271
|
-
log.info({
|
|
3272
|
-
intervalMs: currentWorkerInterval
|
|
3273
|
-
}, "worker interval reset after recovery");
|
|
3274
|
-
}
|
|
3275
|
-
}
|
|
3276
|
-
} catch (err) {
|
|
3277
|
-
consecutiveErrors++;
|
|
3278
|
-
log.error({
|
|
3279
|
-
err: sanitizeError(err),
|
|
3280
|
-
consecutiveErrors
|
|
3281
|
-
}, "worker error");
|
|
3282
|
-
|
|
3283
|
-
// Exponential backoff: 5s → 10s → 20s → 40s → 60s (cap)
|
|
3284
|
-
if (consecutiveErrors >= 3) {
|
|
3285
|
-
const newInterval = Math.min(BASE_WORKER_INTERVAL_MS * Math.pow(2, consecutiveErrors - 2), MAX_WORKER_INTERVAL_MS);
|
|
3286
|
-
if (newInterval !== currentWorkerInterval) {
|
|
3287
|
-
currentWorkerInterval = newInterval;
|
|
3288
|
-
clearInterval(workerInterval);
|
|
3289
|
-
workerInterval = setInterval(workflowWorkerLoop, currentWorkerInterval);
|
|
3290
|
-
log.warn({
|
|
3291
|
-
intervalMs: currentWorkerInterval,
|
|
3292
|
-
consecutiveErrors
|
|
3293
|
-
}, "worker interval increased due to repeated errors");
|
|
3294
|
-
}
|
|
3295
|
-
}
|
|
3296
|
-
} finally {
|
|
3297
|
-
workerRunning = false;
|
|
3298
|
-
}
|
|
3299
|
-
}
|
|
3300
|
-
let workerInterval = setInterval(workflowWorkerLoop, BASE_WORKER_INTERVAL_MS);
|
|
1664
|
+
// Start persistent workflow worker loop (extracted module)
|
|
1665
|
+
startWorkerLoop();
|
|
3301
1666
|
|
|
3302
1667
|
// Initialize shared Supabase client with retry logic before server starts
|
|
3303
1668
|
initSupabase(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
|
|
@@ -3305,8 +1670,7 @@ server.listen(PORT, () => {
|
|
|
3305
1670
|
log.info({
|
|
3306
1671
|
port: PORT,
|
|
3307
1672
|
supabaseUrl: SUPABASE_URL,
|
|
3308
|
-
runtime: process.version
|
|
3309
|
-
workerIntervalMs: BASE_WORKER_INTERVAL_MS
|
|
1673
|
+
runtime: process.version
|
|
3310
1674
|
}, "server listening");
|
|
3311
1675
|
|
|
3312
1676
|
// Initialize code worker pool for fast code step execution
|
|
@@ -3367,11 +1731,12 @@ async function gracefulShutdown(signal) {
|
|
|
3367
1731
|
log.info("HTTP server closed");
|
|
3368
1732
|
});
|
|
3369
1733
|
|
|
3370
|
-
// 2. Clear workflow worker intervals
|
|
3371
|
-
|
|
1734
|
+
// 2. Clear workflow worker + SSE cleanup intervals
|
|
1735
|
+
stopWorkerLoop();
|
|
3372
1736
|
clearInterval(sseCleanupInterval);
|
|
3373
1737
|
|
|
3374
1738
|
// 3. Close all SSE client connections
|
|
1739
|
+
const sseClients = getSseClients();
|
|
3375
1740
|
for (const [, clients] of sseClients) {
|
|
3376
1741
|
for (const res of clients) {
|
|
3377
1742
|
try {
|
|
@@ -3415,11 +1780,7 @@ async function gracefulShutdown(signal) {
|
|
|
3415
1780
|
rateLimiter.shutdown();
|
|
3416
1781
|
|
|
3417
1782
|
// 5. Close pg LISTEN connection
|
|
3418
|
-
|
|
3419
|
-
pgClient.end().catch(() => {});
|
|
3420
|
-
pgClient = null;
|
|
3421
|
-
log.info("pg LISTEN connection closed");
|
|
3422
|
-
}
|
|
1783
|
+
closePgClient();
|
|
3423
1784
|
|
|
3424
1785
|
// 6. Wait for active requests to drain (up to 25 seconds)
|
|
3425
1786
|
const drainStart = Date.now();
|