teleton 0.6.0 → 0.7.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.
Files changed (39) hide show
  1. package/README.md +26 -26
  2. package/dist/{chunk-D5I7GBV7.js → chunk-FNV5FF35.js} +22 -13
  3. package/dist/chunk-LRCPA7SC.js +149 -0
  4. package/dist/{chunk-ADCMUNYU.js → chunk-N3F7E7DR.js} +58 -53
  5. package/dist/chunk-ND2X5FWB.js +368 -0
  6. package/dist/chunk-NERLQY2H.js +421 -0
  7. package/dist/{chunk-YBA6IBGT.js → chunk-OCLG5GKI.js} +24 -24
  8. package/dist/{chunk-6L6KGATM.js → chunk-OGIG552S.js} +1397 -1688
  9. package/dist/chunk-RCMD3U65.js +141 -0
  10. package/dist/{chunk-4IPJ25HE.js → chunk-TCD4NZDA.js} +1045 -658
  11. package/dist/{chunk-ECSCVEQQ.js → chunk-UCN6TI25.js} +7 -3
  12. package/dist/{chunk-WL2Q3VRD.js → chunk-UDD7FYOU.js} +12 -4
  13. package/dist/chunk-VAUJSSD3.js +20 -0
  14. package/dist/chunk-XBE4JB7C.js +8 -0
  15. package/dist/{chunk-GDCODBNO.js → chunk-XBKSS6DM.js} +2 -16
  16. package/dist/cli/index.js +878 -433
  17. package/dist/client-3VWE7NC4.js +29 -0
  18. package/dist/{get-my-gifts-KVULMBJ3.js → get-my-gifts-RI7FAXAL.js} +3 -1
  19. package/dist/index.js +17 -11
  20. package/dist/{memory-TVDOGQXS.js → memory-RD7ZSTRV.js} +7 -5
  21. package/dist/{migrate-QIEMPOMT.js → migrate-GO4NOBT7.js} +14 -9
  22. package/dist/{server-RSWVCVY3.js → server-OWVEZTR3.js} +81 -84
  23. package/dist/setup-server-C7ZTPHD5.js +934 -0
  24. package/dist/{task-dependency-resolver-72DLY2HV.js → task-dependency-resolver-WKZWJLLM.js} +19 -15
  25. package/dist/{task-executor-VXB6DAV2.js → task-executor-PD3H4MLO.js} +4 -1
  26. package/dist/tool-adapter-Y3TCEQOC.js +145 -0
  27. package/dist/{tool-index-DKI2ZNOU.js → tool-index-MIVK3D7H.js} +14 -9
  28. package/dist/{transcript-7V4UNID4.js → transcript-UDJZP6NK.js} +2 -1
  29. package/dist/web/assets/complete-fZLnb5Ot.js +1 -0
  30. package/dist/web/assets/index-B_FcaX5D.css +1 -0
  31. package/dist/web/assets/index-CbeAP4_n.js +67 -0
  32. package/dist/web/assets/index.es-oXiZF7Hc.js +11 -0
  33. package/dist/web/assets/login-telegram-BP7CJDmx.js +1 -0
  34. package/dist/web/assets/run-DOrDowjK.js +1 -0
  35. package/dist/web/index.html +2 -2
  36. package/package.json +7 -3
  37. package/dist/chunk-2QUJLHCZ.js +0 -362
  38. package/dist/web/assets/index-BNhrx9S1.js +0 -67
  39. package/dist/web/assets/index-CqrrRLOh.css +0 -1
package/README.md CHANGED
@@ -12,19 +12,19 @@
12
12
 
13
13
  ---
14
14
 
15
- <p align="center">Teleton is an autonomous AI agent platform that operates as a real Telegram user account (not a bot). It thinks through an agentic loop with tool calling, remembers conversations across sessions with hybrid RAG, and can operate a TON wallet: send crypto, swap on DEXs, bid on domains, verify payments. All from a chat message. It ships with 114 built-in tools, supports 6 LLM providers, and exposes a Plugin SDK so you can build your own tools on top of the platform.</p>
15
+ <p align="center">Teleton is an autonomous AI agent platform that operates as a real Telegram user account (not a bot). It thinks through an agentic loop with tool calling, remembers conversations across sessions with hybrid RAG, and natively integrates the TON blockchain: send crypto, swap on DEXs, bid on domains, verify payments - all from a chat message. It can schedule tasks to run autonomously at any time. It ships with 114 built-in tools, supports 6 LLM providers, and exposes a Plugin SDK so you can build your own tools on top of the platform.</p>
16
16
 
