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
@@ -1,145 +1,30 @@
1
1
  import {
2
- DEFAULT_FETCH_TIMEOUT_MS
3
- } from "./chunk-4DU3C27M.js";
2
+ CachedEmbeddingProvider,
3
+ createEmbeddingProvider,
4
+ hashText,
5
+ serializeEmbedding
6
+ } from "./chunk-FNV5FF35.js";
7
+ import {
8
+ JOURNAL_SCHEMA
9
+ } from "./chunk-UCN6TI25.js";
4
10
  import {
5
- EMBEDDING_CACHE_EVICTION_INTERVAL,
6
- EMBEDDING_CACHE_EVICTION_RATIO,
7
- EMBEDDING_CACHE_MAX_ENTRIES,
8
- EMBEDDING_CACHE_TTL_DAYS,
9
11
  HYBRID_SEARCH_MIN_SCORE,
10
12
  KNOWLEDGE_CHUNK_SIZE,
11
13
  SQLITE_CACHE_SIZE_KB,
12
- SQLITE_MMAP_SIZE,
13
- VOYAGE_BATCH_SIZE
14
- } from "./chunk-O4R7V5Y2.js";
14
+ SQLITE_MMAP_SIZE
15
+ } from "./chunk-RO62LO6Z.js";
15
16
  import {
16
- TELETON_ROOT
17
- } from "./chunk-EYWNOHMJ.js";
17
+ createLogger
18
+ } from "./chunk-RCMD3U65.js";
18
19
 
19
20
  // src/memory/database.ts
20
- import Database2 from "better-sqlite3";
21
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, chmodSync as chmodSync2 } from "fs";
22
- import { dirname as dirname2 } from "path";
23
- import * as sqliteVec from "sqlite-vec";
24
-
25
- // src/utils/module-db.ts
26
21
  import Database from "better-sqlite3";
27
22
  import { existsSync, mkdirSync, chmodSync } from "fs";
28
- import { dirname, join } from "path";
29
- var JOURNAL_SCHEMA = `
30
- CREATE TABLE IF NOT EXISTS journal (
31
- id INTEGER PRIMARY KEY AUTOINCREMENT,
32
- timestamp INTEGER NOT NULL DEFAULT (unixepoch()),
33
- type TEXT NOT NULL CHECK(type IN ('trade', 'gift', 'middleman', 'kol')),
34
- action TEXT NOT NULL,
35
- asset_from TEXT,
36
- asset_to TEXT,
37
- amount_from REAL,
38
- amount_to REAL,
39
- price_ton REAL,
40
- counterparty TEXT,
41
- platform TEXT,
42
- reasoning TEXT,
43
- outcome TEXT CHECK(outcome IN ('pending', 'profit', 'loss', 'neutral', 'cancelled')),
44
- pnl_ton REAL,
45
- pnl_pct REAL,
46
- tx_hash TEXT,
47
- tool_used TEXT,
48
- chat_id TEXT,
49
- user_id INTEGER,
50
- closed_at INTEGER,
51
- created_at INTEGER NOT NULL DEFAULT (unixepoch())
52
- );
53
-
54
- CREATE INDEX IF NOT EXISTS idx_journal_type ON journal(type);
55
- CREATE INDEX IF NOT EXISTS idx_journal_timestamp ON journal(timestamp DESC);
56
- CREATE INDEX IF NOT EXISTS idx_journal_asset_from ON journal(asset_from);
57
- CREATE INDEX IF NOT EXISTS idx_journal_outcome ON journal(outcome);
58
- CREATE INDEX IF NOT EXISTS idx_journal_type_timestamp ON journal(type, timestamp DESC);
59
- `;
60
- var USED_TRANSACTIONS_SCHEMA = `
61
- CREATE TABLE IF NOT EXISTS used_transactions (
62
- tx_hash TEXT PRIMARY KEY,
63
- user_id TEXT NOT NULL,
64
- amount REAL NOT NULL,
65
- game_type TEXT NOT NULL,
66
- used_at INTEGER NOT NULL DEFAULT (unixepoch())
67
- );
68
-
69
- CREATE INDEX IF NOT EXISTS idx_used_tx_user ON used_transactions(user_id);
70
- CREATE INDEX IF NOT EXISTS idx_used_tx_used_at ON used_transactions(used_at);
71
- `;
72
- function openModuleDb(path) {
73
- const dir = dirname(path);
74
- if (!existsSync(dir)) {
75
- mkdirSync(dir, { recursive: true });
76
- }
77
- const db = new Database(path);
78
- try {
79
- chmodSync(path, 384);
80
- } catch {
81
- }
82
- db.pragma("journal_mode = WAL");
83
- return db;
84
- }
85
- function createDbWrapper(getDb, moduleName) {
86
- return function withDb(executor) {
87
- return (params, context) => {
88
- const moduleDb = getDb();
89
- if (!moduleDb) {
90
- return Promise.resolve({
91
- success: false,
92
- error: `${moduleName} module not started`
93
- });
94
- }
95
- return executor(params, { ...context, db: moduleDb });
96
- };
97
- };
98
- }
99
- var MAIN_DB_PATH = join(TELETON_ROOT, "memory.db");
100
- function migrateFromMainDb(moduleDb, tables) {
101
- let totalMigrated = 0;
102
- for (const table of tables) {
103
- if (!/^[a-z_]+$/.test(table)) {
104
- throw new Error(`Invalid table name for migration: "${table}"`);
105
- }
106
- }
107
- for (const table of tables) {
108
- try {
109
- const row = moduleDb.prepare(`SELECT COUNT(*) as c FROM ${table}`).get();
110
- if (row.c > 0) return 0;
111
- } catch {
112
- continue;
113
- }
114
- }
115
- if (!existsSync(MAIN_DB_PATH)) return 0;
116
- try {
117
- moduleDb.exec(`ATTACH DATABASE '${MAIN_DB_PATH}' AS main_db`);
118
- for (const table of tables) {
119
- try {
120
- const exists = moduleDb.prepare(`SELECT name FROM main_db.sqlite_master WHERE type='table' AND name=?`).get(table);
121
- if (!exists) continue;
122
- const src = moduleDb.prepare(`SELECT COUNT(*) as c FROM main_db.${table}`).get();
123
- if (src.c === 0) continue;
124
- moduleDb.exec(`INSERT OR IGNORE INTO ${table} SELECT * FROM main_db.${table}`);
125
- totalMigrated += src.c;
126
- console.log(` \u{1F4E6} Migrated ${src.c} rows from memory.db \u2192 ${table}`);
127
- } catch (e) {
128
- console.warn(` \u26A0\uFE0F Could not migrate table ${table}:`, e);
129
- }
130
- }
131
- moduleDb.exec(`DETACH DATABASE main_db`);
132
- } catch (e) {
133
- console.warn(`\u26A0\uFE0F Migration from memory.db failed:`, e);
134
- try {
135
- moduleDb.exec(`DETACH DATABASE main_db`);
136
- } catch {
137
- }
138
- }
139
- return totalMigrated;
140
- }
23
+ import { dirname } from "path";
24
+ import * as sqliteVec from "sqlite-vec";
141
25
 
