whale-code 6.5.4 → 6.5.6
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 +39 -31
- package/bin/{swagmanager-mcp.js → whale-code.js} +17 -2
- package/dist/cli/app.js +148 -72
- package/dist/cli/app.js.map +1 -0
- package/dist/cli/chat/AgentSelector.js +105 -10
- package/dist/cli/chat/AgentSelector.js.map +1 -0
- package/dist/cli/chat/ChatApp.d.ts +31 -0
- package/dist/cli/chat/ChatApp.js +539 -286
- package/dist/cli/chat/ChatApp.js.map +1 -0
- package/dist/cli/chat/ChatInput.js +1088 -770
- package/dist/cli/chat/ChatInput.js.map +1 -0
- package/dist/cli/chat/MarkdownText.js +39 -14
- package/dist/cli/chat/MarkdownText.js.map +1 -0
- package/dist/cli/chat/MemoryManager.js +181 -46
- package/dist/cli/chat/MemoryManager.js.map +1 -0
- package/dist/cli/chat/MessageList.d.ts +2 -3
- package/dist/cli/chat/MessageList.js +186 -45
- package/dist/cli/chat/MessageList.js.map +1 -0
- package/dist/cli/chat/ModelSelector.js +282 -63
- package/dist/cli/chat/ModelSelector.js.map +1 -0
- package/dist/cli/chat/NodeManager.js +165 -75
- package/dist/cli/chat/NodeManager.js.map +1 -0
- package/dist/cli/chat/NodeSelector.js +171 -30
- package/dist/cli/chat/NodeSelector.js.map +1 -0
- package/dist/cli/chat/PlanApproval.js +281 -57
- package/dist/cli/chat/PlanApproval.js.map +1 -0
- package/dist/cli/chat/RewindViewer.js +559 -144
- package/dist/cli/chat/RewindViewer.js.map +1 -0
- package/dist/cli/chat/SessionManager.js +137 -30
- package/dist/cli/chat/SessionManager.js.map +1 -0
- package/dist/cli/chat/SlashMenu.js +293 -164
- package/dist/cli/chat/SlashMenu.js.map +1 -0
- package/dist/cli/chat/StatusBar.js +172 -9
- package/dist/cli/chat/StatusBar.js.map +1 -0
- package/dist/cli/chat/StoreSelector.js +147 -18
- package/dist/cli/chat/StoreSelector.js.map +1 -0
- package/dist/cli/chat/StreamingText.d.ts +1 -5
- package/dist/cli/chat/StreamingText.js +22 -7
- package/dist/cli/chat/StreamingText.js.map +1 -0
- package/dist/cli/chat/SubagentPanel.d.ts +1 -2
- package/dist/cli/chat/SubagentPanel.js +612 -72
- package/dist/cli/chat/SubagentPanel.js.map +1 -0
- package/dist/cli/chat/TeamPanel.d.ts +1 -0
- package/dist/cli/chat/TeamPanel.js +230 -30
- package/dist/cli/chat/TeamPanel.js.map +1 -0
- package/dist/cli/chat/ThemeSelector.js +84 -24
- package/dist/cli/chat/ThemeSelector.js.map +1 -0
- package/dist/cli/chat/ToolIndicator.js +1476 -371
- package/dist/cli/chat/ToolIndicator.js.map +1 -0
- package/dist/cli/chat/hooks/useAgentLoop.d.ts +1 -0
- package/dist/cli/chat/hooks/useAgentLoop.js +481 -367
- package/dist/cli/chat/hooks/useAgentLoop.js.map +1 -0
- package/dist/cli/chat/hooks/useSlashCommands.d.ts +3 -14
- package/dist/cli/chat/hooks/useSlashCommands.js +744 -572
- package/dist/cli/chat/hooks/useSlashCommands.js.map +1 -0
- package/dist/cli/commands/config-cmd.js +56 -57
- package/dist/cli/commands/config-cmd.js.map +1 -0
- package/dist/cli/commands/db.js +184 -169
- package/dist/cli/commands/db.js.map +1 -0
- package/dist/cli/commands/doctor.js +212 -122
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.js +211 -244
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/mcp.js +127 -122
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/login/LoginApp.js +355 -141
- package/dist/cli/login/LoginApp.js.map +1 -0
- package/dist/cli/print-mode.js +196 -177
- package/dist/cli/print-mode.js.map +1 -0
- package/dist/cli/serve-mode.js +615 -530
- package/dist/cli/serve-mode.js.map +1 -0
- package/dist/cli/services/agent-config.d.ts +29 -0
- package/dist/cli/services/agent-config.js +91 -0
- package/dist/cli/services/agent-config.js.map +1 -0
- package/dist/cli/services/agent-definitions.d.ts +4 -1
- package/dist/cli/services/agent-definitions.js +97 -56
- package/dist/cli/services/agent-definitions.js.map +1 -0
- package/dist/cli/services/agent-events.js +225 -162
- package/dist/cli/services/agent-events.js.map +1 -0
- package/dist/cli/services/agent-loop.js +978 -669
- package/dist/cli/services/agent-loop.js.map +1 -0
- package/dist/cli/services/agent-worker-base.d.ts +35 -5
- package/dist/cli/services/agent-worker-base.js +337 -153
- package/dist/cli/services/agent-worker-base.js.map +1 -0
- package/dist/cli/services/api-retry.js +69 -64
- package/dist/cli/services/api-retry.js.map +1 -0
- package/dist/cli/services/auth-service.d.ts +3 -3
- package/dist/cli/services/auth-service.js +209 -132
- package/dist/cli/services/auth-service.js.map +1 -0
- package/dist/cli/services/background-processes.js +343 -267
- package/dist/cli/services/background-processes.js.map +1 -0
- package/dist/cli/services/browser-auth.d.ts +2 -2
- package/dist/cli/services/browser-auth.js +159 -118
- package/dist/cli/services/browser-auth.js.map +1 -0
- package/dist/cli/services/claude-md-loader.js +40 -36
- package/dist/cli/services/claude-md-loader.js.map +1 -0
- package/dist/cli/services/config-store.d.ts +9 -4
- package/dist/cli/services/config-store.js +164 -117
- package/dist/cli/services/config-store.js.map +1 -0
- package/dist/cli/services/debug-log.d.ts +1 -1
- package/dist/cli/services/debug-log.js +34 -35
- package/dist/cli/services/debug-log.js.map +1 -0
- package/dist/cli/services/env-detect.d.ts +7 -0
- package/dist/cli/services/env-detect.js +9 -0
- package/dist/cli/services/env-detect.js.map +1 -0
- package/dist/cli/services/error-logger.d.ts +2 -3
- package/dist/cli/services/error-logger.js +189 -180
- package/dist/cli/services/error-logger.js.map +1 -0
- package/dist/cli/services/file-history.d.ts +1 -1
- package/dist/cli/services/file-history.js +50 -54
- package/dist/cli/services/file-history.js.map +1 -0
- package/dist/cli/services/format-server-response.js +332 -372
- package/dist/cli/services/format-server-response.js.map +1 -0
- package/dist/cli/services/git-context.js +61 -45
- package/dist/cli/services/git-context.js.map +1 -0
- package/dist/cli/services/hooks.d.ts +2 -2
- package/dist/cli/services/hooks.js +195 -180
- package/dist/cli/services/hooks.js.map +1 -0
- package/dist/cli/services/ink-incremental.d.ts +19 -0
- package/dist/cli/services/ink-incremental.js +59 -0
- package/dist/cli/services/ink-incremental.js.map +1 -0
- package/dist/cli/services/ink-resize-fix.js +54 -44
- package/dist/cli/services/ink-resize-fix.js.map +1 -0
- package/dist/cli/services/ink-sync-output.d.ts +12 -0
- package/dist/cli/services/ink-sync-output.js +16 -0
- package/dist/cli/services/ink-sync-output.js.map +1 -0
- package/dist/cli/services/interactive-tools.js +268 -212
- package/dist/cli/services/interactive-tools.js.map +1 -0
- package/dist/cli/services/keybinding-manager.d.ts +11 -1
- package/dist/cli/services/keybinding-manager.js +126 -63
- package/dist/cli/services/keybinding-manager.js.map +1 -0
- package/dist/cli/services/local-tools.d.ts +1 -1
- package/dist/cli/services/local-tools.js +939 -656
- package/dist/cli/services/local-tools.js.map +1 -0
- package/dist/cli/services/lsp-manager.js +757 -594
- package/dist/cli/services/lsp-manager.js.map +1 -0
- package/dist/cli/services/mcp-client.d.ts +1 -1
- package/dist/cli/services/mcp-client.js +173 -134
- package/dist/cli/services/mcp-client.js.map +1 -0
- package/dist/cli/services/memory-manager.js +53 -40
- package/dist/cli/services/memory-manager.js.map +1 -0
- package/dist/cli/services/model-manager.js +55 -40
- package/dist/cli/services/model-manager.js.map +1 -0
- package/dist/cli/services/model-router.js +115 -85
- package/dist/cli/services/model-router.js.map +1 -0
- package/dist/cli/services/paths.d.ts +30 -0
- package/dist/cli/services/paths.js +81 -0
- package/dist/cli/services/paths.js.map +1 -0
- package/dist/cli/services/permission-modes.js +32 -25
- package/dist/cli/services/permission-modes.js.map +1 -0
- package/dist/cli/services/rewind.js +182 -168
- package/dist/cli/services/rewind.js.map +1 -0
- package/dist/cli/services/ripgrep.js +115 -115
- package/dist/cli/services/ripgrep.js.map +1 -0
- package/dist/cli/services/sandbox.d.ts +1 -1
- package/dist/cli/services/sandbox.js +58 -37
- package/dist/cli/services/sandbox.js.map +1 -0
- package/dist/cli/services/server-tools.js +738 -565
- package/dist/cli/services/server-tools.js.map +1 -0
- package/dist/cli/services/session-persistence.js +69 -74
- package/dist/cli/services/session-persistence.js.map +1 -0
- package/dist/cli/services/subagent-worker.js +42 -27
- package/dist/cli/services/subagent-worker.js.map +1 -0
- package/dist/cli/services/subagent.d.ts +2 -0
- package/dist/cli/services/subagent.js +606 -430
- package/dist/cli/services/subagent.js.map +1 -0
- package/dist/cli/services/system-prompt.js +86 -78
- package/dist/cli/services/system-prompt.js.map +1 -0
- package/dist/cli/services/task-decomposer.d.ts +1 -1
- package/dist/cli/services/task-decomposer.js +172 -139
- package/dist/cli/services/task-decomposer.js.map +1 -0
- package/dist/cli/services/team-lead.d.ts +2 -2
- package/dist/cli/services/team-lead.js +727 -529
- package/dist/cli/services/team-lead.js.map +1 -0
- package/dist/cli/services/team-state.js +319 -319
- package/dist/cli/services/team-state.js.map +1 -0
- package/dist/cli/services/teammate.d.ts +8 -2
- package/dist/cli/services/teammate.js +862 -560
- package/dist/cli/services/teammate.js.map +1 -0
- package/dist/cli/services/telemetry.d.ts +6 -1
- package/dist/cli/services/telemetry.js +180 -157
- package/dist/cli/services/telemetry.js.map +1 -0
- package/dist/cli/services/tools/agent-tools.d.ts +3 -3
- package/dist/cli/services/tools/agent-tools.js +480 -322
- package/dist/cli/services/tools/agent-tools.js.map +1 -0
- package/dist/cli/services/tools/file-ops.js +563 -450
- package/dist/cli/services/tools/file-ops.js.map +1 -0
- package/dist/cli/services/tools/search-tools.js +231 -162
- package/dist/cli/services/tools/search-tools.js.map +1 -0
- package/dist/cli/services/tools/shell-exec.js +197 -151
- package/dist/cli/services/tools/shell-exec.js.map +1 -0
- package/dist/cli/services/tools/task-manager.js +206 -173
- package/dist/cli/services/tools/task-manager.js.map +1 -0
- package/dist/cli/services/tools/web-tools.js +388 -341
- package/dist/cli/services/tools/web-tools.js.map +1 -0
- package/dist/cli/setup/SetupApp.d.ts +2 -2
- package/dist/cli/setup/SetupApp.js +608 -160
- package/dist/cli/setup/SetupApp.js.map +1 -0
- package/dist/cli/shared/ErrorBoundary.d.ts +22 -0
- package/dist/cli/shared/ErrorBoundary.js +73 -0
- package/dist/cli/shared/ErrorBoundary.js.map +1 -0
- package/dist/cli/shared/MatrixIntro.js +66 -69
- package/dist/cli/shared/MatrixIntro.js.map +1 -0
- package/dist/cli/shared/SpinnerSlot.d.ts +14 -0
- package/dist/cli/shared/SpinnerSlot.js +63 -0
- package/dist/cli/shared/SpinnerSlot.js.map +1 -0
- package/dist/cli/shared/Theme.d.ts +1 -1
- package/dist/cli/shared/Theme.js +136 -92
- package/dist/cli/shared/Theme.js.map +1 -0
- package/dist/cli/shared/WhaleBanner.js +99 -11
- package/dist/cli/shared/WhaleBanner.js.map +1 -0
- package/dist/cli/shared/markdown.d.ts +3 -1
- package/dist/cli/shared/markdown.js +736 -674
- package/dist/cli/shared/markdown.js.map +1 -0
- package/dist/cli/shared/marked-terminal.d.js +2 -0
- package/dist/cli/shared/marked-terminal.d.js.map +1 -0
- package/dist/cli/shared/theme-manager.js +99 -90
- package/dist/cli/shared/theme-manager.js.map +1 -0
- package/dist/cli/shared/theme-presets.js +256 -254
- package/dist/cli/shared/theme-presets.js.map +1 -0
- package/dist/cli/status/StatusApp.js +235 -86
- package/dist/cli/status/StatusApp.js.map +1 -0
- package/dist/cli/stores/StoreApp.js +275 -65
- package/dist/cli/stores/StoreApp.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +509 -396
- package/dist/index.js.map +1 -0
- package/dist/local-agent/connection.d.ts +2 -2
- package/dist/local-agent/connection.js +352 -293
- package/dist/local-agent/connection.js.map +1 -0
- package/dist/local-agent/discovery.js +259 -122
- package/dist/local-agent/discovery.js.map +1 -0
- package/dist/local-agent/executor.js +216 -193
- package/dist/local-agent/executor.js.map +1 -0
- package/dist/local-agent/index.d.ts +2 -2
- package/dist/local-agent/index.js +156 -156
- package/dist/local-agent/index.js.map +1 -0
- package/dist/node/adapters/base.js +18 -8
- package/dist/node/adapters/base.js.map +1 -0
- package/dist/node/adapters/discord.js +286 -275
- package/dist/node/adapters/discord.js.map +1 -0
- package/dist/node/adapters/email.js +189 -202
- package/dist/node/adapters/email.js.map +1 -0
- package/dist/node/adapters/imessage.js +145 -142
- package/dist/node/adapters/imessage.js.map +1 -0
- package/dist/node/adapters/slack.js +237 -236
- package/dist/node/adapters/slack.js.map +1 -0
- package/dist/node/adapters/sms.js +149 -151
- package/dist/node/adapters/sms.js.map +1 -0
- package/dist/node/adapters/telegram.js +88 -92
- package/dist/node/adapters/telegram.js.map +1 -0
- package/dist/node/adapters/webchat.js +160 -136
- package/dist/node/adapters/webchat.js.map +1 -0
- package/dist/node/adapters/whatsapp.js +212 -215
- package/dist/node/adapters/whatsapp.js.map +1 -0
- package/dist/node/cli.js +884 -653
- package/dist/node/cli.js.map +1 -0
- package/dist/node/config.js +20 -18
- package/dist/node/config.js.map +1 -0
- package/dist/node/gateway-client.js +191 -181
- package/dist/node/gateway-client.js.map +1 -0
- package/dist/node/portal/clipboard.js +161 -130
- package/dist/node/portal/clipboard.js.map +1 -0
- package/dist/node/portal/discovery.js +51 -45
- package/dist/node/portal/discovery.js.map +1 -0
- package/dist/node/portal/forward.js +64 -58
- package/dist/node/portal/forward.js.map +1 -0
- package/dist/node/portal/index.js +246 -221
- package/dist/node/portal/index.js.map +1 -0
- package/dist/node/portal/multiplexer.js +192 -182
- package/dist/node/portal/multiplexer.js.map +1 -0
- package/dist/node/portal/permissions.js +102 -70
- package/dist/node/portal/permissions.js.map +1 -0
- package/dist/node/portal/protocol.js +153 -116
- package/dist/node/portal/protocol.js.map +1 -0
- package/dist/node/portal/screen.js +80 -69
- package/dist/node/portal/screen.js.map +1 -0
- package/dist/node/portal/session.js +124 -117
- package/dist/node/portal/session.js.map +1 -0
- package/dist/node/portal/shell.js +140 -113
- package/dist/node/portal/shell.js.map +1 -0
- package/dist/node/portal/stream.js +77 -75
- package/dist/node/portal/stream.js.map +1 -0
- package/dist/node/portal/transfer.js +190 -167
- package/dist/node/portal/transfer.js.map +1 -0
- package/dist/node/portal/ui.js +124 -99
- package/dist/node/portal/ui.js.map +1 -0
- package/dist/node/remote-desktop/compile-helper.js +50 -45
- package/dist/node/remote-desktop/compile-helper.js.map +1 -0
- package/dist/node/remote-desktop/index.js +215 -187
- package/dist/node/remote-desktop/index.js.map +1 -0
- package/dist/node/remote-desktop/protocol.js +45 -29
- package/dist/node/remote-desktop/protocol.js.map +1 -0
- package/dist/node/runtime.js +493 -410
- package/dist/node/runtime.js.map +1 -0
- package/dist/server/handlers/__test-utils__/test-db.js +39 -89
- package/dist/server/handlers/__test-utils__/test-db.js.map +1 -0
- package/dist/server/handlers/analytics.js +467 -261
- package/dist/server/handlers/analytics.js.map +1 -0
- package/dist/server/handlers/api-docs.d.ts +6 -0
- package/dist/server/handlers/api-docs.js +1613 -0
- package/dist/server/handlers/api-docs.js.map +1 -0
- package/dist/server/handlers/api-keys.js +295 -232
- package/dist/server/handlers/api-keys.js.map +1 -0
- package/dist/server/handlers/billing.js +330 -239
- package/dist/server/handlers/billing.js.map +1 -0
- package/dist/server/handlers/browser.js +468 -395
- package/dist/server/handlers/browser.js.map +1 -0
- package/dist/server/handlers/catalog.js +1377 -978
- package/dist/server/handlers/catalog.js.map +1 -0
- package/dist/server/handlers/clickhouse.js +157 -109
- package/dist/server/handlers/clickhouse.js.map +1 -0
- package/dist/server/handlers/comms.d.ts +0 -53
- package/dist/server/handlers/comms.js +1443 -970
- package/dist/server/handlers/comms.js.map +1 -0
- package/dist/server/handlers/creations.js +461 -394
- package/dist/server/handlers/creations.js.map +1 -0
- package/dist/server/handlers/crm.js +1082 -791
- package/dist/server/handlers/crm.js.map +1 -0
- package/dist/server/handlers/discovery.js +251 -232
- package/dist/server/handlers/discovery.js.map +1 -0
- package/dist/server/handlers/embeddings.js +241 -164
- package/dist/server/handlers/embeddings.js.map +1 -0
- package/dist/server/handlers/enrichment.js +887 -718
- package/dist/server/handlers/enrichment.js.map +1 -0
- package/dist/server/handlers/image-gen.js +467 -376
- package/dist/server/handlers/image-gen.js.map +1 -0
- package/dist/server/handlers/inventory.js +797 -424
- package/dist/server/handlers/inventory.js.map +1 -0
- package/dist/server/handlers/kali.js +272 -230
- package/dist/server/handlers/kali.js.map +1 -0
- package/dist/server/handlers/llm-providers.js +803 -580
- package/dist/server/handlers/llm-providers.js.map +1 -0
- package/dist/server/handlers/local-agent.js +133 -105
- package/dist/server/handlers/local-agent.js.map +1 -0
- package/dist/server/handlers/media.js +1179 -857
- package/dist/server/handlers/media.js.map +1 -0
- package/dist/server/handlers/meta-ads.js +2669 -2093
- package/dist/server/handlers/meta-ads.js.map +1 -0
- package/dist/server/handlers/nodes.js +1321 -913
- package/dist/server/handlers/nodes.js.map +1 -0
- package/dist/server/handlers/operations.js +183 -157
- package/dist/server/handlers/operations.js.map +1 -0
- package/dist/server/handlers/platform.js +346 -210
- package/dist/server/handlers/platform.js.map +1 -0
- package/dist/server/handlers/remove-bg.js +118 -86
- package/dist/server/handlers/remove-bg.js.map +1 -0
- package/dist/server/handlers/storefront.js +586 -446
- package/dist/server/handlers/storefront.js.map +1 -0
- package/dist/server/handlers/supply-chain.js +546 -326
- package/dist/server/handlers/supply-chain.js.map +1 -0
- package/dist/server/handlers/transcription.js +106 -97
- package/dist/server/handlers/transcription.js.map +1 -0
- package/dist/server/handlers/video-gen.js +593 -424
- package/dist/server/handlers/video-gen.js.map +1 -0
- package/dist/server/handlers/voice.js +1458 -1017
- package/dist/server/handlers/voice.js.map +1 -0
- package/dist/server/handlers/workflow-steps.js +2837 -2116
- package/dist/server/handlers/workflow-steps.js.map +1 -0
- package/dist/server/handlers/workflows.js +1630 -933
- package/dist/server/handlers/workflows.js.map +1 -0
- package/dist/server/index.js +3166 -2390
- package/dist/server/index.js.map +1 -0
- package/dist/server/lib/batch-client.js +471 -409
- package/dist/server/lib/batch-client.js.map +1 -0
- package/dist/server/lib/clickhouse-buffer.js +118 -104
- package/dist/server/lib/clickhouse-buffer.js.map +1 -0
- package/dist/server/lib/clickhouse-client.js +107 -107
- package/dist/server/lib/clickhouse-client.js.map +1 -0
- package/dist/server/lib/coa-renderer.js +1786 -356
- package/dist/server/lib/coa-renderer.js.map +1 -0
- package/dist/server/lib/code-worker-pool.js +227 -177
- package/dist/server/lib/code-worker-pool.js.map +1 -0
- package/dist/server/lib/code-worker.js +174 -164
- package/dist/server/lib/code-worker.js.map +1 -0
- package/dist/server/lib/compaction-service.d.ts +2 -12
- package/dist/server/lib/compaction-service.js +74 -184
- package/dist/server/lib/compaction-service.js.map +1 -0
- package/dist/server/lib/logger.js +36 -24
- package/dist/server/lib/logger.js.map +1 -0
- package/dist/server/lib/otel.js +101 -80
- package/dist/server/lib/otel.js.map +1 -0
- package/dist/server/lib/pdf-renderer.d.ts +1 -1
- package/dist/server/lib/pdf-renderer.js +954 -776
- package/dist/server/lib/pdf-renderer.js.map +1 -0
- package/dist/server/lib/prompt-sanitizer.js +188 -108
- package/dist/server/lib/prompt-sanitizer.js.map +1 -0
- package/dist/server/lib/provider-capabilities.js +136 -138
- package/dist/server/lib/provider-capabilities.js.map +1 -0
- package/dist/server/lib/provider-failover.js +190 -168
- package/dist/server/lib/provider-failover.js.map +1 -0
- package/dist/server/lib/rate-limiter.js +186 -117
- package/dist/server/lib/rate-limiter.js.map +1 -0
- package/dist/server/lib/react-pdf-layout.js +551 -382
- package/dist/server/lib/react-pdf-layout.js.map +1 -0
- package/dist/server/lib/server-agent-loop.d.ts +9 -0
- package/dist/server/lib/server-agent-loop.js +906 -624
- package/dist/server/lib/server-agent-loop.js.map +1 -0
- package/dist/server/lib/server-subagent.d.ts +2 -0
- package/dist/server/lib/server-subagent.js +260 -162
- package/dist/server/lib/server-subagent.js.map +1 -0
- package/dist/server/lib/session-checkpoint.js +105 -96
- package/dist/server/lib/session-checkpoint.js.map +1 -0
- package/dist/server/lib/ssrf-guard.js +193 -184
- package/dist/server/lib/ssrf-guard.js.map +1 -0
- package/dist/server/lib/supabase-client.js +94 -82
- package/dist/server/lib/supabase-client.js.map +1 -0
- package/dist/server/lib/template-resolver.js +154 -176
- package/dist/server/lib/template-resolver.js.map +1 -0
- package/dist/server/lib/utils.js +242 -133
- package/dist/server/lib/utils.js.map +1 -0
- package/dist/server/local-agent-gateway.d.ts +2 -2
- package/dist/server/local-agent-gateway.js +785 -627
- package/dist/server/local-agent-gateway.js.map +1 -0
- package/dist/server/providers/anthropic.js +254 -176
- package/dist/server/providers/anthropic.js.map +1 -0
- package/dist/server/providers/bedrock.js +221 -162
- package/dist/server/providers/bedrock.js.map +1 -0
- package/dist/server/providers/gemini.js +548 -418
- package/dist/server/providers/gemini.js.map +1 -0
- package/dist/server/providers/openai.js +571 -437
- package/dist/server/providers/openai.js.map +1 -0
- package/dist/server/providers/registry.js +23 -18
- package/dist/server/providers/registry.js.map +1 -0
- package/dist/server/providers/shared.js +123 -95
- package/dist/server/providers/shared.js.map +1 -0
- package/dist/server/providers/types.js +1 -11
- package/dist/server/providers/types.js.map +1 -0
- package/dist/server/proxy-handlers.js +209 -165
- package/dist/server/proxy-handlers.js.map +1 -0
- package/dist/server/tool-router.d.ts +13 -0
- package/dist/server/tool-router.js +960 -598
- package/dist/server/tool-router.js.map +1 -0
- package/dist/server/validation.js +248 -188
- package/dist/server/validation.js.map +1 -0
- package/dist/server/worker.js +202 -133
- package/dist/server/worker.js.map +1 -0
- package/dist/setup.d.ts +2 -2
- package/dist/setup.js +151 -147
- package/dist/setup.js.map +1 -0
- package/dist/shared/agent-core.d.ts +191 -24
- package/dist/shared/agent-core.js +971 -462
- package/dist/shared/agent-core.js.map +1 -0
- package/dist/shared/anthropic-types.js +1 -6
- package/dist/shared/anthropic-types.js.map +1 -0
- package/dist/shared/api-client.d.ts +17 -9
- package/dist/shared/api-client.js +419 -327
- package/dist/shared/api-client.js.map +1 -0
- package/dist/shared/compaction.d.ts +36 -0
- package/dist/shared/compaction.js +138 -0
- package/dist/shared/compaction.js.map +1 -0
- package/dist/shared/constants.js +67 -64
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/sse-parser.js +221 -219
- package/dist/shared/sse-parser.js.map +1 -0
- package/dist/shared/tool-dispatch.d.ts +4 -2
- package/dist/shared/tool-dispatch.js +226 -165
- package/dist/shared/tool-dispatch.js.map +1 -0
- package/dist/shared/types.js +1 -6
- package/dist/shared/types.js.map +1 -0
- package/dist/types/cli-highlight.d.js +2 -0
- package/dist/types/cli-highlight.d.js.map +1 -0
- package/dist/types/diff.d.js +2 -0
- package/dist/types/diff.d.js.map +1 -0
- package/dist/types/pdf-parse.d.js +2 -0
- package/dist/types/pdf-parse.d.js.map +1 -0
- package/dist/updater.d.ts +1 -1
- package/dist/updater.js +118 -92
- package/dist/updater.js.map +1 -0
- package/dist/webchat/widget.js +227 -380
- package/dist/webchat/widget.js.map +1 -0
- package/package.json +22 -10
- package/vendor/ink/build/ansi-tokenizer.d.ts +38 -0
- package/vendor/ink/build/ansi-tokenizer.js +316 -0
- package/vendor/ink/build/ansi-tokenizer.js.map +1 -0
- package/vendor/ink/build/apply-styles.js +175 -0
- package/vendor/ink/build/build-layout.js +77 -0
- package/vendor/ink/build/calculate-wrapped-text.js +53 -0
- package/vendor/ink/build/colorize.d.ts +3 -0
- package/vendor/ink/build/colorize.js +48 -0
- package/vendor/ink/build/colorize.js.map +1 -0
- package/vendor/ink/build/components/AccessibilityContext.d.ts +3 -0
- package/vendor/ink/build/components/AccessibilityContext.js +5 -0
- package/vendor/ink/build/components/AccessibilityContext.js.map +1 -0
- package/vendor/ink/build/components/App.d.ts +18 -0
- package/vendor/ink/build/components/App.js +351 -0
- package/vendor/ink/build/components/App.js.map +1 -0
- package/vendor/ink/build/components/AppContext.d.ts +15 -0
- package/vendor/ink/build/components/AppContext.js +11 -0
- package/vendor/ink/build/components/AppContext.js.map +1 -0
- package/vendor/ink/build/components/BackgroundContext.d.ts +4 -0
- package/vendor/ink/build/components/BackgroundContext.js +3 -0
- package/vendor/ink/build/components/BackgroundContext.js.map +1 -0
- package/vendor/ink/build/components/Box.d.ts +117 -0
- package/vendor/ink/build/components/Box.js +34 -0
- package/vendor/ink/build/components/Box.js.map +1 -0
- package/vendor/ink/build/components/Color.js +62 -0
- package/vendor/ink/build/components/Cursor.d.ts +83 -0
- package/vendor/ink/build/components/Cursor.js +53 -0
- package/vendor/ink/build/components/Cursor.js.map +1 -0
- package/vendor/ink/build/components/CursorContext.d.ts +11 -0
- package/vendor/ink/build/components/CursorContext.js +8 -0
- package/vendor/ink/build/components/CursorContext.js.map +1 -0
- package/vendor/ink/build/components/ErrorBoundary.d.ts +18 -0
- package/vendor/ink/build/components/ErrorBoundary.js +23 -0
- package/vendor/ink/build/components/ErrorBoundary.js.map +1 -0
- package/vendor/ink/build/components/ErrorOverview.d.ts +6 -0
- package/vendor/ink/build/components/ErrorOverview.js +84 -0
- package/vendor/ink/build/components/ErrorOverview.js.map +1 -0
- package/vendor/ink/build/components/FocusContext.d.ts +16 -0
- package/vendor/ink/build/components/FocusContext.js +17 -0
- package/vendor/ink/build/components/FocusContext.js.map +1 -0
- package/vendor/ink/build/components/Newline.d.ts +13 -0
- package/vendor/ink/build/components/Newline.js +8 -0
- package/vendor/ink/build/components/Newline.js.map +1 -0
- package/vendor/ink/build/components/Spacer.d.ts +7 -0
- package/vendor/ink/build/components/Spacer.js +11 -0
- package/vendor/ink/build/components/Spacer.js.map +1 -0
- package/vendor/ink/build/components/Static.d.ts +24 -0
- package/vendor/ink/build/components/Static.js +28 -0
- package/vendor/ink/build/components/Static.js.map +1 -0
- package/vendor/ink/build/components/StderrContext.d.ts +15 -0
- package/vendor/ink/build/components/StderrContext.js +13 -0
- package/vendor/ink/build/components/StderrContext.js.map +1 -0
- package/vendor/ink/build/components/StdinContext.d.ts +22 -0
- package/vendor/ink/build/components/StdinContext.js +19 -0
- package/vendor/ink/build/components/StdinContext.js.map +1 -0
- package/vendor/ink/build/components/StdoutContext.d.ts +15 -0
- package/vendor/ink/build/components/StdoutContext.js +13 -0
- package/vendor/ink/build/components/StdoutContext.js.map +1 -0
- package/vendor/ink/build/components/Text.d.ts +55 -0
- package/vendor/ink/build/components/Text.js +50 -0
- package/vendor/ink/build/components/Text.js.map +1 -0
- package/vendor/ink/build/components/Transform.d.ts +16 -0
- package/vendor/ink/build/components/Transform.js +15 -0
- package/vendor/ink/build/components/Transform.js.map +1 -0
- package/vendor/ink/build/cursor-helpers.d.ts +38 -0
- package/vendor/ink/build/cursor-helpers.js +56 -0
- package/vendor/ink/build/cursor-helpers.js.map +1 -0
- package/vendor/ink/build/devtools-window-polyfill.d.ts +1 -0
- package/vendor/ink/build/devtools-window-polyfill.js +65 -0
- package/vendor/ink/build/devtools-window-polyfill.js.map +1 -0
- package/vendor/ink/build/devtools.d.ts +1 -0
- package/vendor/ink/build/devtools.js +11 -0
- package/vendor/ink/build/devtools.js.map +1 -0
- package/vendor/ink/build/dom.d.ts +56 -0
- package/vendor/ink/build/dom.js +124 -0
- package/vendor/ink/build/dom.js.map +1 -0
- package/vendor/ink/build/experimental/apply-style.js +140 -0
- package/vendor/ink/build/experimental/dom.js +123 -0
- package/vendor/ink/build/experimental/output.js +91 -0
- package/vendor/ink/build/experimental/reconciler.js +141 -0
- package/vendor/ink/build/experimental/renderer.js +81 -0
- package/vendor/ink/build/get-max-width.d.ts +3 -0
- package/vendor/ink/build/get-max-width.js +10 -0
- package/vendor/ink/build/get-max-width.js.map +1 -0
- package/vendor/ink/build/hooks/use-app.d.ts +5 -0
- package/vendor/ink/build/hooks/use-app.js +8 -0
- package/vendor/ink/build/hooks/use-app.js.map +1 -0
- package/vendor/ink/build/hooks/use-cursor.d.ts +12 -0
- package/vendor/ink/build/hooks/use-cursor.js +29 -0
- package/vendor/ink/build/hooks/use-cursor.js.map +1 -0
- package/vendor/ink/build/hooks/use-focus-manager.d.ts +28 -0
- package/vendor/ink/build/hooks/use-focus-manager.js +17 -0
- package/vendor/ink/build/hooks/use-focus-manager.js.map +1 -0
- package/vendor/ink/build/hooks/use-focus.d.ts +29 -0
- package/vendor/ink/build/hooks/use-focus.js +42 -0
- package/vendor/ink/build/hooks/use-focus.js.map +1 -0
- package/vendor/ink/build/hooks/use-input.d.ts +131 -0
- package/vendor/ink/build/hooks/use-input.js +124 -0
- package/vendor/ink/build/hooks/use-input.js.map +1 -0
- package/vendor/ink/build/hooks/use-is-screen-reader-enabled.d.ts +5 -0
- package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js +11 -0
- package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js.map +1 -0
- package/vendor/ink/build/hooks/use-stderr.d.ts +5 -0
- package/vendor/ink/build/hooks/use-stderr.js +8 -0
- package/vendor/ink/build/hooks/use-stderr.js.map +1 -0
- package/vendor/ink/build/hooks/use-stdin.d.ts +5 -0
- package/vendor/ink/build/hooks/use-stdin.js +8 -0
- package/vendor/ink/build/hooks/use-stdin.js.map +1 -0
- package/vendor/ink/build/hooks/use-stdout.d.ts +5 -0
- package/vendor/ink/build/hooks/use-stdout.js +8 -0
- package/vendor/ink/build/hooks/use-stdout.js.map +1 -0
- package/vendor/ink/build/hooks/useInput.js +38 -0
- package/vendor/ink/build/index.d.ts +34 -0
- package/vendor/ink/build/index.js +20 -0
- package/vendor/ink/build/index.js.map +1 -0
- package/vendor/ink/build/ink.d.ts +90 -0
- package/vendor/ink/build/ink.js +654 -0
- package/vendor/ink/build/ink.js.map +1 -0
- package/vendor/ink/build/input-parser.d.ts +7 -0
- package/vendor/ink/build/input-parser.js +154 -0
- package/vendor/ink/build/input-parser.js.map +1 -0
- package/vendor/ink/build/instance.js +205 -0
- package/vendor/ink/build/instances.d.ts +3 -0
- package/vendor/ink/build/instances.js +8 -0
- package/vendor/ink/build/instances.js.map +1 -0
- package/vendor/ink/build/kitty-keyboard.d.ts +23 -0
- package/vendor/ink/build/kitty-keyboard.js +32 -0
- package/vendor/ink/build/kitty-keyboard.js.map +1 -0
- package/vendor/ink/build/layout.d.ts +7 -0
- package/vendor/ink/build/layout.js +33 -0
- package/vendor/ink/build/layout.js.map +1 -0
- package/vendor/ink/build/log-update.d.ts +19 -0
- package/vendor/ink/build/log-update.js +243 -0
- package/vendor/ink/build/log-update.js.map +1 -0
- package/vendor/ink/build/measure-element.d.ts +16 -0
- package/vendor/ink/build/measure-element.js +9 -0
- package/vendor/ink/build/measure-element.js.map +1 -0
- package/vendor/ink/build/measure-text.d.ts +6 -0
- package/vendor/ink/build/measure-text.js +21 -0
- package/vendor/ink/build/measure-text.js.map +1 -0
- package/vendor/ink/build/options.d.ts +52 -0
- package/vendor/ink/build/options.js +2 -0
- package/vendor/ink/build/options.js.map +1 -0
- package/vendor/ink/build/output.d.ts +35 -0
- package/vendor/ink/build/output.js +183 -0
- package/vendor/ink/build/output.js.map +1 -0
- package/vendor/ink/build/parse-keypress.d.ts +22 -0
- package/vendor/ink/build/parse-keypress.js +493 -0
- package/vendor/ink/build/parse-keypress.js.map +1 -0
- package/vendor/ink/build/reconciler.d.ts +4 -0
- package/vendor/ink/build/reconciler.js +274 -0
- package/vendor/ink/build/reconciler.js.map +1 -0
- package/vendor/ink/build/render-background.d.ts +4 -0
- package/vendor/ink/build/render-background.js +25 -0
- package/vendor/ink/build/render-background.js.map +1 -0
- package/vendor/ink/build/render-border.d.ts +4 -0
- package/vendor/ink/build/render-border.js +73 -0
- package/vendor/ink/build/render-border.js.map +1 -0
- package/vendor/ink/build/render-node-to-output.d.ts +14 -0
- package/vendor/ink/build/render-node-to-output.js +147 -0
- package/vendor/ink/build/render-node-to-output.js.map +1 -0
- package/vendor/ink/build/render-to-string.d.ts +38 -0
- package/vendor/ink/build/render-to-string.js +115 -0
- package/vendor/ink/build/render-to-string.js.map +1 -0
- package/vendor/ink/build/render.d.ts +121 -0
- package/vendor/ink/build/render.js +55 -0
- package/vendor/ink/build/render.js.map +1 -0
- package/vendor/ink/build/renderer.d.ts +8 -0
- package/vendor/ink/build/renderer.js +55 -0
- package/vendor/ink/build/renderer.js.map +1 -0
- package/vendor/ink/build/sanitize-ansi.d.ts +2 -0
- package/vendor/ink/build/sanitize-ansi.js +27 -0
- package/vendor/ink/build/sanitize-ansi.js.map +1 -0
- package/vendor/ink/build/screen-reader-update.d.ts +13 -0
- package/vendor/ink/build/screen-reader-update.js +38 -0
- package/vendor/ink/build/screen-reader-update.js.map +1 -0
- package/vendor/ink/build/squash-text-nodes.d.ts +3 -0
- package/vendor/ink/build/squash-text-nodes.js +36 -0
- package/vendor/ink/build/squash-text-nodes.js.map +1 -0
- package/vendor/ink/build/styles.d.ts +240 -0
- package/vendor/ink/build/styles.js +232 -0
- package/vendor/ink/build/styles.js.map +1 -0
- package/vendor/ink/build/utils.d.ts +2 -0
- package/vendor/ink/build/utils.js +4 -0
- package/vendor/ink/build/utils.js.map +1 -0
- package/vendor/ink/build/wrap-text.d.ts +3 -0
- package/vendor/ink/build/wrap-text.js +31 -0
- package/vendor/ink/build/wrap-text.js.map +1 -0
- package/vendor/ink/build/write-synchronized.d.ts +4 -0
- package/vendor/ink/build/write-synchronized.js +7 -0
- package/vendor/ink/build/write-synchronized.js.map +1 -0
- package/vendor/ink/license +10 -0
- package/vendor/ink/node_modules/@types/node/LICENSE +21 -0
- package/vendor/ink/node_modules/@types/node/README.md +15 -0
- package/vendor/ink/node_modules/@types/node/assert/strict.d.ts +105 -0
- package/vendor/ink/node_modules/@types/node/assert.d.ts +955 -0
- package/vendor/ink/node_modules/@types/node/async_hooks.d.ts +623 -0
- package/vendor/ink/node_modules/@types/node/buffer.buffer.d.ts +466 -0
- package/vendor/ink/node_modules/@types/node/buffer.d.ts +1810 -0
- package/vendor/ink/node_modules/@types/node/child_process.d.ts +1428 -0
- package/vendor/ink/node_modules/@types/node/cluster.d.ts +486 -0
- package/vendor/ink/node_modules/@types/node/compatibility/iterators.d.ts +21 -0
- package/vendor/ink/node_modules/@types/node/console.d.ts +151 -0
- package/vendor/ink/node_modules/@types/node/constants.d.ts +20 -0
- package/vendor/ink/node_modules/@types/node/crypto.d.ts +4065 -0
- package/vendor/ink/node_modules/@types/node/dgram.d.ts +564 -0
- package/vendor/ink/node_modules/@types/node/diagnostics_channel.d.ts +576 -0
- package/vendor/ink/node_modules/@types/node/dns/promises.d.ts +503 -0
- package/vendor/ink/node_modules/@types/node/dns.d.ts +922 -0
- package/vendor/ink/node_modules/@types/node/domain.d.ts +166 -0
- package/vendor/ink/node_modules/@types/node/events.d.ts +1054 -0
- package/vendor/ink/node_modules/@types/node/fs/promises.d.ts +1329 -0
- package/vendor/ink/node_modules/@types/node/fs.d.ts +4676 -0
- package/vendor/ink/node_modules/@types/node/globals.d.ts +150 -0
- package/vendor/ink/node_modules/@types/node/globals.typedarray.d.ts +101 -0
- package/vendor/ink/node_modules/@types/node/http.d.ts +2167 -0
- package/vendor/ink/node_modules/@types/node/http2.d.ts +2480 -0
- package/vendor/ink/node_modules/@types/node/https.d.ts +405 -0
- package/vendor/ink/node_modules/@types/node/index.d.ts +115 -0
- package/vendor/ink/node_modules/@types/node/inspector/promises.d.ts +41 -0
- package/vendor/ink/node_modules/@types/node/inspector.d.ts +224 -0
- package/vendor/ink/node_modules/@types/node/inspector.generated.d.ts +4226 -0
- package/vendor/ink/node_modules/@types/node/module.d.ts +819 -0
- package/vendor/ink/node_modules/@types/node/net.d.ts +933 -0
- package/vendor/ink/node_modules/@types/node/os.d.ts +507 -0
- package/vendor/ink/node_modules/@types/node/package.json +155 -0
- package/vendor/ink/node_modules/@types/node/path/posix.d.ts +8 -0
- package/vendor/ink/node_modules/@types/node/path/win32.d.ts +8 -0
- package/vendor/ink/node_modules/@types/node/path.d.ts +187 -0
- package/vendor/ink/node_modules/@types/node/perf_hooks.d.ts +643 -0
- package/vendor/ink/node_modules/@types/node/process.d.ts +2156 -0
- package/vendor/ink/node_modules/@types/node/punycode.d.ts +117 -0
- package/vendor/ink/node_modules/@types/node/querystring.d.ts +152 -0
- package/vendor/ink/node_modules/@types/node/quic.d.ts +910 -0
- package/vendor/ink/node_modules/@types/node/readline/promises.d.ts +161 -0
- package/vendor/ink/node_modules/@types/node/readline.d.ts +541 -0
- package/vendor/ink/node_modules/@types/node/repl.d.ts +415 -0
- package/vendor/ink/node_modules/@types/node/sea.d.ts +162 -0
- package/vendor/ink/node_modules/@types/node/sqlite.d.ts +955 -0
- package/vendor/ink/node_modules/@types/node/stream/consumers.d.ts +38 -0
- package/vendor/ink/node_modules/@types/node/stream/promises.d.ts +211 -0
- package/vendor/ink/node_modules/@types/node/stream/web.d.ts +296 -0
- package/vendor/ink/node_modules/@types/node/stream.d.ts +1760 -0
- package/vendor/ink/node_modules/@types/node/string_decoder.d.ts +67 -0
- package/vendor/ink/node_modules/@types/node/test/reporters.d.ts +96 -0
- package/vendor/ink/node_modules/@types/node/test.d.ts +2240 -0
- package/vendor/ink/node_modules/@types/node/timers/promises.d.ts +108 -0
- package/vendor/ink/node_modules/@types/node/timers.d.ts +159 -0
- package/vendor/ink/node_modules/@types/node/tls.d.ts +1198 -0
- package/vendor/ink/node_modules/@types/node/trace_events.d.ts +197 -0
- package/vendor/ink/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +462 -0
- package/vendor/ink/node_modules/@types/node/ts5.6/compatibility/float16array.d.ts +71 -0
- package/vendor/ink/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +36 -0
- package/vendor/ink/node_modules/@types/node/ts5.6/index.d.ts +117 -0
- package/vendor/ink/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts +72 -0
- package/vendor/ink/node_modules/@types/node/ts5.7/index.d.ts +117 -0
- package/vendor/ink/node_modules/@types/node/tty.d.ts +250 -0
- package/vendor/ink/node_modules/@types/node/url.d.ts +519 -0
- package/vendor/ink/node_modules/@types/node/util/types.d.ts +558 -0
- package/vendor/ink/node_modules/@types/node/util.d.ts +1662 -0
- package/vendor/ink/node_modules/@types/node/v8.d.ts +983 -0
- package/vendor/ink/node_modules/@types/node/vm.d.ts +1208 -0
- package/vendor/ink/node_modules/@types/node/wasi.d.ts +202 -0
- package/vendor/ink/node_modules/@types/node/web-globals/abortcontroller.d.ts +59 -0
- package/vendor/ink/node_modules/@types/node/web-globals/blob.d.ts +23 -0
- package/vendor/ink/node_modules/@types/node/web-globals/console.d.ts +9 -0
- package/vendor/ink/node_modules/@types/node/web-globals/crypto.d.ts +39 -0
- package/vendor/ink/node_modules/@types/node/web-globals/domexception.d.ts +68 -0
- package/vendor/ink/node_modules/@types/node/web-globals/encoding.d.ts +11 -0
- package/vendor/ink/node_modules/@types/node/web-globals/events.d.ts +106 -0
- package/vendor/ink/node_modules/@types/node/web-globals/fetch.d.ts +69 -0
- package/vendor/ink/node_modules/@types/node/web-globals/importmeta.d.ts +13 -0
- package/vendor/ink/node_modules/@types/node/web-globals/messaging.d.ts +23 -0
- package/vendor/ink/node_modules/@types/node/web-globals/navigator.d.ts +25 -0
- package/vendor/ink/node_modules/@types/node/web-globals/performance.d.ts +45 -0
- package/vendor/ink/node_modules/@types/node/web-globals/storage.d.ts +24 -0
- package/vendor/ink/node_modules/@types/node/web-globals/streams.d.ts +115 -0
- package/vendor/ink/node_modules/@types/node/web-globals/timers.d.ts +44 -0
- package/vendor/ink/node_modules/@types/node/web-globals/url.d.ts +24 -0
- package/vendor/ink/node_modules/@types/node/worker_threads.d.ts +717 -0
- package/vendor/ink/node_modules/@types/node/zlib.d.ts +618 -0
- package/vendor/ink/node_modules/node-pty/LICENSE +69 -0
- package/vendor/ink/node_modules/node-pty/README.md +164 -0
- package/vendor/ink/node_modules/node-pty/binding.gyp +150 -0
- package/vendor/ink/node_modules/node-pty/lib/conpty_console_list_agent.js +25 -0
- package/vendor/ink/node_modules/node-pty/lib/eventEmitter2.js +47 -0
- package/vendor/ink/node_modules/node-pty/lib/index.js +52 -0
- package/vendor/ink/node_modules/node-pty/lib/interfaces.js +7 -0
- package/vendor/ink/node_modules/node-pty/lib/shared/conout.js +11 -0
- package/vendor/ink/node_modules/node-pty/lib/terminal.js +190 -0
- package/vendor/ink/node_modules/node-pty/lib/types.js +7 -0
- package/vendor/ink/node_modules/node-pty/lib/unixTerminal.js +349 -0
- package/vendor/ink/node_modules/node-pty/lib/utils.js +39 -0
- package/vendor/ink/node_modules/node-pty/lib/windowsConoutConnection.js +125 -0
- package/vendor/ink/node_modules/node-pty/lib/windowsPtyAgent.js +287 -0
- package/vendor/ink/node_modules/node-pty/lib/windowsTerminal.js +201 -0
- package/vendor/ink/node_modules/node-pty/lib/worker/conoutSocketWorker.js +22 -0
- package/vendor/ink/node_modules/node-pty/package.json +65 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/darwin-x64/pty.node +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/linux-arm64/pty.node +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/linux-x64/pty.node +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty.pdb +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.pdb +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty/conpty.dll +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty.node +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty.pdb +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
- package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.pdb +0 -0
- package/vendor/ink/node_modules/node-pty/scripts/post-install.js +76 -0
- package/vendor/ink/node_modules/node-pty/scripts/prebuild.js +34 -0
- package/vendor/ink/node_modules/node-pty/src/unix/pty.cc +875 -0
- package/vendor/ink/node_modules/node-pty/src/unix/spawn-helper.cc +23 -0
- package/vendor/ink/node_modules/node-pty/src/win/conpty.cc +582 -0
- package/vendor/ink/node_modules/node-pty/src/win/conpty.h +41 -0
- package/vendor/ink/node_modules/node-pty/src/win/conpty_console_list.cc +44 -0
- package/vendor/ink/node_modules/node-pty/src/win/path_util.cc +95 -0
- package/vendor/ink/node_modules/node-pty/src/win/path_util.h +26 -0
- package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-arm64/OpenConsole.exe +0 -0
- package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-arm64/conpty.dll +0 -0
- package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-x64/OpenConsole.exe +0 -0
- package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-x64/conpty.dll +0 -0
- package/vendor/ink/node_modules/node-pty/typings/node-pty.d.ts +215 -0
- package/vendor/ink/node_modules/undici-types/LICENSE +21 -0
- package/vendor/ink/node_modules/undici-types/README.md +6 -0
- package/vendor/ink/node_modules/undici-types/agent.d.ts +32 -0
- package/vendor/ink/node_modules/undici-types/api.d.ts +43 -0
- package/vendor/ink/node_modules/undici-types/balanced-pool.d.ts +30 -0
- package/vendor/ink/node_modules/undici-types/cache-interceptor.d.ts +173 -0
- package/vendor/ink/node_modules/undici-types/cache.d.ts +36 -0
- package/vendor/ink/node_modules/undici-types/client-stats.d.ts +15 -0
- package/vendor/ink/node_modules/undici-types/client.d.ts +108 -0
- package/vendor/ink/node_modules/undici-types/connector.d.ts +34 -0
- package/vendor/ink/node_modules/undici-types/content-type.d.ts +21 -0
- package/vendor/ink/node_modules/undici-types/cookies.d.ts +30 -0
- package/vendor/ink/node_modules/undici-types/diagnostics-channel.d.ts +74 -0
- package/vendor/ink/node_modules/undici-types/dispatcher.d.ts +276 -0
- package/vendor/ink/node_modules/undici-types/env-http-proxy-agent.d.ts +22 -0
- package/vendor/ink/node_modules/undici-types/errors.d.ts +161 -0
- package/vendor/ink/node_modules/undici-types/eventsource.d.ts +66 -0
- package/vendor/ink/node_modules/undici-types/fetch.d.ts +211 -0
- package/vendor/ink/node_modules/undici-types/formdata.d.ts +108 -0
- package/vendor/ink/node_modules/undici-types/global-dispatcher.d.ts +9 -0
- package/vendor/ink/node_modules/undici-types/global-origin.d.ts +7 -0
- package/vendor/ink/node_modules/undici-types/h2c-client.d.ts +73 -0
- package/vendor/ink/node_modules/undici-types/handlers.d.ts +15 -0
- package/vendor/ink/node_modules/undici-types/header.d.ts +160 -0
- package/vendor/ink/node_modules/undici-types/index.d.ts +88 -0
- package/vendor/ink/node_modules/undici-types/interceptors.d.ts +73 -0
- package/vendor/ink/node_modules/undici-types/mock-agent.d.ts +68 -0
- package/vendor/ink/node_modules/undici-types/mock-call-history.d.ts +111 -0
- package/vendor/ink/node_modules/undici-types/mock-client.d.ts +27 -0
- package/vendor/ink/node_modules/undici-types/mock-errors.d.ts +12 -0
- package/vendor/ink/node_modules/undici-types/mock-interceptor.d.ts +94 -0
- package/vendor/ink/node_modules/undici-types/mock-pool.d.ts +27 -0
- package/vendor/ink/node_modules/undici-types/package.json +55 -0
- package/vendor/ink/node_modules/undici-types/patch.d.ts +29 -0
- package/vendor/ink/node_modules/undici-types/pool-stats.d.ts +19 -0
- package/vendor/ink/node_modules/undici-types/pool.d.ts +41 -0
- package/vendor/ink/node_modules/undici-types/proxy-agent.d.ts +29 -0
- package/vendor/ink/node_modules/undici-types/readable.d.ts +68 -0
- package/vendor/ink/node_modules/undici-types/retry-agent.d.ts +8 -0
- package/vendor/ink/node_modules/undici-types/retry-handler.d.ts +125 -0
- package/vendor/ink/node_modules/undici-types/round-robin-pool.d.ts +41 -0
- package/vendor/ink/node_modules/undici-types/snapshot-agent.d.ts +109 -0
- package/vendor/ink/node_modules/undici-types/util.d.ts +18 -0
- package/vendor/ink/node_modules/undici-types/utility.d.ts +7 -0
- package/vendor/ink/node_modules/undici-types/webidl.d.ts +341 -0
- package/vendor/ink/node_modules/undici-types/websocket.d.ts +186 -0
- package/vendor/ink/package.json +201 -0
- package/vendor/ink/readme.md +2636 -0
- package/bin/swag-agent.js +0 -9
- package/dist/server/lib/pg-rate-limiter.d.ts +0 -21
- package/dist/server/lib/pg-rate-limiter.js +0 -86
|
@@ -8,679 +8,961 @@
|
|
|
8
8
|
* Consolidates: streaming, prompt caching, context management betas, compaction,
|
|
9
9
|
* loop detection, parallel tool execution, subagent delegation, retry, cost tracking.
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
import { LoopDetector, getContextManagement, getMaxOutputTokens, getThinkingConfig, addPromptCaching, estimateCostUsd, isRetryableError, sanitizeError, routeModel, resolveToolChoice, emitCostWarningIfNeeded, demoteSubagentModel, COMPACTION_TOTAL_BUDGET, DEFAULT_SESSION_COST_BUDGET_USD, AGENT_DEFAULTS } from "../../shared/agent-core.js";
|
|
12
13
|
import { processStreamWithCallbacks } from "../../shared/sse-parser.js";
|
|
13
14
|
import { MODELS } from "../../shared/constants.js";
|
|
14
15
|
import { dispatchTools, buildAssistantContent } from "../../shared/tool-dispatch.js";
|
|
15
16
|
import { getCachedToolDefs, getFullToolSchemas } from "../tool-router.js";
|
|
16
17
|
import { queueSpan, auditRowToSpan } from "./clickhouse-buffer.js";
|
|
17
|
-
import { DELEGATE_TASK_TOOL_DEF, runServerSubagent
|
|
18
|
+
import { DELEGATE_TASK_TOOL_DEF, runServerSubagent } from "./server-subagent.js";
|
|
18
19
|
import { handleTranscribe } from "../handlers/transcription.js";
|
|
19
20
|
import { preCompact } from "./compaction-service.js";
|
|
20
21
|
import { providerFailover } from "./provider-failover.js";
|
|
21
22
|
import { saveCheckpoint } from "./session-checkpoint.js";
|
|
22
23
|
import { createLogger } from "./logger.js";
|
|
23
24
|
const log = createLogger("agent-loop");
|
|
25
|
+
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// TYPES
|
|
28
|
+
// ============================================================================
|
|
29
|
+
|
|
30
|
+
// Re-export for consumers
|
|
31
|
+
|
|
24
32
|
// ============================================================================
|
|
25
33
|
// CONSTANTS
|
|
26
34
|
// ============================================================================
|
|
35
|
+
|
|
27
36
|
const MAX_RETRIES = 3;
|
|
28
37
|
const RETRY_BASE_DELAY_MS = 1000;
|
|
29
38
|
const DEFAULT_MAX_CONCURRENT_TOOLS = 7;
|
|
39
|
+
|
|
30
40
|
// ============================================================================
|
|
31
41
|
// TOOL CHOICE MAPPING — convert ToolChoice to provider-specific format
|
|
32
42
|
// ============================================================================
|
|
43
|
+
|
|
33
44
|
/**
|
|
34
45
|
* Map ToolChoice to Anthropic API `tool_choice` format.
|
|
35
46
|
* Returns undefined if tools should be omitted entirely.
|
|
36
47
|
*/
|
|
37
48
|
function mapToolChoiceForAnthropic(tc) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
if (tc === "auto") return {
|
|
50
|
+
toolChoice: {
|
|
51
|
+
type: "auto"
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
if (tc === "any") return {
|
|
55
|
+
toolChoice: {
|
|
56
|
+
type: "any"
|
|
46
57
|
}
|
|
47
|
-
|
|
58
|
+
};
|
|
59
|
+
if (tc === "none") return {
|
|
60
|
+
omitTools: true
|
|
61
|
+
};
|
|
62
|
+
if (typeof tc === "object" && tc.type === "tool") {
|
|
63
|
+
return {
|
|
64
|
+
toolChoice: {
|
|
65
|
+
type: "tool",
|
|
66
|
+
name: tc.name
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
toolChoice: {
|
|
72
|
+
type: "auto"
|
|
73
|
+
}
|
|
74
|
+
};
|
|
48
75
|
}
|
|
76
|
+
|
|
49
77
|
// ============================================================================
|
|
50
78
|
// UNIFIED AGENT LOOP
|
|
51
79
|
// ============================================================================
|
|
80
|
+
|
|
52
81
|
export async function runServerAgentLoop(opts) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
82
|
+
const {
|
|
83
|
+
anthropic,
|
|
84
|
+
model,
|
|
85
|
+
systemPrompt,
|
|
86
|
+
messages,
|
|
87
|
+
tools: inputTools,
|
|
88
|
+
maxTurns,
|
|
89
|
+
temperature,
|
|
90
|
+
enableDelegation = true,
|
|
91
|
+
enablePromptCaching = true,
|
|
92
|
+
enableStreaming = true,
|
|
93
|
+
enableModelRouting = true,
|
|
94
|
+
maxConcurrentTools = DEFAULT_MAX_CONCURRENT_TOOLS,
|
|
95
|
+
maxCostUsd: maxCostUsdOpt,
|
|
96
|
+
onText,
|
|
97
|
+
onToolStart,
|
|
98
|
+
onCitation,
|
|
99
|
+
documents,
|
|
100
|
+
clientDisconnected = {
|
|
101
|
+
value: false
|
|
102
|
+
},
|
|
103
|
+
startedAt = Date.now(),
|
|
104
|
+
maxDurationMs = 15 * 60 * 1000
|
|
105
|
+
} = opts;
|
|
106
|
+
|
|
107
|
+
// Resolve cost budget: context_config > explicit opt > env var > default
|
|
108
|
+
const ctxOverrides = opts.contextOverrides;
|
|
109
|
+
const envBudget = parseFloat(process.env.WHALE_COST_BUDGET_USD || "");
|
|
110
|
+
const maxCostUsd = ctxOverrides?.session_cost_budget_usd ?? maxCostUsdOpt ?? (isFinite(envBudget) ? envBudget : DEFAULT_SESSION_COST_BUDGET_USD);
|
|
111
|
+
|
|
112
|
+
// Resolve compaction budget from overrides (used for compaction exhaustion checks)
|
|
113
|
+
const effectiveCompactionTrigger = ctxOverrides?.compaction_trigger_tokens ?? 150_000;
|
|
114
|
+
const effectiveCompactionBudget = ctxOverrides?.compaction_total_budget ?? COMPACTION_TOTAL_BUDGET;
|
|
115
|
+
|
|
116
|
+
// Auto-inject delegate_task for all models (subagents always use Claude Haiku/Sonnet)
|
|
117
|
+
// activeTools is mutable — discover_tools adds to it during the session
|
|
118
|
+
const activeTools = [...inputTools];
|
|
119
|
+
if (enableDelegation) {
|
|
120
|
+
if (!activeTools.some(t => t.name === "delegate_task")) {
|
|
121
|
+
activeTools.push(DELEGATE_TASK_TOOL_DEF);
|
|
64
122
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Per-conversation tracking of discovered tools — accumulates tool names
|
|
126
|
+
// activated via discover_tools so they persist across turns within this session.
|
|
127
|
+
// If extendedTools were provided (from a previous session or pre-load), we
|
|
128
|
+
// don't inject them yet (that defeats lazy loading), but we keep the full
|
|
129
|
+
// list available for the executor to reference.
|
|
130
|
+
const discoveredToolNames = new Set();
|
|
131
|
+
|
|
132
|
+
// Alias for backward compat within this function
|
|
133
|
+
const tools = activeTools;
|
|
134
|
+
const loopDetector = new LoopDetector(opts.loopDetectorConfig);
|
|
135
|
+
|
|
136
|
+
// Model routing: extract first user message for complexity estimation
|
|
137
|
+
const firstUserMsg = messages.find(m => m.role === "user");
|
|
138
|
+
const firstUserText = firstUserMsg ? typeof firstUserMsg.content === "string" ? firstUserMsg.content : Array.isArray(firstUserMsg.content) ? firstUserMsg.content.filter(b => b.type === "text" && b.text).map(b => b.text).join(" ") : "" : "";
|
|
139
|
+
|
|
140
|
+
// Pre-computed tool defs — reused across turns, only rebuilt when tools array changes
|
|
141
|
+
let cachedToolDefsForSession = getCachedToolDefs(tools);
|
|
142
|
+
let lastToolCount = tools.length;
|
|
143
|
+
|
|
144
|
+
// Accumulators
|
|
145
|
+
let turnCount = 0;
|
|
146
|
+
let toolCallCount = 0;
|
|
147
|
+
let totalIn = 0;
|
|
148
|
+
let totalOut = 0;
|
|
149
|
+
let cacheCreationTokens = 0;
|
|
150
|
+
let cacheReadTokens = 0;
|
|
151
|
+
let sessionCostUsd = 0;
|
|
152
|
+
let compactionCount = 0;
|
|
153
|
+
let consecutiveCompactions = 0;
|
|
154
|
+
let finalResponse = "";
|
|
155
|
+
let lastStopReason = "end_turn";
|
|
156
|
+
const allTextResponses = [];
|
|
157
|
+
const allToolNames = [];
|
|
158
|
+
const allCitations = [];
|
|
159
|
+
const turnMetrics = [];
|
|
160
|
+
const costWarningsEmitted = new Set();
|
|
161
|
+
while (turnCount < maxTurns) {
|
|
162
|
+
// Abort checks
|
|
163
|
+
if (clientDisconnected.value) {
|
|
164
|
+
log.info("client disconnected, stopping");
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
if (Date.now() - startedAt > maxDurationMs) {
|
|
168
|
+
onText?.("[Request timeout exceeded]");
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
// Cost budget enforcement — prevent runaway spending (skip if unlimited)
|
|
172
|
+
if (isFinite(maxCostUsd) && sessionCostUsd >= maxCostUsd) {
|
|
173
|
+
log.warn({
|
|
174
|
+
sessionCostUsd,
|
|
175
|
+
maxCostUsd
|
|
176
|
+
}, "cost budget exceeded");
|
|
177
|
+
onText?.(`\n[Session cost budget reached ($${sessionCostUsd.toFixed(2)}/$${maxCostUsd.toFixed(2)}). Wrapping up.]`);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
turnCount++;
|
|
181
|
+
loopDetector.resetTurn();
|
|
182
|
+
|
|
183
|
+
// Route model on the FIRST turn only — subsequent turns use the requested model
|
|
184
|
+
// since the conversation may have become complex after tool results.
|
|
185
|
+
// enableModelRouting=false prevents downgrade (e.g. Opus agents that should stay Opus)
|
|
186
|
+
const effectiveModel = turnCount === 1 && enableModelRouting ? routeModel(firstUserText, model) : model;
|
|
187
|
+
if (turnCount === 1 && effectiveModel !== model) {
|
|
188
|
+
log.info({
|
|
189
|
+
from: model,
|
|
190
|
+
to: effectiveModel
|
|
191
|
+
}, "model routed");
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Per-turn model config — uses effectiveModel so routed models get correct settings
|
|
195
|
+
const maxTokens = opts.maxTokens ?? getMaxOutputTokens(effectiveModel);
|
|
196
|
+
const ctxMgmt = getContextManagement(effectiveModel, opts.contextOverrides);
|
|
197
|
+
const thinkingCfg = getThinkingConfig(effectiveModel, true);
|
|
198
|
+
|
|
199
|
+
// Prepare tool definitions — use pre-computed cache, only rebuild when tools change
|
|
200
|
+
// (discover_tools can add tools mid-session, detected via length change)
|
|
201
|
+
if (tools.length !== lastToolCount) {
|
|
202
|
+
cachedToolDefsForSession = getCachedToolDefs(tools);
|
|
203
|
+
lastToolCount = tools.length;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Pre-compaction: mechanically strip redundant data before LLM call
|
|
207
|
+
// Runs every turn but only modifies messages when there's significant bloat
|
|
208
|
+
const {
|
|
209
|
+
messages: preCompacted,
|
|
210
|
+
bytesRemoved
|
|
211
|
+
} = preCompact(messages);
|
|
212
|
+
if (bytesRemoved > 10000) {
|
|
213
|
+
log.info({
|
|
214
|
+
bytesRemoved,
|
|
215
|
+
bytesRemovedKB: Math.round(bytesRemoved / 1024)
|
|
216
|
+
}, "pre-compaction applied");
|
|
217
|
+
// Replace messages in-place so the outer array reference stays valid
|
|
218
|
+
messages.length = 0;
|
|
219
|
+
messages.push(...preCompacted);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Prompt caching: tools + turn boundary
|
|
223
|
+
let finalToolDefs = cachedToolDefsForSession;
|
|
224
|
+
let finalMessages = messages;
|
|
225
|
+
if (enablePromptCaching) {
|
|
226
|
+
const cached = addPromptCaching(cachedToolDefsForSession, messages);
|
|
227
|
+
finalToolDefs = cached.tools;
|
|
228
|
+
finalMessages = cached.messages;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// System prompt: cached block + dynamic cost context (skip cost line if unlimited budget)
|
|
232
|
+
const costContext = isFinite(maxCostUsd) ? `Session cost: $${sessionCostUsd.toFixed(2)} / $${maxCostUsd.toFixed(2)}` : `Session cost: $${sessionCostUsd.toFixed(2)}`;
|
|
233
|
+
const system = enablePromptCaching ? [{
|
|
234
|
+
type: "text",
|
|
235
|
+
text: systemPrompt,
|
|
236
|
+
cache_control: {
|
|
237
|
+
type: "ephemeral"
|
|
238
|
+
}
|
|
239
|
+
}, {
|
|
240
|
+
type: "text",
|
|
241
|
+
text: costContext
|
|
242
|
+
}] : [{
|
|
243
|
+
type: "text",
|
|
244
|
+
text: systemPrompt
|
|
245
|
+
}, {
|
|
246
|
+
type: "text",
|
|
247
|
+
text: costContext
|
|
248
|
+
}];
|
|
249
|
+
|
|
250
|
+
// Resolve tool_choice for this turn
|
|
251
|
+
const recentToolUses = turnMetrics.slice(-3).flatMap(t => t.toolsUsed);
|
|
252
|
+
let resolvedToolChoice = resolveToolChoice({
|
|
253
|
+
toolChoice: opts.toolChoice,
|
|
254
|
+
turnCount,
|
|
255
|
+
recentToolUses,
|
|
256
|
+
availableToolNames: tools.map(t => t.name),
|
|
257
|
+
userMessage: firstUserText
|
|
258
|
+
});
|
|
259
|
+
// Anthropic API: forced tool_choice ("any" or specific tool) is incompatible with thinking — downgrade to "auto"
|
|
260
|
+
if (thinkingCfg.thinking.type !== "disabled" && resolvedToolChoice !== "auto" && resolvedToolChoice !== "none") {
|
|
261
|
+
resolvedToolChoice = "auto";
|
|
262
|
+
}
|
|
263
|
+
const {
|
|
264
|
+
toolChoice: anthropicToolChoice,
|
|
265
|
+
omitTools
|
|
266
|
+
} = mapToolChoiceForAnthropic(resolvedToolChoice);
|
|
267
|
+
if (omitTools) {
|
|
268
|
+
log.info({
|
|
269
|
+
turn: turnCount,
|
|
270
|
+
resolvedToolChoice
|
|
271
|
+
}, "tool_choice=none — omitting tools");
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Provider failover check — route to healthy provider (capability-aware)
|
|
275
|
+
const failoverResult = providerFailover.getActiveProvider(effectiveModel, opts.requiredCapabilities);
|
|
276
|
+
const activeModel = failoverResult.model;
|
|
277
|
+
const activeProvider = failoverResult.provider;
|
|
278
|
+
let turnFailoverInfo;
|
|
279
|
+
if (failoverResult.failedOver) {
|
|
280
|
+
turnFailoverInfo = {
|
|
281
|
+
originalProvider: failoverResult.originalProvider,
|
|
282
|
+
activeProvider: failoverResult.provider,
|
|
283
|
+
model: failoverResult.model
|
|
284
|
+
};
|
|
285
|
+
// Re-compute model config for the failover model
|
|
286
|
+
// (context management, thinking, max tokens may differ)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// API call with retry
|
|
290
|
+
if (enableStreaming) {
|
|
291
|
+
// ---- STREAMING PATH ----
|
|
292
|
+
let stream = null;
|
|
293
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
294
|
+
try {
|
|
295
|
+
// Cast through unknown: context_management.edits is Record<string, unknown>[]
|
|
296
|
+
// from getContextManagement() but SDK expects specific edit union types
|
|
297
|
+
const streamBetas = [...ctxMgmt.betas];
|
|
298
|
+
if (thinkingCfg.beta) streamBetas.push(thinkingCfg.beta);
|
|
299
|
+
// Citations API: add beta when source documents are provided
|
|
300
|
+
if (documents?.length && !streamBetas.includes("citations-2025-04-15")) {
|
|
301
|
+
streamBetas.push("citations-2025-04-15");
|
|
302
|
+
}
|
|
303
|
+
stream = await anthropic.beta.messages.create({
|
|
304
|
+
model: activeModel,
|
|
305
|
+
max_tokens: maxTokens,
|
|
306
|
+
temperature: thinkingCfg.thinking.type !== "disabled" ? 1 : temperature,
|
|
307
|
+
system,
|
|
308
|
+
...(omitTools ? {} : {
|
|
309
|
+
tools: finalToolDefs
|
|
310
|
+
}),
|
|
311
|
+
...(anthropicToolChoice && !omitTools ? {
|
|
312
|
+
tool_choice: anthropicToolChoice
|
|
313
|
+
} : {}),
|
|
314
|
+
messages: finalMessages,
|
|
315
|
+
stream: true,
|
|
316
|
+
thinking: thinkingCfg.thinking,
|
|
317
|
+
betas: streamBetas,
|
|
318
|
+
context_management: ctxMgmt.config,
|
|
319
|
+
...(documents?.length ? {
|
|
320
|
+
documents
|
|
321
|
+
} : {})
|
|
322
|
+
});
|
|
323
|
+
providerFailover.recordSuccess(activeProvider);
|
|
324
|
+
break;
|
|
325
|
+
} catch (err) {
|
|
326
|
+
providerFailover.recordFailure(activeProvider);
|
|
327
|
+
if (attempt < MAX_RETRIES && isRetryableError(err)) {
|
|
328
|
+
const delay = RETRY_BASE_DELAY_MS * Math.pow(2, attempt);
|
|
329
|
+
log.warn({
|
|
330
|
+
attempt: attempt + 1,
|
|
331
|
+
maxRetries: MAX_RETRIES,
|
|
332
|
+
delayMs: delay,
|
|
333
|
+
err: sanitizeError(err)
|
|
334
|
+
}, "retrying API call");
|
|
335
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
throw err;
|
|
149
339
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
340
|
+
}
|
|
341
|
+
if (!stream) throw new Error("Failed to get response after retries");
|
|
342
|
+
|
|
343
|
+
// Process stream events via unified parser
|
|
344
|
+
const streamResult = await processStreamWithCallbacks(stream, {
|
|
345
|
+
onText,
|
|
346
|
+
onToolStart,
|
|
347
|
+
onCitation
|
|
348
|
+
});
|
|
349
|
+
const currentText = streamResult.text;
|
|
350
|
+
const toolUseBlocks = streamResult.toolUseBlocks;
|
|
351
|
+
const compactionContent = streamResult.compactionContent;
|
|
352
|
+
|
|
353
|
+
// Accumulate citations from this turn
|
|
354
|
+
if (streamResult.citations.length > 0) {
|
|
355
|
+
allCitations.push(...streamResult.citations);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Accumulate per-turn tokens into session totals
|
|
359
|
+
const turnIn = streamResult.usage.inputTokens;
|
|
360
|
+
const turnOut = streamResult.usage.outputTokens;
|
|
361
|
+
const turnCacheRead = streamResult.usage.cacheReadTokens;
|
|
362
|
+
const turnCacheCreation = streamResult.usage.cacheCreationTokens;
|
|
363
|
+
totalIn += turnIn;
|
|
364
|
+
totalOut += turnOut;
|
|
365
|
+
cacheCreationTokens += turnCacheCreation;
|
|
366
|
+
cacheReadTokens += turnCacheRead;
|
|
367
|
+
|
|
368
|
+
// Update cost (include cache tokens for accurate pricing)
|
|
369
|
+
sessionCostUsd = estimateCostUsd(totalIn, totalOut, model, 0, cacheReadTokens, cacheCreationTokens);
|
|
370
|
+
|
|
371
|
+
// Graduated cost warnings — give the LLM visibility into spend
|
|
372
|
+
emitCostWarningIfNeeded(sessionCostUsd, maxCostUsd, costWarningsEmitted, onText);
|
|
373
|
+
|
|
374
|
+
// Record per-turn metrics for observability
|
|
375
|
+
const turnToolNames = toolUseBlocks.map(b => b.name);
|
|
376
|
+
turnMetrics.push({
|
|
377
|
+
turn: turnCount,
|
|
378
|
+
inputTokens: turnIn,
|
|
379
|
+
outputTokens: turnOut,
|
|
380
|
+
cacheRead: turnCacheRead,
|
|
381
|
+
cacheCreation: turnCacheCreation,
|
|
382
|
+
toolsUsed: turnToolNames,
|
|
383
|
+
costUsd: estimateCostUsd(turnIn, turnOut, model, 0, turnCacheRead, turnCacheCreation),
|
|
384
|
+
...(turnFailoverInfo ? {
|
|
385
|
+
failover: turnFailoverInfo
|
|
386
|
+
} : {})
|
|
387
|
+
});
|
|
388
|
+
if (currentText) allTextResponses.push(currentText);
|
|
389
|
+
|
|
390
|
+
// Compaction handling — API paused after generating summary.
|
|
391
|
+
// Preserve last 2 messages (1 user + 1 assistant turn) for continuity,
|
|
392
|
+
// then resume. This is NOT a new turn — just context compression.
|
|
393
|
+
lastStopReason = streamResult.stopReason || "end_turn";
|
|
394
|
+
if (streamResult.stopReason === "compaction" && compactionContent) {
|
|
395
|
+
compactionCount++;
|
|
396
|
+
consecutiveCompactions++;
|
|
397
|
+
log.info({
|
|
398
|
+
compactionCount,
|
|
399
|
+
consecutiveCompactions
|
|
400
|
+
}, "compaction — rebuilding context from summary");
|
|
401
|
+
|
|
402
|
+
// Circuit breaker + budget enforcement
|
|
403
|
+
const MAX_CONSECUTIVE_COMPACTIONS = 3;
|
|
404
|
+
const shouldWrapUp = consecutiveCompactions > MAX_CONSECUTIVE_COMPACTIONS || compactionCount * effectiveCompactionTrigger >= effectiveCompactionBudget;
|
|
405
|
+
if (shouldWrapUp) {
|
|
406
|
+
log.warn({
|
|
407
|
+
compactionCount,
|
|
408
|
+
consecutiveCompactions,
|
|
409
|
+
triggerTokens: effectiveCompactionTrigger
|
|
410
|
+
}, "compaction wrap-up triggered");
|
|
411
|
+
onText?.(consecutiveCompactions > MAX_CONSECUTIVE_COMPACTIONS ? "\n[Compaction loop detected — wrapping up.]" : "\n[Context budget reached — wrapping up.]");
|
|
157
412
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
:
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
413
|
+
const compactedMessages = [{
|
|
414
|
+
role: "assistant",
|
|
415
|
+
content: [{
|
|
416
|
+
type: "compaction",
|
|
417
|
+
content: compactionContent
|
|
418
|
+
}]
|
|
419
|
+
}, {
|
|
420
|
+
role: "user",
|
|
421
|
+
content: [{
|
|
422
|
+
type: "text",
|
|
423
|
+
text: shouldWrapUp ? "You have reached the context budget. Please wrap up your current work and provide a final summary of what was accomplished and what remains." : "Continue with your task."
|
|
424
|
+
}]
|
|
425
|
+
}];
|
|
426
|
+
messages.length = 0;
|
|
427
|
+
messages.push(...compactedMessages);
|
|
428
|
+
turnCount--; // Don't count compaction as a turn
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// No tool calls — check if truncated at max_tokens
|
|
433
|
+
if (toolUseBlocks.length === 0) {
|
|
434
|
+
if (streamResult.stopReason === "max_tokens") {
|
|
435
|
+
const assistantContent = buildAssistantContent({
|
|
436
|
+
text: currentText,
|
|
437
|
+
toolUseBlocks: [],
|
|
438
|
+
compactionContent
|
|
439
|
+
});
|
|
440
|
+
messages.push({
|
|
441
|
+
role: "assistant",
|
|
442
|
+
content: assistantContent
|
|
443
|
+
});
|
|
444
|
+
messages.push({
|
|
445
|
+
role: "user",
|
|
446
|
+
content: [{
|
|
447
|
+
type: "text",
|
|
448
|
+
text: "[Your response was truncated due to length. Please continue where you left off.]"
|
|
449
|
+
}]
|
|
450
|
+
});
|
|
451
|
+
continue;
|
|
183
452
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
453
|
+
finalResponse = currentText;
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Reset — model is making progress (tool calls)
|
|
458
|
+
consecutiveCompactions = 0;
|
|
459
|
+
|
|
460
|
+
// Execute tools and build messages for next turn
|
|
461
|
+
const subagentTokens = {
|
|
462
|
+
input: 0,
|
|
463
|
+
output: 0,
|
|
464
|
+
costUsd: 0
|
|
465
|
+
};
|
|
466
|
+
const executor = makeToolExecutor(opts, tools, allToolNames, subagentTokens, discoveredToolNames);
|
|
467
|
+
const {
|
|
468
|
+
results: toolResults
|
|
469
|
+
} = await dispatchTools(toolUseBlocks, executor, {
|
|
470
|
+
loopDetector,
|
|
471
|
+
maxConcurrent: maxConcurrentTools,
|
|
472
|
+
batchErrorLimit: opts.batchErrorLimit ?? AGENT_DEFAULTS.loopBatchErrorLimit,
|
|
473
|
+
// maxResultChars removed — Anthropic context_management handles limits
|
|
474
|
+
transcribeAudio: opts.storeId ? async (base64, mediaType) => {
|
|
475
|
+
const result = await handleTranscribe(opts.supabase, opts.storeId, base64, mediaType);
|
|
476
|
+
if (!result.success || !result.transcript) {
|
|
477
|
+
throw new Error(result.error || "Transcription returned no transcript");
|
|
478
|
+
}
|
|
479
|
+
return result.transcript;
|
|
480
|
+
} : undefined
|
|
481
|
+
});
|
|
482
|
+
toolCallCount += toolUseBlocks.length;
|
|
483
|
+
|
|
484
|
+
// Aggregate subagent tokens into parent totals
|
|
485
|
+
totalIn += subagentTokens.input;
|
|
486
|
+
totalOut += subagentTokens.output;
|
|
487
|
+
sessionCostUsd = estimateCostUsd(totalIn, totalOut, model, 0, cacheReadTokens, cacheCreationTokens) + subagentTokens.costUsd;
|
|
488
|
+
|
|
489
|
+
// Cost warnings after subagent aggregation (subagents can be expensive)
|
|
490
|
+
emitCostWarningIfNeeded(sessionCostUsd, maxCostUsd, costWarningsEmitted, onText);
|
|
491
|
+
const assistantContent = buildAssistantContent({
|
|
492
|
+
text: currentText,
|
|
493
|
+
toolUseBlocks,
|
|
494
|
+
compactionContent
|
|
495
|
+
});
|
|
496
|
+
messages.push({
|
|
497
|
+
role: "assistant",
|
|
498
|
+
content: assistantContent
|
|
499
|
+
});
|
|
500
|
+
messages.push({
|
|
501
|
+
role: "user",
|
|
502
|
+
content: toolResults
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// Session checkpoint — fire-and-forget, never blocks the loop
|
|
506
|
+
if (opts.conversationId) {
|
|
507
|
+
saveCheckpoint(opts.supabase, opts.conversationId, turnCount, messages, {
|
|
508
|
+
input: totalIn,
|
|
509
|
+
output: totalOut,
|
|
510
|
+
cacheRead: cacheReadTokens,
|
|
511
|
+
cacheCreation: cacheCreationTokens
|
|
512
|
+
}, sessionCostUsd, allToolNames).catch(() => {}); // swallow — saveCheckpoint already logs internally
|
|
513
|
+
}
|
|
514
|
+
} else {
|
|
515
|
+
// ---- NON-STREAMING PATH ----
|
|
516
|
+
let response = null;
|
|
517
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
518
|
+
try {
|
|
519
|
+
// Cast through unknown: context_management.edits is Record<string, unknown>[]
|
|
520
|
+
// from getContextManagement() but SDK expects specific edit union types
|
|
521
|
+
const nsBetas = [...ctxMgmt.betas];
|
|
522
|
+
if (thinkingCfg.beta) nsBetas.push(thinkingCfg.beta);
|
|
523
|
+
// Citations API: add beta when source documents are provided
|
|
524
|
+
if (documents?.length && !nsBetas.includes("citations-2025-04-15")) {
|
|
525
|
+
nsBetas.push("citations-2025-04-15");
|
|
526
|
+
}
|
|
527
|
+
response = await anthropic.beta.messages.create({
|
|
528
|
+
model: activeModel,
|
|
529
|
+
max_tokens: maxTokens,
|
|
530
|
+
temperature: thinkingCfg.thinking.type !== "disabled" ? 1 : temperature,
|
|
531
|
+
system,
|
|
532
|
+
...(omitTools ? {} : {
|
|
533
|
+
tools: finalToolDefs
|
|
534
|
+
}),
|
|
535
|
+
...(anthropicToolChoice && !omitTools ? {
|
|
536
|
+
tool_choice: anthropicToolChoice
|
|
537
|
+
} : {}),
|
|
538
|
+
messages: finalMessages,
|
|
539
|
+
thinking: thinkingCfg.thinking,
|
|
540
|
+
betas: nsBetas,
|
|
541
|
+
context_management: ctxMgmt.config,
|
|
542
|
+
...(documents?.length ? {
|
|
543
|
+
documents
|
|
544
|
+
} : {})
|
|
545
|
+
});
|
|
546
|
+
providerFailover.recordSuccess(activeProvider);
|
|
547
|
+
break;
|
|
548
|
+
} catch (err) {
|
|
549
|
+
providerFailover.recordFailure(activeProvider);
|
|
550
|
+
if (attempt < MAX_RETRIES && isRetryableError(err)) {
|
|
551
|
+
const delay = RETRY_BASE_DELAY_MS * Math.pow(2, attempt);
|
|
552
|
+
log.warn({
|
|
553
|
+
attempt: attempt + 1,
|
|
554
|
+
maxRetries: MAX_RETRIES,
|
|
555
|
+
delayMs: delay,
|
|
556
|
+
err: sanitizeError(err)
|
|
557
|
+
}, "retrying API call");
|
|
558
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
throw err;
|
|
187
562
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
563
|
+
}
|
|
564
|
+
if (!response) throw new Error("Failed to get response after retries");
|
|
565
|
+
|
|
566
|
+
// Track tokens
|
|
567
|
+
const nsTurnIn = response.usage?.input_tokens || 0;
|
|
568
|
+
const nsTurnOut = response.usage?.output_tokens || 0;
|
|
569
|
+
const nsTurnCacheCreation = response.usage?.cache_creation_input_tokens ?? 0;
|
|
570
|
+
const nsTurnCacheRead = response.usage?.cache_read_input_tokens ?? 0;
|
|
571
|
+
totalIn += nsTurnIn;
|
|
572
|
+
totalOut += nsTurnOut;
|
|
573
|
+
cacheCreationTokens += nsTurnCacheCreation;
|
|
574
|
+
cacheReadTokens += nsTurnCacheRead;
|
|
575
|
+
|
|
576
|
+
// Extract text, tool_use, cite, and compaction blocks
|
|
577
|
+
let currentText = "";
|
|
578
|
+
let nsCompactionContent = null;
|
|
579
|
+
const toolUseBlocks = [];
|
|
580
|
+
for (const block of response.content) {
|
|
581
|
+
if (block.type === "text") {
|
|
582
|
+
currentText += block.text;
|
|
583
|
+
onText?.(block.text);
|
|
584
|
+
} else if (block.type === "tool_use") {
|
|
585
|
+
toolUseBlocks.push({
|
|
586
|
+
id: block.id,
|
|
587
|
+
name: block.name,
|
|
588
|
+
input: block.input
|
|
589
|
+
});
|
|
590
|
+
onToolStart?.(block.name, block.input);
|
|
591
|
+
} else if (block.type === "cite") {
|
|
592
|
+
const citeBlock = block;
|
|
593
|
+
const citation = {
|
|
594
|
+
type: "cite",
|
|
595
|
+
cited_text: citeBlock.cited_text ?? "",
|
|
596
|
+
document_index: citeBlock.document_index ?? 0,
|
|
597
|
+
start_char_index: citeBlock.start_char_index ?? 0,
|
|
598
|
+
end_char_index: citeBlock.end_char_index ?? 0,
|
|
599
|
+
...(citeBlock.document_title ? {
|
|
600
|
+
document_title: citeBlock.document_title
|
|
601
|
+
} : {})
|
|
602
|
+
};
|
|
603
|
+
allCitations.push(citation);
|
|
604
|
+
onCitation?.(citation);
|
|
605
|
+
} else if (block.type === "compaction") {
|
|
606
|
+
nsCompactionContent = block.content || "";
|
|
201
607
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
log.warn({ attempt: attempt + 1, maxRetries: MAX_RETRIES, delayMs: delay, err: sanitizeError(err) }, "retrying API call");
|
|
239
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
240
|
-
continue;
|
|
241
|
-
}
|
|
242
|
-
throw err;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
if (!stream)
|
|
246
|
-
throw new Error("Failed to get response after retries");
|
|
247
|
-
// Process stream events via unified parser
|
|
248
|
-
const streamResult = await processStreamWithCallbacks(stream, { onText, onToolStart, onCitation });
|
|
249
|
-
const currentText = streamResult.text;
|
|
250
|
-
const toolUseBlocks = streamResult.toolUseBlocks;
|
|
251
|
-
const compactionContent = streamResult.compactionContent;
|
|
252
|
-
// Accumulate citations from this turn
|
|
253
|
-
if (streamResult.citations.length > 0) {
|
|
254
|
-
allCitations.push(...streamResult.citations);
|
|
255
|
-
}
|
|
256
|
-
// Accumulate per-turn tokens into session totals
|
|
257
|
-
const turnIn = streamResult.usage.inputTokens;
|
|
258
|
-
const turnOut = streamResult.usage.outputTokens;
|
|
259
|
-
const turnCacheRead = streamResult.usage.cacheReadTokens;
|
|
260
|
-
const turnCacheCreation = streamResult.usage.cacheCreationTokens;
|
|
261
|
-
totalIn += turnIn;
|
|
262
|
-
totalOut += turnOut;
|
|
263
|
-
cacheCreationTokens += turnCacheCreation;
|
|
264
|
-
cacheReadTokens += turnCacheRead;
|
|
265
|
-
// Update cost (include cache tokens for accurate pricing)
|
|
266
|
-
sessionCostUsd = estimateCostUsd(totalIn, totalOut, model, 0, cacheReadTokens, cacheCreationTokens);
|
|
267
|
-
// Graduated cost warnings — give the LLM visibility into spend
|
|
268
|
-
emitCostWarningIfNeeded(sessionCostUsd, maxCostUsd, costWarningsEmitted, onText);
|
|
269
|
-
// Record per-turn metrics for observability
|
|
270
|
-
const turnToolNames = toolUseBlocks.map(b => b.name);
|
|
271
|
-
turnMetrics.push({
|
|
272
|
-
turn: turnCount,
|
|
273
|
-
inputTokens: turnIn,
|
|
274
|
-
outputTokens: turnOut,
|
|
275
|
-
cacheRead: turnCacheRead,
|
|
276
|
-
cacheCreation: turnCacheCreation,
|
|
277
|
-
toolsUsed: turnToolNames,
|
|
278
|
-
costUsd: estimateCostUsd(turnIn, turnOut, model, 0, turnCacheRead, turnCacheCreation),
|
|
279
|
-
...(turnFailoverInfo ? { failover: turnFailoverInfo } : {}),
|
|
280
|
-
});
|
|
281
|
-
if (currentText)
|
|
282
|
-
allTextResponses.push(currentText);
|
|
283
|
-
// Compaction handling — API paused after generating summary.
|
|
284
|
-
// Preserve last 2 messages (1 user + 1 assistant turn) for continuity,
|
|
285
|
-
// then resume. This is NOT a new turn — just context compression.
|
|
286
|
-
lastStopReason = streamResult.stopReason || "end_turn";
|
|
287
|
-
if (streamResult.stopReason === "compaction" && compactionContent) {
|
|
288
|
-
compactionCount++;
|
|
289
|
-
log.info({ compactionCount }, "compaction — preserving last 2 messages, resuming");
|
|
290
|
-
// Budget enforcement: if cumulative compaction cost exceeds budget, force wrap-up
|
|
291
|
-
if (compactionCount * COMPACTION_TRIGGER_TOKENS >= COMPACTION_TOTAL_BUDGET) {
|
|
292
|
-
log.warn({ compactionCount, triggerTokens: COMPACTION_TRIGGER_TOKENS, estimatedTokens: compactionCount * COMPACTION_TRIGGER_TOKENS }, "compaction budget exhausted");
|
|
293
|
-
onText?.("\n[Context budget reached — wrapping up.]");
|
|
294
|
-
// Rebuild messages: compaction summary + wrap-up instruction
|
|
295
|
-
const compactedMessages = [
|
|
296
|
-
{ role: "assistant", content: [{ type: "compaction", content: compactionContent }] },
|
|
297
|
-
{ role: "user", content: [{ type: "text", text: "You have reached the context budget. Please wrap up your current work and provide a final summary of what was accomplished and what remains." }] },
|
|
298
|
-
];
|
|
299
|
-
messages.length = 0;
|
|
300
|
-
messages.push(...compactedMessages);
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
// Normal compaction: preserve last 2 messages for continuity
|
|
304
|
-
const preserved = messages.slice(-2);
|
|
305
|
-
const compactedMessages = [
|
|
306
|
-
{ role: "assistant", content: [{ type: "compaction", content: compactionContent }] },
|
|
307
|
-
...preserved,
|
|
308
|
-
];
|
|
309
|
-
messages.length = 0;
|
|
310
|
-
messages.push(...compactedMessages);
|
|
311
|
-
turnCount--; // Don't count compaction as a turn
|
|
312
|
-
continue;
|
|
313
|
-
}
|
|
314
|
-
// No tool calls — check if truncated at max_tokens
|
|
315
|
-
if (toolUseBlocks.length === 0) {
|
|
316
|
-
if (streamResult.stopReason === "max_tokens") {
|
|
317
|
-
const assistantContent = buildAssistantContent({ text: currentText, toolUseBlocks: [], compactionContent });
|
|
318
|
-
messages.push({ role: "assistant", content: assistantContent });
|
|
319
|
-
messages.push({ role: "user", content: [{ type: "text", text: "[Your response was truncated due to length. Please continue where you left off.]" }] });
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
finalResponse = currentText;
|
|
323
|
-
break;
|
|
324
|
-
}
|
|
325
|
-
// Execute tools and build messages for next turn
|
|
326
|
-
const subagentTokens = { input: 0, output: 0, costUsd: 0 };
|
|
327
|
-
const executor = makeToolExecutor(opts, tools, allToolNames, subagentTokens, discoveredToolNames);
|
|
328
|
-
const { results: toolResults } = await dispatchTools(toolUseBlocks, executor, {
|
|
329
|
-
loopDetector,
|
|
330
|
-
maxConcurrent: maxConcurrentTools,
|
|
331
|
-
// maxResultChars removed — Anthropic context_management handles limits
|
|
332
|
-
transcribeAudio: opts.storeId
|
|
333
|
-
? async (base64, mediaType) => {
|
|
334
|
-
const result = await handleTranscribe(opts.supabase, opts.storeId, base64, mediaType);
|
|
335
|
-
if (!result.success || !result.transcript) {
|
|
336
|
-
throw new Error(result.error || "Transcription returned no transcript");
|
|
337
|
-
}
|
|
338
|
-
return result.transcript;
|
|
339
|
-
}
|
|
340
|
-
: undefined,
|
|
341
|
-
});
|
|
342
|
-
toolCallCount += toolUseBlocks.length;
|
|
343
|
-
// Aggregate subagent tokens into parent totals
|
|
344
|
-
totalIn += subagentTokens.input;
|
|
345
|
-
totalOut += subagentTokens.output;
|
|
346
|
-
sessionCostUsd = estimateCostUsd(totalIn, totalOut, model, 0, cacheReadTokens, cacheCreationTokens) + subagentTokens.costUsd;
|
|
347
|
-
// Cost warnings after subagent aggregation (subagents can be expensive)
|
|
348
|
-
emitCostWarningIfNeeded(sessionCostUsd, maxCostUsd, costWarningsEmitted, onText);
|
|
349
|
-
const assistantContent = buildAssistantContent({ text: currentText, toolUseBlocks, compactionContent });
|
|
350
|
-
messages.push({ role: "assistant", content: assistantContent });
|
|
351
|
-
messages.push({ role: "user", content: toolResults });
|
|
352
|
-
// Session checkpoint — fire-and-forget, never blocks the loop
|
|
353
|
-
if (opts.conversationId) {
|
|
354
|
-
saveCheckpoint(opts.supabase, opts.conversationId, turnCount, messages, { input: totalIn, output: totalOut, cacheRead: cacheReadTokens, cacheCreation: cacheCreationTokens }, sessionCostUsd, allToolNames).catch(() => { }); // swallow — saveCheckpoint already logs internally
|
|
355
|
-
}
|
|
608
|
+
}
|
|
609
|
+
sessionCostUsd = estimateCostUsd(totalIn, totalOut, model, 0, cacheReadTokens, cacheCreationTokens);
|
|
610
|
+
|
|
611
|
+
// Graduated cost warnings (non-streaming path)
|
|
612
|
+
emitCostWarningIfNeeded(sessionCostUsd, maxCostUsd, costWarningsEmitted, onText);
|
|
613
|
+
|
|
614
|
+
// Record per-turn metrics (non-streaming)
|
|
615
|
+
const nsTurnToolNames = toolUseBlocks.map(b => b.name);
|
|
616
|
+
turnMetrics.push({
|
|
617
|
+
turn: turnCount,
|
|
618
|
+
inputTokens: nsTurnIn,
|
|
619
|
+
outputTokens: nsTurnOut,
|
|
620
|
+
cacheRead: nsTurnCacheRead,
|
|
621
|
+
cacheCreation: nsTurnCacheCreation,
|
|
622
|
+
toolsUsed: nsTurnToolNames,
|
|
623
|
+
costUsd: estimateCostUsd(nsTurnIn, nsTurnOut, model, 0, nsTurnCacheRead, nsTurnCacheCreation),
|
|
624
|
+
...(turnFailoverInfo ? {
|
|
625
|
+
failover: turnFailoverInfo
|
|
626
|
+
} : {})
|
|
627
|
+
});
|
|
628
|
+
if (currentText) allTextResponses.push(currentText);
|
|
629
|
+
lastStopReason = response.stop_reason || "end_turn";
|
|
630
|
+
|
|
631
|
+
// Compaction handling (non-streaming) — same logic as streaming path
|
|
632
|
+
if (response.stop_reason === "compaction" && nsCompactionContent !== null) {
|
|
633
|
+
compactionCount++;
|
|
634
|
+
consecutiveCompactions++;
|
|
635
|
+
log.info({
|
|
636
|
+
compactionCount,
|
|
637
|
+
consecutiveCompactions,
|
|
638
|
+
streaming: false
|
|
639
|
+
}, "compaction — rebuilding context from summary");
|
|
640
|
+
const MAX_CONSECUTIVE_COMPACTIONS = 3;
|
|
641
|
+
const shouldWrapUp = consecutiveCompactions > MAX_CONSECUTIVE_COMPACTIONS || compactionCount * effectiveCompactionTrigger >= effectiveCompactionBudget;
|
|
642
|
+
if (shouldWrapUp) {
|
|
643
|
+
onText?.(consecutiveCompactions > MAX_CONSECUTIVE_COMPACTIONS ? "\n[Compaction loop detected — wrapping up.]" : "\n[Context budget reached — wrapping up.]");
|
|
356
644
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
throw err;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
if (!response)
|
|
399
|
-
throw new Error("Failed to get response after retries");
|
|
400
|
-
// Track tokens
|
|
401
|
-
const nsTurnIn = response.usage?.input_tokens || 0;
|
|
402
|
-
const nsTurnOut = response.usage?.output_tokens || 0;
|
|
403
|
-
const nsTurnCacheCreation = response.usage?.cache_creation_input_tokens ?? 0;
|
|
404
|
-
const nsTurnCacheRead = response.usage?.cache_read_input_tokens ?? 0;
|
|
405
|
-
totalIn += nsTurnIn;
|
|
406
|
-
totalOut += nsTurnOut;
|
|
407
|
-
cacheCreationTokens += nsTurnCacheCreation;
|
|
408
|
-
cacheReadTokens += nsTurnCacheRead;
|
|
409
|
-
// Extract text, tool_use, cite, and compaction blocks
|
|
410
|
-
let currentText = "";
|
|
411
|
-
let nsCompactionContent = null;
|
|
412
|
-
const toolUseBlocks = [];
|
|
413
|
-
for (const block of response.content) {
|
|
414
|
-
if (block.type === "text") {
|
|
415
|
-
currentText += block.text;
|
|
416
|
-
onText?.(block.text);
|
|
417
|
-
}
|
|
418
|
-
else if (block.type === "tool_use") {
|
|
419
|
-
toolUseBlocks.push({
|
|
420
|
-
id: block.id,
|
|
421
|
-
name: block.name,
|
|
422
|
-
input: block.input,
|
|
423
|
-
});
|
|
424
|
-
onToolStart?.(block.name, block.input);
|
|
425
|
-
}
|
|
426
|
-
else if (block.type === "cite") {
|
|
427
|
-
const citeBlock = block;
|
|
428
|
-
const citation = {
|
|
429
|
-
type: "cite",
|
|
430
|
-
cited_text: citeBlock.cited_text ?? "",
|
|
431
|
-
document_index: citeBlock.document_index ?? 0,
|
|
432
|
-
start_char_index: citeBlock.start_char_index ?? 0,
|
|
433
|
-
end_char_index: citeBlock.end_char_index ?? 0,
|
|
434
|
-
...(citeBlock.document_title ? { document_title: citeBlock.document_title } : {}),
|
|
435
|
-
};
|
|
436
|
-
allCitations.push(citation);
|
|
437
|
-
onCitation?.(citation);
|
|
438
|
-
}
|
|
439
|
-
else if (block.type === "compaction") {
|
|
440
|
-
nsCompactionContent = block.content || "";
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
sessionCostUsd = estimateCostUsd(totalIn, totalOut, model, 0, cacheReadTokens, cacheCreationTokens);
|
|
444
|
-
// Graduated cost warnings (non-streaming path)
|
|
445
|
-
emitCostWarningIfNeeded(sessionCostUsd, maxCostUsd, costWarningsEmitted, onText);
|
|
446
|
-
// Record per-turn metrics (non-streaming)
|
|
447
|
-
const nsTurnToolNames = toolUseBlocks.map(b => b.name);
|
|
448
|
-
turnMetrics.push({
|
|
449
|
-
turn: turnCount,
|
|
450
|
-
inputTokens: nsTurnIn,
|
|
451
|
-
outputTokens: nsTurnOut,
|
|
452
|
-
cacheRead: nsTurnCacheRead,
|
|
453
|
-
cacheCreation: nsTurnCacheCreation,
|
|
454
|
-
toolsUsed: nsTurnToolNames,
|
|
455
|
-
costUsd: estimateCostUsd(nsTurnIn, nsTurnOut, model, 0, nsTurnCacheRead, nsTurnCacheCreation),
|
|
456
|
-
...(turnFailoverInfo ? { failover: turnFailoverInfo } : {}),
|
|
457
|
-
});
|
|
458
|
-
if (currentText)
|
|
459
|
-
allTextResponses.push(currentText);
|
|
460
|
-
lastStopReason = response.stop_reason || "end_turn";
|
|
461
|
-
// Compaction handling (non-streaming) — same logic as streaming path
|
|
462
|
-
if (response.stop_reason === "compaction" && nsCompactionContent !== null) {
|
|
463
|
-
compactionCount++;
|
|
464
|
-
log.info({ compactionCount, streaming: false }, "compaction — preserving last 2 messages");
|
|
465
|
-
if (compactionCount * COMPACTION_TRIGGER_TOKENS >= COMPACTION_TOTAL_BUDGET) {
|
|
466
|
-
onText?.("\n[Context budget reached — wrapping up.]");
|
|
467
|
-
const compactedMessages = [
|
|
468
|
-
{ role: "assistant", content: [{ type: "compaction", content: nsCompactionContent }] },
|
|
469
|
-
{ role: "user", content: [{ type: "text", text: "You have reached the context budget. Please wrap up your current work and provide a final summary." }] },
|
|
470
|
-
];
|
|
471
|
-
messages.length = 0;
|
|
472
|
-
messages.push(...compactedMessages);
|
|
473
|
-
continue;
|
|
474
|
-
}
|
|
475
|
-
const preserved = messages.slice(-2);
|
|
476
|
-
const compactedMessages = [
|
|
477
|
-
{ role: "assistant", content: [{ type: "compaction", content: nsCompactionContent }] },
|
|
478
|
-
...preserved,
|
|
479
|
-
];
|
|
480
|
-
messages.length = 0;
|
|
481
|
-
messages.push(...compactedMessages);
|
|
482
|
-
turnCount--;
|
|
483
|
-
continue;
|
|
484
|
-
}
|
|
485
|
-
// No tool calls — check if truncated at max_tokens
|
|
486
|
-
if (toolUseBlocks.length === 0) {
|
|
487
|
-
if (response.stop_reason === "max_tokens") {
|
|
488
|
-
const assistantContent = buildAssistantContent({ text: currentText, toolUseBlocks: [] });
|
|
489
|
-
messages.push({ role: "assistant", content: assistantContent });
|
|
490
|
-
messages.push({ role: "user", content: [{ type: "text", text: "[Your response was truncated due to length. Please continue where you left off.]" }] });
|
|
491
|
-
continue;
|
|
492
|
-
}
|
|
493
|
-
finalResponse = currentText;
|
|
494
|
-
break;
|
|
495
|
-
}
|
|
496
|
-
// Execute tools
|
|
497
|
-
const nonStreamSubTokens = { input: 0, output: 0, costUsd: 0 };
|
|
498
|
-
const nsExecutor = makeToolExecutor(opts, tools, allToolNames, nonStreamSubTokens, discoveredToolNames);
|
|
499
|
-
const { results: toolResults } = await dispatchTools(toolUseBlocks, nsExecutor, {
|
|
500
|
-
loopDetector,
|
|
501
|
-
maxConcurrent: maxConcurrentTools,
|
|
502
|
-
// maxResultChars removed — Anthropic context_management handles limits
|
|
503
|
-
});
|
|
504
|
-
toolCallCount += toolUseBlocks.length;
|
|
505
|
-
// Aggregate subagent tokens into parent totals
|
|
506
|
-
totalIn += nonStreamSubTokens.input;
|
|
507
|
-
totalOut += nonStreamSubTokens.output;
|
|
508
|
-
sessionCostUsd = estimateCostUsd(totalIn, totalOut, model, 0, cacheReadTokens, cacheCreationTokens) + nonStreamSubTokens.costUsd;
|
|
509
|
-
// Cost warnings after subagent aggregation (non-streaming)
|
|
510
|
-
emitCostWarningIfNeeded(sessionCostUsd, maxCostUsd, costWarningsEmitted, onText);
|
|
511
|
-
const assistantContent = buildAssistantContent({ text: currentText, toolUseBlocks });
|
|
512
|
-
messages.push({ role: "assistant", content: assistantContent });
|
|
513
|
-
messages.push({ role: "user", content: toolResults });
|
|
514
|
-
// Session checkpoint — fire-and-forget, never blocks the loop
|
|
515
|
-
if (opts.conversationId) {
|
|
516
|
-
saveCheckpoint(opts.supabase, opts.conversationId, turnCount, messages, { input: totalIn, output: totalOut, cacheRead: cacheReadTokens, cacheCreation: cacheCreationTokens }, sessionCostUsd, allToolNames).catch(() => { }); // swallow — saveCheckpoint already logs internally
|
|
517
|
-
}
|
|
645
|
+
const compactedMessages = [{
|
|
646
|
+
role: "assistant",
|
|
647
|
+
content: [{
|
|
648
|
+
type: "compaction",
|
|
649
|
+
content: nsCompactionContent
|
|
650
|
+
}]
|
|
651
|
+
}, {
|
|
652
|
+
role: "user",
|
|
653
|
+
content: [{
|
|
654
|
+
type: "text",
|
|
655
|
+
text: shouldWrapUp ? "You have reached the context budget. Please wrap up your current work and provide a final summary." : "Continue with your task."
|
|
656
|
+
}]
|
|
657
|
+
}];
|
|
658
|
+
messages.length = 0;
|
|
659
|
+
messages.push(...compactedMessages);
|
|
660
|
+
turnCount--;
|
|
661
|
+
continue;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// No tool calls — check if truncated at max_tokens
|
|
665
|
+
if (toolUseBlocks.length === 0) {
|
|
666
|
+
if (response.stop_reason === "max_tokens") {
|
|
667
|
+
const assistantContent = buildAssistantContent({
|
|
668
|
+
text: currentText,
|
|
669
|
+
toolUseBlocks: []
|
|
670
|
+
});
|
|
671
|
+
messages.push({
|
|
672
|
+
role: "assistant",
|
|
673
|
+
content: assistantContent
|
|
674
|
+
});
|
|
675
|
+
messages.push({
|
|
676
|
+
role: "user",
|
|
677
|
+
content: [{
|
|
678
|
+
type: "text",
|
|
679
|
+
text: "[Your response was truncated due to length. Please continue where you left off.]"
|
|
680
|
+
}]
|
|
681
|
+
});
|
|
682
|
+
continue;
|
|
518
683
|
}
|
|
684
|
+
finalResponse = currentText;
|
|
685
|
+
break;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Reset — model is making progress (tool calls)
|
|
689
|
+
consecutiveCompactions = 0;
|
|
690
|
+
|
|
691
|
+
// Execute tools
|
|
692
|
+
const nonStreamSubTokens = {
|
|
693
|
+
input: 0,
|
|
694
|
+
output: 0,
|
|
695
|
+
costUsd: 0
|
|
696
|
+
};
|
|
697
|
+
const nsExecutor = makeToolExecutor(opts, tools, allToolNames, nonStreamSubTokens, discoveredToolNames);
|
|
698
|
+
const {
|
|
699
|
+
results: toolResults
|
|
700
|
+
} = await dispatchTools(toolUseBlocks, nsExecutor, {
|
|
701
|
+
loopDetector,
|
|
702
|
+
maxConcurrent: maxConcurrentTools,
|
|
703
|
+
batchErrorLimit: opts.batchErrorLimit ?? AGENT_DEFAULTS.loopBatchErrorLimit
|
|
704
|
+
// maxResultChars removed — Anthropic context_management handles limits
|
|
705
|
+
});
|
|
706
|
+
toolCallCount += toolUseBlocks.length;
|
|
707
|
+
|
|
708
|
+
// Aggregate subagent tokens into parent totals
|
|
709
|
+
totalIn += nonStreamSubTokens.input;
|
|
710
|
+
totalOut += nonStreamSubTokens.output;
|
|
711
|
+
sessionCostUsd = estimateCostUsd(totalIn, totalOut, model, 0, cacheReadTokens, cacheCreationTokens) + nonStreamSubTokens.costUsd;
|
|
712
|
+
|
|
713
|
+
// Cost warnings after subagent aggregation (non-streaming)
|
|
714
|
+
emitCostWarningIfNeeded(sessionCostUsd, maxCostUsd, costWarningsEmitted, onText);
|
|
715
|
+
const assistantContent = buildAssistantContent({
|
|
716
|
+
text: currentText,
|
|
717
|
+
toolUseBlocks
|
|
718
|
+
});
|
|
719
|
+
messages.push({
|
|
720
|
+
role: "assistant",
|
|
721
|
+
content: assistantContent
|
|
722
|
+
});
|
|
723
|
+
messages.push({
|
|
724
|
+
role: "user",
|
|
725
|
+
content: toolResults
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
// Session checkpoint — fire-and-forget, never blocks the loop
|
|
729
|
+
if (opts.conversationId) {
|
|
730
|
+
saveCheckpoint(opts.supabase, opts.conversationId, turnCount, messages, {
|
|
731
|
+
input: totalIn,
|
|
732
|
+
output: totalOut,
|
|
733
|
+
cacheRead: cacheReadTokens,
|
|
734
|
+
cacheCreation: cacheCreationTokens
|
|
735
|
+
}, sessionCostUsd, allToolNames).catch(() => {}); // swallow — saveCheckpoint already logs internally
|
|
736
|
+
}
|
|
519
737
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
738
|
+
}
|
|
739
|
+
const fullText = allTextResponses.join("\n\n") || finalResponse;
|
|
740
|
+
return {
|
|
741
|
+
finalText: fullText,
|
|
742
|
+
allTextResponses,
|
|
743
|
+
turnCount,
|
|
744
|
+
toolCallCount,
|
|
745
|
+
toolsUsed: [...new Set(allToolNames)],
|
|
746
|
+
tokens: {
|
|
747
|
+
input: totalIn,
|
|
748
|
+
output: totalOut,
|
|
749
|
+
cacheCreation: cacheCreationTokens,
|
|
750
|
+
cacheRead: cacheReadTokens
|
|
751
|
+
},
|
|
752
|
+
costUsd: sessionCostUsd,
|
|
753
|
+
loopDetectorStats: loopDetector.getSessionStats(),
|
|
754
|
+
turns: turnMetrics,
|
|
755
|
+
citations: allCitations,
|
|
756
|
+
stopReason: lastStopReason
|
|
757
|
+
};
|
|
539
758
|
}
|
|
759
|
+
|
|
540
760
|
// ============================================================================
|
|
541
761
|
// TOOL EXECUTOR FACTORY — creates executor for dispatchTools with delegation
|
|
542
762
|
// ============================================================================
|
|
763
|
+
|
|
543
764
|
function makeToolExecutor(opts, tools, allToolNames, subagentTokens, discoveredToolNames) {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
765
|
+
const {
|
|
766
|
+
anthropic,
|
|
767
|
+
supabase,
|
|
768
|
+
storeId,
|
|
769
|
+
traceId,
|
|
770
|
+
userId,
|
|
771
|
+
userEmail,
|
|
772
|
+
conversationId,
|
|
773
|
+
agentId,
|
|
774
|
+
executeTool,
|
|
775
|
+
onToolResult,
|
|
776
|
+
onToolProgress,
|
|
777
|
+
onSubagentProgress,
|
|
778
|
+
clientDisconnected = {
|
|
779
|
+
value: false
|
|
780
|
+
},
|
|
781
|
+
startedAt = Date.now(),
|
|
782
|
+
maxDurationMs = 15 * 60 * 1000
|
|
783
|
+
} = opts;
|
|
784
|
+
return async (name, input) => {
|
|
785
|
+
allToolNames.push(name);
|
|
786
|
+
|
|
787
|
+
// Subagent delegation — demote models to control cost (sub-agents should never run Opus)
|
|
788
|
+
if (name === "delegate_task") {
|
|
789
|
+
const subPrompt = String(input.prompt || "");
|
|
790
|
+
const subModel = demoteSubagentModel(input.model ? String(input.model) : undefined);
|
|
791
|
+
const defaultSubMaxTurns = opts.subagentMaxTurns ?? AGENT_DEFAULTS.subagentMaxTurns;
|
|
792
|
+
const subMaxTurns = Math.min(Math.max(1, Number(input.max_turns) || defaultSubMaxTurns), 12);
|
|
793
|
+
const subTools = tools.filter(t => t.name !== "delegate_task");
|
|
794
|
+
const subId = `sub-${Date.now().toString(36)}`;
|
|
795
|
+
onSubagentProgress?.({
|
|
796
|
+
subagentId: subId,
|
|
797
|
+
event: "started",
|
|
798
|
+
model: subModel
|
|
799
|
+
});
|
|
800
|
+
const subStartTime = Date.now();
|
|
801
|
+
const subResult = await runServerSubagent({
|
|
802
|
+
anthropic,
|
|
803
|
+
supabase,
|
|
804
|
+
storeId,
|
|
805
|
+
prompt: subPrompt,
|
|
806
|
+
model: subModel,
|
|
807
|
+
maxTurns: subMaxTurns,
|
|
808
|
+
tools: subTools,
|
|
809
|
+
executeTool: async (toolName, args) => executeTool(toolName, args, "server_subagent"),
|
|
810
|
+
onProgress: onSubagentProgress,
|
|
811
|
+
clientDisconnected,
|
|
812
|
+
startedAt,
|
|
813
|
+
maxDurationMs,
|
|
814
|
+
maxOutputTokens: opts.subagentMaxTokens,
|
|
815
|
+
temperature: opts.subagentTemperature
|
|
816
|
+
});
|
|
817
|
+
onSubagentProgress?.({
|
|
818
|
+
subagentId: subId,
|
|
819
|
+
event: "done",
|
|
820
|
+
output: subResult.output
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
// Audit log
|
|
824
|
+
const subDurationMs = Date.now() - subStartTime;
|
|
825
|
+
const subModelId = subModel === "opus" ? MODELS.OPUS : subModel === "sonnet" ? MODELS.SONNET : MODELS.HAIKU;
|
|
826
|
+
try {
|
|
827
|
+
const subEndTime = Date.now();
|
|
828
|
+
queueSpan(auditRowToSpan({
|
|
829
|
+
action: "chat.subagent_complete",
|
|
830
|
+
severity: "info",
|
|
831
|
+
store_id: storeId || null,
|
|
832
|
+
resource_type: "chat_subagent",
|
|
833
|
+
resource_id: agentId || null,
|
|
834
|
+
request_id: traceId || null,
|
|
835
|
+
conversation_id: conversationId || null,
|
|
836
|
+
source: "server_subagent",
|
|
837
|
+
user_id: userId || null,
|
|
838
|
+
user_email: userEmail || null,
|
|
839
|
+
input_tokens: subResult.tokensUsed.input,
|
|
840
|
+
output_tokens: subResult.tokensUsed.output,
|
|
841
|
+
total_cost: subResult.costUsd,
|
|
842
|
+
model: subModelId,
|
|
843
|
+
duration_ms: subDurationMs,
|
|
844
|
+
trace_id: traceId || null,
|
|
845
|
+
span_kind: "INTERNAL",
|
|
846
|
+
service_name: "agent-server",
|
|
847
|
+
status_code: subResult.success ? "OK" : "ERROR",
|
|
848
|
+
start_time: new Date(subEndTime - subDurationMs).toISOString(),
|
|
849
|
+
end_time: new Date(subEndTime).toISOString(),
|
|
850
|
+
stop_reason: subResult.stopReason || undefined,
|
|
851
|
+
turn_number: subResult.turnCount || 1,
|
|
852
|
+
parent_conversation_id: conversationId || undefined,
|
|
853
|
+
details: {
|
|
854
|
+
subagent_model: subModel,
|
|
855
|
+
turn_count: subResult.turnCount,
|
|
856
|
+
tool_calls: subResult.toolsUsed.length,
|
|
857
|
+
tool_names: subResult.toolsUsed,
|
|
858
|
+
cost_usd: subResult.costUsd,
|
|
859
|
+
success: subResult.success,
|
|
860
|
+
prompt_preview: subPrompt.substring(0, 200),
|
|
861
|
+
"gen_ai.request.model": subModelId,
|
|
862
|
+
"gen_ai.usage.input_tokens": subResult.tokensUsed.input,
|
|
863
|
+
"gen_ai.usage.output_tokens": subResult.tokensUsed.output,
|
|
864
|
+
"gen_ai.usage.cache_read_tokens": subResult.tokensUsed.cacheRead || 0,
|
|
865
|
+
"gen_ai.usage.cache_creation_tokens": subResult.tokensUsed.cacheCreation || 0,
|
|
866
|
+
"gen_ai.usage.cost": subResult.costUsd
|
|
867
|
+
}
|
|
868
|
+
}));
|
|
869
|
+
} catch (err) {
|
|
870
|
+
log.error({
|
|
871
|
+
err: err.message
|
|
872
|
+
}, "failed to log subagent delegation audit");
|
|
873
|
+
}
|
|
874
|
+
subagentTokens.input += subResult.tokensUsed.input;
|
|
875
|
+
subagentTokens.output += subResult.tokensUsed.output;
|
|
876
|
+
subagentTokens.costUsd += subResult.costUsd;
|
|
877
|
+
allToolNames.push(...subResult.toolsUsed);
|
|
878
|
+
return {
|
|
879
|
+
success: subResult.success,
|
|
880
|
+
output: subResult.output
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// Regular tool execution — pass onToolProgress for streaming tools (kali)
|
|
885
|
+
const result = await executeTool(name, input, undefined, onToolProgress);
|
|
886
|
+
onToolResult?.(name, result.success, result.success ? result.data : result.error);
|
|
887
|
+
|
|
888
|
+
// discover_tools: dynamically add discovered tools to the active set
|
|
889
|
+
if (name === "discover_tools" && result.success && result.data) {
|
|
890
|
+
const refreshRequested = !!input.refresh;
|
|
891
|
+
const discovered = result.data?.tools;
|
|
892
|
+
|
|
893
|
+
// If refresh requested, remove previously-discovered tools so they can be re-loaded
|
|
894
|
+
// with fresh schemas from DB. Core tools and delegate_task are never removed.
|
|
895
|
+
if (refreshRequested) {
|
|
896
|
+
const coreNames = new Set((opts.tools || []).map(t => t.name));
|
|
897
|
+
coreNames.add("delegate_task");
|
|
898
|
+
for (let i = tools.length - 1; i >= 0; i--) {
|
|
899
|
+
if (discoveredToolNames.has(tools[i].name) && !coreNames.has(tools[i].name)) {
|
|
900
|
+
tools.splice(i, 1);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
discoveredToolNames.clear();
|
|
904
|
+
log.info("discover_tools refresh — cleared previously discovered tools");
|
|
905
|
+
}
|
|
906
|
+
if (Array.isArray(discovered)) {
|
|
907
|
+
// Use getFullToolSchemas as authoritative source — supplements handler response
|
|
908
|
+
// with any schemas the handler returned, ensuring we have complete definitions.
|
|
909
|
+
const discoveredNames = discovered.filter(t => t.name).map(t => t.name);
|
|
910
|
+
const fullSchemas = getFullToolSchemas(discoveredNames);
|
|
911
|
+
// Build a map for O(1) lookup: prefer full schemas from cache, fall back to handler data
|
|
912
|
+
const schemaMap = new Map();
|
|
913
|
+
for (const t of discovered) {
|
|
914
|
+
if (t.name && t.input_schema) {
|
|
915
|
+
schemaMap.set(t.name, {
|
|
916
|
+
name: t.name,
|
|
917
|
+
description: t.description || t.name,
|
|
918
|
+
input_schema: t.input_schema
|
|
561
919
|
});
|
|
562
|
-
|
|
563
|
-
// Audit log
|
|
564
|
-
const subDurationMs = Date.now() - subStartTime;
|
|
565
|
-
const subModelId = subModel === "opus" ? MODELS.OPUS
|
|
566
|
-
: subModel === "sonnet" ? MODELS.SONNET : MODELS.HAIKU;
|
|
567
|
-
try {
|
|
568
|
-
const subEndTime = Date.now();
|
|
569
|
-
queueSpan(auditRowToSpan({
|
|
570
|
-
action: "chat.subagent_complete", severity: "info",
|
|
571
|
-
store_id: storeId || null, resource_type: "chat_subagent",
|
|
572
|
-
resource_id: agentId || null, request_id: traceId || null,
|
|
573
|
-
conversation_id: conversationId || null, source: "server_subagent",
|
|
574
|
-
user_id: userId || null,
|
|
575
|
-
user_email: userEmail || null,
|
|
576
|
-
input_tokens: subResult.tokensUsed.input, output_tokens: subResult.tokensUsed.output,
|
|
577
|
-
total_cost: subResult.costUsd, model: subModelId, duration_ms: subDurationMs,
|
|
578
|
-
trace_id: traceId || null,
|
|
579
|
-
span_kind: "INTERNAL",
|
|
580
|
-
service_name: "agent-server",
|
|
581
|
-
status_code: subResult.success ? "OK" : "ERROR",
|
|
582
|
-
start_time: new Date(subEndTime - subDurationMs).toISOString(),
|
|
583
|
-
end_time: new Date(subEndTime).toISOString(),
|
|
584
|
-
stop_reason: subResult.stopReason || undefined,
|
|
585
|
-
turn_number: subResult.turnCount || 1,
|
|
586
|
-
parent_conversation_id: conversationId || undefined,
|
|
587
|
-
details: {
|
|
588
|
-
subagent_model: subModel, turn_count: subResult.turnCount,
|
|
589
|
-
tool_calls: subResult.toolsUsed.length, tool_names: subResult.toolsUsed,
|
|
590
|
-
cost_usd: subResult.costUsd, success: subResult.success,
|
|
591
|
-
prompt_preview: subPrompt.substring(0, 200),
|
|
592
|
-
"gen_ai.request.model": subModelId,
|
|
593
|
-
"gen_ai.usage.input_tokens": subResult.tokensUsed.input,
|
|
594
|
-
"gen_ai.usage.output_tokens": subResult.tokensUsed.output,
|
|
595
|
-
"gen_ai.usage.cache_read_tokens": subResult.tokensUsed.cacheRead || 0,
|
|
596
|
-
"gen_ai.usage.cache_creation_tokens": subResult.tokensUsed.cacheCreation || 0,
|
|
597
|
-
"gen_ai.usage.cost": subResult.costUsd,
|
|
598
|
-
},
|
|
599
|
-
}));
|
|
600
|
-
}
|
|
601
|
-
catch (err) {
|
|
602
|
-
log.error({ err: err.message }, "failed to log subagent delegation audit");
|
|
603
|
-
}
|
|
604
|
-
subagentTokens.input += subResult.tokensUsed.input;
|
|
605
|
-
subagentTokens.output += subResult.tokensUsed.output;
|
|
606
|
-
subagentTokens.costUsd += subResult.costUsd;
|
|
607
|
-
allToolNames.push(...subResult.toolsUsed);
|
|
608
|
-
return { success: subResult.success, output: subResult.output };
|
|
920
|
+
}
|
|
609
921
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
onToolResult?.(name, result.success, result.success ? result.data : result.error);
|
|
613
|
-
// discover_tools: dynamically add discovered tools to the active set
|
|
614
|
-
if (name === "discover_tools" && result.success && result.data) {
|
|
615
|
-
const refreshRequested = !!input.refresh;
|
|
616
|
-
const discovered = result.data?.tools;
|
|
617
|
-
// If refresh requested, remove previously-discovered tools so they can be re-loaded
|
|
618
|
-
// with fresh schemas from DB. Core tools and delegate_task are never removed.
|
|
619
|
-
if (refreshRequested) {
|
|
620
|
-
const coreNames = new Set((opts.tools || []).map(t => t.name));
|
|
621
|
-
coreNames.add("delegate_task");
|
|
622
|
-
for (let i = tools.length - 1; i >= 0; i--) {
|
|
623
|
-
if (discoveredToolNames.has(tools[i].name) && !coreNames.has(tools[i].name)) {
|
|
624
|
-
tools.splice(i, 1);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
discoveredToolNames.clear();
|
|
628
|
-
log.info("discover_tools refresh — cleared previously discovered tools");
|
|
629
|
-
}
|
|
630
|
-
if (Array.isArray(discovered)) {
|
|
631
|
-
// Use getFullToolSchemas as authoritative source — supplements handler response
|
|
632
|
-
// with any schemas the handler returned, ensuring we have complete definitions.
|
|
633
|
-
const discoveredNames = discovered.filter((t) => t.name).map((t) => t.name);
|
|
634
|
-
const fullSchemas = getFullToolSchemas(discoveredNames);
|
|
635
|
-
// Build a map for O(1) lookup: prefer full schemas from cache, fall back to handler data
|
|
636
|
-
const schemaMap = new Map();
|
|
637
|
-
for (const t of discovered) {
|
|
638
|
-
if (t.name && t.input_schema) {
|
|
639
|
-
schemaMap.set(t.name, { name: t.name, description: t.description || t.name, input_schema: t.input_schema });
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
for (const t of fullSchemas) {
|
|
643
|
-
schemaMap.set(t.name, t); // Full cache schemas override handler data (more complete)
|
|
644
|
-
}
|
|
645
|
-
const activated = [];
|
|
646
|
-
const alreadyActive = [];
|
|
647
|
-
for (const [toolName, toolDef] of schemaMap) {
|
|
648
|
-
// Track as discovered regardless of whether already active
|
|
649
|
-
discoveredToolNames.add(toolName);
|
|
650
|
-
if (!tools.some(existing => existing.name === toolName)) {
|
|
651
|
-
tools.push(toolDef);
|
|
652
|
-
activated.push(toolName);
|
|
653
|
-
}
|
|
654
|
-
else if (refreshRequested) {
|
|
655
|
-
// Re-add after refresh cleared it, or update existing schema
|
|
656
|
-
tools.push(toolDef);
|
|
657
|
-
activated.push(toolName);
|
|
658
|
-
}
|
|
659
|
-
else {
|
|
660
|
-
alreadyActive.push(toolName);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
if (activated.length > 0) {
|
|
664
|
-
log.info({ activatedTools: activated, refreshed: refreshRequested }, "discover_tools activated");
|
|
665
|
-
}
|
|
666
|
-
// Return a cleaner message to the model
|
|
667
|
-
return {
|
|
668
|
-
success: true,
|
|
669
|
-
output: JSON.stringify({
|
|
670
|
-
activated,
|
|
671
|
-
already_active: alreadyActive,
|
|
672
|
-
refreshed: refreshRequested,
|
|
673
|
-
message: activated.length > 0
|
|
674
|
-
? `Activated ${activated.length} tool(s): ${activated.join(", ")}. You can now use them.`
|
|
675
|
-
: "Requested tools were already active.",
|
|
676
|
-
total_discovered: discoveredToolNames.size,
|
|
677
|
-
}),
|
|
678
|
-
};
|
|
679
|
-
}
|
|
922
|
+
for (const t of fullSchemas) {
|
|
923
|
+
schemaMap.set(t.name, t); // Full cache schemas override handler data (more complete)
|
|
680
924
|
}
|
|
925
|
+
const activated = [];
|
|
926
|
+
const alreadyActive = [];
|
|
927
|
+
for (const [toolName, toolDef] of schemaMap) {
|
|
928
|
+
// Track as discovered regardless of whether already active
|
|
929
|
+
discoveredToolNames.add(toolName);
|
|
930
|
+
if (!tools.some(existing => existing.name === toolName)) {
|
|
931
|
+
tools.push(toolDef);
|
|
932
|
+
activated.push(toolName);
|
|
933
|
+
} else if (refreshRequested) {
|
|
934
|
+
// Re-add after refresh cleared it, or update existing schema
|
|
935
|
+
tools.push(toolDef);
|
|
936
|
+
activated.push(toolName);
|
|
937
|
+
} else {
|
|
938
|
+
alreadyActive.push(toolName);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
if (activated.length > 0) {
|
|
942
|
+
log.info({
|
|
943
|
+
activatedTools: activated,
|
|
944
|
+
refreshed: refreshRequested
|
|
945
|
+
}, "discover_tools activated");
|
|
946
|
+
}
|
|
947
|
+
// Return a cleaner message to the model
|
|
681
948
|
return {
|
|
682
|
-
|
|
683
|
-
|
|
949
|
+
success: true,
|
|
950
|
+
output: JSON.stringify({
|
|
951
|
+
activated,
|
|
952
|
+
already_active: alreadyActive,
|
|
953
|
+
refreshed: refreshRequested,
|
|
954
|
+
message: activated.length > 0 ? `Activated ${activated.length} tool(s): ${activated.join(", ")}. You can now use them.` : "Requested tools were already active.",
|
|
955
|
+
total_discovered: discoveredToolNames.size
|
|
956
|
+
})
|
|
684
957
|
};
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
return {
|
|
961
|
+
success: result.success,
|
|
962
|
+
output: JSON.stringify(result.success ? result.data : {
|
|
963
|
+
error: result.error
|
|
964
|
+
})
|
|
685
965
|
};
|
|
966
|
+
};
|
|
686
967
|
}
|
|
968
|
+
//# sourceMappingURL=server-agent-loop.js.map
|