17
- ### Key Highlights
17
+ ### Key Highlights
18
18
 
19
- - **Full Telegram access**: Operates as a real user via MTProto (GramJS), not a limited bot
20
- - **Agentic loop**: Up to 5 iterations of tool calling per message the agent thinks, acts, observes, and repeats
21
- - **Multi-Provider LLM**: Anthropic, OpenAI, Google Gemini, xAI Grok, Groq, OpenRouter
22
- - **TON Blockchain**: Built-in W5R1 wallet, send/receive TON & jettons, swap on STON.fi and DeDust, NFTs, DNS domains
23
- - **Persistent memory**: Hybrid RAG (sqlite-vec + FTS5), auto-compaction with AI summarization, daily logs
24
- - **114 built-in tools**: Messaging, media, blockchain, DEX trading, deals, DNS, journaling, and more
25
- - **Plugin SDK**: Extend the agent with custom tools frozen SDK with isolated databases, secrets management, lifecycle hooks
26
- - **MCP Client**: Connect external tool servers (stdio/SSE) with 2 lines of YAML no code, no rebuild
27
- - **Secure by design**: Prompt injection defense, sandboxed workspace, plugin isolation, wallet encryption
19
+ - **Full Telegram access** - Operates as a real user via MTProto (GramJS), not a limited bot
20
+ - **Agentic loop** - Up to 5 iterations of tool calling per message, the agent thinks, acts, observes, and repeats
21
+ - **Multi-Provider LLM** - Anthropic, OpenAI, Google Gemini, xAI Grok, Groq, OpenRouter
22
+ - **TON Blockchain** - Built-in W5R1 wallet, send/receive TON & jettons, swap on STON.fi and DeDust, NFTs, DNS domains
23
+ - **Persistent memory** - Hybrid RAG (sqlite-vec + FTS5), auto-compaction with AI summarization, daily logs
24
+ - **114 built-in tools** - Messaging, media, blockchain, DEX trading, deals, DNS, journaling, and more
25
+ - **Plugin SDK** - Extend the agent with custom tools, frozen SDK with isolated databases, secrets management, lifecycle hooks
26
+ - **MCP Client** - Connect external tool servers (stdio/SSE) with 2 lines of YAML, no code, no rebuild
27
+ - **Secure by design** - Prompt injection defense, sandboxed workspace, plugin isolation, wallet encryption
28
28
 
29
29
  ---
30
30
 
@@ -59,8 +59,8 @@
59
59
  | **Message Debouncing** | Intelligent batching of rapid group messages (DMs are always instant) |
60
60
  | **Daily Logs** | Automatic session summaries preserved across resets |
61
61
  | **Multi-Policy Access** | Configurable DM/group policies (open, allowlist, pairing, disabled) with per-group module permissions |
62
- | **Tool RAG** | Semantic tool selection sends only the top-K most relevant tools per message (hybrid vector + FTS5, configurable `top_k`, `always_include` patterns) |
63
- | **MCP Client** | Connect external MCP tool servers (stdio or SSE) auto-discovery, namespaced tools, managed via CLI or WebUI |
62
+ | **Tool RAG** | Semantic tool selection - sends only the top-K most relevant tools per message (hybrid vector + FTS5, configurable `top_k`, `always_include` patterns) |
63
+ | **MCP Client** | Connect external MCP tool servers (stdio or SSE) - auto-discovery, namespaced tools, managed via CLI or WebUI |
64
64
  | **Sandboxed Workspace** | Secure file system with recursive URL decoding, symlink detection, and immutable config files |
65
65
 
66
66
  ---
@@ -139,7 +139,7 @@ You: /status
139
139
  Agent: [Displays uptime, model, tool count, wallet balance]
140
140
  ```
141
141
 
142
- > **Need more details?** See [GETTING_STARTED.md](GETTING_STARTED.md) for the full guide admin commands, troubleshooting, workspace templates, plugins, and more.
142
+ > **Need more details?** See [GETTING_STARTED.md](GETTING_STARTED.md) for the full guide - admin commands, troubleshooting, workspace templates, plugins, and more.
143
143
 
144
144
  ---
145
145
 
@@ -182,7 +182,7 @@ webui: # Optional: Web dashboard
182
182
 
183
183
  ### MCP Servers
184
184
 
185
- Connect external tool servers via the [Model Context Protocol](https://modelcontextprotocol.io/). No code needed tools are auto-discovered and registered at startup.
185
+ Connect external tool servers via the [Model Context Protocol](https://modelcontextprotocol.io/). No code needed - tools are auto-discovered and registered at startup.
186
186
 
187
187
  **Via CLI (recommended):**
188
188
  ```bash
