teleton 0.5.2 → 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 (40) hide show
  1. package/README.md +243 -105
  2. package/dist/chunk-FNV5FF35.js +331 -0
  3. package/dist/chunk-LRCPA7SC.js +149 -0
  4. package/dist/{chunk-WUTMT6DW.js → chunk-N3F7E7DR.js} +114 -566
  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-WOXBZOQX.js → chunk-OGIG552S.js} +2152 -4488
  9. package/dist/chunk-RCMD3U65.js +141 -0
  10. package/dist/{chunk-O4R7V5Y2.js → chunk-RO62LO6Z.js} +11 -1
  11. package/dist/chunk-TCD4NZDA.js +3226 -0
  12. package/dist/chunk-UCN6TI25.js +143 -0
  13. package/dist/{chunk-WL2Q3VRD.js → chunk-UDD7FYOU.js} +12 -4
  14. package/dist/chunk-VAUJSSD3.js +20 -0
  15. package/dist/chunk-XBE4JB7C.js +8 -0
  16. package/dist/chunk-XBKSS6DM.js +58 -0
  17. package/dist/cli/index.js +1179 -412
  18. package/dist/client-3VWE7NC4.js +29 -0
  19. package/dist/{get-my-gifts-KVULMBJ3.js → get-my-gifts-RI7FAXAL.js} +3 -1
  20. package/dist/index.js +17 -8
  21. package/dist/{memory-Y5J7CXAR.js → memory-RD7ZSTRV.js} +16 -10
  22. package/dist/{migrate-UEQCDWL2.js → migrate-GO4NOBT7.js} +14 -6
  23. package/dist/{server-BQY7CM2N.js → server-OWVEZTR3.js} +869 -93
  24. package/dist/setup-server-C7ZTPHD5.js +934 -0
  25. package/dist/{task-dependency-resolver-TRPILAHM.js → task-dependency-resolver-WKZWJLLM.js} +19 -15
  26. package/dist/{task-executor-N7XNVK5N.js → task-executor-PD3H4MLO.js} +5 -2
  27. package/dist/tool-adapter-Y3TCEQOC.js +145 -0
  28. package/dist/tool-index-MIVK3D7H.js +250 -0
  29. package/dist/{transcript-7V4UNID4.js → transcript-UDJZP6NK.js} +2 -1
  30. package/dist/web/assets/complete-fZLnb5Ot.js +1 -0
  31. package/dist/web/assets/index-B_FcaX5D.css +1 -0
  32. package/dist/web/assets/index-CbeAP4_n.js +67 -0
  33. package/dist/web/assets/index.es-oXiZF7Hc.js +11 -0
  34. package/dist/web/assets/login-telegram-BP7CJDmx.js +1 -0
  35. package/dist/web/assets/run-DOrDowjK.js +1 -0
  36. package/dist/web/index.html +2 -2
  37. package/package.json +21 -15
  38. package/dist/chunk-5WWR4CU3.js +0 -124
  39. package/dist/web/assets/index-CDMbujHf.css +0 -1
  40. package/dist/web/assets/index-DDX8oQ2z.js +0 -67
