apteva 0.4.57 → 0.7.1

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.
Files changed (142) hide show
  1. package/README.md +216 -54
  2. package/cli.js +35 -0
  3. package/install.js +92 -0
  4. package/package.json +15 -76
  5. package/LICENSE +0 -63
  6. package/bin/apteva.js +0 -196
  7. package/dist/ActivityPage.kxzzb4yc.js +0 -3
  8. package/dist/ApiDocsPage.zq998hbm.js +0 -4
  9. package/dist/App.55rea8mn.js +0 -61
  10. package/dist/App.5ywb23z4.js +0 -53
  11. package/dist/App.6thds120.js +0 -4
  12. package/dist/App.9tctxzqm.js +0 -8
  13. package/dist/App.a8r8ttaz.js +0 -4
  14. package/dist/App.agsv5bje.js +0 -4
  15. package/dist/App.cepapqmx.js +0 -4
  16. package/dist/App.dp041gb3.js +0 -221
  17. package/dist/App.fds72zb5.js +0 -4
  18. package/dist/App.fg9qj2dq.js +0 -4
  19. package/dist/App.ndfejbm9.js +0 -4
  20. package/dist/App.nxmfmq1h.js +0 -13
  21. package/dist/App.qdfyt8ba.js +0 -4
  22. package/dist/App.x2d0ygt6.js +0 -4
  23. package/dist/App.yt9p4nr3.js +0 -20
  24. package/dist/App.zn4mw16t.js +0 -1
  25. package/dist/ConnectionsPage.8r96ryw7.js +0 -3
  26. package/dist/McpPage.3cwh0gnd.js +0 -3
  27. package/dist/SettingsPage.ykgdh5ev.js +0 -3
  28. package/dist/SkillsPage.4np1s65b.js +0 -3
  29. package/dist/TasksPage.4g08t7p6.js +0 -3
  30. package/dist/TelemetryPage.72w9pwcp.js +0 -3
  31. package/dist/TestsPage.z4fk3r7r.js +0 -3
  32. package/dist/ThreadsPage.63tcajeh.js +0 -3
  33. package/dist/apteva-kit.css +0 -1
  34. package/dist/icon.png +0 -0
  35. package/dist/index.html +0 -16
  36. package/dist/styles.css +0 -1
  37. package/scripts/postinstall.mjs +0 -102
  38. package/src/auth/index.ts +0 -394
  39. package/src/auth/middleware.ts +0 -213
  40. package/src/binary.ts +0 -536
  41. package/src/channels/index.ts +0 -40
  42. package/src/channels/telegram.ts +0 -311
  43. package/src/crypto.ts +0 -301
  44. package/src/db-tests.ts +0 -174
  45. package/src/db.ts +0 -3133
  46. package/src/integrations/agentdojo.ts +0 -559
  47. package/src/integrations/composio.ts +0 -437
  48. package/src/integrations/index.ts +0 -87
  49. package/src/integrations/skillsmp.ts +0 -318
  50. package/src/mcp-client.ts +0 -605
  51. package/src/mcp-handler.ts +0 -394
  52. package/src/mcp-platform.ts +0 -2403
  53. package/src/openapi.ts +0 -2410
  54. package/src/providers.ts +0 -597
  55. package/src/routes/api/agent-utils.ts +0 -890
  56. package/src/routes/api/agents.ts +0 -916
  57. package/src/routes/api/api-keys.ts +0 -95
  58. package/src/routes/api/channels.ts +0 -182
  59. package/src/routes/api/helpers.ts +0 -12
  60. package/src/routes/api/integrations.ts +0 -639
  61. package/src/routes/api/mcp.ts +0 -574
  62. package/src/routes/api/meta-agent.ts +0 -195
  63. package/src/routes/api/projects.ts +0 -112
  64. package/src/routes/api/providers.ts +0 -424
  65. package/src/routes/api/skills.ts +0 -537
  66. package/src/routes/api/system.ts +0 -333
  67. package/src/routes/api/telemetry.ts +0 -203
  68. package/src/routes/api/tests.ts +0 -148
  69. package/src/routes/api/triggers.ts +0 -518
  70. package/src/routes/api/users.ts +0 -148
  71. package/src/routes/api/webhooks.ts +0 -171
  72. package/src/routes/api.ts +0 -53
  73. package/src/routes/auth.ts +0 -251
  74. package/src/routes/share.ts +0 -86
  75. package/src/routes/static.ts +0 -131
  76. package/src/server.ts +0 -642
  77. package/src/test-runner.ts +0 -598
  78. package/src/triggers/agentdojo.ts +0 -253
  79. package/src/triggers/composio.ts +0 -264
  80. package/src/triggers/index.ts +0 -71
  81. package/src/tui/AgentList.tsx +0 -145
  82. package/src/tui/App.tsx +0 -102
  83. package/src/tui/Login.tsx +0 -104
  84. package/src/tui/api.ts +0 -72
  85. package/src/tui/index.tsx +0 -7
  86. package/src/web/App.tsx +0 -455
  87. package/src/web/components/activity/ActivityPage.tsx +0 -314
  88. package/src/web/components/activity/index.ts +0 -1
  89. package/src/web/components/agents/AgentCard.tsx +0 -189
  90. package/src/web/components/agents/AgentPanel.tsx +0 -2244
  91. package/src/web/components/agents/AgentsView.tsx +0 -180
  92. package/src/web/components/agents/CreateAgentModal.tsx +0 -475
  93. package/src/web/components/agents/index.ts +0 -4
  94. package/src/web/components/api/ApiDocsPage.tsx +0 -842
  95. package/src/web/components/auth/CreateAccountStep.tsx +0 -176
  96. package/src/web/components/auth/LoginPage.tsx +0 -91
  97. package/src/web/components/auth/index.ts +0 -2
  98. package/src/web/components/common/Icons.tsx +0 -250
  99. package/src/web/components/common/LoadingSpinner.tsx +0 -44
  100. package/src/web/components/common/Modal.tsx +0 -199
  101. package/src/web/components/common/Select.tsx +0 -97
  102. package/src/web/components/common/index.ts +0 -20
  103. package/src/web/components/connections/ConnectionsPage.tsx +0 -54
  104. package/src/web/components/connections/IntegrationsTab.tsx +0 -170
  105. package/src/web/components/connections/OverviewTab.tsx +0 -137
  106. package/src/web/components/connections/TriggersTab.tsx +0 -1346
  107. package/src/web/components/dashboard/Dashboard.tsx +0 -572
  108. package/src/web/components/dashboard/index.ts +0 -1
  109. package/src/web/components/index.ts +0 -21
  110. package/src/web/components/layout/ErrorBanner.tsx +0 -18
  111. package/src/web/components/layout/Header.tsx +0 -332
  112. package/src/web/components/layout/Sidebar.tsx +0 -231
  113. package/src/web/components/layout/index.ts +0 -3
  114. package/src/web/components/mcp/IntegrationsPanel.tsx +0 -857
  115. package/src/web/components/mcp/McpPage.tsx +0 -2515
  116. package/src/web/components/mcp/index.ts +0 -1
  117. package/src/web/components/meta-agent/MetaAgent.tsx +0 -245
  118. package/src/web/components/onboarding/OnboardingWizard.tsx +0 -404
  119. package/src/web/components/onboarding/index.ts +0 -1
  120. package/src/web/components/settings/SettingsPage.tsx +0 -2776
  121. package/src/web/components/settings/index.ts +0 -1
  122. package/src/web/components/skills/SkillsPage.tsx +0 -1200
  123. package/src/web/components/tasks/TasksPage.tsx +0 -1116
  124. package/src/web/components/tasks/index.ts +0 -1
  125. package/src/web/components/telemetry/TelemetryPage.tsx +0 -1129
  126. package/src/web/components/tests/TestsPage.tsx +0 -594
  127. package/src/web/components/threads/ThreadsPage.tsx +0 -315
  128. package/src/web/context/AuthContext.tsx +0 -242
  129. package/src/web/context/ProjectContext.tsx +0 -214
  130. package/src/web/context/TelemetryContext.tsx +0 -299
  131. package/src/web/context/ThemeContext.tsx +0 -90
  132. package/src/web/context/UIModeContext.tsx +0 -49
  133. package/src/web/context/index.ts +0 -12
  134. package/src/web/hooks/index.ts +0 -3
  135. package/src/web/hooks/useAgents.ts +0 -115
  136. package/src/web/hooks/useOnboarding.ts +0 -20
  137. package/src/web/hooks/useProviders.ts +0 -75
  138. package/src/web/icon.png +0 -0
  139. package/src/web/index.html +0 -16
  140. package/src/web/styles.css +0 -118
  141. package/src/web/themes.ts +0 -162
  142. package/src/web/types.ts +0 -298