@@ -209,7 +209,7 @@ mcp:
209
209
 
210
210
  **Via WebUI:**
211
211
 
212
- When the WebUI is enabled, the **MCP Servers** page lets you add/remove servers, configure environment variables (API keys), and view connection status and tool lists all from the browser.
212
+ When the WebUI is enabled, the **MCP Servers** page lets you add/remove servers, configure environment variables (API keys), and view connection status and tool lists - all from the browser.
213
213
 
214
214
  Tools are namespaced as `mcp_<server>_<tool>` (e.g. `mcp_filesystem_read_file`). Each server supports `scope` (always, dm-only, group-only, admin-only) and `enabled` toggle.
215
215
 
@@ -219,8 +219,8 @@ The agent has two built-in web tools powered by [Tavily](https://tavily.com/) (f
219
219
 
220
220
  | Tool | Description |
221
221
  |------|-------------|
222
- | `web_search` | Search the web returns titles, URLs, content snippets, relevance scores. Supports `topic`: general, news, finance |
223
- | `web_fetch` | Extract readable text from a URL articles, docs, links shared by users |
222
+ | `web_search` | Search the web - returns titles, URLs, content snippets, relevance scores. Supports `topic`: general, news, finance |
223
+ | `web_fetch` | Extract readable text from a URL - articles, docs, links shared by users |
224
224
 
225
225
  Both tools require a Tavily API key. Set it via CLI or config:
226
226
 
@@ -258,7 +258,7 @@ Configurable keys: `tavily_api_key`, `tonapi_key`, `telegram.bot_token`, `telegr
258
258
 
259
259
  ### Environment Variables
260
260
 
261
- All environment variables override the corresponding `config.yaml` value at startup useful for Docker and CI:
261
+ All environment variables override the corresponding `config.yaml` value at startup - useful for Docker and CI:
262
262
 
263
263
  | Variable | Description | Default |
264
264
  |----------|-------------|---------|
@@ -339,7 +339,7 @@ ssh -L 7777:localhost:7777 user@remote-server
339
339
 
340
340
  ### Workspace Files
341
341
 
342
- The agent's personality and rules are configured via markdown files in `~/.teleton/workspace/`. Default templates are generated during `teleton setup` you can edit any of them to customize your agent:
342
+ The agent's personality and rules are configured via markdown files in `~/.teleton/workspace/`. Default templates are generated during `teleton setup` - you can edit any of them to customize your agent:
343
343
 
344
344
  | File | Purpose | Mutable by Agent |
345
345
  |------|---------|-----------------|
@@ -349,7 +349,7 @@ The agent's personality and rules are configured via markdown files in `~/.telet
349
349
  | `MEMORY.md` | Persistent memory (facts, contacts, decisions) | Yes |
350
350
  | `memory/*.md` | Session summaries, daily logs (auto-generated) | Yes |
351
351
 
352
- > **Tip**: Templates are located in `src/templates/` if installing from source. Edit the workspace copies in `~/.teleton/workspace/` not the source templates.
352
+ > **Tip**: Templates are located in `src/templates/` if installing from source. Edit the workspace copies in `~/.teleton/workspace/` - not the source templates.
353
353
 
354
354
  ### Admin Commands
355
355
 
@@ -535,7 +535,7 @@ npm run format # Prettier
535
535
 
536
536
  ### Plugins
537
537
 
538
- Plugins extend the agent with custom tools. Drop a `.js` file or folder in `~/.teleton/plugins/` loaded at startup, hot-reloaded in dev mode, no rebuild needed. See [official example plugins](https://github.com/TONresistor/teleton-plugins) for complete working examples.
538
+ Plugins extend the agent with custom tools. Drop a `.js` file or folder in `~/.teleton/plugins/` - loaded at startup, hot-reloaded in dev mode, no rebuild needed. See [official example plugins](https://github.com/TONresistor/teleton-plugins) for complete working examples.
539
539
 
540
540
  ```
541
541
  ~/.teleton/plugins/
@@ -602,12 +602,12 @@ When `tools` is a function, the SDK provides namespaced access to core services:
602
602
  | | **Moderation**: `banUser()`, `unbanUser()`, `muteUser()` |
603
603
  | | **Stars & Gifts**: `getStarsBalance()`, `sendGift()`, `getAvailableGifts()`, `getMyGifts()`, `getResaleGifts()`, `buyResaleGift()` |
604
604
  | | **Advanced**: `getMe()`, `isAvailable()`, `getRawClient()`, `setTyping()`, `sendStory()` |
605
- | `sdk.secrets` | `get()`, `require()`, `has()` 3-tier resolution (env var → secrets file → plugin config) |
606
- | `sdk.storage` | `get()`, `set()`, `delete()`, `has()`, `clear()` KV store with TTL support |
607
- | `sdk.db` | Raw `better-sqlite3` database isolated per plugin at `~/.teleton/plugins/data/<name>.db` |
605
+ | `sdk.secrets` | `get()`, `require()`, `has()` - 3-tier resolution (env var → secrets file → plugin config) |
606
+ | `sdk.storage` | `get()`, `set()`, `delete()`, `has()`, `clear()` - KV store with TTL support |
607
+ | `sdk.db` | Raw `better-sqlite3` database - isolated per plugin at `~/.teleton/plugins/data/<name>.db` |
608
608
  | `sdk.config` | Sanitized app config (no API keys exposed) |
609
609
  | `sdk.pluginConfig` | Plugin-specific config from `config.yaml` `plugins:` section |
610
- | `sdk.log` | `info()`, `warn()`, `error()`, `debug()` Prefixed logger |
610
+ | `sdk.log` | `info()`, `warn()`, `error()`, `debug()` - Prefixed logger |
611
611
 
612
612
  **Lifecycle hooks**: `migrate(db)`, `start(ctx)`, `stop()`, `onMessage(event)`, `onCallbackQuery(event)`
613
613
 
@@ -1,7 +1,6 @@
1
1
  import {
2
- VOYAGE_API_URL,
3
- fetchWithTimeout
4
- } from "./chunk-GDCODBNO.js";
2
+ VOYAGE_API_URL
3
+ } from "./chunk-XBKSS6DM.js";
5
4
  import {
6
5
  EMBEDDING_CACHE_EVICTION_INTERVAL,
7
6
  EMBEDDING_CACHE_EVICTION_RATIO,
@@ -9,9 +8,15 @@ import {
9
8
  EMBEDDING_CACHE_TTL_DAYS,
10
9
  VOYAGE_BATCH_SIZE
11
10
  } from "./chunk-RO62LO6Z.js";
11
+ import {
12
+ fetchWithTimeout
13
+ } from "./chunk-VAUJSSD3.js";
12
14
  import {
13
15
  TELETON_ROOT
14
16
  } from "./chunk-EYWNOHMJ.js";
17
+ import {
18
+ createLogger
19
+ } from "./chunk-RCMD3U65.js";
15
20
 
16
21
  // src/memory/embeddings/provider.ts
17
22
  var NoopEmbeddingProvider = class {
@@ -86,18 +91,19 @@ var AnthropicEmbeddingProvider = class {
86
91
  // src/memory/embeddings/local.ts
87
92
  import { pipeline, env } from "@huggingface/transformers";
88
93
  import { join } from "path";
94
+ var log = createLogger("Memory");
89
95
  env.cacheDir = join(TELETON_ROOT, "models");
90
96
  var extractorPromise = null;
91
97
  function getExtractor(model) {
92
98
  if (!extractorPromise) {
93
- console.log(`\u{1F4E6} Loading local embedding model: ${model} (cache: ${env.cacheDir})`);
99
+ log.info(`Loading local embedding model: ${model} (cache: ${env.cacheDir})`);
94
100
  extractorPromise = pipeline("feature-extraction", model, {
95
101
  dtype: "fp32"
96
102
  }).then((ext) => {
97
- console.log(`\u2705 Local embedding model ready`);
103
+ log.info(`Local embedding model ready`);
98
104
  return ext;
99
105
  }).catch((err) => {
100
- console.error(`\u274C Failed to load embedding model: ${err.message}`);
106
+ log.error(`Failed to load embedding model: ${err.message}`);
101
107
  extractorPromise = null;
102
108
  throw err;
103
109
  });
@@ -124,8 +130,8 @@ var LocalEmbeddingProvider = class {
124
130
  await getExtractor(this.model);
125
131
  return true;
126
132
  } catch (err) {
127
- console.warn(
128
- `\u26A0\uFE0F Local embedding model unavailable \u2014 falling back to FTS5-only search (no vector embeddings)`
133
+ log.warn(
134
+ `Local embedding model unavailable \u2014 falling back to FTS5-only search (no vector embeddings)`
129
135
  );
130
136
  this._disabled = true;
131
137
  return false;
@@ -193,7 +199,7 @@ function deserializeEmbedding(data) {
193
199
  }
194
200
 
195
201
  // src/memory/embeddings/cached.ts
196
- var CachedEmbeddingProvider = class {
202
+ var CachedEmbeddingProvider = class _CachedEmbeddingProvider {
197
203
  constructor(inner, db) {
198
204
  this.inner = inner;
199
205
  this.db = db;
@@ -204,6 +210,7 @@ var CachedEmbeddingProvider = class {
204
210
  id;
205
211
  model;
206
212
  dimensions;
213
+ static log = createLogger("Memory");
207
214
  hits = 0;
208
215
  misses = 0;
209
216
  ops = 0;
@@ -284,8 +291,8 @@ var CachedEmbeddingProvider = class {
284
291
  const total = this.hits + this.misses;
285
292
  if (total > 0 && total % 100 === 0) {
286
293
  const rate = (this.hits / total * 100).toFixed(0);
287
- console.log(
288
- `\u{1F4CA} Embedding cache: ${this.hits} hits, ${this.misses} misses (${rate}% hit rate)`
294
+ _CachedEmbeddingProvider.log.info(
295
+ `Embedding cache: ${this.hits} hits, ${this.misses} misses (${rate}% hit rate)`
289
296
  );
290
297
  }
291
298
  }
@@ -302,10 +309,12 @@ var CachedEmbeddingProvider = class {
302
309
  SELECT hash, model, provider FROM embedding_cache ORDER BY accessed_at ASC LIMIT ?
303
310
  )`
304
311
  ).run(toDelete);
305
- console.log(`\u{1F9F9} Embedding cache eviction: removed ${toDelete} entries (${count} total)`);
312
+ _CachedEmbeddingProvider.log.info(
313
+ `Embedding cache eviction: removed ${toDelete} entries (${count} total)`
314
+ );
306
315
  }
307
316
  } catch (err) {
308
- console.warn("\u26A0\uFE0F Embedding cache eviction error:", err);
317
+ _CachedEmbeddingProvider.log.warn({ err }, "Embedding cache eviction error");
309
318
  }
