teleton 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -26
- package/dist/{chunk-D5I7GBV7.js → chunk-FNV5FF35.js} +22 -13
- package/dist/chunk-LRCPA7SC.js +149 -0
- package/dist/{chunk-ADCMUNYU.js → chunk-N3F7E7DR.js} +58 -53
- package/dist/chunk-ND2X5FWB.js +368 -0
- package/dist/chunk-NERLQY2H.js +421 -0
- package/dist/{chunk-YBA6IBGT.js → chunk-OCLG5GKI.js} +24 -24
- package/dist/{chunk-6L6KGATM.js → chunk-OGIG552S.js} +1397 -1688
- package/dist/chunk-RCMD3U65.js +141 -0
- package/dist/{chunk-4IPJ25HE.js → chunk-TCD4NZDA.js} +1045 -658
- package/dist/{chunk-ECSCVEQQ.js → chunk-UCN6TI25.js} +7 -3
- package/dist/{chunk-WL2Q3VRD.js → chunk-UDD7FYOU.js} +12 -4
- package/dist/chunk-VAUJSSD3.js +20 -0
- package/dist/chunk-XBE4JB7C.js +8 -0
- package/dist/{chunk-GDCODBNO.js → chunk-XBKSS6DM.js} +2 -16
- package/dist/cli/index.js +878 -433
- package/dist/client-3VWE7NC4.js +29 -0
- package/dist/{get-my-gifts-KVULMBJ3.js → get-my-gifts-RI7FAXAL.js} +3 -1
- package/dist/index.js +17 -11
- package/dist/{memory-TVDOGQXS.js → memory-RD7ZSTRV.js} +7 -5
- package/dist/{migrate-QIEMPOMT.js → migrate-GO4NOBT7.js} +14 -9
- package/dist/{server-RSWVCVY3.js → server-OWVEZTR3.js} +81 -84
- package/dist/setup-server-C7ZTPHD5.js +934 -0
- package/dist/{task-dependency-resolver-72DLY2HV.js → task-dependency-resolver-WKZWJLLM.js} +19 -15
- package/dist/{task-executor-VXB6DAV2.js → task-executor-PD3H4MLO.js} +4 -1
- package/dist/tool-adapter-Y3TCEQOC.js +145 -0
- package/dist/{tool-index-DKI2ZNOU.js → tool-index-MIVK3D7H.js} +14 -9
- package/dist/{transcript-7V4UNID4.js → transcript-UDJZP6NK.js} +2 -1
- package/dist/web/assets/complete-fZLnb5Ot.js +1 -0
- package/dist/web/assets/index-B_FcaX5D.css +1 -0
- package/dist/web/assets/index-CbeAP4_n.js +67 -0
- package/dist/web/assets/index.es-oXiZF7Hc.js +11 -0
- package/dist/web/assets/login-telegram-BP7CJDmx.js +1 -0
- package/dist/web/assets/run-DOrDowjK.js +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +7 -3
- package/dist/chunk-2QUJLHCZ.js +0 -362
- package/dist/web/assets/index-BNhrx9S1.js +0 -67
- package/dist/web/assets/index-CqrrRLOh.css +0 -1
|
@@ -3,16 +3,19 @@ import {
|
|
|
3
3
|
createEmbeddingProvider,
|
|
4
4
|
hashText,
|
|
5
5
|
serializeEmbedding
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-FNV5FF35.js";
|
|
7
7
|
import {
|
|
8
8
|
JOURNAL_SCHEMA
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-UCN6TI25.js";
|
|
10
10
|
import {
|
|
11
11
|
HYBRID_SEARCH_MIN_SCORE,
|
|
12
12
|
KNOWLEDGE_CHUNK_SIZE,
|
|
13
13
|
SQLITE_CACHE_SIZE_KB,
|
|
14
14
|
SQLITE_MMAP_SIZE
|
|
15
15
|
} from "./chunk-RO62LO6Z.js";
|
|
16
|
+
import {
|
|
17
|
+
createLogger
|
|
18
|
+
} from "./chunk-RCMD3U65.js";
|
|
16
19
|
|
|
17
20
|
// src/memory/database.ts
|
|
18
21
|
import Database from "better-sqlite3";
|
|
@@ -21,6 +24,7 @@ import { dirname } from "path";
|
|
|
21
24
|
import * as sqliteVec from "sqlite-vec";
|
|
22
25
|
|
|
23
26
|
// src/memory/schema.ts
|
|
27
|
+
var log = createLogger("Memory");
|
|
24
28
|
function compareSemver(a, b) {
|
|
25
29
|
const parseVersion = (v) => {
|
|
26
30
|
const parts = v.split("-")[0].split(".").map(Number);
|
|
@@ -313,11 +317,11 @@ var CURRENT_SCHEMA_VERSION = "1.11.0";
|
|
|
313
317
|
function runMigrations(db) {
|
|
314
318
|
const currentVersion = getSchemaVersion(db);
|
|
315
319
|
if (!currentVersion || versionLessThan(currentVersion, "1.1.0")) {
|
|
316
|
-
|
|
320
|
+
log.info("Running migration: Adding scheduled task columns...");
|
|
317
321
|
try {
|
|
318
322
|
const tableExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='tasks'").get();
|
|
319
323
|
if (!tableExists) {
|
|
320
|
-
|
|
324
|
+
log.info("Tasks table doesn't exist yet, skipping column migration");
|
|
321
325
|
setSchemaVersion(db, CURRENT_SCHEMA_VERSION);
|
|
322
326
|
return;
|
|
323
327
|
}
|
|
@@ -350,15 +354,15 @@ function runMigrations(db) {
|
|
|
350
354
|
CREATE INDEX IF NOT EXISTS idx_task_deps_task ON task_dependencies(task_id);
|
|
351
355
|
CREATE INDEX IF NOT EXISTS idx_task_deps_parent ON task_dependencies(depends_on_task_id);
|
|
352
356
|
`);
|
|
353
|
-
|
|
357
|
+
log.info("Migration 1.1.0 complete: Scheduled tasks support added");
|
|
354
358
|
} catch (error) {
|
|
355
|
-
|
|
359
|
+
log.error({ err: error }, "Migration 1.1.0 failed");
|
|
356
360
|
throw error;
|
|
357
361
|
}
|
|
358
362
|
}
|
|
359
363
|
if (!currentVersion || versionLessThan(currentVersion, "1.2.0")) {
|
|
360
364
|
try {
|
|
361
|
-
|
|
365
|
+
log.info("Running migration 1.2.0: Extend sessions table for SQLite backend");
|
|
362
366
|
const addColumnIfNotExists = (table, column, type) => {
|
|
363
367
|
try {
|
|
364
368
|
db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${type}`);
|
|
@@ -387,14 +391,14 @@ function runMigrations(db) {
|
|
|
387
391
|
);
|
|
388
392
|
}
|
|
389
393
|
db.exec("CREATE INDEX IF NOT EXISTS idx_sessions_updated ON sessions(updated_at DESC)");
|
|
390
|
-
|
|
394
|
+
log.info("Migration 1.2.0 complete: Sessions table extended");
|
|
391
395
|
} catch (error) {
|
|
392
|
-
|
|
396
|
+
log.error({ err: error }, "Migration 1.2.0 failed");
|
|
393
397
|
throw error;
|
|
394
398
|
}
|
|
395
399
|
}
|
|
396
400
|
if (!currentVersion || versionLessThan(currentVersion, "1.9.0")) {
|
|
397
|
-
|
|
401
|
+
log.info("Running migration 1.9.0: Upgrade embedding_cache to BLOB storage");
|
|
398
402
|
try {
|
|
399
403
|
db.exec(`DROP TABLE IF EXISTS embedding_cache`);
|
|
400
404
|
db.exec(`
|
|
@@ -410,14 +414,14 @@ function runMigrations(db) {
|
|
|
410
414
|
);
|
|
411
415
|
CREATE INDEX IF NOT EXISTS idx_embedding_cache_accessed ON embedding_cache(accessed_at);
|
|
412
416
|
`);
|
|
413
|
-
|
|
417
|
+
log.info("Migration 1.9.0 complete: embedding_cache upgraded to BLOB storage");
|
|
414
418
|
} catch (error) {
|
|
415
|
-
|
|
419
|
+
log.error({ err: error }, "Migration 1.9.0 failed");
|
|
416
420
|
throw error;
|
|
417
421
|
}
|
|
418
422
|
}
|
|
419
423
|
if (!currentVersion || versionLessThan(currentVersion, "1.10.0")) {
|
|
420
|
-
|
|
424
|
+
log.info("Running migration 1.10.0: Add tool_config table for runtime tool management");
|
|
421
425
|
try {
|
|
422
426
|
db.exec(`
|
|
423
427
|
CREATE TABLE IF NOT EXISTS tool_config (
|
|
@@ -428,37 +432,37 @@ function runMigrations(db) {
|
|
|
428
432
|
updated_by INTEGER
|
|
429
433
|
);
|
|
430
434
|
`);
|
|
431
|
-
|
|
435
|
+
log.info("Migration 1.10.0 complete: tool_config table created");
|
|
432
436
|
} catch (error) {
|
|
433
|
-
|
|
437
|
+
log.error({ err: error }, "Migration 1.10.0 failed");
|
|
434
438
|
throw error;
|
|
435
439
|
}
|
|
436
440
|
}
|
|
437
441
|
if (!currentVersion || versionLessThan(currentVersion, "1.10.1")) {
|
|
438
|
-
|
|
439
|
-
"\u{1F504} Running migration 1.10.1: Fix tool_config scope CHECK constraint (add admin-only)"
|
|
440
|
-
);
|
|
442
|
+
log.info("Running migration 1.10.1: Fix tool_config scope CHECK constraint (add admin-only)");
|
|
441
443
|
try {
|
|
442
|
-
db.
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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");
|
|
455
459
|
} catch (error) {
|
|
456
|
-
|
|
460
|
+
log.error({ err: error }, "Migration 1.10.1 failed");
|
|
457
461
|
throw error;
|
|
458
462
|
}
|
|
459
463
|
}
|
|
460
464
|
if (!currentVersion || versionLessThan(currentVersion, "1.11.0")) {
|
|
461
|
-
|
|
465
|
+
log.info("Running migration 1.11.0: Add tool_index tables for Tool RAG");
|
|
462
466
|
try {
|
|
463
467
|
db.exec(`
|
|
464
468
|
CREATE TABLE IF NOT EXISTS tool_index (
|
|
@@ -490,9 +494,9 @@ function runMigrations(db) {
|
|
|
490
494
|
VALUES (new.rowid, new.search_text, new.name);
|
|
491
495
|
END;
|
|
492
496
|
`);
|
|
493
|
-
|
|
497
|
+
log.info("Migration 1.11.0 complete: tool_index tables created");
|
|
494
498
|
} catch (error) {
|
|
495
|
-
|
|
499
|
+
log.error({ err: error }, "Migration 1.11.0 failed");
|
|
496
500
|
throw error;
|
|
497
501
|
}
|
|
498
502
|
}
|
|
@@ -500,6 +504,7 @@ function runMigrations(db) {
|
|
|
500
504
|
}
|
|
501
505
|
|
|
502
506
|
// src/memory/database.ts
|
|
507
|
+
var log2 = createLogger("Memory");
|
|
503
508
|
var MemoryDatabase = class {
|
|
504
509
|
db;
|
|
505
510
|
config;
|
|
@@ -511,7 +516,7 @@ var MemoryDatabase = class {
|
|
|
511
516
|
mkdirSync(dir, { recursive: true });
|
|
512
517
|
}
|
|
513
518
|
this.db = new Database(config.path, {
|
|
514
|
-
verbose: process.env.DEBUG_SQL ?
|
|
519
|
+
verbose: process.env.DEBUG_SQL ? (msg) => log2.debug(String(msg)) : void 0
|
|
515
520
|
});
|
|
516
521
|
try {
|
|
517
522
|
chmodSync(config.path, 384);
|
|
@@ -551,18 +556,16 @@ var MemoryDatabase = class {
|
|
|
551
556
|
ensureVectorTables(this.db, dims);
|
|
552
557
|
this.vectorReady = true;
|
|
553
558
|
} catch (error) {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
);
|
|
557
|
-
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");
|
|
558
561
|
this.config.enableVectorSearch = false;
|
|
559
562
|
}
|
|
560
563
|
}
|
|
561
564
|
migrate(from, to) {
|
|
562
|
-
|
|
565
|
+
log2.info(`Migrating database from ${from} to ${to}...`);
|
|
563
566
|
runMigrations(this.db);
|
|
564
567
|
ensureSchema(this.db);
|
|
565
|
-
|
|
568
|
+
log2.info("Migration complete");
|
|
566
569
|
}
|
|
567
570
|
getDb() {
|
|
568
571
|
return this.db;
|
|
@@ -811,6 +814,7 @@ var KnowledgeIndexer = class {
|
|
|
811
814
|
|
|
812
815
|
// src/memory/agent/sessions.ts
|
|
813
816
|
import { randomUUID } from "crypto";
|
|
817
|
+
var log3 = createLogger("Memory");
|
|
814
818
|
var SessionStore = class {
|
|
815
819
|
constructor(db, embedder, vectorEnabled) {
|
|
816
820
|
this.db = db;
|
|
@@ -931,13 +935,12 @@ ${session.summary}`;
|
|
|
931
935
|
).run(knowledgeId, sessionId, text, hash);
|
|
932
936
|
if (embedding && this.vectorEnabled) {
|
|
933
937
|
const embeddingBuffer = serializeEmbedding(embedding);
|
|
934
|
-
|
|
935
|
-
this.db.prepare(`
|
|
936
|
-
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);
|
|
937
940
|
}
|
|
938
|
-
|
|
941
|
+
log3.info(`Indexed session ${sessionId} to knowledge base`);
|
|
939
942
|
} catch (error) {
|
|
940
|
-
|
|
943
|
+
log3.error({ err: error }, "Error indexing session");
|
|
941
944
|
}
|
|
942
945
|
}
|
|
943
946
|
deleteSession(sessionId) {
|
|
@@ -1302,6 +1305,7 @@ var UserStore = class {
|
|
|
1302
1305
|
};
|
|
1303
1306
|
|
|
1304
1307
|
// src/memory/search/hybrid.ts
|
|
1308
|
+
var log4 = createLogger("Memory");
|
|
1305
1309
|
function escapeFts5Query(query) {
|
|
1306
1310
|
return query.replace(/["\*\-\+\(\)\:\^\~\?\.\@\#\$\%\&\!\[\]\{\}\|\\\/<>=,;'`]/g, " ").replace(/\s+/g, " ").trim();
|
|
1307
1311
|
}
|
|
@@ -1349,7 +1353,7 @@ var HybridSearch = class {
|
|
|
1349
1353
|
vectorScore: 1 - row.distance
|
|
1350
1354
|
}));
|
|
1351
1355
|
} catch (error) {
|
|
1352
|
-
|
|
1356
|
+
log4.error({ err: error }, "Vector search error (knowledge)");
|
|
1353
1357
|
return [];
|
|
1354
1358
|
}
|
|
1355
1359
|
}
|
|
@@ -1372,7 +1376,7 @@ var HybridSearch = class {
|
|
|
1372
1376
|
keywordScore: this.bm25ToScore(row.score)
|
|
1373
1377
|
}));
|
|
1374
1378
|
} catch (error) {
|
|
1375
|
-
|
|
1379
|
+
log4.error({ err: error }, "FTS5 search error (knowledge)");
|
|
1376
1380
|
return [];
|
|
1377
1381
|
}
|
|
1378
1382
|
}
|
|
@@ -1407,7 +1411,7 @@ var HybridSearch = class {
|
|
|
1407
1411
|
vectorScore: 1 - row.distance
|
|
1408
1412
|
}));
|
|
1409
1413
|
} catch (error) {
|
|
1410
|
-
|
|
1414
|
+
log4.error({ err: error }, "Vector search error (messages)");
|
|
1411
1415
|
return [];
|
|
1412
1416
|
}
|
|
1413
1417
|
}
|
|
@@ -1437,7 +1441,7 @@ var HybridSearch = class {
|
|
|
1437
1441
|
keywordScore: this.bm25ToScore(row.score)
|
|
1438
1442
|
}));
|
|
1439
1443
|
} catch (error) {
|
|
1440
|
-
|
|
1444
|
+
log4.error({ err: error }, "FTS5 search error (messages)");
|
|
1441
1445
|
return [];
|
|
1442
1446
|
}
|
|
1443
1447
|
}
|
|
@@ -1467,6 +1471,7 @@ var HybridSearch = class {
|
|
|
1467
1471
|
};
|
|
1468
1472
|
|
|
1469
1473
|
// src/memory/search/context.ts
|
|
1474
|
+
var log5 = createLogger("Memory");
|
|
1470
1475
|
var ContextBuilder = class {
|
|
1471
1476
|
constructor(db, embedder, vectorEnabled) {
|
|
1472
1477
|
this.db = db;
|
|
@@ -1500,7 +1505,7 @@ var ContextBuilder = class {
|
|
|
1500
1505
|
});
|
|
1501
1506
|
relevantKnowledge.push(...knowledgeResults.map((r) => r.text));
|
|
1502
1507
|
} catch (error) {
|
|
1503
|
-
|
|
1508
|
+
log5.warn({ err: error }, "Knowledge search failed");
|
|
1504
1509
|
}
|
|
1505
1510
|
}
|
|
1506
1511
|
const recentTextsSet = new Set(
|
|
@@ -1530,7 +1535,7 @@ var ContextBuilder = class {
|
|
|
1530
1535
|
}
|
|
1531
1536
|
}
|
|
1532
1537
|
} catch (error) {
|
|
1533
|
-
|
|
1538
|
+
log5.warn({ err: error }, "Feed search failed");
|
|
1534
1539
|
}
|
|
1535
1540
|
if (relevantFeed.length === 0 && recentTgMessages.length > 0) {
|
|
1536
1541
|
const recentTexts = recentTgMessages.filter((m) => m.text && m.text.length > 0).slice(-maxRelevantChunks).map((m) => {
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getProviderMetadata
|
|
3
|
+
} from "./chunk-LRCPA7SC.js";
|
|
4
|
+
import {
|
|
5
|
+
appendToTranscript,
|
|
6
|
+
readTranscript
|
|
7
|
+
} from "./chunk-OCLG5GKI.js";
|
|
8
|
+
import {
|
|
9
|
+
fetchWithTimeout
|
|
10
|
+
} from "./chunk-VAUJSSD3.js";
|
|
11
|
+
import {
|
|
12
|
+
createLogger
|
|
13
|
+
} from "./chunk-RCMD3U65.js";
|
|
14
|
+
|
|
15
|
+
// src/agent/client.ts
|
|
16
|
+
import {
|
|
17
|
+
complete,
|
|
18
|
+
getModel
|
|
19
|
+
} from "@mariozechner/pi-ai";
|
|
20
|
+
|
|
21
|
+
// src/agent/schema-sanitizer.ts
|
|
22
|
+
var UNSUPPORTED_KEYS = /* @__PURE__ */ new Set([
|
|
23
|
+
"$schema",
|
|
24
|
+
"$id",
|
|
25
|
+
"$ref",
|
|
26
|
+
"$defs",
|
|
27
|
+
"$anchor",
|
|
28
|
+
"title",
|
|
29
|
+
"default",
|
|
30
|
+
"examples"
|
|
31
|
+
]);
|
|
32
|
+
function sanitizeSchema(schema) {
|
|
33
|
+
if (!schema || typeof schema !== "object") return schema;
|
|
34
|
+
const result = { ...schema };
|
|
35
|
+
for (const key of UNSUPPORTED_KEYS) {
|
|
36
|
+
delete result[key];
|
|
37
|
+
}
|
|
38
|
+
if (Array.isArray(result.anyOf)) {
|
|
39
|
+
const items = result.anyOf;
|
|
40
|
+
const nonNull = items.filter((s) => s.type !== "null");
|
|
41
|
+
const allConst = nonNull.length > 0 && nonNull.every((s) => s.const !== void 0);
|
|
42
|
+
if (allConst) {
|
|
43
|
+
const enumValues = nonNull.map((s) => s.const);
|
|
44
|
+
const inferredType = nonNull[0]?.type || "string";
|
|
45
|
+
delete result.anyOf;
|
|
46
|
+
result.type = inferredType;
|
|
47
|
+
result.enum = enumValues;
|
|
48
|
+
} else if (nonNull.length > 0) {
|
|
49
|
+
delete result.anyOf;
|
|
50
|
+
const first = nonNull[0];
|
|
51
|
+
if (first.type) result.type = first.type;
|
|
52
|
+
if (first.enum) result.enum = first.enum;
|
|
53
|
+
if (first.description && !result.description) {
|
|
54
|
+
result.description = first.description;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (Array.isArray(result.anyOf)) {
|
|
59
|
+
delete result.anyOf;
|
|
60
|
+
if (!result.type) result.type = "string";
|
|
61
|
+
}
|
|
62
|
+
if (result.const !== void 0) {
|
|
63
|
+
result.enum = [result.const];
|
|
64
|
+
if (!result.type) {
|
|
65
|
+
const jsType = typeof result.const;
|
|
66
|
+
result.type = jsType === "string" ? "string" : jsType === "boolean" ? "boolean" : "number";
|
|
67
|
+
}
|
|
68
|
+
delete result.const;
|
|
69
|
+
}
|
|
70
|
+
if (result.properties && typeof result.properties === "object") {
|
|
71
|
+
const props = result.properties;
|
|
72
|
+
const sanitized = {};
|
|
73
|
+
for (const [key, value] of Object.entries(props)) {
|
|
74
|
+
sanitized[key] = value && typeof value === "object" && !Array.isArray(value) ? sanitizeSchema(value) : value;
|
|
75
|
+
}
|
|
76
|
+
result.properties = sanitized;
|
|
77
|
+
}
|
|
78
|
+
if (result.items && typeof result.items === "object" && !Array.isArray(result.items)) {
|
|
79
|
+
result.items = sanitizeSchema(result.items);
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
function sanitizeToolsForGemini(tools) {
|
|
84
|
+
return tools.map(
|
|
85
|
+
(tool) => ({
|
|
86
|
+
...tool,
|
|
87
|
+
parameters: sanitizeSchema({ ...tool.parameters })
|
|
88
|
+
})
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/agent/client.ts
|
|
93
|
+
var log = createLogger("LLM");
|
|
94
|
+
function isOAuthToken(apiKey, provider) {
|
|
95
|
+
if (provider && provider !== "anthropic") return false;
|
|
96
|
+
return apiKey.startsWith("sk-ant-oat01-");
|
|
97
|
+
}
|
|
98
|
+
function getEffectiveApiKey(provider, rawKey) {
|
|
99
|
+
if (provider === "local") return "local";
|
|
100
|
+
if (provider === "cocoon") return "";
|
|
101
|
+
return rawKey;
|
|
102
|
+
}
|
|
103
|
+
var modelCache = /* @__PURE__ */ new Map();
|
|
104
|
+
var COCOON_MODELS = {};
|
|
105
|
+
async function registerCocoonModels(httpPort) {
|
|
106
|
+
try {
|
|
107
|
+
const res = await fetch(`http://localhost:${httpPort}/v1/models`);
|
|
108
|
+
if (!res.ok) return [];
|
|
109
|
+
const body = await res.json();
|
|
110
|
+
const models = body.data || body.models || [];
|
|
111
|
+
if (!Array.isArray(models)) return [];
|
|
112
|
+
const ids = [];
|
|
113
|
+
for (const m of models) {
|
|
114
|
+
const id = m.id || m.name || String(m);
|
|
115
|
+
COCOON_MODELS[id] = {
|
|
116
|
+
id,
|
|
117
|
+
name: id,
|
|
118
|
+
api: "openai-completions",
|
|
119
|
+
provider: "cocoon",
|
|
120
|
+
baseUrl: `http://localhost:${httpPort}/v1`,
|
|
121
|
+
reasoning: false,
|
|
122
|
+
input: ["text"],
|
|
123
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
124
|
+
contextWindow: 128e3,
|
|
125
|
+
maxTokens: 4096,
|
|
126
|
+
compat: {
|
|
127
|
+
supportsStore: false,
|
|
128
|
+
supportsDeveloperRole: false,
|
|
129
|
+
supportsReasoningEffort: false
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
ids.push(id);
|
|
133
|
+
}
|
|
134
|
+
return ids;
|
|
135
|
+
} catch {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
var LOCAL_MODELS = {};
|
|
140
|
+
async function registerLocalModels(baseUrl) {
|
|
141
|
+
try {
|
|
142
|
+
const parsed = new URL(baseUrl);
|
|
143
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
144
|
+
log.warn(`Local LLM base_url must use http or https (got ${parsed.protocol})`);
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
const url = baseUrl.replace(/\/+$/, "");
|
|
148
|
+
const res = await fetchWithTimeout(`${url}/models`, { timeoutMs: 1e4 });
|
|
149
|
+
if (!res.ok) return [];
|
|
150
|
+
const body = await res.json();
|
|
151
|
+
const rawModels = body.data || body.models || [];
|
|
152
|
+
if (!Array.isArray(rawModels)) return [];
|
|
153
|
+
const models = rawModels.slice(0, 500);
|
|
154
|
+
const ids = [];
|
|
155
|
+
for (const m of models) {
|
|
156
|
+
const id = m.id || m.name || String(m);
|
|
157
|
+
LOCAL_MODELS[id] = {
|
|
158
|
+
id,
|
|
159
|
+
name: id,
|
|
160
|
+
api: "openai-completions",
|
|
161
|
+
provider: "local",
|
|
162
|
+
baseUrl: url,
|
|
163
|
+
reasoning: false,
|
|
164
|
+
input: ["text"],
|
|
165
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
166
|
+
contextWindow: 128e3,
|
|
167
|
+
maxTokens: 4096,
|
|
168
|
+
compat: {
|
|
169
|
+
supportsStore: false,
|
|
170
|
+
supportsDeveloperRole: false,
|
|
171
|
+
supportsReasoningEffort: false,
|
|
172
|
+
supportsStrictMode: false,
|
|
173
|
+
maxTokensField: "max_tokens"
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
ids.push(id);
|
|
177
|
+
}
|
|
178
|
+
return ids;
|
|
179
|
+
} catch {
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
var MOONSHOT_MODELS = {
|
|
184
|
+
"kimi-k2.5": {
|
|
185
|
+
id: "kimi-k2.5",
|
|
186
|
+
name: "Kimi K2.5",
|
|
187
|
+
api: "openai-completions",
|
|
188
|
+
provider: "moonshot",
|
|
189
|
+
baseUrl: "https://api.moonshot.ai/v1",
|
|
190
|
+
reasoning: false,
|
|
191
|
+
input: ["text", "image"],
|
|
192
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
193
|
+
contextWindow: 256e3,
|
|
194
|
+
maxTokens: 8192
|
|
195
|
+
},
|
|
196
|
+
"kimi-k2-thinking": {
|
|
197
|
+
id: "kimi-k2-thinking",
|
|
198
|
+
name: "Kimi K2 Thinking",
|
|
199
|
+
api: "openai-completions",
|
|
200
|
+
provider: "moonshot",
|
|
201
|
+
baseUrl: "https://api.moonshot.ai/v1",
|
|
202
|
+
reasoning: true,
|
|
203
|
+
input: ["text"],
|
|
204
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
205
|
+
contextWindow: 256e3,
|
|
206
|
+
maxTokens: 8192
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
function getProviderModel(provider, modelId) {
|
|
210
|
+
const cacheKey = `${provider}:${modelId}`;
|
|
211
|
+
const cached = modelCache.get(cacheKey);
|
|
212
|
+
if (cached) return cached;
|
|
213
|
+
const meta = getProviderMetadata(provider);
|
|
214
|
+
if (meta.piAiProvider === "cocoon") {
|
|
215
|
+
let model = COCOON_MODELS[modelId];
|
|
216
|
+
if (!model) {
|
|
217
|
+
model = Object.values(COCOON_MODELS)[0];
|
|
218
|
+
if (model) log.warn(`Cocoon model "${modelId}" not found, using "${model.id}"`);
|
|
219
|
+
}
|
|
220
|
+
if (model) {
|
|
221
|
+
modelCache.set(cacheKey, model);
|
|
222
|
+
return model;
|
|
223
|
+
}
|
|
224
|
+
throw new Error("No Cocoon models available. Is the cocoon client running?");
|
|
225
|
+
}
|
|
226
|
+
if (meta.piAiProvider === "local") {
|
|
227
|
+
let model = LOCAL_MODELS[modelId];
|
|
228
|
+
if (!model) {
|
|
229
|
+
model = Object.values(LOCAL_MODELS)[0];
|
|
230
|
+
if (model) log.warn(`Local model "${modelId}" not found, using "${model.id}"`);
|
|
231
|
+
}
|
|
232
|
+
if (model) {
|
|
233
|
+
modelCache.set(cacheKey, model);
|
|
234
|
+
return model;
|
|
235
|
+
}
|
|
236
|
+
throw new Error("No local models available. Is the LLM server running?");
|
|
237
|
+
}
|
|
238
|
+
if (meta.piAiProvider === "moonshot") {
|
|
239
|
+
const model = MOONSHOT_MODELS[modelId] ?? MOONSHOT_MODELS[meta.defaultModel];
|
|
240
|
+
if (model) {
|
|
241
|
+
modelCache.set(cacheKey, model);
|
|
242
|
+
return model;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
const model = getModel(meta.piAiProvider, modelId);
|
|
247
|
+
if (!model) {
|
|
248
|
+
throw new Error(`getModel returned undefined for ${provider}/${modelId}`);
|
|
249
|
+
}
|
|
250
|
+
modelCache.set(cacheKey, model);
|
|
251
|
+
return model;
|
|
252
|
+
} catch (e) {
|
|
253
|
+
log.warn(`Model ${modelId} not found for ${provider}, falling back to ${meta.defaultModel}`);
|
|
254
|
+
const fallbackKey = `${provider}:${meta.defaultModel}`;
|
|
255
|
+
const fallbackCached = modelCache.get(fallbackKey);
|
|
256
|
+
if (fallbackCached) return fallbackCached;
|
|
257
|
+
try {
|
|
258
|
+
const model = getModel(meta.piAiProvider, meta.defaultModel);
|
|
259
|
+
if (!model) {
|
|
260
|
+
throw new Error(
|
|
261
|
+
`Fallback model ${meta.defaultModel} also returned undefined for ${provider}`
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
modelCache.set(fallbackKey, model);
|
|
265
|
+
return model;
|
|
266
|
+
} catch {
|
|
267
|
+
throw new Error(
|
|
268
|
+
`Could not find model ${modelId} or fallback ${meta.defaultModel} for ${provider}`
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function getUtilityModel(provider, overrideModel) {
|
|
274
|
+
const meta = getProviderMetadata(provider);
|
|
275
|
+
const modelId = overrideModel || meta.utilityModel;
|
|
276
|
+
return getProviderModel(provider, modelId);
|
|
277
|
+
}
|
|
278
|
+
async function chatWithContext(config, options) {
|
|
279
|
+
const provider = config.provider || "anthropic";
|
|
280
|
+
const model = getProviderModel(provider, config.model);
|
|
281
|
+
const isCocoon = provider === "cocoon";
|
|
282
|
+
let tools = provider === "google" && options.tools ? sanitizeToolsForGemini(options.tools) : options.tools;
|
|
283
|
+
let systemPrompt = options.systemPrompt || options.context.systemPrompt || "";
|
|
284
|
+
let cocoonAllowedTools;
|
|
285
|
+
if (isCocoon) {
|
|
286
|
+
systemPrompt = "/no_think\n" + systemPrompt;
|
|
287
|
+
if (tools && tools.length > 0) {
|
|
288
|
+
cocoonAllowedTools = new Set(tools.map((t) => t.name));
|
|
289
|
+
const { injectToolsIntoSystemPrompt } = await import("./tool-adapter-Y3TCEQOC.js");
|
|
290
|
+
systemPrompt = injectToolsIntoSystemPrompt(systemPrompt, tools);
|
|
291
|
+
tools = void 0;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const context = {
|
|
295
|
+
...options.context,
|
|
296
|
+
systemPrompt,
|
|
297
|
+
tools
|
|
298
|
+
};
|
|
299
|
+
const temperature = provider === "moonshot" ? 1 : options.temperature ?? config.temperature;
|
|
300
|
+
const completeOptions = {
|
|
301
|
+
apiKey: getEffectiveApiKey(provider, config.api_key),
|
|
302
|
+
maxTokens: options.maxTokens ?? config.max_tokens,
|
|
303
|
+
temperature,
|
|
304
|
+
sessionId: options.sessionId
|
|
305
|
+
};
|
|
306
|
+
if (isCocoon) {
|
|
307
|
+
const { stripCocoonPayload } = await import("./tool-adapter-Y3TCEQOC.js");
|
|
308
|
+
completeOptions.onPayload = stripCocoonPayload;
|
|
309
|
+
}
|
|
310
|
+
const response = await complete(model, context, completeOptions);
|
|
311
|
+
if (isCocoon) {
|
|
312
|
+
const textBlock = response.content.find((b) => b.type === "text");
|
|
313
|
+
if (textBlock?.type === "text" && textBlock.text.includes("<tool_call>")) {
|
|
314
|
+
const { parseToolCallsFromText, extractPlainText } = await import("./tool-adapter-Y3TCEQOC.js");
|
|
315
|
+
const syntheticCalls = parseToolCallsFromText(textBlock.text, cocoonAllowedTools);
|
|
316
|
+
if (syntheticCalls.length > 0) {
|
|
317
|
+
const plainText = extractPlainText(textBlock.text);
|
|
318
|
+
response.content = [
|
|
319
|
+
...plainText ? [{ type: "text", text: plainText }] : [],
|
|
320
|
+
...syntheticCalls
|
|
321
|
+
];
|
|
322
|
+
response.stopReason = "toolUse";
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
const thinkRe = /<think>[\s\S]*?<\/think>/g;
|
|
327
|
+
for (const block of response.content) {
|
|
328
|
+
if (block.type === "text" && block.text.includes("<think>")) {
|
|
329
|
+
block.text = block.text.replace(thinkRe, "").trim();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (options.persistTranscript && options.sessionId) {
|
|
333
|
+
appendToTranscript(options.sessionId, response);
|
|
334
|
+
}
|
|
335
|
+
const textContent = response.content.find((block) => block.type === "text");
|
|
336
|
+
const text = textContent?.type === "text" ? textContent.text : "";
|
|
337
|
+
const updatedContext = {
|
|
338
|
+
...context,
|
|
339
|
+
messages: [...context.messages, response]
|
|
340
|
+
};
|
|
341
|
+
return {
|
|
342
|
+
message: response,
|
|
343
|
+
text,
|
|
344
|
+
context: updatedContext
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
function loadContextFromTranscript(sessionId, systemPrompt) {
|
|
348
|
+
const messages = readTranscript(sessionId);
|
|
349
|
+
return {
|
|
350
|
+
systemPrompt,
|
|
351
|
+
messages
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
function createClient(_config) {
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export {
|
|
359
|
+
isOAuthToken,
|
|
360
|
+
getEffectiveApiKey,
|
|
361
|
+
registerCocoonModels,
|
|
362
|
+
registerLocalModels,
|
|
363
|
+
getProviderModel,
|
|
364
|
+
getUtilityModel,
|
|
365
|
+
chatWithContext,
|
|
366
|
+
loadContextFromTranscript,
|
|
367
|
+
createClient
|
|
368
|
+
};
|