@@ -0,0 +1,331 @@
1
+ import {
2
+ VOYAGE_API_URL
3
+ } from "./chunk-XBKSS6DM.js";
4
+ import {
5
+ EMBEDDING_CACHE_EVICTION_INTERVAL,
6
+ EMBEDDING_CACHE_EVICTION_RATIO,
7
+ EMBEDDING_CACHE_MAX_ENTRIES,
8
+ EMBEDDING_CACHE_TTL_DAYS,
9
+ VOYAGE_BATCH_SIZE
10
+ } from "./chunk-RO62LO6Z.js";
11
+ import {
12
+ fetchWithTimeout
13
+ } from "./chunk-VAUJSSD3.js";
14
+ import {
15
+ TELETON_ROOT
16
+ } from "./chunk-EYWNOHMJ.js";
17
+ import {
18
+ createLogger
19
+ } from "./chunk-RCMD3U65.js";
20
+
21
+ // src/memory/embeddings/provider.ts
22
+ var NoopEmbeddingProvider = class {
23
+ id = "noop";
24
+ model = "none";
25
+ dimensions = 0;
26
+ async embedQuery(_text) {
27
+ return [];
28
+ }
29
+ async embedBatch(_texts) {
30
+ return [];
31
+ }
32
+ };
33
+
34
+ // src/memory/embeddings/anthropic.ts
35
+ var AnthropicEmbeddingProvider = class {
36
+ id = "anthropic";
37
+ model;
38
+ dimensions;
39
+ apiKey;
40
+ baseUrl = VOYAGE_API_URL;
41
+ constructor(config) {
42
+ this.apiKey = config.apiKey;
43
+ this.model = config.model ?? "voyage-3-lite";
44
+ const dims = {
45
+ "voyage-3": 1024,
46
+ "voyage-3-lite": 512,
47
+ "voyage-code-3": 1024,
48
+ "voyage-finance-2": 1024,
49
+ "voyage-multilingual-2": 1024,
50
+ "voyage-law-2": 1024
51
+ };
52
+ this.dimensions = dims[this.model] ?? 512;
53
+ }
54
+ async embedQuery(text) {
55
+ const result = await this.embed([text]);
56
+ return result[0] ?? [];
57
+ }
58
+ async embedBatch(texts) {
59
+ if (texts.length === 0) return [];
60
+ const batchSize = VOYAGE_BATCH_SIZE;
61
+ const results = [];
62
+ for (let i = 0; i < texts.length; i += batchSize) {
63
+ const batch = texts.slice(i, i + batchSize);
64
+ const embeddings = await this.embed(batch);
65
+ results.push(...embeddings);
66
+ }
67
+ return results;
68
+ }
69
+ async embed(texts) {
70
+ const response = await fetchWithTimeout(`${this.baseUrl}/embeddings`, {
71
+ method: "POST",
72
+ headers: {
73
+ "Content-Type": "application/json",
74
+ Authorization: `Bearer ${this.apiKey}`
75
+ },
76
+ body: JSON.stringify({
77
+ input: texts,
78
+ model: this.model,
79
+ input_type: "document"
80
+ })
81
+ });
82
+ if (!response.ok) {
83
+ const error = await response.text();
84
+ throw new Error(`Voyage API error: ${response.status} ${error}`);
85
+ }
86
+ const data = await response.json();
87
+ return data.data.map((item) => item.embedding);
88
+ }
89
+ };
90
+
91
+ // src/memory/embeddings/local.ts
92
+ import { pipeline, env } from "@huggingface/transformers";
93
+ import { join } from "path";
94
+ var log = createLogger("Memory");
95
+ env.cacheDir = join(TELETON_ROOT, "models");
96
+ var extractorPromise = null;
97
+ function getExtractor(model) {
98
+ if (!extractorPromise) {
99
+ log.info(`Loading local embedding model: ${model} (cache: ${env.cacheDir})`);
100
+ extractorPromise = pipeline("feature-extraction", model, {
101
+ dtype: "fp32"
102
+ }).then((ext) => {
103
+ log.info(`Local embedding model ready`);
104
+ return ext;
105
+ }).catch((err) => {
106
+ log.error(`Failed to load embedding model: ${err.message}`);
107
+ extractorPromise = null;
108
+ throw err;
109
+ });
110
+ }
111
+ return extractorPromise;
112
+ }
113
+ var LocalEmbeddingProvider = class {
114
+ id = "local";
115
+ model;
116
+ dimensions;
117
+ _disabled = false;
118
+ constructor(config) {
119
+ this.model = config.model || "Xenova/all-MiniLM-L6-v2";
120
+ this.dimensions = 384;
121
+ }
122
+ /**
123
+ * Pre-download and load the model at startup.
124
+ * If loading fails, marks this provider as disabled (returns empty embeddings).
125
+ * Call this once during app init — avoids retry spam on every message.
126
+ * @returns true if model loaded successfully, false if fallback to noop
127
+ */
128
+ async warmup() {
129
+ try {
130
+ await getExtractor(this.model);
131
+ return true;
132
+ } catch (err) {
133
+ log.warn(
134
+ `Local embedding model unavailable \u2014 falling back to FTS5-only search (no vector embeddings)`
135
+ );
136
+ this._disabled = true;
137
+ return false;
138
+ }
139
+ }
140
+ async embedQuery(text) {
141
+ if (this._disabled) return [];
142
+ const extractor = await getExtractor(this.model);
143
+ const output = await extractor(text, { pooling: "mean", normalize: true });
144
+ return Array.from(output.data);
145
+ }
146
+ async embedBatch(texts) {
147
+ if (this._disabled) return [];
148
+ if (texts.length === 0) return [];
149
+ const extractor = await getExtractor(this.model);
150
+ const output = await extractor(texts, { pooling: "mean", normalize: true });
151
+ const data = output.data;
152
+ const dims = this.dimensions;
153
+ const results = [];
154
+ for (let i = 0; i < texts.length; i++) {
155
+ results.push(Array.from(data.slice(i * dims, (i + 1) * dims)));
156
+ }
157
+ return results;
158
+ }
159
+ };
160
+
161
+ // src/memory/embeddings/index.ts
162
+ import { createHash } from "crypto";
163
+ function createEmbeddingProvider(config) {
164
+ switch (config.provider) {
165
+ case "anthropic":
166
+ if (!config.apiKey) {
167
+ throw new Error("API key required for Anthropic embedding provider");
168
+ }
169
+ return new AnthropicEmbeddingProvider({
170
+ apiKey: config.apiKey,
171
+ model: config.model
172
+ });
173
+ case "local":
174
+ return new LocalEmbeddingProvider({
175
+ model: config.model
176
+ });
177
+ case "none":
178
+ return new NoopEmbeddingProvider();
179
+ default:
180
+ throw new Error(`Unknown embedding provider: ${config.provider}`);
181
+ }
182
+ }
183
+ function hashText(text) {
184
+ return createHash("sha256").update(text).digest("hex");
185
+ }
186
+ function serializeEmbedding(embedding) {
187
+ return Buffer.from(new Float32Array(embedding).buffer);
188
+ }
189
+ function deserializeEmbedding(data) {
190
+ try {
191
+ if (Buffer.isBuffer(data)) {
192
+ const floats = new Float32Array(data.buffer, data.byteOffset, data.byteLength / 4);
193
+ return Array.from(floats);
194
+ }
195
+ return JSON.parse(data);
196
+ } catch {
197
+ return [];
198
+ }
199
+ }
200
+
201
+ // src/memory/embeddings/cached.ts
202
+ var CachedEmbeddingProvider = class _CachedEmbeddingProvider {
203
+ constructor(inner, db) {
204
+ this.inner = inner;
205
+ this.db = db;
206
+ this.id = inner.id;
207
+ this.model = inner.model;
208
+ this.dimensions = inner.dimensions;
209
+ }
210
+ id;
211
+ model;
212
+ dimensions;
213
+ static log = createLogger("Memory");
214
+ hits = 0;
215
+ misses = 0;
216
+ ops = 0;
217
+ cacheGet(hash) {
218
+ return this.db.prepare(
219
+ `SELECT embedding FROM embedding_cache WHERE hash = ? AND model = ? AND provider = ?`
220
+ ).get(hash, this.model, this.id);
221
+ }
222
+ cachePut(hash, blob) {
223
+ this.db.prepare(
224
+ `INSERT OR REPLACE INTO embedding_cache (hash, embedding, model, provider, dims, created_at, accessed_at)
225
+ VALUES (?, ?, ?, ?, ?, unixepoch(), unixepoch())`
226
+ ).run(hash, blob, this.model, this.id, this.dimensions);
227
+ }
228
+ cacheTouch(hash) {
229
+ this.db.prepare(
230
+ `UPDATE embedding_cache SET accessed_at = unixepoch() WHERE hash = ? AND model = ? AND provider = ?`
231
+ ).run(hash, this.model, this.id);
232
+ }
233
+ async warmup() {
234
+ return this.inner.warmup?.() ?? true;
235
+ }
236
+ async embedQuery(text) {
237
+ const hash = hashText(text);
238
+ const row = this.cacheGet(hash);
239
+ if (row) {
240
+ this.hits++;
241
+ this.cacheTouch(hash);
242
+ this.tick();
243
+ return deserializeEmbedding(row.embedding);
244
+ }
245
+ this.misses++;
246
+ const embedding = await this.inner.embedQuery(text);
247
+ this.cachePut(hash, serializeEmbedding(embedding));
248
+ this.tick();
249
+ return embedding;
250
+ }
251
+ async embedBatch(texts) {
252
+ if (texts.length === 0) return [];
253
+ const hashes = texts.map(hashText);
254
+ const results = new Array(texts.length).fill(null);
255
+ const missIndices = [];
256
+ const missTexts = [];
257
+ for (let i = 0; i < texts.length; i++) {
258
+ const row = this.cacheGet(hashes[i]);
259
+ if (row) {
260
+ this.hits++;
261
+ this.cacheTouch(hashes[i]);
262
+ results[i] = deserializeEmbedding(row.embedding);
263
+ } else {
264
+ this.misses++;
265
+ missIndices.push(i);
266
+ missTexts.push(texts[i]);
267
+ }
268
+ }
269
+ if (missTexts.length > 0) {
270
+ const newEmbeddings = await this.inner.embedBatch(missTexts);
271
+ for (let j = 0; j < missIndices.length; j++) {
272
+ const idx = missIndices[j];
273
+ const embedding = newEmbeddings[j] ?? [];
274
+ results[idx] = embedding;
275
+ if (embedding.length > 0) {
276
+ this.cachePut(hashes[idx], serializeEmbedding(embedding));
277
+ }
278
+ }
279
+ }
280
+ this.ops += texts.length;
281
+ this.maybeEvict();
282
+ this.maybeLogStats();
283
+ return results;
284
+ }
285
+ tick() {
286
+ this.ops++;
287
+ this.maybeEvict();
288
+ this.maybeLogStats();
289
+ }
290
+ maybeLogStats() {
291
+ const total = this.hits + this.misses;
292
+ if (total > 0 && total % 100 === 0) {
293
+ const rate = (this.hits / total * 100).toFixed(0);
294
+ _CachedEmbeddingProvider.log.info(
295
+ `Embedding cache: ${this.hits} hits, ${this.misses} misses (${rate}% hit rate)`
296
+ );
297
+ }
298
+ }
299
+ maybeEvict() {
300
+ if (this.ops % EMBEDDING_CACHE_EVICTION_INTERVAL !== 0) return;
301
+ try {
302
+ const cutoff = Math.floor(Date.now() / 1e3) - EMBEDDING_CACHE_TTL_DAYS * 86400;
303
+ this.db.prepare(`DELETE FROM embedding_cache WHERE accessed_at < ?`).run(cutoff);
304
+ const count = this.db.prepare(`SELECT COUNT(*) as cnt FROM embedding_cache`).get().cnt;
305
+ if (count > EMBEDDING_CACHE_MAX_ENTRIES) {
306
+ const toDelete = Math.ceil(count * EMBEDDING_CACHE_EVICTION_RATIO);
307
+ this.db.prepare(
308
+ `DELETE FROM embedding_cache WHERE (hash, model, provider) IN (
309
+ SELECT hash, model, provider FROM embedding_cache ORDER BY accessed_at ASC LIMIT ?
310
+ )`
311
+ ).run(toDelete);
312
+ _CachedEmbeddingProvider.log.info(
313
+ `Embedding cache eviction: removed ${toDelete} entries (${count} total)`
314
+ );
315
+ }
316
+ } catch (err) {
317
+ _CachedEmbeddingProvider.log.warn({ err }, "Embedding cache eviction error");
318
+ }
319
+ }
320
+ };
321
+
322
+ export {
323
+ NoopEmbeddingProvider,
324
+ AnthropicEmbeddingProvider,
325
+ LocalEmbeddingProvider,
326
+ CachedEmbeddingProvider,
327
+ createEmbeddingProvider,
328
+ hashText,
329
+ serializeEmbedding,
330
+ deserializeEmbedding
331
+ };
@@ -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
+ };