310
319
  }
311
320
  };
@@ -0,0 +1,149 @@
1
+ // src/config/providers.ts
2
+ var PROVIDER_REGISTRY = {
3
+ anthropic: {
4
+ id: "anthropic",
5
+ displayName: "Anthropic (Claude)",
6
+ envVar: "ANTHROPIC_API_KEY",
7
+ keyPrefix: "sk-ant-",
8
+ keyHint: "sk-ant-api03-...",
9
+ consoleUrl: "https://console.anthropic.com/",
10
+ defaultModel: "claude-opus-4-5-20251101",
11
+ utilityModel: "claude-3-5-haiku-20241022",
12
+ toolLimit: null,
13
+ piAiProvider: "anthropic"
14
+ },
15
+ openai: {
16
+ id: "openai",
17
+ displayName: "OpenAI (GPT-4o)",
18
+ envVar: "OPENAI_API_KEY",
19
+ keyPrefix: "sk-",
20
+ keyHint: "sk-proj-...",
21
+ consoleUrl: "https://platform.openai.com/api-keys",
22
+ defaultModel: "gpt-4o",
23
+ utilityModel: "gpt-4o-mini",
24
+ toolLimit: 128,
25
+ piAiProvider: "openai"
26
+ },
27
+ google: {
28
+ id: "google",
29
+ displayName: "Google (Gemini)",
30
+ envVar: "GOOGLE_API_KEY",
31
+ keyPrefix: null,
32
+ keyHint: "AIza...",
33
+ consoleUrl: "https://aistudio.google.com/apikey",
34
+ defaultModel: "gemini-2.5-flash",
35
+ utilityModel: "gemini-2.0-flash-lite",
36
+ toolLimit: 128,
37
+ piAiProvider: "google"
38
+ },
39
+ xai: {
40
+ id: "xai",
41
+ displayName: "xAI (Grok)",
42
+ envVar: "XAI_API_KEY",
43
+ keyPrefix: "xai-",
44
+ keyHint: "xai-...",
45
+ consoleUrl: "https://console.x.ai/",
46
+ defaultModel: "grok-3",
47
+ utilityModel: "grok-3-mini-fast",
48
+ toolLimit: 128,
49
+ piAiProvider: "xai"
50
+ },
51
+ groq: {
52
+ id: "groq",
53
+ displayName: "Groq",
54
+ envVar: "GROQ_API_KEY",
55
+ keyPrefix: "gsk_",
56
+ keyHint: "gsk_...",
57
+ consoleUrl: "https://console.groq.com/keys",
58
+ defaultModel: "llama-3.3-70b-versatile",
59
+ utilityModel: "llama-3.1-8b-instant",
60
+ toolLimit: 128,
61
+ piAiProvider: "groq"
62
+ },
63
+ openrouter: {
64
+ id: "openrouter",
65
+ displayName: "OpenRouter",
66
+ envVar: "OPENROUTER_API_KEY",
67
+ keyPrefix: "sk-or-",
68
+ keyHint: "sk-or-v1-...",
69
+ consoleUrl: "https://openrouter.ai/keys",
70
+ defaultModel: "anthropic/claude-opus-4.5",
71
+ utilityModel: "google/gemini-2.5-flash-lite",
72
+ toolLimit: 128,
73
+ piAiProvider: "openrouter"
74
+ },
75
+ moonshot: {
76
+ id: "moonshot",
77
+ displayName: "Moonshot (Kimi K2.5)",
78
+ envVar: "MOONSHOT_API_KEY",
79
+ keyPrefix: "sk-",
80
+ keyHint: "sk-...",
81
+ consoleUrl: "https://platform.moonshot.ai/",
82
+ defaultModel: "kimi-k2.5",
83
+ utilityModel: "kimi-k2.5",
84
+ toolLimit: 128,
85
+ piAiProvider: "moonshot"
86
+ },
87
+ mistral: {
88
+ id: "mistral",
89
+ displayName: "Mistral AI",
90
+ envVar: "MISTRAL_API_KEY",
91
+ keyPrefix: null,
92
+ keyHint: "...",
93
+ consoleUrl: "https://console.mistral.ai/api-keys",
94
+ defaultModel: "devstral-small-2507",
95
+ utilityModel: "ministral-8b-latest",
96
+ toolLimit: 128,
97
+ piAiProvider: "mistral"
98
+ },
99
+ cocoon: {
100
+ id: "cocoon",
101
+ displayName: "Cocoon Network (Decentralized)",
102
+ envVar: "",
103
+ keyPrefix: null,
104
+ keyHint: "No API key needed \u2014 pays in TON",
105
+ consoleUrl: "https://cocoon.network",
106
+ defaultModel: "Qwen/Qwen3-32B",
107
+ utilityModel: "Qwen/Qwen3-32B",
108
+ toolLimit: 128,
109
+ piAiProvider: "cocoon"
110
+ },
111
+ local: {
112
+ id: "local",
113
+ displayName: "Local (Ollama, vLLM, LM Studio...)",
114
+ envVar: "",
115
+ keyPrefix: null,
116
+ keyHint: "No API key needed",
117
+ consoleUrl: "",
118
+ defaultModel: "auto",
119
+ utilityModel: "auto",
120
+ toolLimit: 128,
121
+ piAiProvider: "local"
122
+ }
123
+ };
124
+ function getProviderMetadata(provider) {
125
+ const meta = PROVIDER_REGISTRY[provider];
126
+ if (!meta) {
127
+ throw new Error(`Unknown provider: ${provider}`);
128
+ }
129
+ return meta;
130
+ }
131
+ function getSupportedProviders() {
132
+ return Object.values(PROVIDER_REGISTRY);
133
+ }
134
+ function validateApiKeyFormat(provider, key) {
135
+ const meta = PROVIDER_REGISTRY[provider];
136
+ if (!meta) return `Unknown provider: ${provider}`;
137
+ if (provider === "cocoon" || provider === "local") return void 0;
138
+ if (!key || key.trim().length === 0) return "API key is required";
139
+ if (meta.keyPrefix && !key.startsWith(meta.keyPrefix)) {
140
+ return `Invalid format (should start with ${meta.keyPrefix})`;
141
+ }
142
+ return void 0;
143
+ }
144
+
145
+ export {
146
+ getProviderMetadata,
147
+ getSupportedProviders,
148
+ validateApiKeyFormat
149
+ };