142
26
  // src/memory/schema.ts
27
+ var log = createLogger("Memory");
143
28
  function compareSemver(a, b) {
144
29
  const parseVersion = (v) => {
145
30
  const parts = v.split("-")[0].split(".").map(Number);
@@ -428,15 +313,15 @@ function setSchemaVersion(db, version) {
428
313
  `
429
314
  ).run(version);
430
315
  }
431
- var CURRENT_SCHEMA_VERSION = "1.10.1";
316
+ var CURRENT_SCHEMA_VERSION = "1.11.0";
432
317
  function runMigrations(db) {
433
318
  const currentVersion = getSchemaVersion(db);
434
319
  if (!currentVersion || versionLessThan(currentVersion, "1.1.0")) {
435
- console.log("\u{1F4E6} Running migration: Adding scheduled task columns...");
320
+ log.info("Running migration: Adding scheduled task columns...");
436
321
  try {
437
322
  const tableExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='tasks'").get();
438
323
  if (!tableExists) {
439
- console.log(" Tasks table doesn't exist yet, skipping column migration");
324
+ log.info("Tasks table doesn't exist yet, skipping column migration");
440
325
  setSchemaVersion(db, CURRENT_SCHEMA_VERSION);
441
326
  return;
442
327
  }
@@ -469,15 +354,15 @@ function runMigrations(db) {
469
354
  CREATE INDEX IF NOT EXISTS idx_task_deps_task ON task_dependencies(task_id);
470
355
  CREATE INDEX IF NOT EXISTS idx_task_deps_parent ON task_dependencies(depends_on_task_id);
471
356
  `);
472
- console.log("\u2705 Migration 1.1.0 complete: Scheduled tasks support added");
357
+ log.info("Migration 1.1.0 complete: Scheduled tasks support added");
473
358
  } catch (error) {
474
- console.error("\u274C Migration 1.1.0 failed:", error);
359
+ log.error({ err: error }, "Migration 1.1.0 failed");
475
360
  throw error;
476
361
  }
477
362
  }
