whale-code 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -0
- package/bin/swag-agent.js +9 -0
- package/bin/swagmanager-mcp.js +321 -0
- package/dist/cli/app.d.ts +26 -0
- package/dist/cli/app.js +64 -0
- package/dist/cli/chat/AgentSelector.d.ts +14 -0
- package/dist/cli/chat/AgentSelector.js +14 -0
- package/dist/cli/chat/ChatApp.d.ts +9 -0
- package/dist/cli/chat/ChatApp.js +267 -0
- package/dist/cli/chat/ChatInput.d.ts +39 -0
- package/dist/cli/chat/ChatInput.js +509 -0
- package/dist/cli/chat/MarkdownText.d.ts +10 -0
- package/dist/cli/chat/MarkdownText.js +20 -0
- package/dist/cli/chat/MessageList.d.ts +37 -0
- package/dist/cli/chat/MessageList.js +80 -0
- package/dist/cli/chat/ModelSelector.d.ts +20 -0
- package/dist/cli/chat/ModelSelector.js +73 -0
- package/dist/cli/chat/RewindViewer.d.ts +26 -0
- package/dist/cli/chat/RewindViewer.js +185 -0
- package/dist/cli/chat/StoreSelector.d.ts +14 -0
- package/dist/cli/chat/StoreSelector.js +24 -0
- package/dist/cli/chat/StreamingText.d.ts +12 -0
- package/dist/cli/chat/StreamingText.js +12 -0
- package/dist/cli/chat/SubagentPanel.d.ts +45 -0
- package/dist/cli/chat/SubagentPanel.js +110 -0
- package/dist/cli/chat/TeamPanel.d.ts +21 -0
- package/dist/cli/chat/TeamPanel.js +42 -0
- package/dist/cli/chat/ToolIndicator.d.ts +25 -0
- package/dist/cli/chat/ToolIndicator.js +436 -0
- package/dist/cli/chat/hooks/useAgentLoop.d.ts +39 -0
- package/dist/cli/chat/hooks/useAgentLoop.js +382 -0
- package/dist/cli/chat/hooks/useSlashCommands.d.ts +37 -0
- package/dist/cli/chat/hooks/useSlashCommands.js +387 -0
- package/dist/cli/commands/config-cmd.d.ts +10 -0
- package/dist/cli/commands/config-cmd.js +99 -0
- package/dist/cli/commands/doctor.d.ts +14 -0
- package/dist/cli/commands/doctor.js +172 -0
- package/dist/cli/commands/init.d.ts +16 -0
- package/dist/cli/commands/init.js +278 -0
- package/dist/cli/commands/mcp.d.ts +12 -0
- package/dist/cli/commands/mcp.js +162 -0
- package/dist/cli/login/LoginApp.d.ts +7 -0
- package/dist/cli/login/LoginApp.js +157 -0
- package/dist/cli/print-mode.d.ts +31 -0
- package/dist/cli/print-mode.js +202 -0
- package/dist/cli/serve-mode.d.ts +37 -0
- package/dist/cli/serve-mode.js +636 -0
- package/dist/cli/services/agent-definitions.d.ts +25 -0
- package/dist/cli/services/agent-definitions.js +91 -0
- package/dist/cli/services/agent-events.d.ts +178 -0
- package/dist/cli/services/agent-events.js +175 -0
- package/dist/cli/services/agent-loop.d.ts +90 -0
- package/dist/cli/services/agent-loop.js +762 -0
- package/dist/cli/services/agent-worker-base.d.ts +97 -0
- package/dist/cli/services/agent-worker-base.js +220 -0
- package/dist/cli/services/auth-service.d.ts +30 -0
- package/dist/cli/services/auth-service.js +160 -0
- package/dist/cli/services/background-processes.d.ts +126 -0
- package/dist/cli/services/background-processes.js +318 -0
- package/dist/cli/services/browser-auth.d.ts +24 -0
- package/dist/cli/services/browser-auth.js +180 -0
- package/dist/cli/services/claude-md-loader.d.ts +16 -0
- package/dist/cli/services/claude-md-loader.js +58 -0
- package/dist/cli/services/config-store.d.ts +47 -0
- package/dist/cli/services/config-store.js +79 -0
- package/dist/cli/services/debug-log.d.ts +10 -0
- package/dist/cli/services/debug-log.js +52 -0
- package/dist/cli/services/error-logger.d.ts +58 -0
- package/dist/cli/services/error-logger.js +269 -0
- package/dist/cli/services/file-history.d.ts +21 -0
- package/dist/cli/services/file-history.js +83 -0
- package/dist/cli/services/format-server-response.d.ts +16 -0
- package/dist/cli/services/format-server-response.js +440 -0
- package/dist/cli/services/git-context.d.ts +11 -0
- package/dist/cli/services/git-context.js +66 -0
- package/dist/cli/services/hooks.d.ts +85 -0
- package/dist/cli/services/hooks.js +258 -0
- package/dist/cli/services/interactive-tools.d.ts +125 -0
- package/dist/cli/services/interactive-tools.js +260 -0
- package/dist/cli/services/keybinding-manager.d.ts +52 -0
- package/dist/cli/services/keybinding-manager.js +115 -0
- package/dist/cli/services/local-tools.d.ts +22 -0
- package/dist/cli/services/local-tools.js +697 -0
- package/dist/cli/services/lsp-manager.d.ts +18 -0
- package/dist/cli/services/lsp-manager.js +717 -0
- package/dist/cli/services/mcp-client.d.ts +48 -0
- package/dist/cli/services/mcp-client.js +157 -0
- package/dist/cli/services/memory-manager.d.ts +16 -0
- package/dist/cli/services/memory-manager.js +57 -0
- package/dist/cli/services/model-manager.d.ts +18 -0
- package/dist/cli/services/model-manager.js +71 -0
- package/dist/cli/services/model-router.d.ts +26 -0
- package/dist/cli/services/model-router.js +149 -0
- package/dist/cli/services/permission-modes.d.ts +13 -0
- package/dist/cli/services/permission-modes.js +43 -0
- package/dist/cli/services/rewind.d.ts +84 -0
- package/dist/cli/services/rewind.js +194 -0
- package/dist/cli/services/ripgrep.d.ts +28 -0
- package/dist/cli/services/ripgrep.js +138 -0
- package/dist/cli/services/sandbox.d.ts +29 -0
- package/dist/cli/services/sandbox.js +97 -0
- package/dist/cli/services/server-tools.d.ts +61 -0
- package/dist/cli/services/server-tools.js +543 -0
- package/dist/cli/services/session-persistence.d.ts +23 -0
- package/dist/cli/services/session-persistence.js +99 -0
- package/dist/cli/services/subagent-worker.d.ts +19 -0
- package/dist/cli/services/subagent-worker.js +41 -0
- package/dist/cli/services/subagent.d.ts +47 -0
- package/dist/cli/services/subagent.js +647 -0
- package/dist/cli/services/system-prompt.d.ts +7 -0
- package/dist/cli/services/system-prompt.js +198 -0
- package/dist/cli/services/team-lead.d.ts +73 -0
- package/dist/cli/services/team-lead.js +512 -0
- package/dist/cli/services/team-state.d.ts +77 -0
- package/dist/cli/services/team-state.js +398 -0
- package/dist/cli/services/teammate.d.ts +31 -0
- package/dist/cli/services/teammate.js +689 -0
- package/dist/cli/services/telemetry.d.ts +61 -0
- package/dist/cli/services/telemetry.js +209 -0
- package/dist/cli/services/tools/agent-tools.d.ts +14 -0
- package/dist/cli/services/tools/agent-tools.js +347 -0
- package/dist/cli/services/tools/file-ops.d.ts +15 -0
- package/dist/cli/services/tools/file-ops.js +487 -0
- package/dist/cli/services/tools/search-tools.d.ts +8 -0
- package/dist/cli/services/tools/search-tools.js +186 -0
- package/dist/cli/services/tools/shell-exec.d.ts +10 -0
- package/dist/cli/services/tools/shell-exec.js +168 -0
- package/dist/cli/services/tools/task-manager.d.ts +28 -0
- package/dist/cli/services/tools/task-manager.js +209 -0
- package/dist/cli/services/tools/web-tools.d.ts +11 -0
- package/dist/cli/services/tools/web-tools.js +395 -0
- package/dist/cli/setup/SetupApp.d.ts +9 -0
- package/dist/cli/setup/SetupApp.js +191 -0
- package/dist/cli/shared/MatrixIntro.d.ts +4 -0
- package/dist/cli/shared/MatrixIntro.js +83 -0
- package/dist/cli/shared/Theme.d.ts +74 -0
- package/dist/cli/shared/Theme.js +127 -0
- package/dist/cli/shared/WhaleBanner.d.ts +10 -0
- package/dist/cli/shared/WhaleBanner.js +12 -0
- package/dist/cli/shared/markdown.d.ts +21 -0
- package/dist/cli/shared/markdown.js +756 -0
- package/dist/cli/status/StatusApp.d.ts +4 -0
- package/dist/cli/status/StatusApp.js +105 -0
- package/dist/cli/stores/StoreApp.d.ts +7 -0
- package/dist/cli/stores/StoreApp.js +81 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +538 -0
- package/dist/local-agent/connection.d.ts +48 -0
- package/dist/local-agent/connection.js +332 -0
- package/dist/local-agent/discovery.d.ts +18 -0
- package/dist/local-agent/discovery.js +146 -0
- package/dist/local-agent/executor.d.ts +34 -0
- package/dist/local-agent/executor.js +241 -0
- package/dist/local-agent/index.d.ts +14 -0
- package/dist/local-agent/index.js +198 -0
- package/dist/node/adapters/base.d.ts +35 -0
- package/dist/node/adapters/base.js +10 -0
- package/dist/node/adapters/discord.d.ts +29 -0
- package/dist/node/adapters/discord.js +299 -0
- package/dist/node/adapters/email.d.ts +23 -0
- package/dist/node/adapters/email.js +218 -0
- package/dist/node/adapters/imessage.d.ts +17 -0
- package/dist/node/adapters/imessage.js +118 -0
- package/dist/node/adapters/slack.d.ts +26 -0
- package/dist/node/adapters/slack.js +259 -0
- package/dist/node/adapters/sms.d.ts +23 -0
- package/dist/node/adapters/sms.js +161 -0
- package/dist/node/adapters/telegram.d.ts +17 -0
- package/dist/node/adapters/telegram.js +101 -0
- package/dist/node/adapters/webchat.d.ts +27 -0
- package/dist/node/adapters/webchat.js +160 -0
- package/dist/node/adapters/whatsapp.d.ts +28 -0
- package/dist/node/adapters/whatsapp.js +230 -0
- package/dist/node/cli.d.ts +2 -0
- package/dist/node/cli.js +325 -0
- package/dist/node/config.d.ts +17 -0
- package/dist/node/config.js +31 -0
- package/dist/node/runtime.d.ts +50 -0
- package/dist/node/runtime.js +351 -0
- package/dist/server/handlers/__test-utils__/mock-supabase.d.ts +11 -0
- package/dist/server/handlers/__test-utils__/mock-supabase.js +393 -0
- package/dist/server/handlers/analytics.d.ts +17 -0
- package/dist/server/handlers/analytics.js +266 -0
- package/dist/server/handlers/api-keys.d.ts +6 -0
- package/dist/server/handlers/api-keys.js +221 -0
- package/dist/server/handlers/billing.d.ts +33 -0
- package/dist/server/handlers/billing.js +272 -0
- package/dist/server/handlers/browser.d.ts +10 -0
- package/dist/server/handlers/browser.js +517 -0
- package/dist/server/handlers/catalog.d.ts +99 -0
- package/dist/server/handlers/catalog.js +976 -0
- package/dist/server/handlers/comms.d.ts +254 -0
- package/dist/server/handlers/comms.js +588 -0
- package/dist/server/handlers/creations.d.ts +6 -0
- package/dist/server/handlers/creations.js +479 -0
- package/dist/server/handlers/crm.d.ts +89 -0
- package/dist/server/handlers/crm.js +538 -0
- package/dist/server/handlers/discovery.d.ts +6 -0
- package/dist/server/handlers/discovery.js +288 -0
- package/dist/server/handlers/embeddings.d.ts +92 -0
- package/dist/server/handlers/embeddings.js +197 -0
- package/dist/server/handlers/enrichment.d.ts +8 -0
- package/dist/server/handlers/enrichment.js +768 -0
- package/dist/server/handlers/image-gen.d.ts +6 -0
- package/dist/server/handlers/image-gen.js +409 -0
- package/dist/server/handlers/inventory.d.ts +319 -0
- package/dist/server/handlers/inventory.js +447 -0
- package/dist/server/handlers/kali.d.ts +10 -0
- package/dist/server/handlers/kali.js +210 -0
- package/dist/server/handlers/llm-providers.d.ts +6 -0
- package/dist/server/handlers/llm-providers.js +673 -0
- package/dist/server/handlers/local-agent.d.ts +6 -0
- package/dist/server/handlers/local-agent.js +118 -0
- package/dist/server/handlers/meta-ads.d.ts +111 -0
- package/dist/server/handlers/meta-ads.js +2279 -0
- package/dist/server/handlers/nodes.d.ts +33 -0
- package/dist/server/handlers/nodes.js +699 -0
- package/dist/server/handlers/operations.d.ts +138 -0
- package/dist/server/handlers/operations.js +131 -0
- package/dist/server/handlers/platform.d.ts +23 -0
- package/dist/server/handlers/platform.js +227 -0
- package/dist/server/handlers/supply-chain.d.ts +19 -0
- package/dist/server/handlers/supply-chain.js +327 -0
- package/dist/server/handlers/transcription.d.ts +17 -0
- package/dist/server/handlers/transcription.js +121 -0
- package/dist/server/handlers/video-gen.d.ts +6 -0
- package/dist/server/handlers/video-gen.js +466 -0
- package/dist/server/handlers/voice.d.ts +8 -0
- package/dist/server/handlers/voice.js +1146 -0
- package/dist/server/handlers/workflow-steps.d.ts +86 -0
- package/dist/server/handlers/workflow-steps.js +2349 -0
- package/dist/server/handlers/workflows.d.ts +7 -0
- package/dist/server/handlers/workflows.js +989 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +2427 -0
- package/dist/server/lib/batch-client.d.ts +80 -0
- package/dist/server/lib/batch-client.js +467 -0
- package/dist/server/lib/code-worker-pool.d.ts +31 -0
- package/dist/server/lib/code-worker-pool.js +224 -0
- package/dist/server/lib/code-worker.d.ts +1 -0
- package/dist/server/lib/code-worker.js +188 -0
- package/dist/server/lib/compaction-service.d.ts +32 -0
- package/dist/server/lib/compaction-service.js +162 -0
- package/dist/server/lib/logger.d.ts +19 -0
- package/dist/server/lib/logger.js +46 -0
- package/dist/server/lib/otel.d.ts +38 -0
- package/dist/server/lib/otel.js +126 -0
- package/dist/server/lib/pg-rate-limiter.d.ts +21 -0
- package/dist/server/lib/pg-rate-limiter.js +86 -0
- package/dist/server/lib/prompt-sanitizer.d.ts +37 -0
- package/dist/server/lib/prompt-sanitizer.js +177 -0
- package/dist/server/lib/provider-capabilities.d.ts +85 -0
- package/dist/server/lib/provider-capabilities.js +190 -0
- package/dist/server/lib/provider-failover.d.ts +74 -0
- package/dist/server/lib/provider-failover.js +210 -0
- package/dist/server/lib/rate-limiter.d.ts +39 -0
- package/dist/server/lib/rate-limiter.js +147 -0
- package/dist/server/lib/server-agent-loop.d.ts +107 -0
- package/dist/server/lib/server-agent-loop.js +667 -0
- package/dist/server/lib/server-subagent.d.ts +78 -0
- package/dist/server/lib/server-subagent.js +203 -0
- package/dist/server/lib/session-checkpoint.d.ts +51 -0
- package/dist/server/lib/session-checkpoint.js +145 -0
- package/dist/server/lib/ssrf-guard.d.ts +13 -0
- package/dist/server/lib/ssrf-guard.js +240 -0
- package/dist/server/lib/supabase-client.d.ts +7 -0
- package/dist/server/lib/supabase-client.js +78 -0
- package/dist/server/lib/template-resolver.d.ts +31 -0
- package/dist/server/lib/template-resolver.js +215 -0
- package/dist/server/lib/utils.d.ts +16 -0
- package/dist/server/lib/utils.js +147 -0
- package/dist/server/local-agent-gateway.d.ts +82 -0
- package/dist/server/local-agent-gateway.js +426 -0
- package/dist/server/providers/anthropic.d.ts +20 -0
- package/dist/server/providers/anthropic.js +199 -0
- package/dist/server/providers/bedrock.d.ts +20 -0
- package/dist/server/providers/bedrock.js +194 -0
- package/dist/server/providers/gemini.d.ts +24 -0
- package/dist/server/providers/gemini.js +486 -0
- package/dist/server/providers/openai.d.ts +24 -0
- package/dist/server/providers/openai.js +522 -0
- package/dist/server/providers/registry.d.ts +32 -0
- package/dist/server/providers/registry.js +58 -0
- package/dist/server/providers/shared.d.ts +32 -0
- package/dist/server/providers/shared.js +124 -0
- package/dist/server/providers/types.d.ts +92 -0
- package/dist/server/providers/types.js +12 -0
- package/dist/server/proxy-handlers.d.ts +6 -0
- package/dist/server/proxy-handlers.js +89 -0
- package/dist/server/tool-router.d.ts +149 -0
- package/dist/server/tool-router.js +803 -0
- package/dist/server/validation.d.ts +24 -0
- package/dist/server/validation.js +301 -0
- package/dist/server/worker.d.ts +19 -0
- package/dist/server/worker.js +201 -0
- package/dist/setup.d.ts +8 -0
- package/dist/setup.js +181 -0
- package/dist/shared/agent-core.d.ts +157 -0
- package/dist/shared/agent-core.js +534 -0
- package/dist/shared/anthropic-types.d.ts +105 -0
- package/dist/shared/anthropic-types.js +7 -0
- package/dist/shared/api-client.d.ts +90 -0
- package/dist/shared/api-client.js +379 -0
- package/dist/shared/constants.d.ts +33 -0
- package/dist/shared/constants.js +80 -0
- package/dist/shared/sse-parser.d.ts +26 -0
- package/dist/shared/sse-parser.js +259 -0
- package/dist/shared/tool-dispatch.d.ts +52 -0
- package/dist/shared/tool-dispatch.js +191 -0
- package/dist/shared/types.d.ts +72 -0
- package/dist/shared/types.js +7 -0
- package/dist/updater.d.ts +25 -0
- package/dist/updater.js +140 -0
- package/dist/webchat/widget.d.ts +0 -0
- package/dist/webchat/widget.js +397 -0
- package/package.json +95 -0
- package/src/cli/services/builtin-skills/commit.md +19 -0
- package/src/cli/services/builtin-skills/review-pr.md +21 -0
- package/src/cli/services/builtin-skills/review.md +18 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified API Client — ONE server proxy caller with retry and config builder.
|
|
3
|
+
*
|
|
4
|
+
* Replaces proxy+direct call paths in agent-loop, subagent, teammate.
|
|
5
|
+
* CLI-only: always calls through server proxy (no direct Anthropic SDK usage).
|
|
6
|
+
*/
|
|
7
|
+
import type { ContextProfile, APIRequestConfig } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Build all Anthropic API config from a simple profile.
|
|
10
|
+
*
|
|
11
|
+
* Profiles:
|
|
12
|
+
* - 'main': clear at 80K/keep 3, compact at 120K (Opus only)
|
|
13
|
+
* - 'subagent': clear at 60K/keep 2, no compaction, 8192 max tokens
|
|
14
|
+
* - 'teammate': clear at 80K/keep 3, no compaction
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildAPIRequest(opts: {
|
|
17
|
+
model: string;
|
|
18
|
+
contextProfile: ContextProfile;
|
|
19
|
+
thinkingEnabled?: boolean;
|
|
20
|
+
maxOutputTokens?: number;
|
|
21
|
+
}): APIRequestConfig;
|
|
22
|
+
export interface CallServerProxyConfig {
|
|
23
|
+
proxyUrl: string;
|
|
24
|
+
token: string;
|
|
25
|
+
model: string;
|
|
26
|
+
system: Array<Record<string, unknown>>;
|
|
27
|
+
messages: Array<Record<string, unknown>>;
|
|
28
|
+
tools: Array<Record<string, unknown>>;
|
|
29
|
+
apiConfig: APIRequestConfig;
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
timeoutMs?: number;
|
|
32
|
+
fallbackModel?: string;
|
|
33
|
+
storeId?: string;
|
|
34
|
+
onFallback?: (fromModel: string, toModel: string) => void;
|
|
35
|
+
onRetry?: (attempt: number, maxRetries: number, error: string) => void;
|
|
36
|
+
/** Called on 401 to refresh the auth token. Returns new token or null. */
|
|
37
|
+
onTokenRefresh?: () => Promise<string | null>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Call server proxy endpoint and return raw SSE stream.
|
|
41
|
+
* Retries with exponential backoff on 429/500/529.
|
|
42
|
+
*/
|
|
43
|
+
export declare function callServerProxy(config: CallServerProxyConfig): Promise<ReadableStream<Uint8Array>>;
|
|
44
|
+
/**
|
|
45
|
+
* Build system blocks with prompt caching.
|
|
46
|
+
* Cached system prompt + optional dynamic cost context (after cache breakpoint).
|
|
47
|
+
*/
|
|
48
|
+
export declare function buildSystemBlocks(systemPrompt: string, costContext?: string, enableCaching?: boolean): Array<Record<string, unknown>>;
|
|
49
|
+
/**
|
|
50
|
+
* Prepare messages and tools with prompt caching.
|
|
51
|
+
* Skips cache_control injection for Gemini (uses implicit caching).
|
|
52
|
+
*/
|
|
53
|
+
export declare function prepareWithCaching(tools: Array<Record<string, unknown>>, messages: Array<Record<string, unknown>>, model?: string): {
|
|
54
|
+
tools: Array<Record<string, unknown>>;
|
|
55
|
+
messages: Array<Record<string, unknown>>;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Client-side context trimming for Gemini (no server-side context management).
|
|
59
|
+
* When estimated input tokens exceed threshold, replaces old tool result contents
|
|
60
|
+
* with "[trimmed]" to stay within Gemini's 1M context window.
|
|
61
|
+
*/
|
|
62
|
+
export declare function trimGeminiContext(messages: Array<Record<string, unknown>>, estimatedTokens: number, threshold?: number, keepRecent?: number): Array<Record<string, unknown>>;
|
|
63
|
+
/**
|
|
64
|
+
* Client-side context trimming for OpenAI (no server-side context management).
|
|
65
|
+
* When estimated input tokens exceed threshold, replaces old tool result contents
|
|
66
|
+
* with "[trimmed]" to stay within OpenAI's 200K context window.
|
|
67
|
+
*/
|
|
68
|
+
/**
|
|
69
|
+
* Call server transcription endpoint (OpenAI Whisper via our Fly.io proxy).
|
|
70
|
+
* Used by tool-dispatch when __AUDIO__ marker is detected in tool results.
|
|
71
|
+
*/
|
|
72
|
+
export declare function callTranscribe(opts: {
|
|
73
|
+
proxyUrl: string;
|
|
74
|
+
token: string;
|
|
75
|
+
storeId: string;
|
|
76
|
+
audioBase64: string;
|
|
77
|
+
mediaType: string;
|
|
78
|
+
}): Promise<string>;
|
|
79
|
+
export declare function trimOpenAIContext(messages: Array<Record<string, unknown>>, estimatedTokens: number, threshold?: number, keepRecent?: number): Array<Record<string, unknown>>;
|
|
80
|
+
/**
|
|
81
|
+
* Request conversation compaction from the server (Haiku summarization).
|
|
82
|
+
* Used by non-Anthropic providers (OpenAI, Gemini) that lack native compaction.
|
|
83
|
+
* Returns summary string or null on failure (caller keeps unsummarized history).
|
|
84
|
+
*/
|
|
85
|
+
export declare function requestProviderCompaction(opts: {
|
|
86
|
+
proxyUrl: string;
|
|
87
|
+
token: string;
|
|
88
|
+
messages: Array<Record<string, unknown>>;
|
|
89
|
+
systemPrompt: string;
|
|
90
|
+
}): Promise<string | null>;
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified API Client — ONE server proxy caller with retry and config builder.
|
|
3
|
+
*
|
|
4
|
+
* Replaces proxy+direct call paths in agent-loop, subagent, teammate.
|
|
5
|
+
* CLI-only: always calls through server proxy (no direct Anthropic SDK usage).
|
|
6
|
+
*/
|
|
7
|
+
import { getContextManagement, getMaxOutputTokens, getThinkingConfig, isRetryableError, addPromptCaching, } from "./agent-core.js";
|
|
8
|
+
import { getProvider } from "./constants.js";
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// CONSTANTS
|
|
11
|
+
// ============================================================================
|
|
12
|
+
const MAX_RETRIES = 3;
|
|
13
|
+
const RETRY_BASE_DELAY_MS = 1000;
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// API REQUEST CONFIG BUILDER
|
|
16
|
+
// ============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Build all Anthropic API config from a simple profile.
|
|
19
|
+
*
|
|
20
|
+
* Profiles:
|
|
21
|
+
* - 'main': clear at 80K/keep 3, compact at 120K (Opus only)
|
|
22
|
+
* - 'subagent': clear at 60K/keep 2, no compaction, 8192 max tokens
|
|
23
|
+
* - 'teammate': clear at 80K/keep 3, no compaction
|
|
24
|
+
*/
|
|
25
|
+
export function buildAPIRequest(opts) {
|
|
26
|
+
const { model, contextProfile, thinkingEnabled = false, maxOutputTokens } = opts;
|
|
27
|
+
// Context management config per profile
|
|
28
|
+
// Non-Anthropic models (Gemini, OpenAI, etc.) don't support Anthropic betas or context management
|
|
29
|
+
const provider = getProvider(model);
|
|
30
|
+
const isAnthropicModel = provider === "anthropic" || provider === "bedrock";
|
|
31
|
+
let betas = isAnthropicModel ? ["context-management-2025-06-27"] : [];
|
|
32
|
+
let edits = [];
|
|
33
|
+
switch (contextProfile) {
|
|
34
|
+
case "main": {
|
|
35
|
+
const ctxMgmt = getContextManagement(model);
|
|
36
|
+
betas = [...ctxMgmt.betas];
|
|
37
|
+
edits = ctxMgmt.config.edits;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
case "subagent":
|
|
41
|
+
if (isAnthropicModel) {
|
|
42
|
+
edits = [
|
|
43
|
+
{
|
|
44
|
+
type: "clear_thinking_20251015",
|
|
45
|
+
keep: { type: "thinking_turns", value: 1 },
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: "clear_tool_uses_20250919",
|
|
49
|
+
trigger: { type: "input_tokens", value: 60_000 },
|
|
50
|
+
keep: { type: "tool_uses", value: 2 },
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
break;
|
|
55
|
+
case "teammate": {
|
|
56
|
+
const ctxMgmt = getContextManagement(model);
|
|
57
|
+
betas = [...ctxMgmt.betas];
|
|
58
|
+
edits = ctxMgmt.config.edits;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Thinking config
|
|
63
|
+
const thinkingCfg = getThinkingConfig(model, thinkingEnabled);
|
|
64
|
+
if (thinkingCfg.beta)
|
|
65
|
+
betas.push(thinkingCfg.beta);
|
|
66
|
+
// Max tokens — caller is responsible for setting appropriate limits per context
|
|
67
|
+
const maxTokens = getMaxOutputTokens(model, maxOutputTokens);
|
|
68
|
+
// Build thinking param (ensure budget < maxTokens)
|
|
69
|
+
// Only include for Anthropic/Bedrock — Gemini/OpenAI handle thinking internally
|
|
70
|
+
let thinking;
|
|
71
|
+
if (isAnthropicModel && thinkingCfg.thinking.type !== "disabled") {
|
|
72
|
+
thinking = thinkingCfg.thinking.budget_tokens
|
|
73
|
+
? { ...thinkingCfg.thinking, budget_tokens: Math.min(thinkingCfg.thinking.budget_tokens, maxTokens - 1) }
|
|
74
|
+
: thinkingCfg.thinking;
|
|
75
|
+
}
|
|
76
|
+
// Strip clear_thinking edits when thinking is disabled — API requires thinking
|
|
77
|
+
// to be enabled or adaptive for clear_thinking_20251015 to be accepted
|
|
78
|
+
if (!thinking) {
|
|
79
|
+
edits = edits.filter(e => e.type !== "clear_thinking_20251015");
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
betas,
|
|
83
|
+
contextManagement: { edits },
|
|
84
|
+
thinking,
|
|
85
|
+
maxTokens,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Call server proxy endpoint and return raw SSE stream.
|
|
90
|
+
* Retries with exponential backoff on 429/500/529.
|
|
91
|
+
*/
|
|
92
|
+
export async function callServerProxy(config) {
|
|
93
|
+
const { proxyUrl, signal, timeoutMs } = config;
|
|
94
|
+
let tokenRefreshed = false;
|
|
95
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
96
|
+
try {
|
|
97
|
+
const body = {
|
|
98
|
+
mode: "proxy",
|
|
99
|
+
messages: config.messages,
|
|
100
|
+
system: config.system,
|
|
101
|
+
tools: config.tools,
|
|
102
|
+
model: config.model,
|
|
103
|
+
max_tokens: config.apiConfig.maxTokens,
|
|
104
|
+
stream: true,
|
|
105
|
+
betas: config.apiConfig.betas,
|
|
106
|
+
...(config.apiConfig.contextManagement?.edits?.length
|
|
107
|
+
? { context_management: config.apiConfig.contextManagement }
|
|
108
|
+
: {}),
|
|
109
|
+
};
|
|
110
|
+
if (config.apiConfig.thinking) {
|
|
111
|
+
body.thinking = config.apiConfig.thinking;
|
|
112
|
+
}
|
|
113
|
+
if (config.storeId) {
|
|
114
|
+
body.store_id = config.storeId;
|
|
115
|
+
}
|
|
116
|
+
const fetchOpts = {
|
|
117
|
+
method: "POST",
|
|
118
|
+
headers: {
|
|
119
|
+
"Content-Type": "application/json",
|
|
120
|
+
"Authorization": `Bearer ${config.token}`,
|
|
121
|
+
},
|
|
122
|
+
body: JSON.stringify(body),
|
|
123
|
+
signal,
|
|
124
|
+
};
|
|
125
|
+
// Apply timeout if specified
|
|
126
|
+
let controller;
|
|
127
|
+
let timeout;
|
|
128
|
+
if (timeoutMs && !signal) {
|
|
129
|
+
controller = new AbortController();
|
|
130
|
+
timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
131
|
+
fetchOpts.signal = controller.signal;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
const response = await fetch(proxyUrl, fetchOpts);
|
|
135
|
+
if (timeout)
|
|
136
|
+
clearTimeout(timeout);
|
|
137
|
+
if (response.ok && response.body) {
|
|
138
|
+
return response.body;
|
|
139
|
+
}
|
|
140
|
+
const errorBody = await response.text();
|
|
141
|
+
// Auto-refresh on 401 (token invalidated server-side before local expiry)
|
|
142
|
+
if (response.status === 401 && config.onTokenRefresh && !tokenRefreshed) {
|
|
143
|
+
const newToken = await config.onTokenRefresh();
|
|
144
|
+
if (newToken) {
|
|
145
|
+
tokenRefreshed = true;
|
|
146
|
+
config.token = newToken;
|
|
147
|
+
continue; // retry with new token
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
throw Object.assign(new Error(`Proxy error (${response.status}): ${errorBody}`), { status: response.status });
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
if (timeout)
|
|
154
|
+
clearTimeout(timeout);
|
|
155
|
+
throw err;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
if (signal?.aborted)
|
|
160
|
+
throw err;
|
|
161
|
+
if (attempt < MAX_RETRIES && isRetryableError(err)) {
|
|
162
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
163
|
+
config.onRetry?.(attempt + 1, MAX_RETRIES, errMsg);
|
|
164
|
+
const delay = RETRY_BASE_DELAY_MS * Math.pow(2, attempt);
|
|
165
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
166
|
+
// Fallback model on last retry
|
|
167
|
+
if (attempt === MAX_RETRIES - 1 && config.fallbackModel) {
|
|
168
|
+
const fromModel = config.model;
|
|
169
|
+
config.model = config.fallbackModel;
|
|
170
|
+
config.onFallback?.(fromModel, config.model);
|
|
171
|
+
}
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
throw err;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
throw new Error("Failed to get response after retries");
|
|
178
|
+
}
|
|
179
|
+
// ============================================================================
|
|
180
|
+
// HELPERS — system prompt + caching setup
|
|
181
|
+
// ============================================================================
|
|
182
|
+
/**
|
|
183
|
+
* Build system blocks with prompt caching.
|
|
184
|
+
* Cached system prompt + optional dynamic cost context (after cache breakpoint).
|
|
185
|
+
*/
|
|
186
|
+
export function buildSystemBlocks(systemPrompt, costContext, enableCaching = true) {
|
|
187
|
+
const system = [];
|
|
188
|
+
if (enableCaching) {
|
|
189
|
+
system.push({
|
|
190
|
+
type: "text",
|
|
191
|
+
text: systemPrompt,
|
|
192
|
+
cache_control: { type: "ephemeral" },
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
system.push({ type: "text", text: systemPrompt });
|
|
197
|
+
}
|
|
198
|
+
if (costContext) {
|
|
199
|
+
system.push({ type: "text", text: costContext });
|
|
200
|
+
}
|
|
201
|
+
return system;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Prepare messages and tools with prompt caching.
|
|
205
|
+
* Skips cache_control injection for Gemini (uses implicit caching).
|
|
206
|
+
*/
|
|
207
|
+
export function prepareWithCaching(tools, messages, model) {
|
|
208
|
+
if (model) {
|
|
209
|
+
const provider = getProvider(model);
|
|
210
|
+
if (provider === "gemini" || provider === "openai") {
|
|
211
|
+
return { tools, messages };
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return addPromptCaching(tools, messages);
|
|
215
|
+
}
|
|
216
|
+
// ============================================================================
|
|
217
|
+
// GEMINI CONTEXT TRIMMING
|
|
218
|
+
// ============================================================================
|
|
219
|
+
/**
|
|
220
|
+
* Client-side context trimming for Gemini (no server-side context management).
|
|
221
|
+
* When estimated input tokens exceed threshold, replaces old tool result contents
|
|
222
|
+
* with "[trimmed]" to stay within Gemini's 1M context window.
|
|
223
|
+
*/
|
|
224
|
+
export function trimGeminiContext(messages, estimatedTokens, threshold = 950_000, keepRecent = 5) {
|
|
225
|
+
if (estimatedTokens < threshold)
|
|
226
|
+
return messages;
|
|
227
|
+
// Find all tool_result blocks and trim oldest ones
|
|
228
|
+
let toolResultCount = 0;
|
|
229
|
+
for (const msg of messages) {
|
|
230
|
+
if (Array.isArray(msg.content)) {
|
|
231
|
+
for (const block of msg.content) {
|
|
232
|
+
if (block.type === "tool_result")
|
|
233
|
+
toolResultCount++;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (toolResultCount <= keepRecent)
|
|
238
|
+
return messages;
|
|
239
|
+
const trimCount = toolResultCount - keepRecent;
|
|
240
|
+
let trimmed = 0;
|
|
241
|
+
return messages.map((msg) => {
|
|
242
|
+
if (!Array.isArray(msg.content))
|
|
243
|
+
return msg;
|
|
244
|
+
const content = msg.content.map((block) => {
|
|
245
|
+
if (block.type === "tool_result" && trimmed < trimCount) {
|
|
246
|
+
trimmed++;
|
|
247
|
+
if (typeof block.content === "string") {
|
|
248
|
+
return { ...block, content: "[trimmed]" };
|
|
249
|
+
}
|
|
250
|
+
else if (Array.isArray(block.content)) {
|
|
251
|
+
return { ...block, content: [{ type: "text", text: "[trimmed]" }] };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return block;
|
|
255
|
+
});
|
|
256
|
+
return { ...msg, content };
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
// ============================================================================
|
|
260
|
+
// OPENAI CONTEXT TRIMMING
|
|
261
|
+
// ============================================================================
|
|
262
|
+
/**
|
|
263
|
+
* Client-side context trimming for OpenAI (no server-side context management).
|
|
264
|
+
* When estimated input tokens exceed threshold, replaces old tool result contents
|
|
265
|
+
* with "[trimmed]" to stay within OpenAI's 200K context window.
|
|
266
|
+
*/
|
|
267
|
+
// ============================================================================
|
|
268
|
+
// AUDIO TRANSCRIPTION CLIENT
|
|
269
|
+
// ============================================================================
|
|
270
|
+
/**
|
|
271
|
+
* Call server transcription endpoint (OpenAI Whisper via our Fly.io proxy).
|
|
272
|
+
* Used by tool-dispatch when __AUDIO__ marker is detected in tool results.
|
|
273
|
+
*/
|
|
274
|
+
export async function callTranscribe(opts) {
|
|
275
|
+
const { proxyUrl, token, storeId, audioBase64, mediaType } = opts;
|
|
276
|
+
// Use same server URL as proxy, just different mode
|
|
277
|
+
const response = await fetch(proxyUrl, {
|
|
278
|
+
method: "POST",
|
|
279
|
+
headers: {
|
|
280
|
+
"Content-Type": "application/json",
|
|
281
|
+
Authorization: `Bearer ${token}`,
|
|
282
|
+
},
|
|
283
|
+
body: JSON.stringify({
|
|
284
|
+
mode: "transcribe",
|
|
285
|
+
audio_base64: audioBase64,
|
|
286
|
+
media_type: mediaType,
|
|
287
|
+
store_id: storeId,
|
|
288
|
+
}),
|
|
289
|
+
});
|
|
290
|
+
if (!response.ok) {
|
|
291
|
+
const errText = await response.text();
|
|
292
|
+
throw new Error(`Transcription failed (${response.status}): ${errText}`);
|
|
293
|
+
}
|
|
294
|
+
const data = (await response.json());
|
|
295
|
+
if (!data.success || !data.transcript) {
|
|
296
|
+
throw new Error(data.error || "Transcription returned no transcript");
|
|
297
|
+
}
|
|
298
|
+
return data.transcript;
|
|
299
|
+
}
|
|
300
|
+
// ============================================================================
|
|
301
|
+
// OPENAI CONTEXT TRIMMING
|
|
302
|
+
// ============================================================================
|
|
303
|
+
export function trimOpenAIContext(messages, estimatedTokens, threshold = 190_000, keepRecent = 5) {
|
|
304
|
+
if (estimatedTokens < threshold)
|
|
305
|
+
return messages;
|
|
306
|
+
// Find all tool_result blocks and trim oldest ones
|
|
307
|
+
let toolResultCount = 0;
|
|
308
|
+
for (const msg of messages) {
|
|
309
|
+
if (Array.isArray(msg.content)) {
|
|
310
|
+
for (const block of msg.content) {
|
|
311
|
+
if (block.type === "tool_result")
|
|
312
|
+
toolResultCount++;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (toolResultCount <= keepRecent)
|
|
317
|
+
return messages;
|
|
318
|
+
const trimCount = toolResultCount - keepRecent;
|
|
319
|
+
let trimmed = 0;
|
|
320
|
+
return messages.map((msg) => {
|
|
321
|
+
if (!Array.isArray(msg.content))
|
|
322
|
+
return msg;
|
|
323
|
+
const content = msg.content.map((block) => {
|
|
324
|
+
if (block.type === "tool_result" && trimmed < trimCount) {
|
|
325
|
+
trimmed++;
|
|
326
|
+
if (typeof block.content === "string") {
|
|
327
|
+
return { ...block, content: "[trimmed]" };
|
|
328
|
+
}
|
|
329
|
+
else if (Array.isArray(block.content)) {
|
|
330
|
+
return { ...block, content: [{ type: "text", text: "[trimmed]" }] };
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return block;
|
|
334
|
+
});
|
|
335
|
+
return { ...msg, content };
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
// ============================================================================
|
|
339
|
+
// PROVIDER COMPACTION CLIENT
|
|
340
|
+
// ============================================================================
|
|
341
|
+
const COMPACTION_TIMEOUT_MS = 30_000;
|
|
342
|
+
/**
|
|
343
|
+
* Request conversation compaction from the server (Haiku summarization).
|
|
344
|
+
* Used by non-Anthropic providers (OpenAI, Gemini) that lack native compaction.
|
|
345
|
+
* Returns summary string or null on failure (caller keeps unsummarized history).
|
|
346
|
+
*/
|
|
347
|
+
export async function requestProviderCompaction(opts) {
|
|
348
|
+
const { proxyUrl, token, messages, systemPrompt } = opts;
|
|
349
|
+
try {
|
|
350
|
+
const controller = new AbortController();
|
|
351
|
+
const timeout = setTimeout(() => controller.abort(), COMPACTION_TIMEOUT_MS);
|
|
352
|
+
try {
|
|
353
|
+
const response = await fetch(proxyUrl, {
|
|
354
|
+
method: "POST",
|
|
355
|
+
headers: {
|
|
356
|
+
"Content-Type": "application/json",
|
|
357
|
+
Authorization: `Bearer ${token}`,
|
|
358
|
+
},
|
|
359
|
+
body: JSON.stringify({
|
|
360
|
+
mode: "compact",
|
|
361
|
+
messages,
|
|
362
|
+
system_prompt: systemPrompt,
|
|
363
|
+
}),
|
|
364
|
+
signal: controller.signal,
|
|
365
|
+
});
|
|
366
|
+
clearTimeout(timeout);
|
|
367
|
+
if (!response.ok)
|
|
368
|
+
return null;
|
|
369
|
+
const data = (await response.json());
|
|
370
|
+
return data.success && data.compaction_content ? data.compaction_content : null;
|
|
371
|
+
}
|
|
372
|
+
finally {
|
|
373
|
+
clearTimeout(timeout);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
return null; // Graceful failure — caller keeps unsummarized history
|
|
378
|
+
}
|
|
379
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared constants — single source of truth for model IDs, thresholds, and limits.
|
|
3
|
+
*/
|
|
4
|
+
export type ModelProvider = "anthropic" | "bedrock" | "gemini" | "openai";
|
|
5
|
+
export declare const MODELS: {
|
|
6
|
+
readonly OPUS: "claude-opus-4-6";
|
|
7
|
+
readonly SONNET: "claude-sonnet-4-6";
|
|
8
|
+
readonly SONNET_4: "claude-sonnet-4-20250514";
|
|
9
|
+
readonly HAIKU: "claude-haiku-4-5-20251001";
|
|
10
|
+
readonly BEDROCK_SONNET: "anthropic.claude-sonnet-4-6";
|
|
11
|
+
readonly BEDROCK_SONNET_4: "us.anthropic.claude-sonnet-4-20250514-v1:0";
|
|
12
|
+
readonly BEDROCK_SONNET_45: "us.anthropic.claude-sonnet-4-5-20250929-v1:0";
|
|
13
|
+
readonly BEDROCK_HAIKU: "us.anthropic.claude-haiku-4-5-20251001-v1:0";
|
|
14
|
+
readonly GEMINI_3_PRO: "gemini-3-pro-preview";
|
|
15
|
+
readonly GEMINI_3_FLASH: "gemini-3-flash-preview";
|
|
16
|
+
readonly GEMINI_25_PRO: "gemini-2.5-pro";
|
|
17
|
+
readonly GEMINI_25_FLASH: "gemini-2.5-flash";
|
|
18
|
+
readonly GEMINI_25_FLASH_LITE: "gemini-2.5-flash-lite";
|
|
19
|
+
readonly GPT_5: "gpt-5";
|
|
20
|
+
readonly GPT_5_MINI: "gpt-5-mini";
|
|
21
|
+
readonly GPT_5_NANO: "gpt-5-nano";
|
|
22
|
+
readonly O3: "o3";
|
|
23
|
+
readonly O4_MINI: "o4-mini";
|
|
24
|
+
readonly GPT_4O: "gpt-4o";
|
|
25
|
+
};
|
|
26
|
+
/** Maps short model aliases to full model IDs */
|
|
27
|
+
export declare const MODEL_MAP: Record<string, string>;
|
|
28
|
+
/** Allowed model IDs for server validation */
|
|
29
|
+
export declare const ALLOWED_MODELS: string[];
|
|
30
|
+
/** Detect provider from full model ID */
|
|
31
|
+
export declare function getProvider(modelId: string): ModelProvider;
|
|
32
|
+
/** Check if an OpenAI model is a reasoning model (o-series) */
|
|
33
|
+
export declare function isOpenAIReasoningModel(modelId: string): boolean;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared constants — single source of truth for model IDs, thresholds, and limits.
|
|
3
|
+
*/
|
|
4
|
+
export const MODELS = {
|
|
5
|
+
// Anthropic (direct API)
|
|
6
|
+
OPUS: "claude-opus-4-6",
|
|
7
|
+
SONNET: "claude-sonnet-4-6",
|
|
8
|
+
SONNET_4: "claude-sonnet-4-20250514",
|
|
9
|
+
HAIKU: "claude-haiku-4-5-20251001",
|
|
10
|
+
// Bedrock (Claude on AWS)
|
|
11
|
+
BEDROCK_SONNET: "anthropic.claude-sonnet-4-6",
|
|
12
|
+
BEDROCK_SONNET_4: "us.anthropic.claude-sonnet-4-20250514-v1:0",
|
|
13
|
+
BEDROCK_SONNET_45: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
14
|
+
BEDROCK_HAIKU: "us.anthropic.claude-haiku-4-5-20251001-v1:0",
|
|
15
|
+
// Google Gemini
|
|
16
|
+
GEMINI_3_PRO: "gemini-3-pro-preview",
|
|
17
|
+
GEMINI_3_FLASH: "gemini-3-flash-preview",
|
|
18
|
+
GEMINI_25_PRO: "gemini-2.5-pro",
|
|
19
|
+
GEMINI_25_FLASH: "gemini-2.5-flash",
|
|
20
|
+
GEMINI_25_FLASH_LITE: "gemini-2.5-flash-lite",
|
|
21
|
+
// OpenAI
|
|
22
|
+
GPT_5: "gpt-5",
|
|
23
|
+
GPT_5_MINI: "gpt-5-mini",
|
|
24
|
+
GPT_5_NANO: "gpt-5-nano",
|
|
25
|
+
O3: "o3",
|
|
26
|
+
O4_MINI: "o4-mini",
|
|
27
|
+
GPT_4O: "gpt-4o",
|
|
28
|
+
};
|
|
29
|
+
/** Maps short model aliases to full model IDs */
|
|
30
|
+
export const MODEL_MAP = {
|
|
31
|
+
// Auto-routing (resolved at runtime by model-router)
|
|
32
|
+
auto: "auto",
|
|
33
|
+
// Anthropic
|
|
34
|
+
"whale/agent": MODELS.OPUS, // OpenClaw bridge sends this model ID
|
|
35
|
+
opus: MODELS.OPUS,
|
|
36
|
+
sonnet: MODELS.SONNET,
|
|
37
|
+
"sonnet-4.6": MODELS.SONNET,
|
|
38
|
+
"sonnet-4": MODELS.SONNET_4,
|
|
39
|
+
haiku: MODELS.HAIKU,
|
|
40
|
+
// Bedrock
|
|
41
|
+
"bedrock-sonnet": MODELS.BEDROCK_SONNET,
|
|
42
|
+
"bedrock-sonnet-4": MODELS.BEDROCK_SONNET_4,
|
|
43
|
+
"bedrock-sonnet-4.5": MODELS.BEDROCK_SONNET_45,
|
|
44
|
+
"bedrock-haiku": MODELS.BEDROCK_HAIKU,
|
|
45
|
+
// Gemini
|
|
46
|
+
"gemini-3-pro": MODELS.GEMINI_3_PRO,
|
|
47
|
+
"gemini-3-flash": MODELS.GEMINI_3_FLASH,
|
|
48
|
+
"gemini-pro": MODELS.GEMINI_25_PRO,
|
|
49
|
+
"gemini-flash": MODELS.GEMINI_25_FLASH,
|
|
50
|
+
"gemini-flash-lite": MODELS.GEMINI_25_FLASH_LITE,
|
|
51
|
+
// OpenAI
|
|
52
|
+
"gpt-5": MODELS.GPT_5,
|
|
53
|
+
"5": MODELS.GPT_5,
|
|
54
|
+
"gpt-5-mini": MODELS.GPT_5_MINI,
|
|
55
|
+
"5-mini": MODELS.GPT_5_MINI,
|
|
56
|
+
"gpt-5-nano": MODELS.GPT_5_NANO,
|
|
57
|
+
"5-nano": MODELS.GPT_5_NANO,
|
|
58
|
+
"o3": MODELS.O3,
|
|
59
|
+
"o4-mini": MODELS.O4_MINI,
|
|
60
|
+
"gpt-4o": MODELS.GPT_4O,
|
|
61
|
+
"4o": MODELS.GPT_4O,
|
|
62
|
+
};
|
|
63
|
+
/** Allowed model IDs for server validation */
|
|
64
|
+
export const ALLOWED_MODELS = [...Object.values(MODELS), "auto"];
|
|
65
|
+
/** Detect provider from full model ID */
|
|
66
|
+
export function getProvider(modelId) {
|
|
67
|
+
if (modelId === "auto")
|
|
68
|
+
return "anthropic"; // auto resolves to Claude models
|
|
69
|
+
if (modelId.includes(".anthropic.") || modelId.startsWith("anthropic."))
|
|
70
|
+
return "bedrock";
|
|
71
|
+
if (modelId.startsWith("gemini-"))
|
|
72
|
+
return "gemini";
|
|
73
|
+
if (modelId.startsWith("gpt-") || /^o\d/.test(modelId))
|
|
74
|
+
return "openai";
|
|
75
|
+
return "anthropic";
|
|
76
|
+
}
|
|
77
|
+
/** Check if an OpenAI model is a reasoning model (o-series) */
|
|
78
|
+
export function isOpenAIReasoningModel(modelId) {
|
|
79
|
+
return /^o\d/.test(modelId);
|
|
80
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified SSE Parser — ONE implementation replacing 4 duplicates.
|
|
3
|
+
*
|
|
4
|
+
* Used by:
|
|
5
|
+
* - agent-loop.ts (processStreamWithCallbacks for real-time UI)
|
|
6
|
+
* - subagent.ts (collectStreamResult for batch collection)
|
|
7
|
+
* - teammate.ts (collectStreamResult for batch collection)
|
|
8
|
+
* - server-agent-loop.ts (processStreamWithCallbacks for SSE relay)
|
|
9
|
+
*/
|
|
10
|
+
import type { BetaStreamEvent } from "./anthropic-types.js";
|
|
11
|
+
import type { StreamResult, StreamCallbacks } from "./types.js";
|
|
12
|
+
/**
|
|
13
|
+
* Parse SSE stream from proxy HTTP response into typed events.
|
|
14
|
+
* Handles `data: {...}\n\n` format with [DONE] sentinel.
|
|
15
|
+
*/
|
|
16
|
+
export declare function parseSSEStream(body: ReadableStream<Uint8Array>, signal?: AbortSignal): AsyncGenerator<BetaStreamEvent>;
|
|
17
|
+
/**
|
|
18
|
+
* Collect all events into a StreamResult. No callbacks — used by
|
|
19
|
+
* subagent and teammate where real-time text isn't needed.
|
|
20
|
+
*/
|
|
21
|
+
export declare function collectStreamResult(events: AsyncIterable<BetaStreamEvent>): Promise<StreamResult>;
|
|
22
|
+
/**
|
|
23
|
+
* Process streaming events with optional real-time callbacks.
|
|
24
|
+
* Used by agent-loop (needs onText for UI) and as internal impl for collect.
|
|
25
|
+
*/
|
|
26
|
+
export declare function processStreamWithCallbacks(events: AsyncIterable<BetaStreamEvent>, callbacks: StreamCallbacks, signal?: AbortSignal): Promise<StreamResult>;
|