package/src/providers.ts DELETED
@@ -1,597 +0,0 @@
1
- import { ProviderKeysDB, SettingsDB } from "./db";
2
- import { encrypt, decrypt, createKeyHint, validateKeyFormat } from "./crypto";
3
-
4
- // Provider configuration with API URLs and key testing endpoints
5
- export const PROVIDERS = {
6
- anthropic: {
7
- id: "anthropic",
8
- name: "Anthropic",
9
- displayName: "Anthropic",
10
- type: "llm" as const,
11
- envVar: "ANTHROPIC_API_KEY",
12
- docsUrl: "https://console.anthropic.com/settings/keys",
13
- testEndpoint: "https://api.anthropic.com/v1/messages",
14
- models: [
15
- { value: "claude-sonnet-4-6", label: "Claude Sonnet 4.6", recommended: true, input_cost: 3, output_cost: 15, cache_creation_cost: 3.75, cache_read_cost: 0.3 },
16
- { value: "claude-haiku-4-5", label: "Claude Haiku 4.5 (Fast)", input_cost: 0.8, output_cost: 4, cache_creation_cost: 1, cache_read_cost: 0.08 },
17
- ],
18
- },
19
- openai: {
20
- id: "openai",
21
- name: "OpenAI",
22
- displayName: "OpenAI",
23
- type: "llm" as const,
24
- envVar: "OPENAI_API_KEY",
25
- docsUrl: "https://platform.openai.com/api-keys",
26
- testEndpoint: "https://api.openai.com/v1/models",
27
- models: [
28
- { value: "gpt-5.4", label: "GPT-5.4 (Latest)", recommended: true, input_cost: 2.5, output_cost: 10 },
29
- ],
30
- },
31
- groq: {
32
- id: "groq",
33
- name: "Groq",
34
- displayName: "Groq",
35
- type: "llm" as const,
36
- envVar: "GROQ_API_KEY",
37
- docsUrl: "https://console.groq.com/keys",
38
- testEndpoint: "https://api.groq.com/openai/v1/models",
39
- models: [
40
- { value: "llama-3.3-70b-versatile", label: "Llama 3.3 70B", recommended: true, input_cost: 0, output_cost: 0 },
41
- { value: "llama-3.1-8b-instant", label: "Llama 3.1 8B (Fast)", input_cost: 0, output_cost: 0 },
42
- ],
43
- },
44
- gemini: {
45
- id: "gemini",
46
- name: "Google",
47
- displayName: "Google Gemini",
48
- type: "llm" as const,
49
- envVar: "GEMINI_API_KEY",
50
- docsUrl: "https://aistudio.google.com/app/apikey",
51
- testEndpoint: "https://generativelanguage.googleapis.com/v1/models",
52
- models: [
53
- { value: "gemini-3.1-pro-preview", label: "Gemini 3.1 Pro Preview (Latest)", recommended: true, input_cost: 2, output_cost: 12 },
54
- { value: "gemini-3-pro-preview", label: "Gemini 3 Pro Preview", input_cost: 2, output_cost: 12 },
55
- { value: "gemini-3.1-flash-lite-preview", label: "Gemini 3.1 Flash Lite Preview (Fast)", input_cost: 0.25, output_cost: 1.5 },
56
- { value: "gemini-3-flash-preview", label: "Gemini 3 Flash Preview", input_cost: 0.5, output_cost: 3 },
57
- ],
58
- },
59
- xai: {
60
- id: "xai",
61
- name: "xAI",
62
- displayName: "xAI Grok",
63
- type: "llm" as const,
64
- envVar: "XAI_API_KEY",
65
- docsUrl: "https://console.x.ai/",
66
- testEndpoint: "https://api.x.ai/v1/models",
67
- models: [
68
- { value: "grok-2", label: "Grok 2", recommended: true, input_cost: 2, output_cost: 10 },
69
- { value: "grok-2-mini", label: "Grok 2 Mini (Fast)", input_cost: 0.3, output_cost: 1 },
70
- ],
71
- },
72
- together: {
73
- id: "together",
74
- name: "Together",
75
- displayName: "Together AI",
76
- type: "llm" as const,
77
- envVar: "TOGETHER_API_KEY",
78
- docsUrl: "https://api.together.xyz/settings/api-keys",
79
- testEndpoint: "https://api.together.xyz/v1/models",
80
- models: [
81
- { value: "moonshotai/Kimi-K2.5", label: "Kimi K2.5", recommended: true, input_cost: 1, output_cost: 4 },
82
- { value: "moonshotai/Kimi-K2-Thinking", label: "Kimi K2 Thinking (Reasoning)", input_cost: 1, output_cost: 4 },
83
- ],
84
- },
85
- fireworks: {
86
- id: "fireworks",
87
- name: "Fireworks",
88
- displayName: "Fireworks AI",
89
- type: "llm" as const,
90
- envVar: "FIREWORKS_API_KEY",
91
- docsUrl: "https://fireworks.ai/api-keys",
92
- testEndpoint: "https://api.fireworks.ai/inference/v1/models",
93
- models: [
94
- { value: "accounts/fireworks/models/kimi-k2p5", label: "Kimi K2.5", recommended: true, input_cost: 1, output_cost: 4 },
95
- { value: "accounts/fireworks/models/kimi-k2-thinking", label: "Kimi K2 Thinking (Reasoning)", input_cost: 1, output_cost: 4 },
96
- { value: "accounts/fireworks/models/minimax-m2p5", label: "MiniMax M2.5", input_cost: 1, output_cost: 4 },
97
- { value: "accounts/fireworks/models/glm-5", label: "GLM 5", input_cost: 1, output_cost: 4 },
98
- ],
99
- },
100
- moonshot: {
101
- id: "moonshot",
102
- name: "Moonshot",
103
- displayName: "Moonshot AI",
104
- type: "llm" as const,
105
- envVar: "MOONSHOT_API_KEY",
106
- docsUrl: "https://platform.moonshot.cn/console/api-keys",
107
- testEndpoint: "https://api.moonshot.cn/v1/models",
108
- models: [
109
- { value: "moonshot-v1-128k", label: "Kimi 128K", recommended: true, input_cost: 1, output_cost: 4 },
110
- { value: "moonshot-v1-32k", label: "Kimi 32K (Fast)", input_cost: 0.5, output_cost: 2 },
111
- ],
112
- },
113
- venice: {
114
- id: "venice",
115
- name: "Venice",
116
- displayName: "Venice AI",
117
- type: "llm" as const,
118
- envVar: "VENICE_API_KEY",
119
- docsUrl: "https://docs.venice.ai/overview/pricing",
120
- testEndpoint: "https://api.venice.ai/api/v1/models",
121
- models: [
122
- { value: "llama-3.3-70b", label: "Llama 3.3 70B", recommended: true, input_cost: 0.7, output_cost: 2.8 },
123
- { value: "olafangensan-glm-4.7-flash-heretic", label: "GLM 4.7 Flash Heretic", input_cost: 0.14, output_cost: 0.8 },
124
- { value: "qwen3-235b-a22b-instruct-2507", label: "Qwen 3 235B Instruct", input_cost: 0.15, output_cost: 0.75 },
125
- { value: "deepseek-v3.2", label: "DeepSeek V3.2", input_cost: 0.4, output_cost: 1 },
126
- { value: "venice-uncensored", label: "Venice Uncensored 1.1", input_cost: 0.2, output_cost: 0.9 },
127
- ],
128
- },
129
- cerebras: {
130
- id: "cerebras",
131
- name: "Cerebras",
132
- displayName: "Cerebras",
133
- type: "llm" as const,
134
- envVar: "CEREBRAS_API_KEY",
135
- docsUrl: "https://cloud.cerebras.ai/",
136
- testEndpoint: "https://api.cerebras.ai/v1/models",
137
- models: [
138
- { value: "gpt-oss-120b", label: "GPT-OSS 120B", recommended: true, input_cost: 0.2, output_cost: 1 },
139
- { value: "llama-4-scout-17b-16e-instruct", label: "Llama 4 Scout 17B (Fast)", input_cost: 0.05, output_cost: 0.25 },
140
- { value: "llama3.3-70b", label: "Llama 3.3 70B", input_cost: 0.1, output_cost: 0.5 },
141
- ],
142
- },
143
- ollama: {
144
- id: "ollama",
145
- name: "Ollama",
146
- displayName: "Ollama (Local)",
147
- type: "llm" as const,
148
- envVar: "OLLAMA_BASE_URL",
149
- docsUrl: "https://ollama.ai/download",
150
- testEndpoint: "", // Dynamic - uses configured base URL
151
- isLocal: true,
152
- defaultBaseUrl: "http://localhost:11434",
153
- models: [
154
- // Default models - actual list fetched dynamically from Ollama
155
- { value: "llama3.3", label: "Llama 3.3 (70B)", recommended: true, input_cost: 0, output_cost: 0 },
156
- { value: "llama3.2", label: "Llama 3.2 (3B)", input_cost: 0, output_cost: 0 },
157
- { value: "qwen2.5", label: "Qwen 2.5", input_cost: 0, output_cost: 0 },
158
- { value: "mistral", label: "Mistral", input_cost: 0, output_cost: 0 },
159
- { value: "deepseek-r1", label: "DeepSeek R1", input_cost: 0, output_cost: 0 },
160
- ],
161
- },
162
- // Browser Providers
163
- browserbase: {
164
- id: "browserbase",
165
- name: "Browserbase",
166
- displayName: "Browserbase",
167
- type: "browser" as const,
168
- envVar: "BROWSERBASE_API_KEY",
169
- docsUrl: "https://www.browserbase.com/",
170
- description: "Cloud browser sessions with proxies and stealth mode",
171
- models: [],
172
- },
173
- steel: {
174
- id: "steel",
175
- name: "Steel",
176
- displayName: "Steel.dev",
177
- type: "browser" as const,
178
- envVar: "STEEL_API_KEY",
179
- docsUrl: "https://steel.dev/",
180
- description: "Cloud browser automation with CDP",
181
- models: [],
182
- },
183
- browserengine: {
184
- id: "browserengine",
185
- name: "BrowserEngine",
186
- displayName: "BrowserEngine",
187
- type: "browser" as const,
188
- envVar: "BROWSERENGINE_API_KEY",
189
- docsUrl: "https://browserengine.co",
190
- description: "Cloud browser automation with stealth browsing and proxies",
191
- models: [],
192
- },
193
- cdp: {
194
- id: "cdp",
195
- name: "CDP",
196
- displayName: "Direct CDP",
197
- type: "browser" as const,
198
- envVar: "CDP_URL",
199
- docsUrl: "",
200
- description: "Connect directly to any browser via Chrome DevTools Protocol",
201
- isLocal: true,
202
- models: [],
203
- },
204
- // Voice Providers
205
- elevenlabs: {
206
- id: "elevenlabs",
207
- name: "ElevenLabs",
208
- displayName: "ElevenLabs",
209
- type: "voice" as const,
210
- envVar: "ELEVENLABS_API_KEY",
211
- docsUrl: "https://elevenlabs.io/app/settings/api-keys",
212
- description: "Speech-to-text and text-to-speech for voice conversations",
213
- models: [],
214
- },
215
- deepgram: {
216
- id: "deepgram",
217
- name: "Deepgram",
218
- displayName: "Deepgram",
219
- type: "voice" as const,
220
- envVar: "DEEPGRAM_API_KEY",
221
- docsUrl: "https://console.deepgram.com/",
222
- description: "Fast speech-to-text and text-to-speech with low latency",
223
- models: [],
224
- },
225
- // Local Voice Providers
226
- speaches: {
227
- id: "speaches",
228
- name: "Speaches",
229
- displayName: "Speaches (Local)",
230
- type: "voice" as const,
231
- voiceSubtype: "both" as const,
232
- envVar: "SPEACHES_BASE_URL",
233
- docsUrl: "https://github.com/speaches-ai/speaches",
234
- description: "Local STT + TTS server with OpenAI-compatible API",
235
- isLocal: true,
236
- defaultBaseUrl: "http://localhost:8000",
237
- models: [
238
- { value: "Systran/faster-whisper-large-v3", label: "Whisper Large V3 (STT)", recommended: true, input_cost: 0, output_cost: 0 },
239
- { value: "Systran/faster-whisper-medium", label: "Whisper Medium (STT)", input_cost: 0, output_cost: 0 },
240
- { value: "hexgrad/Kokoro-82M", label: "Kokoro 82M (TTS)", recommended: true, input_cost: 0, output_cost: 0 },
241
- ],
242
- },
243
- whisper_cpp: {
244
- id: "whisper_cpp",
245
- name: "Whisper.cpp",
246
- displayName: "Whisper.cpp (Local)",
247
- type: "voice" as const,
248
- voiceSubtype: "stt" as const,
249
- envVar: "WHISPER_CPP_BASE_URL",
250
- docsUrl: "https://github.com/ggerganov/whisper.cpp",
251
- description: "High-performance local speech-to-text",
252
- isLocal: true,
253
- defaultBaseUrl: "http://localhost:8080",
254
- models: [
255
- { value: "large-v3", label: "Large V3", recommended: true, input_cost: 0, output_cost: 0 },
256
- { value: "large-v3-turbo", label: "Large V3 Turbo (Fast)", input_cost: 0, output_cost: 0 },
257
- { value: "medium", label: "Medium", input_cost: 0, output_cost: 0 },
258
- { value: "small", label: "Small (Fast)", input_cost: 0, output_cost: 0 },
259
- { value: "base", label: "Base (Fastest)", input_cost: 0, output_cost: 0 },
260
- ],
261
- },
262
- kokoro: {
263
- id: "kokoro",
264
- name: "Kokoro",
265
- displayName: "Kokoro (Local)",
266
- type: "voice" as const,
267
- voiceSubtype: "tts" as const,
268
- envVar: "KOKORO_BASE_URL",
269
- docsUrl: "https://github.com/remsky/Kokoro-FastAPI",
270
- description: "High-quality local text-to-speech, CPU-only, 82M params",
271
- isLocal: true,
272
- defaultBaseUrl: "http://localhost:8880",
273
- models: [
274
- { value: "kokoro", label: "Kokoro 82M", recommended: true, input_cost: 0, output_cost: 0 },
275
- ],
276
- },
277
- piper: {
278
- id: "piper",
279
- name: "Piper",
280
- displayName: "Piper (Local)",
281
- type: "voice" as const,
282
- voiceSubtype: "tts" as const,
283
- envVar: "PIPER_BASE_URL",
284
- docsUrl: "https://github.com/rhasspy/piper",
285
- description: "Fast local text-to-speech, runs on any hardware",
286
- isLocal: true,
287
- defaultBaseUrl: "http://localhost:5000",
288
- models: [
289
- { value: "en_US-amy-medium", label: "Amy (Medium)", recommended: true, input_cost: 0, output_cost: 0 },
290
- { value: "en_US-lessac-medium", label: "Lessac (Medium)", input_cost: 0, output_cost: 0 },
291
- ],
292
- },
293
- fish_speech: {
294
- id: "fish_speech",
295
- name: "Fish Speech",
296
- displayName: "Fish Speech (Local)",
297
- type: "voice" as const,
298
- voiceSubtype: "tts" as const,
299
- envVar: "FISH_SPEECH_BASE_URL",
300
- docsUrl: "https://github.com/fishaudio/fish-speech",
301
- description: "High-quality local TTS with voice cloning",
302
- isLocal: true,
303
- defaultBaseUrl: "http://localhost:8180",
304
- models: [
305
- { value: "fish-speech-1.5", label: "Fish Speech 1.5", recommended: true, input_cost: 0, output_cost: 0 },
306
- ],
307
- },
308
- // MCP Integrations
309
- composio: {
310
- id: "composio",
311
- name: "Composio",
312
- displayName: "Composio",
313
- type: "integration" as const,
314
- envVar: "COMPOSIO_API_KEY",
315
- docsUrl: "https://app.composio.dev/settings",
316
- description: "500+ app integrations via MCP gateway",
317
- models: [],
318
- },
319
- smithery: {
320
- id: "smithery",
321
- name: "Smithery",
322
- displayName: "Smithery",
323
- type: "integration" as const,
324
- envVar: "SMITHERY_API_KEY",
325
- docsUrl: "https://smithery.ai/settings",
326
- description: "MCP server registry and hosting",
327
- models: [],
328
- },
329
- agentdojo: {
330
- id: "agentdojo",
331
- name: "AgentDojo",
332
- displayName: "AgentDojo",
333
- type: "integration" as const,
334
- envVar: "AGENTDOJO_API_KEY",
335
- docsUrl: "https://agentdojo.com/settings",
336
- description: "Hosted MCP tools and agent capabilities",
337
- models: [],
338
- },
339
- // Skills Integrations
340
- skillsmp: {
341
- id: "skillsmp",
342
- name: "SkillsMP",
343
- displayName: "SkillsMP",
344
- type: "integration" as const,
345
- envVar: "SKILLSMP_API_KEY",
346
- docsUrl: "https://skillsmp.com/settings",
347
- description: "Agent skills marketplace (optional - public registry available without key)",
348
- models: [],
349
- },
350
- } as const;
351
-
352
- export type ProviderId = keyof typeof PROVIDERS;
353
-
354
- /** Get cost per 1M tokens for a given provider + model. Returns { input_cost, output_cost, cache_creation_cost, cache_read_cost } in USD. */
355
- export function getModelCost(provider: string, model: string): { input_cost: number; output_cost: number; cache_creation_cost: number; cache_read_cost: number } {
356
- const providerDef = PROVIDERS[provider as ProviderId];
357
- if (!providerDef || !("models" in providerDef)) return { input_cost: 0, output_cost: 0, cache_creation_cost: 0, cache_read_cost: 0 };
358
- const modelDef = (providerDef.models as ReadonlyArray<{ value: string; input_cost?: number; output_cost?: number; cache_creation_cost?: number; cache_read_cost?: number }>)
359
- .find(m => m.value === model);
360
- if (!modelDef) return { input_cost: 0, output_cost: 0, cache_creation_cost: 0, cache_read_cost: 0 };
361
- return {
362
- input_cost: modelDef.input_cost ?? 0,
363
- output_cost: modelDef.output_cost ?? 0,
364
- cache_creation_cost: modelDef.cache_creation_cost ?? 0,
365
- cache_read_cost: modelDef.cache_read_cost ?? 0,
366
- };
367
- }
368
-
369
- // Provider Keys Management
370
- export const ProviderKeys = {
371
- // Save an API key (encrypts before storing)
372
- // projectId: null = global key, string = project-scoped key
373
- async save(
374
- providerId: string,
375
- apiKey: string,
376
- projectId: string | null = null,
377
- name: string | null = null
378
- ): Promise<{ success: boolean; error?: string; id?: string }> {
379
- // Validate format
380
- const validation = validateKeyFormat(providerId, apiKey);
381
- if (!validation.valid) {
382
- return { success: false, error: validation.error };
383
- }
384
-
385
- try {
386
- const encryptedKey = encrypt(apiKey.trim());
387
- // For multi-field JSON keys (e.g. browserbase), use the api_key field for the hint
388
- let hintSource = apiKey.trim();
389
- if (providerId === "browserbase") {
390
- try {
391
- const parsed = JSON.parse(hintSource);
392
- if (parsed.api_key) hintSource = parsed.api_key;
393
- } catch {}
394
- }
395
- const keyHint = createKeyHint(hintSource);
396
- const record = ProviderKeysDB.save(providerId, encryptedKey, keyHint, projectId, name);
397
- return { success: true, id: record.id };
398
- } catch (err) {
399
- return { success: false, error: `Failed to save key: ${err}` };
400
- }
401
- },
402
-
403
- // Get decrypted API key for a provider (global key, falls back to env var)
404
- getDecrypted(providerId: string): string | null {
405
- const record = ProviderKeysDB.findByProvider(providerId);
406
- if (record) {
407
- try {
408
- return decrypt(record.encrypted_key);
409
- } catch (err) {
410
- console.error(`Failed to decrypt key for ${providerId}:`, err);
411
- }
412
- }
413
-
414
- // Fall back to environment variable
415
- const provider = PROVIDERS[providerId as ProviderId];
416
- if (provider?.envVar) {
417
- const envVal = process.env[provider.envVar];
418
- if (envVal) return envVal;
419
- }
420
- return null;
421
- },
422
-
423
- // Get decrypted API key for a provider and project
424
- // Falls back to global key if no project-specific key exists
425
- getDecryptedForProject(providerId: string, projectId: string | null): string | null {
426
- console.log(`[ProviderKeys.getDecryptedForProject] providerId=${providerId}, projectId=${projectId}`);
427
- // Try project-specific key first
428
- if (projectId) {
429
- const projectRecord = ProviderKeysDB.findByProviderAndProject(providerId, projectId);
430
- console.log(`[ProviderKeys.getDecryptedForProject] project record found: ${!!projectRecord}`);
431
- if (projectRecord) {
432
- try {
433
- const key = decrypt(projectRecord.encrypted_key);
434
- console.log(`[ProviderKeys.getDecryptedForProject] decrypted project key OK, length=${key?.length}`);
435
- return key;
436
- } catch (err) {
437
- console.error(`Failed to decrypt project key for ${providerId}/${projectId}:`, err);
438
- }
439
- }
440
- }
441
- // Fall back to global key
442
- const globalKey = this.getDecrypted(providerId);
443
- console.log(`[ProviderKeys.getDecryptedForProject] global fallback: found=${!!globalKey}, length=${globalKey?.length || 0}`);
444
- return globalKey;
445
- },
446
-
447
- // Check if a provider has a key configured (global)
448
- hasKey(providerId: string): boolean {
449
- return ProviderKeysDB.findByProvider(providerId) !== null;
450
- },
451
-
452
- // Check if a provider has a key for a specific project (or global)
453
- hasKeyForProject(providerId: string, projectId: string | null): boolean {
454
- if (projectId && ProviderKeysDB.findByProviderAndProject(providerId, projectId)) {
455
- return true;
456
- }
457
- return ProviderKeysDB.findByProvider(providerId) !== null;
458
- },
459
-
460
- // Get all configured providers with their status (without exposing keys)
461
- getAll(): Array<{
462
- id: string;
463
- provider_id: string;
464
- key_hint: string;
465
- is_valid: boolean;
466
- last_tested_at: string | null;
467
- created_at: string;
468
- project_id: string | null;
469
- name: string | null;
470
- }> {
471
- return ProviderKeysDB.findAll().map(k => ({
472
- id: k.id,
473
- provider_id: k.provider_id,
474
- key_hint: k.key_hint,
475
- is_valid: k.is_valid,
476
- last_tested_at: k.last_tested_at,
477
- created_at: k.created_at,
478
- project_id: k.project_id,
479
- name: k.name,
480
- }));
481
- },
482
-
483
- // Get all keys for a specific provider
484
- getAllByProvider(providerId: string): Array<{
485
- id: string;
486
- provider_id: string;
487
- key_hint: string;
488
- is_valid: boolean;
489
- last_tested_at: string | null;
490
- created_at: string;
491
- project_id: string | null;
492
- name: string | null;
493
- }> {
494
- return ProviderKeysDB.findAllByProvider(providerId).map(k => ({
495
- id: k.id,
496
- provider_id: k.provider_id,
497
- key_hint: k.key_hint,
498
- is_valid: k.is_valid,
499
- last_tested_at: k.last_tested_at,
500
- created_at: k.created_at,
501
- project_id: k.project_id,
502
- name: k.name,
503
- }));
504
- },
505
-
506
- // Delete a provider key (global)
507
- delete(providerId: string): boolean {
508
- return ProviderKeysDB.delete(providerId);
509
- },
510
-
511
- // Delete a provider key by ID
512
- deleteById(id: string): boolean {
513
- return ProviderKeysDB.deleteById(id);
514
- },
515
-
516
- // Test if an API key is valid by making a test request
517
- // TODO: Implement actual API testing per provider (Anthropic needs POST, others GET)
518
- async test(providerId: string, apiKey?: string): Promise<{ valid: boolean; error?: string }> {
519
- const key = apiKey || this.getDecrypted(providerId);
520
- if (!key) {
521
- return { valid: false, error: "No API key available" };
522
- }
523
-
524
- const provider = PROVIDERS[providerId as ProviderId];
525
- if (!provider) {
526
- return { valid: false, error: "Unknown provider" };
527
- }
528
-
529
- // For now, just validate format - actual API testing to be implemented later
530
- const validation = validateKeyFormat(providerId, key);
531
- if (!validation.valid) {
532
- return { valid: false, error: validation.error };
533
- }
534
-
535
- return { valid: true };
536
- },
537
-
538
- // Get list of provider IDs that have valid keys (global only)
539
- getConfiguredProviders(): string[] {
540
- return ProviderKeysDB.getConfiguredProviders();
541
- },
542
-
543
- // Get list of all provider IDs that have keys (including project-scoped)
544
- getAllConfiguredProviders(): string[] {
545
- return ProviderKeysDB.getAllConfiguredProviders();
546
- },
547
- };
548
-
549
- // Onboarding status management
550
- export const Onboarding = {
551
- isComplete(): boolean {
552
- return SettingsDB.get("onboarding_completed") === "true";
553
- },
554
-
555
- complete(): void {
556
- SettingsDB.set("onboarding_completed", "true");
557
- },
558
-
559
- reset(): void {
560
- SettingsDB.delete("onboarding_completed");
561
- },
562
-
563
- getStatus(): {
564
- completed: boolean;
565
- providers_configured: string[];
566
- has_any_keys: boolean;
567
- } {
568
- return {
569
- completed: this.isComplete(),
570
- providers_configured: ProviderKeys.getConfiguredProviders(),
571
- has_any_keys: ProviderKeysDB.hasAnyKeys(),
572
- };
573
- },
574
- };
575
-
576
- // Get provider list with configuration status for frontend
577
- export function getProvidersWithStatus() {
578
- const configuredProviders = new Set(ProviderKeysDB.getAllConfiguredProviders());
579
- const keyStatuses = new Map(
580
- ProviderKeys.getAll().map(k => [k.provider_id, k])
581
- );
582
-
583
- return Object.values(PROVIDERS).map(provider => ({
584
- id: provider.id,
585
- name: provider.displayName,
586
- type: provider.type,
587
- docsUrl: provider.docsUrl,
588
- description: "description" in provider ? provider.description : undefined,
589
- models: provider.models,
590
- hasKey: configuredProviders.has(provider.id),
591
- keyHint: keyStatuses.get(provider.id)?.key_hint || null,
592
- isValid: keyStatuses.get(provider.id)?.is_valid ?? null,
593
- isLocal: "isLocal" in provider ? provider.isLocal : undefined,
594
- voiceSubtype: "voiceSubtype" in provider ? provider.voiceSubtype : undefined,
595
- defaultBaseUrl: "defaultBaseUrl" in provider ? provider.defaultBaseUrl : undefined,
596
- }));
597
- }