478
363
  if (!currentVersion || versionLessThan(currentVersion, "1.2.0")) {
479
364
  try {
480
- console.log("\u{1F504} Running migration 1.2.0: Extend sessions table for SQLite backend");
365
+ log.info("Running migration 1.2.0: Extend sessions table for SQLite backend");
481
366
  const addColumnIfNotExists = (table, column, type) => {
482
367
  try {
483
368
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${type}`);
@@ -506,14 +391,14 @@ function runMigrations(db) {
506
391
  );
507
392
  }
508
393
  db.exec("CREATE INDEX IF NOT EXISTS idx_sessions_updated ON sessions(updated_at DESC)");
509
- console.log("\u2705 Migration 1.2.0 complete: Sessions table extended");
394
+ log.info("Migration 1.2.0 complete: Sessions table extended");
510
395
  } catch (error) {
511
- console.error("\u274C Migration 1.2.0 failed:", error);
396
+ log.error({ err: error }, "Migration 1.2.0 failed");
512
397
  throw error;
513
398
  }
514
399
  }
515
400
  if (!currentVersion || versionLessThan(currentVersion, "1.9.0")) {
516
- console.log("\u{1F504} Running migration 1.9.0: Upgrade embedding_cache to BLOB storage");
401
+ log.info("Running migration 1.9.0: Upgrade embedding_cache to BLOB storage");
517
402
  try {
518
403
  db.exec(`DROP TABLE IF EXISTS embedding_cache`);
519
404
  db.exec(`
@@ -529,14 +414,14 @@ function runMigrations(db) {
529
414
  );
530
415
  CREATE INDEX IF NOT EXISTS idx_embedding_cache_accessed ON embedding_cache(accessed_at);
531
416
  `);
532
- console.log("\u2705 Migration 1.9.0 complete: embedding_cache upgraded to BLOB storage");
417
+ log.info("Migration 1.9.0 complete: embedding_cache upgraded to BLOB storage");
533
418
  } catch (error) {
534
- console.error("\u274C Migration 1.9.0 failed:", error);
419
+ log.error({ err: error }, "Migration 1.9.0 failed");
535
420
  throw error;
536
421
  }
537
422
  }
538
423
  if (!currentVersion || versionLessThan(currentVersion, "1.10.0")) {
539
- console.log("\u{1F504} Running migration 1.10.0: Add tool_config table for runtime tool management");
424
+ log.info("Running migration 1.10.0: Add tool_config table for runtime tool management");
540
425
  try {
541
426
  db.exec(`
542
427
  CREATE TABLE IF NOT EXISTS tool_config (
@@ -547,32 +432,71 @@ function runMigrations(db) {
547
432
  updated_by INTEGER
548
433
  );
549
434
  `);
550
- console.log("\u2705 Migration 1.10.0 complete: tool_config table created");
435
+ log.info("Migration 1.10.0 complete: tool_config table created");
551
436
  } catch (error) {
552
- console.error("\u274C Migration 1.10.0 failed:", error);
437
+ log.error({ err: error }, "Migration 1.10.0 failed");
553
438
  throw error;
554
439
  }
555
440
  }
556
441
  if (!currentVersion || versionLessThan(currentVersion, "1.10.1")) {
557
- console.log(
558
- "\u{1F504} Running migration 1.10.1: Fix tool_config scope CHECK constraint (add admin-only)"
559
- );
442
+ log.info("Running migration 1.10.1: Fix tool_config scope CHECK constraint (add admin-only)");
443
+ try {
444
+ db.transaction(() => {
445
+ db.exec(`
446
+ CREATE TABLE IF NOT EXISTS tool_config_new (
447
+ tool_name TEXT PRIMARY KEY,
448
+ enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0, 1)),
449
+ scope TEXT CHECK(scope IN ('always', 'dm-only', 'group-only', 'admin-only')),
450
+ updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
451
+ updated_by INTEGER
452
+ );
453
+ INSERT OR IGNORE INTO tool_config_new SELECT * FROM tool_config;
454
+ DROP TABLE tool_config;
455
+ ALTER TABLE tool_config_new RENAME TO tool_config;
456
+ `);
457
+ })();
458
+ log.info("Migration 1.10.1 complete: tool_config CHECK constraint updated");
459
+ } catch (error) {
460
+ log.error({ err: error }, "Migration 1.10.1 failed");
461
+ throw error;
462
+ }
463
+ }
464
+ if (!currentVersion || versionLessThan(currentVersion, "1.11.0")) {
465
+ log.info("Running migration 1.11.0: Add tool_index tables for Tool RAG");
560
466
  try {
561
467
  db.exec(`
562
- CREATE TABLE IF NOT EXISTS tool_config_new (
563
- tool_name TEXT PRIMARY KEY,
564
- enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0, 1)),
565
- scope TEXT CHECK(scope IN ('always', 'dm-only', 'group-only', 'admin-only')),
566
- updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
567
- updated_by INTEGER
468
+ CREATE TABLE IF NOT EXISTS tool_index (
469
+ name TEXT PRIMARY KEY,
470
+ description TEXT NOT NULL,
471
+ search_text TEXT NOT NULL,
472
+ updated_at INTEGER NOT NULL DEFAULT (unixepoch())
473
+ );
474
+
475
+ CREATE VIRTUAL TABLE IF NOT EXISTS tool_index_fts USING fts5(
476
+ search_text,
477
+ name UNINDEXED,
478
+ content='tool_index',
479
+ content_rowid='rowid'
568
480
  );
569
- INSERT OR IGNORE INTO tool_config_new SELECT * FROM tool_config;
570
- DROP TABLE tool_config;
571
- ALTER TABLE tool_config_new RENAME TO tool_config;
481
+
482
+ CREATE TRIGGER IF NOT EXISTS tool_index_fts_insert AFTER INSERT ON tool_index BEGIN
483
+ INSERT INTO tool_index_fts(rowid, search_text, name)
484
+ VALUES (new.rowid, new.search_text, new.name);
485
+ END;
486
+
487
+ CREATE TRIGGER IF NOT EXISTS tool_index_fts_delete AFTER DELETE ON tool_index BEGIN
488
+ DELETE FROM tool_index_fts WHERE rowid = old.rowid;
489
+ END;
490
+
491
+ CREATE TRIGGER IF NOT EXISTS tool_index_fts_update AFTER UPDATE ON tool_index BEGIN
492
+ DELETE FROM tool_index_fts WHERE rowid = old.rowid;
493
+ INSERT INTO tool_index_fts(rowid, search_text, name)
494
+ VALUES (new.rowid, new.search_text, new.name);
495
+ END;
572
496
  `);
573
- console.log("\u2705 Migration 1.10.1 complete: tool_config CHECK constraint updated");
497
+ log.info("Migration 1.11.0 complete: tool_index tables created");
574
498
  } catch (error) {
575
- console.error("\u274C Migration 1.10.1 failed:", error);
499
+ log.error({ err: error }, "Migration 1.11.0 failed");
576
500
  throw error;
577
501
  }
578
502
  }
@@ -580,21 +504,22 @@ function runMigrations(db) {
580
504
  }
581
505
 
582
506
  // src/memory/database.ts
507
+ var log2 = createLogger("Memory");
583
508
  var MemoryDatabase = class {
584
509
  db;
585
510
  config;
586
511
  vectorReady = false;
587
512
  constructor(config) {
588
513
  this.config = config;
589
- const dir = dirname2(config.path);
590
- if (!existsSync2(dir)) {
591
- mkdirSync2(dir, { recursive: true });
514
+ const dir = dirname(config.path);
515
+ if (!existsSync(dir)) {
516
+ mkdirSync(dir, { recursive: true });
592
517
  }
593
- this.db = new Database2(config.path, {
594
- verbose: process.env.DEBUG_SQL ? console.log : void 0
518
+ this.db = new Database(config.path, {
519
+ verbose: process.env.DEBUG_SQL ? (msg) => log2.debug(String(msg)) : void 0
595
520
  });
596
521
  try {
597
- chmodSync2(config.path, 384);
522
+ chmodSync(config.path, 384);
598
523
  } catch {
599
524
  }
600
525
  this.db.pragma("journal_mode = WAL");
@@ -631,18 +556,16 @@ var MemoryDatabase = class {
631
556
  ensureVectorTables(this.db, dims);
632
557
  this.vectorReady = true;
633
558
  } catch (error) {
634
- console.warn(
635
- `\u26A0\uFE0F sqlite-vec not available, vector search disabled: ${error.message}`
636
- );
637
- console.warn(" Falling back to keyword-only search");
559
+ log2.warn(`sqlite-vec not available, vector search disabled: ${error.message}`);
560
+ log2.warn("Falling back to keyword-only search");
638
561
  this.config.enableVectorSearch = false;
639
562
  }
640
563
  }
641
564
  migrate(from, to) {
642
- console.log(`Migrating database from ${from} to ${to}...`);
565
+ log2.info(`Migrating database from ${from} to ${to}...`);
643
566
  runMigrations(this.db);
644
567
  ensureSchema(this.db);
645
- console.log("Migration complete");
568
+ log2.info("Migration complete");
646
569
  }
647
570
  getDb() {
648
571
  return this.db;
@@ -743,365 +666,9 @@ function closeDatabase() {
743
666
  }
744
667
  }
745
668
 
746
- // src/memory/embeddings/index.ts
747
- import { createHash } from "crypto";
748
-
749
- // src/memory/embeddings/provider.ts
750
- var NoopEmbeddingProvider = class {
751
- id = "noop";
752
- model = "none";
753
- dimensions = 0;
754
- async embedQuery(_text) {
755
- return [];
756
- }
757
- async embedBatch(_texts) {
758
- return [];
759
- }
760
- };
761
-
762
- // src/utils/fetch.ts
763
- var DEFAULT_TIMEOUT_MS = DEFAULT_FETCH_TIMEOUT_MS;
764
- function fetchWithTimeout(url, init) {
765
- const { timeoutMs = DEFAULT_TIMEOUT_MS, ...fetchInit } = init ?? {};
766
- if (fetchInit.signal) {
767
- return fetch(url, fetchInit);
768
- }
769
- return fetch(url, {
770
- ...fetchInit,
771
- signal: AbortSignal.timeout(timeoutMs)
772
- });
773
- }
774
-
775
- // src/constants/api-endpoints.ts
776
- var TONAPI_BASE_URL = "https://tonapi.io/v2";
777
- var _tonapiKey;
778
- function setTonapiKey(key) {
779
- _tonapiKey = key;
780
- }
781
- function tonapiHeaders() {
782
- const headers = { Accept: "application/json" };
783
- if (_tonapiKey) {
784
- headers["Authorization"] = `Bearer ${_tonapiKey}`;
785
- }
786
- return headers;
787
- }
788
- var TONAPI_MAX_RPS = 5;
789
- var _tonapiTimestamps = [];
790
- async function waitForTonapiSlot() {
791
- const clean = () => {
792
- const cutoff = Date.now() - 1e3;
793
- while (_tonapiTimestamps.length > 0 && _tonapiTimestamps[0] <= cutoff) {
794
- _tonapiTimestamps.shift();
795
- }
796
- };
797
- clean();
798
- if (_tonapiTimestamps.length >= TONAPI_MAX_RPS) {
799
- const waitMs = _tonapiTimestamps[0] + 1e3 - Date.now() + 50;
800
- if (waitMs > 0) await new Promise((r) => setTimeout(r, waitMs));
801
- clean();
802
- }
803
- _tonapiTimestamps.push(Date.now());
804
- }
805
- async function tonapiFetch(path, init) {
806
- await waitForTonapiSlot();
807
- return fetchWithTimeout(`${TONAPI_BASE_URL}${path}`, {
808
- ...init,
809
- headers: { ...tonapiHeaders(), ...init?.headers }
810
- });
811
- }
812
- var STONFI_API_BASE_URL = "https://api.ston.fi/v1";
813
- var GECKOTERMINAL_API_URL = "https://api.geckoterminal.com/api/v2";
814
- var COINGECKO_API_URL = "https://api.coingecko.com/api/v3";
815
- var OPENAI_TTS_URL = "https://api.openai.com/v1/audio/speech";
816
- var ELEVENLABS_TTS_URL = "https://api.elevenlabs.io/v1/text-to-speech";
817
- var VOYAGE_API_URL = "https://api.voyageai.com/v1";
818
-
819
- // src/memory/embeddings/anthropic.ts
820
- var AnthropicEmbeddingProvider = class {
821
- id = "anthropic";
822
- model;
823
- dimensions;
824
- apiKey;
825
- baseUrl = VOYAGE_API_URL;
826
- constructor(config) {
827
- this.apiKey = config.apiKey;
828
- this.model = config.model ?? "voyage-3-lite";
829
- const dims = {
830
- "voyage-3": 1024,
831
- "voyage-3-lite": 512,
832
- "voyage-code-3": 1024,
833
- "voyage-finance-2": 1024,
834
- "voyage-multilingual-2": 1024,
835
- "voyage-law-2": 1024
836
- };
837
- this.dimensions = dims[this.model] ?? 512;
838
- }
839
- async embedQuery(text) {
840
- const result = await this.embed([text]);
841
- return result[0] ?? [];
842
- }
843
- async embedBatch(texts) {
844
- if (texts.length === 0) return [];
845
- const batchSize = VOYAGE_BATCH_SIZE;
846
- const results = [];
847
- for (let i = 0; i < texts.length; i += batchSize) {
848
- const batch = texts.slice(i, i + batchSize);
849
- const embeddings = await this.embed(batch);
850
- results.push(...embeddings);
851
- }
852
- return results;
853
- }
854
- async embed(texts) {
855
- const response = await fetchWithTimeout(`${this.baseUrl}/embeddings`, {
856
- method: "POST",
857
- headers: {
858
- "Content-Type": "application/json",
859
- Authorization: `Bearer ${this.apiKey}`
860
- },
861
- body: JSON.stringify({
862
- input: texts,
863
- model: this.model,
864
- input_type: "document"
865
- })
866
- });
867
- if (!response.ok) {
868
- const error = await response.text();
869
- throw new Error(`Voyage API error: ${response.status} ${error}`);
870
- }
871
- const data = await response.json();
872
- return data.data.map((item) => item.embedding);
873
- }
874
- };
875
-
876
- // src/memory/embeddings/local.ts
877
- import { pipeline, env } from "@huggingface/transformers";
878
- import { join as join2 } from "path";
879
- env.cacheDir = join2(TELETON_ROOT, "models");
880
- var extractorPromise = null;
881
- function getExtractor(model) {
882
- if (!extractorPromise) {
883
- console.log(`\u{1F4E6} Loading local embedding model: ${model} (cache: ${env.cacheDir})`);
884
- extractorPromise = pipeline("feature-extraction", model, {
885
- dtype: "fp32"
886
- }).then((ext) => {
887
- console.log(`\u2705 Local embedding model ready`);
888
- return ext;
889
- }).catch((err) => {
890
- console.error(`\u274C Failed to load embedding model: ${err.message}`);
891
- extractorPromise = null;
892
- throw err;
893
- });
894
- }
895
- return extractorPromise;
896
- }
897
- var LocalEmbeddingProvider = class {
898
- id = "local";
899
- model;
900
- dimensions;
901
- _disabled = false;
902
- constructor(config) {
903
- this.model = config.model || "Xenova/all-MiniLM-L6-v2";
904
- this.dimensions = 384;
905
- }
906
- /**
907
- * Pre-download and load the model at startup.
908
- * If loading fails, marks this provider as disabled (returns empty embeddings).
909
- * Call this once during app init — avoids retry spam on every message.
910
- * @returns true if model loaded successfully, false if fallback to noop
911
- */
912
- async warmup() {
913
- try {
914
- await getExtractor(this.model);
915
- return true;
916
- } catch (err) {
917
- console.warn(
918
- `\u26A0\uFE0F Local embedding model unavailable \u2014 falling back to FTS5-only search (no vector embeddings)`
919
- );
920
- this._disabled = true;
921
- return false;
922
- }
923
- }
924
- async embedQuery(text) {
925
- if (this._disabled) return [];
926
- const extractor = await getExtractor(this.model);
927
- const output = await extractor(text, { pooling: "mean", normalize: true });
928
- return Array.from(output.data);
929
- }
930
- async embedBatch(texts) {
931
- if (this._disabled) return [];
932
- if (texts.length === 0) return [];
933
- const extractor = await getExtractor(this.model);
934
- const output = await extractor(texts, { pooling: "mean", normalize: true });
935
- const data = output.data;
936
- const dims = this.dimensions;
937
- const results = [];
938
- for (let i = 0; i < texts.length; i++) {
939
- results.push(Array.from(data.slice(i * dims, (i + 1) * dims)));
940
- }
941
- return results;
942
- }
943
- };
944
-
945
- // src/memory/embeddings/cached.ts
946
- var CachedEmbeddingProvider = class {
947
- constructor(inner, db) {
948
- this.inner = inner;
949
- this.db = db;
950
- this.id = inner.id;
951
- this.model = inner.model;
952
- this.dimensions = inner.dimensions;
953
- }
954
- id;
955
- model;
956
- dimensions;
957
- hits = 0;
958
- misses = 0;
959
- ops = 0;
960
- cacheGet(hash) {
961
- return this.db.prepare(
962
- `SELECT embedding FROM embedding_cache WHERE hash = ? AND model = ? AND provider = ?`
963
- ).get(hash, this.model, this.id);
964
- }
965
- cachePut(hash, blob) {
966
- this.db.prepare(
967
- `INSERT OR REPLACE INTO embedding_cache (hash, embedding, model, provider, dims, created_at, accessed_at)
968
- VALUES (?, ?, ?, ?, ?, unixepoch(), unixepoch())`
969
- ).run(hash, blob, this.model, this.id, this.dimensions);
970
- }
971
- cacheTouch(hash) {
972
- this.db.prepare(
973
- `UPDATE embedding_cache SET accessed_at = unixepoch() WHERE hash = ? AND model = ? AND provider = ?`
974
- ).run(hash, this.model, this.id);
975
- }
976
- async warmup() {
977
- return this.inner.warmup?.() ?? true;
978
- }
979
- async embedQuery(text) {
980
- const hash = hashText(text);
981
- const row = this.cacheGet(hash);
982
- if (row) {
983
- this.hits++;
984
- this.cacheTouch(hash);
985
- this.tick();
986
- return deserializeEmbedding(row.embedding);
987
- }
988
- this.misses++;
989
- const embedding = await this.inner.embedQuery(text);
990
- this.cachePut(hash, serializeEmbedding(embedding));
991
- this.tick();
992
- return embedding;
993
- }
994
- async embedBatch(texts) {
995
- if (texts.length === 0) return [];
996
- const hashes = texts.map(hashText);
997
- const results = new Array(texts.length).fill(null);
998
- const missIndices = [];
999
- const missTexts = [];
1000
- for (let i = 0; i < texts.length; i++) {
1001
- const row = this.cacheGet(hashes[i]);
1002
- if (row) {
1003
- this.hits++;
1004
- this.cacheTouch(hashes[i]);
1005
- results[i] = deserializeEmbedding(row.embedding);
1006
- } else {
1007
- this.misses++;
1008
- missIndices.push(i);
1009
- missTexts.push(texts[i]);
1010
- }
1011
- }
1012
- if (missTexts.length > 0) {
1013
- const newEmbeddings = await this.inner.embedBatch(missTexts);
1014
- for (let j = 0; j < missIndices.length; j++) {
1015
- const idx = missIndices[j];
1016
- const embedding = newEmbeddings[j] ?? [];
1017
- results[idx] = embedding;
1018
- if (embedding.length > 0) {
1019
- this.cachePut(hashes[idx], serializeEmbedding(embedding));
1020
- }
1021
- }
1022
- }
1023
- this.ops += texts.length;
1024
- this.maybeEvict();
1025
- this.maybeLogStats();
1026
- return results;
1027
- }
1028
- tick() {
1029
- this.ops++;
1030
- this.maybeEvict();
1031
- this.maybeLogStats();
1032
- }
1033
- maybeLogStats() {
1034
- const total = this.hits + this.misses;
1035
- if (total > 0 && total % 100 === 0) {
1036
- const rate = (this.hits / total * 100).toFixed(0);
1037
- console.log(
1038
- `\u{1F4CA} Embedding cache: ${this.hits} hits, ${this.misses} misses (${rate}% hit rate)`
1039
- );
1040
- }
1041
- }
1042
- maybeEvict() {
1043
- if (this.ops % EMBEDDING_CACHE_EVICTION_INTERVAL !== 0) return;
1044
- try {
1045
- const cutoff = Math.floor(Date.now() / 1e3) - EMBEDDING_CACHE_TTL_DAYS * 86400;
1046
- this.db.prepare(`DELETE FROM embedding_cache WHERE accessed_at < ?`).run(cutoff);
1047
- const count = this.db.prepare(`SELECT COUNT(*) as cnt FROM embedding_cache`).get().cnt;
1048
- if (count > EMBEDDING_CACHE_MAX_ENTRIES) {
1049
- const toDelete = Math.ceil(count * EMBEDDING_CACHE_EVICTION_RATIO);
1050
- this.db.prepare(
1051
- `DELETE FROM embedding_cache WHERE (hash, model, provider) IN (
1052
- SELECT hash, model, provider FROM embedding_cache ORDER BY accessed_at ASC LIMIT ?
1053
- )`
1054
- ).run(toDelete);
1055
- console.log(`\u{1F9F9} Embedding cache eviction: removed ${toDelete} entries (${count} total)`);
1056
- }
1057
- } catch (err) {
1058
- console.warn("\u26A0\uFE0F Embedding cache eviction error:", err);
1059
- }
1060
- }
1061
- };
1062
-
1063
- // src/memory/embeddings/index.ts
1064
- function createEmbeddingProvider(config) {
1065
- switch (config.provider) {
1066
- case "anthropic":
1067
- if (!config.apiKey) {
1068
- throw new Error("API key required for Anthropic embedding provider");
1069
- }
1070
- return new AnthropicEmbeddingProvider({
1071
- apiKey: config.apiKey,
1072
- model: config.model
1073
- });
1074
- case "local":
1075
- return new LocalEmbeddingProvider({
1076
- model: config.model
1077
- });
1078
- case "none":
1079
- return new NoopEmbeddingProvider();
1080
- default:
1081
- throw new Error(`Unknown embedding provider: ${config.provider}`);
1082
- }
1083
- }
1084
- function hashText(text) {
1085
- return createHash("sha256").update(text).digest("hex");
1086
- }
1087
- function serializeEmbedding(embedding) {
1088
- return Buffer.from(new Float32Array(embedding).buffer);
1089
- }
1090
- function deserializeEmbedding(data) {
1091
- try {
1092
- if (Buffer.isBuffer(data)) {
1093
- const floats = new Float32Array(data.buffer, data.byteOffset, data.byteLength / 4);
1094
- return Array.from(floats);
1095
- }
1096
- return JSON.parse(data);
1097
- } catch {
1098
- return [];
1099
- }
1100
- }
1101
-
1102
669
  // src/memory/agent/knowledge.ts
1103
- import { readFileSync, existsSync as existsSync3, readdirSync, statSync } from "fs";
1104
- import { join as join3 } from "path";
670
+ import { readFileSync, existsSync as existsSync2, readdirSync, statSync } from "fs";
671
+ import { join } from "path";
1105
672
  var KnowledgeIndexer = class {
1106
673
  constructor(db, workspaceDir, embedder, vectorEnabled) {
1107
674
  this.db = db;
@@ -1124,7 +691,7 @@ var KnowledgeIndexer = class {
1124
691
  return { indexed, skipped };
1125
692
  }
1126
693
  async indexFile(absPath) {
1127
- if (!existsSync3(absPath) || !absPath.endsWith(".md")) {
694
+ if (!existsSync2(absPath) || !absPath.endsWith(".md")) {
1128
695
  return false;
1129
696
  }
1130
697
  const content = readFileSync(absPath, "utf-8");
@@ -1172,15 +739,15 @@ var KnowledgeIndexer = class {
1172
739
  }
1173
740
  listMemoryFiles() {
1174
741
  const files = [];
1175
- const memoryMd = join3(this.workspaceDir, "MEMORY.md");
1176
- if (existsSync3(memoryMd)) {
742
+ const memoryMd = join(this.workspaceDir, "MEMORY.md");
743
+ if (existsSync2(memoryMd)) {
1177
744
  files.push(memoryMd);
1178
745
  }
1179
- const memoryDir = join3(this.workspaceDir, "memory");
1180
- if (existsSync3(memoryDir)) {
746
+ const memoryDir = join(this.workspaceDir, "memory");
747
+ if (existsSync2(memoryDir)) {
1181
748
  const entries = readdirSync(memoryDir);
1182
749
  for (const entry of entries) {
1183
- const absPath = join3(memoryDir, entry);
750
+ const absPath = join(memoryDir, entry);
1184
751
  if (statSync(absPath).isFile() && entry.endsWith(".md")) {
1185
752
  files.push(absPath);
1186
753
  }
@@ -1247,6 +814,7 @@ var KnowledgeIndexer = class {
1247
814
 
1248
815
  // src/memory/agent/sessions.ts
1249
816
  import { randomUUID } from "crypto";
817
+ var log3 = createLogger("Memory");
1250
818
  var SessionStore = class {
1251
819
  constructor(db, embedder, vectorEnabled) {
1252
820
  this.db = db;
@@ -1367,13 +935,12 @@ ${session.summary}`;
1367
935
  ).run(knowledgeId, sessionId, text, hash);
1368
936
  if (embedding && this.vectorEnabled) {
1369
937
  const embeddingBuffer = serializeEmbedding(embedding);
1370
- const rowid = this.db.prepare(`SELECT rowid FROM knowledge WHERE id = ?`).get(knowledgeId);
1371
- this.db.prepare(`DELETE FROM knowledge_vec WHERE rowid = ?`).run(rowid.rowid);
1372
- this.db.prepare(`INSERT INTO knowledge_vec (rowid, embedding) VALUES (?, ?)`).run(rowid.rowid, embeddingBuffer);
938
+ this.db.prepare(`DELETE FROM knowledge_vec WHERE id = ?`).run(knowledgeId);
939
+ this.db.prepare(`INSERT INTO knowledge_vec (id, embedding) VALUES (?, ?)`).run(knowledgeId, embeddingBuffer);
1373
940
  }
1374
- console.log(`Indexed session ${sessionId} to knowledge base`);
941
+ log3.info(`Indexed session ${sessionId} to knowledge base`);
1375
942
  } catch (error) {
1376
- console.error("Error indexing session:", error);
943
+ log3.error({ err: error }, "Error indexing session");
1377
944
  }
