teleton 0.7.4 → 0.8.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 (50) hide show
  1. package/README.md +43 -30
  2. package/dist/chunk-3RG5ZIWI.js +10 -0
  3. package/dist/{chunk-U7FQYCBQ.js → chunk-7TECSLJ4.js} +2 -2
  4. package/dist/{chunk-LAQOUFOJ.js → chunk-H36RFKRI.js} +7583 -11185
  5. package/dist/{chunk-RO62LO6Z.js → chunk-IJBWWQE4.js} +4 -0
  6. package/dist/{chunk-BGC2IUM5.js → chunk-JHYZYFZJ.js} +69 -20
  7. package/dist/{chunk-QOQWUUA4.js → chunk-OJCLKU5Z.js} +68 -2
  8. package/dist/{chunk-OCLG5GKI.js → chunk-P36I6OIV.js} +2 -2
  9. package/dist/chunk-PHSAHTK4.js +314 -0
  10. package/dist/{chunk-5PLZ3KSO.js → chunk-QVBSUYVX.js} +14 -42
  11. package/dist/{chunk-4DU3C27M.js → chunk-R4YSJ4EY.js} +5 -1
  12. package/dist/chunk-RQBAMUCV.js +10281 -0
  13. package/dist/{chunk-XDYDA2KV.js → chunk-SD4NLLYG.js} +293 -64
  14. package/dist/chunk-TVRZJIZX.js +292 -0
  15. package/dist/{chunk-EK7M5K26.js → chunk-U56QTM46.js} +3 -3
  16. package/dist/{chunk-XBKSS6DM.js → chunk-VFA7QMCZ.js} +5 -3
  17. package/dist/{chunk-VAUJSSD3.js → chunk-XQUHC3JZ.js} +1 -1
  18. package/dist/cli/index.js +96 -33
  19. package/dist/{client-RTNALK7W.js → client-LNZTDQSA.js} +6 -7
  20. package/dist/{get-my-gifts-TPVUGUWT.js → get-my-gifts-OMGKOEPM.js} +1 -1
  21. package/dist/index.js +15 -17
  22. package/dist/{memory-JQZ6MTRU.js → memory-AS7WKGTW.js} +7 -8
  23. package/dist/{migrate-GS5ACQDA.js → migrate-POHWYEIW.js} +7 -8
  24. package/dist/{multipart-parser-S3YC6NRJ.js → multipart-parser-UFQLJOV2.js} +2 -2
  25. package/dist/{paths-TMNTEDDD.js → paths-XA2RJH4S.js} +1 -1
  26. package/dist/{server-TCJOBV3D.js → server-H3QA252W.js} +39 -12
  27. package/dist/{setup-server-YHYJLAMA.js → setup-server-QXED3D2L.js} +24 -12
  28. package/dist/store-GAFULOOX.js +34 -0
  29. package/dist/{task-dependency-resolver-WKZWJLLM.js → task-dependency-resolver-3FIKQ7Z6.js} +3 -3
  30. package/dist/{task-executor-PD3H4MLO.js → task-executor-RUTFG6VG.js} +2 -2
  31. package/dist/{tasks-QSCWSMPS.js → tasks-BEZ4QRI2.js} +1 -1
  32. package/dist/{tool-adapter-Y3TCEQOC.js → tool-adapter-IH5VGBOO.js} +1 -1
  33. package/dist/{tool-index-6HBRVXVG.js → tool-index-H3SHOJC3.js} +6 -6
  34. package/dist/{transcript-UDJZP6NK.js → transcript-IMNE6KU3.js} +2 -2
  35. package/dist/web/assets/index-BrVqauzj.css +1 -0
  36. package/dist/web/assets/index-DYeEkvJ6.js +72 -0
  37. package/dist/web/assets/{index.es-CqZHj0tz.js → index.es-DkU1GvWU.js} +1 -1
  38. package/dist/web/index.html +2 -2
  39. package/package.json +2 -2
  40. package/dist/BigInteger-DQ33LTTE.js +0 -5
  41. package/dist/chunk-JQDLW7IE.js +0 -107
  42. package/dist/chunk-QGM4M3NI.js +0 -37
  43. package/dist/chunk-RMLQS3X6.js +0 -161
  44. package/dist/chunk-TSKJCWQQ.js +0 -1263
  45. package/dist/chunk-UCN6TI25.js +0 -143
  46. package/dist/chunk-YFG2QHLA.js +0 -3585
  47. package/dist/web/assets/index-B6M9knfJ.css +0 -1
  48. package/dist/web/assets/index-DAGeQfVZ.js +0 -72
  49. package/scripts/patch-gramjs.sh +0 -46
  50. package/scripts/postinstall.mjs +0 -16
