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.
- package/README.md +43 -30
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/{chunk-U7FQYCBQ.js → chunk-7TECSLJ4.js} +2 -2
- package/dist/{chunk-LAQOUFOJ.js → chunk-H36RFKRI.js} +7583 -11185
- package/dist/{chunk-RO62LO6Z.js → chunk-IJBWWQE4.js} +4 -0
- package/dist/{chunk-BGC2IUM5.js → chunk-JHYZYFZJ.js} +69 -20
- package/dist/{chunk-QOQWUUA4.js → chunk-OJCLKU5Z.js} +68 -2
- package/dist/{chunk-OCLG5GKI.js → chunk-P36I6OIV.js} +2 -2
- package/dist/chunk-PHSAHTK4.js +314 -0
- package/dist/{chunk-5PLZ3KSO.js → chunk-QVBSUYVX.js} +14 -42
- package/dist/{chunk-4DU3C27M.js → chunk-R4YSJ4EY.js} +5 -1
- package/dist/chunk-RQBAMUCV.js +10281 -0
- package/dist/{chunk-XDYDA2KV.js → chunk-SD4NLLYG.js} +293 -64
- package/dist/chunk-TVRZJIZX.js +292 -0
- package/dist/{chunk-EK7M5K26.js → chunk-U56QTM46.js} +3 -3
- package/dist/{chunk-XBKSS6DM.js → chunk-VFA7QMCZ.js} +5 -3
- package/dist/{chunk-VAUJSSD3.js → chunk-XQUHC3JZ.js} +1 -1
- package/dist/cli/index.js +96 -33
- package/dist/{client-RTNALK7W.js → client-LNZTDQSA.js} +6 -7
- package/dist/{get-my-gifts-TPVUGUWT.js → get-my-gifts-OMGKOEPM.js} +1 -1
- package/dist/index.js +15 -17
- package/dist/{memory-JQZ6MTRU.js → memory-AS7WKGTW.js} +7 -8
- package/dist/{migrate-GS5ACQDA.js → migrate-POHWYEIW.js} +7 -8
- package/dist/{multipart-parser-S3YC6NRJ.js → multipart-parser-UFQLJOV2.js} +2 -2
- package/dist/{paths-TMNTEDDD.js → paths-XA2RJH4S.js} +1 -1
- package/dist/{server-TCJOBV3D.js → server-H3QA252W.js} +39 -12
- package/dist/{setup-server-YHYJLAMA.js → setup-server-QXED3D2L.js} +24 -12
- package/dist/store-GAFULOOX.js +34 -0
- package/dist/{task-dependency-resolver-WKZWJLLM.js → task-dependency-resolver-3FIKQ7Z6.js} +3 -3
- package/dist/{task-executor-PD3H4MLO.js → task-executor-RUTFG6VG.js} +2 -2
- package/dist/{tasks-QSCWSMPS.js → tasks-BEZ4QRI2.js} +1 -1
- package/dist/{tool-adapter-Y3TCEQOC.js → tool-adapter-IH5VGBOO.js} +1 -1
- package/dist/{tool-index-6HBRVXVG.js → tool-index-H3SHOJC3.js} +6 -6
- package/dist/{transcript-UDJZP6NK.js → transcript-IMNE6KU3.js} +2 -2
- package/dist/web/assets/index-BrVqauzj.css +1 -0
- package/dist/web/assets/index-DYeEkvJ6.js +72 -0
- package/dist/web/assets/{index.es-CqZHj0tz.js → index.es-DkU1GvWU.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +2 -2
- package/dist/BigInteger-DQ33LTTE.js +0 -5
- package/dist/chunk-JQDLW7IE.js +0 -107
- package/dist/chunk-QGM4M3NI.js +0 -37
- package/dist/chunk-RMLQS3X6.js +0 -161
- package/dist/chunk-TSKJCWQQ.js +0 -1263
- package/dist/chunk-UCN6TI25.js +0 -143
- package/dist/chunk-YFG2QHLA.js +0 -3585
- package/dist/web/assets/index-B6M9knfJ.css +0 -1
- package/dist/web/assets/index-DAGeQfVZ.js +0 -72
- package/scripts/patch-gramjs.sh +0 -46
- 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-
|
|
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-
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
513
|
+
log2.info("Migration 1.1.0 complete: Scheduled tasks support added");
|
|
358
514
|
} catch (error) {
|
|
359
|
-
|
|
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
|
-
|
|
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
|
-
|
|
550
|
+
log2.info("Migration 1.2.0 complete: Sessions table extended");
|
|
395
551
|
} catch (error) {
|
|
396
|
-
|
|
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
|
-
|
|
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
|
-
|
|
573
|
+
log2.info("Migration 1.9.0 complete: embedding_cache upgraded to BLOB storage");
|
|
418
574
|
} catch (error) {
|
|
419
|
-
|
|
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
|
-
|
|
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
|
-
|
|
591
|
+
log2.info("Migration 1.10.0 complete: tool_config table created");
|
|
436
592
|
} catch (error) {
|
|
437
|
-
|
|
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
|
-
|
|
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
|
-
|
|
614
|
+
log2.info("Migration 1.10.1 complete: tool_config CHECK constraint updated");
|
|
459
615
|
} catch (error) {
|
|
460
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
515
|
-
if (!
|
|
516
|
-
|
|
719
|
+
const dir = dirname2(config.path);
|
|
720
|
+
if (!existsSync2(dir)) {
|
|
721
|
+
mkdirSync2(dir, { recursive: true });
|
|
517
722
|
}
|
|
518
|
-
this.db = new
|
|
519
|
-
verbose: process.env.DEBUG_SQL ? (msg) =>
|
|
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
|
-
|
|
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
|
-
|
|
560
|
-
|
|
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
|
-
|
|
770
|
+
log3.info(`Migrating database from ${from} to ${to}...`);
|
|
566
771
|
runMigrations(this.db);
|
|
567
772
|
ensureSchema(this.db);
|
|
568
|
-
|
|
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
|
|
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 (!
|
|
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 =
|
|
743
|
-
if (
|
|
947
|
+
const memoryMd = join2(this.workspaceDir, "MEMORY.md");
|
|
948
|
+
if (existsSync3(memoryMd)) {
|
|
744
949
|
files.push(memoryMd);
|
|
745
950
|
}
|
|
746
|
-
const memoryDir =
|
|
747
|
-
if (
|
|
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 =
|
|
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
|
|
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
|
-
|
|
1146
|
+
log4.info(`Indexed session ${sessionId} to knowledge base`);
|
|
942
1147
|
} catch (error) {
|
|
943
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
1533
|
-
|
|
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
|
-
|
|
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,
|