1378
945
  }
1379
946
  deleteSession(sessionId) {
@@ -1738,6 +1305,7 @@ var UserStore = class {
1738
1305
  };
1739
1306
 
1740
1307
  // src/memory/search/hybrid.ts
1308
+ var log4 = createLogger("Memory");
1741
1309
  function escapeFts5Query(query) {
1742
1310
  return query.replace(/["\*\-\+\(\)\:\^\~\?\.\@\#\$\%\&\!\[\]\{\}\|\\\/<>=,;'`]/g, " ").replace(/\s+/g, " ").trim();
1743
1311
  }
@@ -1785,7 +1353,7 @@ var HybridSearch = class {
1785
1353
  vectorScore: 1 - row.distance
1786
1354
  }));
1787
1355
  } catch (error) {
1788
- console.error("Vector search error (knowledge):", error);
1356
+ log4.error({ err: error }, "Vector search error (knowledge)");
1789
1357
  return [];
1790
1358
  }
1791
1359
  }
@@ -1808,7 +1376,7 @@ var HybridSearch = class {
1808
1376
  keywordScore: this.bm25ToScore(row.score)
1809
1377
  }));
1810
1378
  } catch (error) {
1811
- console.error("FTS5 search error (knowledge):", error);
1379
+ log4.error({ err: error }, "FTS5 search error (knowledge)");
1812
1380
  return [];
1813
1381
  }