@@ -1,30 +1,160 @@
1
- import {
2
- JOURNAL_SCHEMA
3
- } from "./chunk-UCN6TI25.js";
4
1
  import {
5
2
  CachedEmbeddingProvider,
6
3
  createEmbeddingProvider,
7
4
  hashText,
8
5
  serializeEmbedding
9
- } from "./chunk-EK7M5K26.js";
6
+ } from "./chunk-U56QTM46.js";
10
7
  import {
8
+ FEED_MESSAGE_MAX_CHARS,
11
9
  HYBRID_SEARCH_MIN_SCORE,
12
10
  KNOWLEDGE_CHUNK_SIZE,
13
11
  SQLITE_CACHE_SIZE_KB,
14
12
  SQLITE_MMAP_SIZE
15
- } from "./chunk-RO62LO6Z.js";
13
+ } from "./chunk-IJBWWQE4.js";
14
+ import {
15
+ TELETON_ROOT
16
+ } from "./chunk-EYWNOHMJ.js";
16
17
  import {
17
18
  createLogger
18
19
  } from "./chunk-RCMD3U65.js";
19
20
 
20
21
  // src/memory/database.ts
22
+ import Database2 from "better-sqlite3";
23
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, chmodSync as chmodSync2 } from "fs";
24
+ import { dirname as dirname2 } from "path";
25
+ import * as sqliteVec from "sqlite-vec";
26
+
27
+ // src/utils/module-db.ts
21
28
  import Database from "better-sqlite3";
22
29
  import { existsSync, mkdirSync, chmodSync } from "fs";