1814
1382
  }
@@ -1843,7 +1411,7 @@ var HybridSearch = class {
1843
1411
  vectorScore: 1 - row.distance
1844
1412
  }));
1845
1413
  } catch (error) {
1846
- console.error("Vector search error (messages):", error);
1414
+ log4.error({ err: error }, "Vector search error (messages)");
1847
1415
  return [];
1848
1416
  }
1849
1417
  }
@@ -1873,7 +1441,7 @@ var HybridSearch = class {
1873
1441
  keywordScore: this.bm25ToScore(row.score)
1874
1442
  }));
1875
1443
  } catch (error) {
1876
- console.error("FTS5 search error (messages):", error);
1444
+ log4.error({ err: error }, "FTS5 search error (messages)");
1877
1445
  return [];
1878
1446
  }
1879
1447
  }
@@ -1903,6 +1471,7 @@ var HybridSearch = class {
1903
1471
  };
1904
1472
 
1905
1473
  // src/memory/search/context.ts
1474
+ var log5 = createLogger("Memory");
1906
1475
  var ContextBuilder = class {
1907
1476
  constructor(db, embedder, vectorEnabled) {
1908
1477
  this.db = db;
@@ -1936,7 +1505,7 @@ var ContextBuilder = class {
1936
1505
  });
1937
1506
  relevantKnowledge.push(...knowledgeResults.map((r) => r.text));
1938
1507
  } catch (error) {
1939
- console.warn("Knowledge search failed:", error);
1508
+ log5.warn({ err: error }, "Knowledge search failed");
1940
1509
  }