23
- import { dirname } from "path";
24
- import * as sqliteVec from "sqlite-vec";
30
+ import { dirname, join } from "path";
31
+ var log = createLogger("Utils");
32
+ var JOURNAL_SCHEMA = `
33
+ CREATE TABLE IF NOT EXISTS journal (
34
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
35
+ timestamp INTEGER NOT NULL DEFAULT (unixepoch()),
36
+ type TEXT NOT NULL CHECK(type IN ('trade', 'gift', 'middleman', 'kol')),
37
+ action TEXT NOT NULL,
38
+ asset_from TEXT,
39
+ asset_to TEXT,
40
+ amount_from REAL,
41
+ amount_to REAL,
42
+ price_ton REAL,
43
+ counterparty TEXT,
44
+ platform TEXT,
45
+ reasoning TEXT,
46
+ outcome TEXT CHECK(outcome IN ('pending', 'profit', 'loss', 'neutral', 'cancelled')),
47
+ pnl_ton REAL,
48
+ pnl_pct REAL,
49
+ tx_hash TEXT,
50
+ tool_used TEXT,
51
+ chat_id TEXT,
52
+ user_id INTEGER,
53
+ closed_at INTEGER,
54
+ created_at INTEGER NOT NULL DEFAULT (unixepoch())
55
+ );
56
+
57
+ CREATE INDEX IF NOT EXISTS idx_journal_type ON journal(type);
58
+ CREATE INDEX IF NOT EXISTS idx_journal_timestamp ON journal(timestamp DESC);
59
+ CREATE INDEX IF NOT EXISTS idx_journal_asset_from ON journal(asset_from);
60
+ CREATE INDEX IF NOT EXISTS idx_journal_outcome ON journal(outcome);
61
+ CREATE INDEX IF NOT EXISTS idx_journal_type_timestamp ON journal(type, timestamp DESC);
62
+ `;
63
+ var USED_TRANSACTIONS_SCHEMA = `
64
+ CREATE TABLE IF NOT EXISTS used_transactions (
65
+ tx_hash TEXT PRIMARY KEY,
66
+ user_id TEXT NOT NULL,
67
+ amount REAL NOT NULL,
68
+ game_type TEXT NOT NULL,
69
+ used_at INTEGER NOT NULL DEFAULT (unixepoch())
70
+ );
71
+
72
+ CREATE INDEX IF NOT EXISTS idx_used_tx_user ON used_transactions(user_id);
73
+ CREATE INDEX IF NOT EXISTS idx_used_tx_used_at ON used_transactions(used_at);
74
+ `;
75
+ function openModuleDb(path) {
76
+ const dir = dirname(path);
77
+ if (!existsSync(dir)) {
78
+ mkdirSync(dir, { recursive: true });
79
+ }
80
+ const db = new Database(path);
81
+ try {
82
+ chmodSync(path, 384);
83
+ } catch {
84
+ }
85
+ db.pragma("journal_mode = WAL");
86
+ return db;
87
+ }
88
+ function createDbWrapper(getDb, moduleName) {
89
+ return function withDb(executor) {
90
+ return (params, context) => {
91
+ const moduleDb = getDb();
92
+ if (!moduleDb) {
93
+ return Promise.resolve({
94
+ success: false,
95
+ error: `${moduleName} module not started`
96
+ });
97
+ }
98
+ return executor(params, { ...context, db: moduleDb });
99
+ };
100
+ };
101
+ }
102
+ var MAIN_DB_PATH = join(TELETON_ROOT, "memory.db");
103
+ function migrateFromMainDb(moduleDb, tables) {
104
+ let totalMigrated = 0;
105
+ for (const table of tables) {
106
+ if (!/^[a-z_]+$/.test(table)) {
107
+ throw new Error(`Invalid table name for migration: "${table}"`);
108
+ }
109
+ }
110
+ for (const table of tables) {
111
+ try {
112
+ const row = moduleDb.prepare(`SELECT COUNT(*) as c FROM ${table}`).get();
113
+ if (row.c > 0) return 0;
114
+ } catch {
115
+ continue;
116
+ }
117
+ }
118
+ if (!existsSync(MAIN_DB_PATH)) return 0;
119
+ try {
120
+ moduleDb.exec(`ATTACH DATABASE '${MAIN_DB_PATH}' AS main_db`);
121
+ for (const table of tables) {
122
+ try {
123
+ const exists = moduleDb.prepare(`SELECT name FROM main_db.sqlite_master WHERE type='table' AND name=?`).get(table);
124
+ if (!exists) continue;
125
+ const src = moduleDb.prepare(`SELECT COUNT(*) as c FROM main_db.${table}`).get();
126
+ if (src.c === 0) continue;
127
+ const dstCols = moduleDb.prepare(`PRAGMA table_info(${table})`).all().map((r) => r.name);
128
+ const srcCols = moduleDb.prepare(`PRAGMA main_db.table_info(${table})`).all().map((r) => r.name);
129
+ const shared = dstCols.filter((c) => srcCols.includes(c));
130
+ if (shared.length === 0) continue;
131
+ const cols = shared.join(", ");
132
+ moduleDb.exec(
133
+ `INSERT OR IGNORE INTO ${table} (${cols}) SELECT ${cols} FROM main_db.${table}`
134
+ );
135
+ totalMigrated += src.c;
136
+ try {
137
+ moduleDb.exec(`DROP TABLE main_db.${table}`);
138
+ } catch {
139
+ }
140
+ log.info(`Migrated ${src.c} rows from memory.db \u2192 ${table} (source dropped)`);
141
+ } catch (e) {
142
+ log.warn({ err: e }, `Could not migrate table ${table}`);
143
+ }
144
+ }
145
+ moduleDb.exec(`DETACH DATABASE main_db`);
146
+ } catch (e) {
147
+ log.warn({ err: e }, `Migration from memory.db failed`);
148
+ try {
149
+ moduleDb.exec(`DETACH DATABASE main_db`);
150
+ } catch {
151
+ }
152
+ }
153
+ return totalMigrated;
154
+ }
25
155
 
26
156
  // src/memory/schema.ts