1941
1510
  }
1942
1511
  const recentTextsSet = new Set(
@@ -1966,7 +1535,7 @@ var ContextBuilder = class {
1966
1535
  }
1967
1536
  }
1968
1537
  } catch (error) {
1969
- console.warn("Feed search failed:", error);
1538
+ log5.warn({ err: error }, "Feed search failed");
1970
1539
  }
1971
1540
  if (relevantFeed.length === 0 && recentTgMessages.length > 0) {
1972
1541
  const recentTexts = recentTgMessages.filter((m) => m.text && m.text.length > 0).slice(-maxRelevantChunks).map((m) => {
@@ -2004,11 +1573,6 @@ function initializeMemory(config) {
2004
1573
  }
2005
1574
 
2006
1575
  export {
2007
- JOURNAL_SCHEMA,
2008
- USED_TRANSACTIONS_SCHEMA,
2009
- openModuleDb,
2010
- createDbWrapper,
2011
- migrateFromMainDb,
2012
1576
  ensureSchema,
2013
1577
  ensureVectorTables,
2014
1578
  getSchemaVersion,
@@ -2018,22 +1582,6 @@ export {
2018
1582
  MemoryDatabase,
2019
1583
  getDatabase,
2020
1584
  closeDatabase,
2021
- NoopEmbeddingProvider,
2022
- fetchWithTimeout,
2023
- setTonapiKey,
2024
- tonapiFetch,
2025
- STONFI_API_BASE_URL,
2026
- GECKOTERMINAL_API_URL,
2027
- COINGECKO_API_URL,
2028
- OPENAI_TTS_URL,
2029
- ELEVENLABS_TTS_URL,
2030
- AnthropicEmbeddingProvider,
2031
- LocalEmbeddingProvider,
2032
- CachedEmbeddingProvider,
2033
- createEmbeddingProvider,
2034
- hashText,
2035
- serializeEmbedding,
2036
- deserializeEmbedding,
2037
1585
  KnowledgeIndexer,
2038
1586
  SessionStore,
2039
1587
  MessageStore,