27
- var log = createLogger("Memory");
157
+ var log2 = createLogger("Memory");
28
158
  function compareSemver(a, b) {
29
159
  const parseVersion = (v) => {
30
160
  const parts = v.split("-")[0].split(".").map(Number);
@@ -119,7 +249,9 @@ function ensureSchema(db) {
119
249
  context_tokens INTEGER, -- Current context size
120
250
  model TEXT, -- Model used (claude-opus-4-5-20251101)
121
251
  provider TEXT, -- Provider (anthropic)
122
- last_reset_date TEXT -- YYYY-MM-DD of last daily reset
252
+ last_reset_date TEXT, -- YYYY-MM-DD of last daily reset
253
+ input_tokens INTEGER DEFAULT 0, -- Accumulated input tokens
254
+ output_tokens INTEGER DEFAULT 0 -- Accumulated output tokens
123
255
  );
124
256
 
125
257
  CREATE INDEX IF NOT EXISTS idx_sessions_chat ON sessions(chat_id);
@@ -271,6 +403,30 @@ function ensureSchema(db) {
271
403
 
272
404
  CREATE INDEX IF NOT EXISTS idx_embedding_cache_accessed ON embedding_cache(accessed_at);
273
405
 
406
+ -- =====================================================
407
+ -- EXEC AUDIT (Command Execution History)
408
+ -- =====================================================
409
+
410
+ CREATE TABLE IF NOT EXISTS exec_audit (
411
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
412
+ timestamp INTEGER NOT NULL DEFAULT (unixepoch()),
413
+ user_id INTEGER NOT NULL,
414
+ username TEXT,
415
+ tool TEXT NOT NULL,
416
+ command TEXT NOT NULL,
417
+ status TEXT NOT NULL DEFAULT 'running'
418
+ CHECK(status IN ('running', 'success', 'failed', 'timeout', 'killed')),
419
+ exit_code INTEGER,
420
+ signal TEXT,
421
+ duration_ms INTEGER,
422
+ stdout TEXT,
423
+ stderr TEXT,
424
+ truncated INTEGER NOT NULL DEFAULT 0
425
+ );
426
+
427
+ CREATE INDEX IF NOT EXISTS idx_exec_audit_timestamp ON exec_audit(timestamp DESC);
428
+ CREATE INDEX IF NOT EXISTS idx_exec_audit_user ON exec_audit(user_id);
429
+
274
430
  -- =====================================================
275
431
  -- JOURNAL (Trading & Business Operations)
276
432
  -- =====================================================
@@ -313,15 +469,15 @@ function setSchemaVersion(db, version) {
313
469
  `
314
470
  ).run(version);
315
471
  }
316
- var CURRENT_SCHEMA_VERSION = "1.11.0";
472
+ var CURRENT_SCHEMA_VERSION = "1.13.0";
317
473
  function runMigrations(db) {
318
474
  const currentVersion = getSchemaVersion(db);
319
475
  if (!currentVersion || versionLessThan(currentVersion, "1.1.0")) {
320
- log.info("Running migration: Adding scheduled task columns...");
476
+ log2.info("Running migration: Adding scheduled task columns...");
321
477
  try {
322
478
  const tableExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='tasks'").get();
323
479
  if (!tableExists) {
324
- log.info("Tasks table doesn't exist yet, skipping column migration");
480
+ log2.info("Tasks table doesn't exist yet, skipping column migration");
325
481
  setSchemaVersion(db, CURRENT_SCHEMA_VERSION);
326
482
  return;
327
483
  }
@@ -354,15 +510,15 @@ function runMigrations(db) {
354
510
  CREATE INDEX IF NOT EXISTS idx_task_deps_task ON task_dependencies(task_id);
355
511
  CREATE INDEX IF NOT EXISTS idx_task_deps_parent ON task_dependencies(depends_on_task_id);
356
512
  `);
357
- log.info("Migration 1.1.0 complete: Scheduled tasks support added");
513
+ log2.info("Migration 1.1.0 complete: Scheduled tasks support added");
358
514
  } catch (error) {
359
- log.error({ err: error }, "Migration 1.1.0 failed");
515
+ log2.error({ err: error }, "Migration 1.1.0 failed");
360
516
  throw error;
361
517
  }
362
518
  }
363
519
  if (!currentVersion || versionLessThan(currentVersion, "1.2.0")) {
364
520
  try {
365
- log.info("Running migration 1.2.0: Extend sessions table for SQLite backend");
521
+ log2.info("Running migration 1.2.0: Extend sessions table for SQLite backend");
366
522
  const addColumnIfNotExists = (table, column, type) => {
367
523
  try {
368
524
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${type}`);
@@ -391,14 +547,14 @@ function runMigrations(db) {
391
547
  );
392
548
  }
393
549
  db.exec("CREATE INDEX IF NOT EXISTS idx_sessions_updated ON sessions(updated_at DESC)");
394
- log.info("Migration 1.2.0 complete: Sessions table extended");
550
+ log2.info("Migration 1.2.0 complete: Sessions table extended");
395
551
  } catch (error) {
396
- log.error({ err: error }, "Migration 1.2.0 failed");
552
+ log2.error({ err: error }, "Migration 1.2.0 failed");
397
553
  throw error;
398
554
  }
399
555
  }
400
556
  if (!currentVersion || versionLessThan(currentVersion, "1.9.0")) {
401
- log.info("Running migration 1.9.0: Upgrade embedding_cache to BLOB storage");
557
+ log2.info("Running migration 1.9.0: Upgrade embedding_cache to BLOB storage");
402
558
  try {
403
559
  db.exec(`DROP TABLE IF EXISTS embedding_cache`);
404
560
  db.exec(`
@@ -414,14 +570,14 @@ function runMigrations(db) {
414
570
  );
415
571
  CREATE INDEX IF NOT EXISTS idx_embedding_cache_accessed ON embedding_cache(accessed_at);
416
572
  `);
417
- log.info("Migration 1.9.0 complete: embedding_cache upgraded to BLOB storage");
573
+ log2.info("Migration 1.9.0 complete: embedding_cache upgraded to BLOB storage");
418
574
  } catch (error) {
419
- log.error({ err: error }, "Migration 1.9.0 failed");
575
+ log2.error({ err: error }, "Migration 1.9.0 failed");
420
576
  throw error;
421
577
  }
422
578
  }
423
579
  if (!currentVersion || versionLessThan(currentVersion, "1.10.0")) {
424
- log.info("Running migration 1.10.0: Add tool_config table for runtime tool management");
580
+ log2.info("Running migration 1.10.0: Add tool_config table for runtime tool management");
425
581
  try {
426
582
  db.exec(`
427
583
  CREATE TABLE IF NOT EXISTS tool_config (
@@ -432,14 +588,14 @@ function runMigrations(db) {
432
588
  updated_by INTEGER
433
589
  );
434
590
  `);
435
- log.info("Migration 1.10.0 complete: tool_config table created");
591
+ log2.info("Migration 1.10.0 complete: tool_config table created");
436
592
  } catch (error) {
437
- log.error({ err: error }, "Migration 1.10.0 failed");
593
+ log2.error({ err: error }, "Migration 1.10.0 failed");
438
594
  throw error;
439
595
  }
440
596
  }
441
597
  if (!currentVersion || versionLessThan(currentVersion, "1.10.1")) {
442
- log.info("Running migration 1.10.1: Fix tool_config scope CHECK constraint (add admin-only)");
598
+ log2.info("Running migration 1.10.1: Fix tool_config scope CHECK constraint (add admin-only)");
443
599
  try {
444
600
  db.transaction(() => {
445
601
  db.exec(`
@@ -455,14 +611,14 @@ function runMigrations(db) {
455
611
  ALTER TABLE tool_config_new RENAME TO tool_config;
456
612
  `);
457
613
  })();
458
- log.info("Migration 1.10.1 complete: tool_config CHECK constraint updated");
614
+ log2.info("Migration 1.10.1 complete: tool_config CHECK constraint updated");
459
615
  } catch (error) {
460
- log.error({ err: error }, "Migration 1.10.1 failed");
616
+ log2.error({ err: error }, "Migration 1.10.1 failed");
461
617
  throw error;
462
618
  }
463
619
  }
464
620
  if (!currentVersion || versionLessThan(currentVersion, "1.11.0")) {
465
- log.info("Running migration 1.11.0: Add tool_index tables for Tool RAG");
621
+ log2.info("Running migration 1.11.0: Add tool_index tables for Tool RAG");
466
622
  try {
467
623
  db.exec(`
468
624
  CREATE TABLE IF NOT EXISTS tool_index (
@@ -494,9 +650,58 @@ function runMigrations(db) {
494
650
  VALUES (new.rowid, new.search_text, new.name);
495
651
  END;
496
652
  `);
497
- log.info("Migration 1.11.0 complete: tool_index tables created");
653
+ log2.info("Migration 1.11.0 complete: tool_index tables created");
654
+ } catch (error) {
655
+ log2.error({ err: error }, "Migration 1.11.0 failed");
656
+ throw error;
657
+ }
658
+ }
659
+ if (!currentVersion || versionLessThan(currentVersion, "1.12.0")) {
660
+ log2.info("Running migration 1.12.0: Add exec_audit table");
661
+ try {
662
+ db.exec(`
663
+ CREATE TABLE IF NOT EXISTS exec_audit (
664
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
665
+ timestamp INTEGER NOT NULL DEFAULT (unixepoch()),
666
+ user_id INTEGER NOT NULL,
667
+ username TEXT,
668
+ tool TEXT NOT NULL,
669
+ command TEXT NOT NULL,
670
+ status TEXT NOT NULL DEFAULT 'pending',
671
+ exit_code INTEGER,
672
+ signal TEXT,
673
+ duration_ms INTEGER,
674
+ stdout TEXT,
675
+ stderr TEXT,
676
+ truncated INTEGER NOT NULL DEFAULT 0
677
+ );
678
+
679
+ CREATE INDEX IF NOT EXISTS idx_exec_audit_timestamp ON exec_audit(timestamp DESC);
680
+ CREATE INDEX IF NOT EXISTS idx_exec_audit_user ON exec_audit(user_id);
681
+ `);
682
+ log2.info("Migration 1.12.0 complete: exec_audit table created");
683
+ } catch (error) {
684
+ log2.error({ err: error }, "Migration 1.12.0 failed");
685
+ throw error;
686
+ }
687
+ }
688
+ if (!currentVersion || versionLessThan(currentVersion, "1.13.0")) {
689
+ log2.info("Running migration 1.13.0: Add token usage columns to sessions");
690
+ try {
691
+ const addColumnIfNotExists = (table, column, type) => {
692
+ try {
693
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${type}`);
694
+ } catch (e) {
695
+ if (!e.message.includes("duplicate column name")) {
696
+ throw e;
697
+ }
698
+ }
699
+ };
700
+ addColumnIfNotExists("sessions", "input_tokens", "INTEGER DEFAULT 0");
701
+ addColumnIfNotExists("sessions", "output_tokens", "INTEGER DEFAULT 0");
702
+ log2.info("Migration 1.13.0 complete: Token usage columns added to sessions");
498
703
  } catch (error) {
499
- log.error({ err: error }, "Migration 1.11.0 failed");
704
+ log2.error({ err: error }, "Migration 1.13.0 failed");
500
705
  throw error;
501
706
  }
502
707
  }
@@ -504,22 +709,22 @@ function runMigrations(db) {
504
709
  }
505
710
 
506
711
  // src/memory/database.ts
507
- var log2 = createLogger("Memory");
712
+ var log3 = createLogger("Memory");
508
713
  var MemoryDatabase = class {
509
714
  db;
510
715
  config;
511
716
  vectorReady = false;
512
717
  constructor(config) {
513
718
  this.config = config;
514
- const dir = dirname(config.path);
515
- if (!existsSync(dir)) {
516
- mkdirSync(dir, { recursive: true });
719
+ const dir = dirname2(config.path);
720
+ if (!existsSync2(dir)) {
721
+ mkdirSync2(dir, { recursive: true });
517
722
  }
518
- this.db = new Database(config.path, {
519
- verbose: process.env.DEBUG_SQL ? (msg) => log2.debug(String(msg)) : void 0
723
+ this.db = new Database2(config.path, {
724
+ verbose: process.env.DEBUG_SQL ? (msg) => log3.debug(String(msg)) : void 0
520
725
  });
521
726
  try {
522
- chmodSync(config.path, 384);
727
+ chmodSync2(config.path, 384);
523
728
  } catch {
524
729
  }
525
730
  this.db.pragma("journal_mode = WAL");
@@ -556,16 +761,16 @@ var MemoryDatabase = class {
556
761
  ensureVectorTables(this.db, dims);
557
762
  this.vectorReady = true;
558
763
  } catch (error) {
559
- log2.warn(`sqlite-vec not available, vector search disabled: ${error.message}`);
560
- log2.warn("Falling back to keyword-only search");
764
+ log3.warn(`sqlite-vec not available, vector search disabled: ${error.message}`);
765
+ log3.warn("Falling back to keyword-only search");
561
766
  this.config.enableVectorSearch = false;
562
767
  }
563
768
  }
564
769
  migrate(from, to) {
565
- log2.info(`Migrating database from ${from} to ${to}...`);
770
+ log3.info(`Migrating database from ${from} to ${to}...`);
566
771
  runMigrations(this.db);
567
772
  ensureSchema(this.db);
568
- log2.info("Migration complete");
773
+ log3.info("Migration complete");
569
774
  }
570
775
  getDb() {
571
776
  return this.db;
@@ -667,8 +872,8 @@ function closeDatabase() {
667
872
  }
668
873
 
669
874
  // src/memory/agent/knowledge.ts
670
- import { readFileSync, existsSync as existsSync2, readdirSync, statSync } from "fs";
671
- import { join } from "path";
875
+ import { readFileSync, existsSync as existsSync3, readdirSync, statSync } from "fs";
876
+ import { join as join2 } from "path";
672
877
  var KnowledgeIndexer = class {
673
878
  constructor(db, workspaceDir, embedder, vectorEnabled) {
674
879
  this.db = db;
@@ -691,7 +896,7 @@ var KnowledgeIndexer = class {
691
896
  return { indexed, skipped };
692
897
  }
693
898
  async indexFile(absPath) {
694
- if (!existsSync2(absPath) || !absPath.endsWith(".md")) {
899
+ if (!existsSync3(absPath) || !absPath.endsWith(".md")) {
695
900
  return false;
696
901
  }
697
902
  const content = readFileSync(absPath, "utf-8");
@@ -739,15 +944,15 @@ var KnowledgeIndexer = class {
739
944
  }
740
945
  listMemoryFiles() {
741
946
  const files = [];
742
- const memoryMd = join(this.workspaceDir, "MEMORY.md");
743
- if (existsSync2(memoryMd)) {
947
+ const memoryMd = join2(this.workspaceDir, "MEMORY.md");
948
+ if (existsSync3(memoryMd)) {
744
949
  files.push(memoryMd);
745
950
  }
746
- const memoryDir = join(this.workspaceDir, "memory");
747
- if (existsSync2(memoryDir)) {
951
+ const memoryDir = join2(this.workspaceDir, "memory");
952
+ if (existsSync3(memoryDir)) {
748
953
  const entries = readdirSync(memoryDir);
749
954
  for (const entry of entries) {
750
- const absPath = join(memoryDir, entry);
955
+ const absPath = join2(memoryDir, entry);
751
956
  if (statSync(absPath).isFile() && entry.endsWith(".md")) {
752
957
  files.push(absPath);
753
958
  }
@@ -814,7 +1019,7 @@ var KnowledgeIndexer = class {
814
1019
 
815
1020
  // src/memory/agent/sessions.ts
816
1021
  import { randomUUID } from "crypto";
817
- var log3 = createLogger("Memory");
1022
+ var log4 = createLogger("Memory");
818
1023
  var SessionStore = class {
819
1024
  constructor(db, embedder, vectorEnabled) {
820
1025
  this.db = db;
@@ -938,9 +1143,9 @@ ${session.summary}`;
938
1143
  this.db.prepare(`DELETE FROM knowledge_vec WHERE id = ?`).run(knowledgeId);
939
1144
  this.db.prepare(`INSERT INTO knowledge_vec (id, embedding) VALUES (?, ?)`).run(knowledgeId, embeddingBuffer);
940
1145
  }
941
- log3.info(`Indexed session ${sessionId} to knowledge base`);
1146
+ log4.info(`Indexed session ${sessionId} to knowledge base`);
942
1147
  } catch (error) {
943
- log3.error({ err: error }, "Error indexing session");
1148
+ log4.error({ err: error }, "Error indexing session");
944
1149
  }
945
1150
  }
946
1151
  deleteSession(sessionId) {
@@ -1305,7 +1510,7 @@ var UserStore = class {
1305
1510
  };
1306
1511
 
1307
1512
  // src/memory/search/hybrid.ts
1308
- var log4 = createLogger("Memory");
1513
+ var log5 = createLogger("Memory");
1309
1514
  function escapeFts5Query(query) {
1310
1515
  return query.replace(/["\*\-\+\(\)\:\^\~\?\.\@\#\$\%\&\!\[\]\{\}\|\\\/<>=,;'`]/g, " ").replace(/\s+/g, " ").trim();
1311
1516
  }
@@ -1353,7 +1558,7 @@ var HybridSearch = class {
1353
1558
  vectorScore: 1 - row.distance
1354
1559
  }));
1355
1560
  } catch (error) {
1356
- log4.error({ err: error }, "Vector search error (knowledge)");
1561
+ log5.error({ err: error }, "Vector search error (knowledge)");
1357
1562
  return [];
1358
1563
  }
1359
1564
  }
@@ -1376,7 +1581,7 @@ var HybridSearch = class {
1376
1581
  keywordScore: this.bm25ToScore(row.score)
1377
1582
  }));
1378
1583
  } catch (error) {
1379
- log4.error({ err: error }, "FTS5 search error (knowledge)");
1584
+ log5.error({ err: error }, "FTS5 search error (knowledge)");
1380
1585
  return [];
1381
1586
  }
1382
1587
  }
@@ -1411,7 +1616,7 @@ var HybridSearch = class {
1411
1616
  vectorScore: 1 - row.distance
1412
1617
  }));
1413
1618
  } catch (error) {
1414
- log4.error({ err: error }, "Vector search error (messages)");
1619
+ log5.error({ err: error }, "Vector search error (messages)");
1415
1620
  return [];
1416
1621
  }
1417
1622
  }
@@ -1441,7 +1646,7 @@ var HybridSearch = class {
1441
1646
  keywordScore: this.bm25ToScore(row.score)
1442
1647
  }));
1443
1648
  } catch (error) {
1444
- log4.error({ err: error }, "FTS5 search error (messages)");
1649
+ log5.error({ err: error }, "FTS5 search error (messages)");
1445
1650
  return [];
1446
1651
  }
1447
1652
  }
@@ -1471,7 +1676,25 @@ var HybridSearch = class {
1471
1676
  };
1472
1677
 
1473
1678
  // src/memory/search/context.ts
1474
- var log5 = createLogger("Memory");
1679
+ var log6 = createLogger("Memory");
1680
+ function reorderForEdges(items) {
1681
+ if (items.length <= 2) return items;
1682
+ const result = new Array(items.length);
1683
+ let left = 0;
1684
+ let right = items.length - 1;
1685
+ for (let i = 0; i < items.length; i++) {
1686
+ if (i % 2 === 0) {
1687
+ result[left++] = items[i];
1688
+ } else {
1689
+ result[right--] = items[i];
1690
+ }
1691
+ }
1692
+ return result;
1693
+ }
1694
+ function truncateFeedMessage(text) {
1695
+ if (text.length <= FEED_MESSAGE_MAX_CHARS) return text;
1696
+ return text.slice(0, FEED_MESSAGE_MAX_CHARS) + "... [truncated]";
1697
+ }
1475
1698
  var ContextBuilder = class {
1476
1699
  constructor(db, embedder, vectorEnabled) {
1477
1700
  this.db = db;
@@ -1491,7 +1714,7 @@ var ContextBuilder = class {
1491
1714
  maxRecentMessages = 20,
1492
1715
  maxRelevantChunks = 5
1493
1716
  } = options;
1494
- const queryEmbedding = await this.embedder.embedQuery(query);
1717
+ const queryEmbedding = options.queryEmbedding ?? await this.embedder.embedQuery(query);
1495
1718
  const recentTgMessages = this.messageStore.getRecentMessages(chatId, maxRecentMessages);
1496
1719
  const recentMessages = recentTgMessages.map((m) => ({
1497
1720
  role: m.isFromAgent ? "assistant" : "user",
@@ -1503,9 +1726,9 @@ var ContextBuilder = class {
1503
1726
  const knowledgeResults = await this.hybridSearch.searchKnowledge(query, queryEmbedding, {
1504
1727
  limit: maxRelevantChunks
1505
1728
  });
1506
- relevantKnowledge.push(...knowledgeResults.map((r) => r.text));
1729
+ relevantKnowledge.push(...reorderForEdges(knowledgeResults.map((r) => r.text)));
1507
1730
  } catch (error) {
1508
- log5.warn({ err: error }, "Knowledge search failed");
1731
+ log6.warn({ err: error }, "Knowledge search failed");
1509
1732
  }
1510
1733
  }
1511
1734
  const recentTextsSet = new Set(
@@ -1520,7 +1743,7 @@ var ContextBuilder = class {
1520
1743
  });
1521
1744
  for (const r of feedResults) {
1522
1745
  if (!recentTextsSet.has(r.text)) {
1523
- relevantFeed.push(r.text);
1746
+ relevantFeed.push(truncateFeedMessage(r.text));
1524
1747
  }
1525
1748
  }
1526
1749
  if (searchAllChats) {
@@ -1529,13 +1752,14 @@ var ContextBuilder = class {
1529
1752
  });
1530
1753
  const existingTexts = new Set(relevantFeed);
1531
1754
  for (const r of globalResults) {
1532
- if (!existingTexts.has(r.text)) {
1533
- relevantFeed.push(`[From chat ${r.source}]: ${r.text}`);
1755
+ const truncated = truncateFeedMessage(r.text);
1756
+ if (!existingTexts.has(truncated)) {
1757
+ relevantFeed.push(`[From chat ${r.source}]: ${truncated}`);
1534
1758
  }
1535
1759
  }
1536
1760
  }
1537
1761
  } catch (error) {
1538
- log5.warn({ err: error }, "Feed search failed");
1762
+ log6.warn({ err: error }, "Feed search failed");
1539
1763
  }
1540
1764
  if (relevantFeed.length === 0 && recentTgMessages.length > 0) {
1541
1765
  const recentTexts = recentTgMessages.filter((m) => m.text && m.text.length > 0).slice(-maxRelevantChunks).map((m) => {
@@ -1573,6 +1797,11 @@ function initializeMemory(config) {
1573
1797
  }
1574
1798
 
1575
1799
  export {
1800
+ JOURNAL_SCHEMA,
1801
+ USED_TRANSACTIONS_SCHEMA,
1802
+ openModuleDb,
1803
+ createDbWrapper,
1804
+ migrateFromMainDb,
1576
1805
  ensureSchema,
1577
1806
  ensureVectorTables,
1578
1807
  getSchemaVersion,