teleton 0.5.2 → 0.6.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.
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-4DU3C27M.js";
4
4
  import {
5
5
  MAX_DEPENDENTS_PER_TASK
6
- } from "./chunk-O4R7V5Y2.js";
6
+ } from "./chunk-RO62LO6Z.js";
7
7
  import "./chunk-QGM4M3NI.js";
8
8
 
9
9
  // src/telegram/task-dependency-resolver.ts
@@ -3,7 +3,7 @@ import {
3
3
  MAX_TOTAL_PROMPT_CHARS,
4
4
  SECONDS_PER_DAY,
5
5
  SECONDS_PER_HOUR
6
- } from "./chunk-O4R7V5Y2.js";
6
+ } from "./chunk-RO62LO6Z.js";
7
7
  import "./chunk-QGM4M3NI.js";
8
8
 
9
9
  // src/telegram/task-executor.ts
@@ -0,0 +1,245 @@
1
+ import {
2
+ serializeEmbedding
3
+ } from "./chunk-D5I7GBV7.js";
4
+ import "./chunk-GDCODBNO.js";
5
+ import "./chunk-4DU3C27M.js";
6
+ import {
7
+ TOOL_RAG_KEYWORD_WEIGHT,
8
+ TOOL_RAG_MIN_SCORE,
9
+ TOOL_RAG_VECTOR_WEIGHT
10
+ } from "./chunk-RO62LO6Z.js";
11
+ import "./chunk-EYWNOHMJ.js";
12
+ import "./chunk-QGM4M3NI.js";
13
+
14
+ // src/agent/tools/tool-index.ts
15
+ function escapeFts5Query(query) {
16
+ return query.replace(/["\*\-\+\(\)\:\^\~\?\.\@\#\$\%\&\!\[\]\{\}\|\\\/<>=,;'`]/g, " ").replace(/\s+/g, " ").trim();
17
+ }
18
+ function bm25ToScore(rank) {
19
+ return 1 / (1 + Math.exp(rank));
20
+ }
21
+ var ToolIndex = class {
22
+ constructor(db, embedder, vectorEnabled, config) {
23
+ this.db = db;
24
+ this.embedder = embedder;
25
+ this.vectorEnabled = vectorEnabled;
26
+ this.config = config;
27
+ }
28
+ _isIndexed = false;
29
+ get isIndexed() {
30
+ return this._isIndexed;
31
+ }
32
+ /**
33
+ * Create the vector table (dimensions are dynamic, so can't be in schema migration).
34
+ */
35
+ ensureSchema() {
36
+ if (!this.vectorEnabled || this.embedder.dimensions === 0) return;
37
+ try {
38
+ const existing = this.db.prepare(`SELECT sql FROM sqlite_master WHERE type='table' AND name='tool_index_vec'`).get();
39
+ if (existing?.sql && !existing.sql.includes(`[${this.embedder.dimensions}]`)) {
40
+ this.db.exec(`DROP TABLE IF EXISTS tool_index_vec`);
41
+ }
42
+ this.db.exec(`
43
+ CREATE VIRTUAL TABLE IF NOT EXISTS tool_index_vec USING vec0(
44
+ name TEXT PRIMARY KEY,
45
+ embedding FLOAT[${this.embedder.dimensions}] distance_metric=cosine
46
+ );
47
+ `);
48
+ } catch (error) {
49
+ console.error("[tool-rag] Failed to create vector table:", error);
50
+ this.vectorEnabled = false;
51
+ }
52
+ }
53
+ /**
54
+ * Index all registered tools. Replaces any previous index.
55
+ */
56
+ async indexAll(tools) {
57
+ try {
58
+ this.db.exec(`DELETE FROM tool_index`);
59
+ if (this.vectorEnabled) {
60
+ try {
61
+ this.db.exec(`DELETE FROM tool_index_vec`);
62
+ } catch {
63
+ }
64
+ }
65
+ const entries = tools.map((t) => ({
66
+ name: t.name,
67
+ description: t.description ?? "",
68
+ searchText: `${t.name} \u2014 ${t.description ?? ""}`
69
+ }));
70
+ const embeddings = [];
71
+ if (this.vectorEnabled && this.embedder.dimensions > 0) {
72
+ const texts = entries.map((e) => e.searchText);
73
+ const batchSize = 128;
74
+ for (let i = 0; i < texts.length; i += batchSize) {
75
+ const batch = texts.slice(i, i + batchSize);
76
+ const batchEmbeddings = await this.embedder.embedBatch(batch);
77
+ embeddings.push(...batchEmbeddings);
78
+ }
79
+ }
80
+ const insertTool = this.db.prepare(`
81
+ INSERT INTO tool_index (name, description, search_text, updated_at)
82
+ VALUES (?, ?, ?, unixepoch())
83
+ `);
84
+ const insertVec = this.vectorEnabled ? this.db.prepare(`INSERT INTO tool_index_vec (name, embedding) VALUES (?, ?)`) : null;
85
+ const txn = this.db.transaction(() => {
86
+ for (let i = 0; i < entries.length; i++) {
87
+ const e = entries[i];
88
+ insertTool.run(e.name, e.description, e.searchText);
89
+ if (insertVec && embeddings[i]?.length > 0) {
90
+ insertVec.run(e.name, serializeEmbedding(embeddings[i]));
91
+ }
92
+ }
93
+ });
94
+ txn();
95
+ this._isIndexed = true;
96
+ return entries.length;
97
+ } catch (error) {
98
+ console.error("[tool-rag] Indexing failed:", error);
99
+ this._isIndexed = false;
100
+ return 0;
101
+ }
102
+ }
103
+ /**
104
+ * Delta update for hot-reload plugins.
105
+ */
106
+ async reindexTools(removed, added) {
107
+ try {
108
+ if (removed.length > 0) {
109
+ const deleteTool = this.db.prepare(`DELETE FROM tool_index WHERE name = ?`);
110
+ const deleteVec = this.vectorEnabled ? this.db.prepare(`DELETE FROM tool_index_vec WHERE name = ?`) : null;
111
+ for (const name of removed) {
112
+ deleteTool.run(name);
113
+ deleteVec?.run(name);
114
+ }
115
+ }
116
+ if (added.length > 0) {
117
+ const entries = added.map((t) => ({
118
+ name: t.name,
119
+ description: t.description ?? "",
120
+ searchText: `${t.name} \u2014 ${t.description ?? ""}`
121
+ }));
122
+ let embeddings = [];
123
+ if (this.vectorEnabled && this.embedder.dimensions > 0) {
124
+ embeddings = await this.embedder.embedBatch(entries.map((e) => e.searchText));
125
+ }
126
+ const insertTool = this.db.prepare(`
127
+ INSERT OR REPLACE INTO tool_index (name, description, search_text, updated_at)
128
+ VALUES (?, ?, ?, unixepoch())
129
+ `);
130
+ const deleteVec = this.vectorEnabled ? this.db.prepare(`DELETE FROM tool_index_vec WHERE name = ?`) : null;
131
+ const insertVec = this.vectorEnabled ? this.db.prepare(`INSERT INTO tool_index_vec (name, embedding) VALUES (?, ?)`) : null;
132
+ const txn = this.db.transaction(() => {
133
+ for (let i = 0; i < entries.length; i++) {
134
+ const e = entries[i];
135
+ insertTool.run(e.name, e.description, e.searchText);
136
+ if (insertVec && embeddings[i]?.length > 0) {
137
+ deleteVec.run(e.name);
138
+ insertVec.run(e.name, serializeEmbedding(embeddings[i]));
139
+ }
140
+ }
141
+ });
142
+ txn();
143
+ }
144
+ console.log(`[tool-rag] Delta reindex: -${removed.length} +${added.length} tools`);
145
+ } catch (error) {
146
+ console.error("[tool-rag] Delta reindex failed:", error);
147
+ }
148
+ }
149
+ /**
150
+ * Hybrid search: vector + FTS5, same pattern as HybridSearch.
151
+ */
152
+ async search(query, queryEmbedding, limit) {
153
+ const topK = limit ?? this.config.topK;
154
+ const vectorResults = this.vectorEnabled ? this.vectorSearch(queryEmbedding, topK * 3) : [];
155
+ const keywordResults = this.keywordSearch(query, topK * 3);
156
+ return this.mergeResults(vectorResults, keywordResults, topK);
157
+ }
158
+ /**
159
+ * Check if a tool name matches any always-include pattern.
160
+ */
161
+ isAlwaysIncluded(toolName) {
162
+ for (const pattern of this.config.alwaysInclude) {
163
+ if (pattern.endsWith("*")) {
164
+ const prefix = pattern.slice(0, -1);
165
+ if (toolName.startsWith(prefix)) return true;
166
+ } else if (toolName === pattern) {
167
+ return true;
168
+ }
169
+ }
170
+ return false;
171
+ }
172
+ vectorSearch(embedding, limit) {
173
+ if (!this.vectorEnabled || embedding.length === 0) return [];
174
+ try {
175
+ const embeddingBuffer = serializeEmbedding(embedding);
176
+ const rows = this.db.prepare(
177
+ `
178
+ SELECT tv.name, ti.description, tv.distance
179
+ FROM (
180
+ SELECT name, distance
181
+ FROM tool_index_vec
182
+ WHERE embedding MATCH ? AND k = ?
183
+ ) tv
184
+ JOIN tool_index ti ON ti.name = tv.name
185
+ `
186
+ ).all(embeddingBuffer, limit);
187
+ return rows.map((row) => ({
188
+ name: row.name,
189
+ description: row.description,
190
+ score: 1 - row.distance,
191
+ vectorScore: 1 - row.distance
192
+ }));
193
+ } catch (error) {
194
+ console.error("[tool-rag] Vector search error:", error);
195
+ return [];
196
+ }
197
+ }
198
+ keywordSearch(query, limit) {
199
+ const safeQuery = escapeFts5Query(query);
200
+ if (!safeQuery) return [];
201
+ try {
202
+ const rows = this.db.prepare(
203
+ `
204
+ SELECT ti.name, ti.description, rank as score
205
+ FROM tool_index_fts tf
206
+ JOIN tool_index ti ON ti.rowid = tf.rowid
207
+ WHERE tool_index_fts MATCH ?
208
+ ORDER BY rank
209
+ LIMIT ?
210
+ `
211
+ ).all(safeQuery, limit);
212
+ return rows.map((row) => ({
213
+ name: row.name,
214
+ description: row.description,
215
+ score: bm25ToScore(row.score),
216
+ keywordScore: bm25ToScore(row.score)
217
+ }));
218
+ } catch (error) {
219
+ console.error("[tool-rag] FTS5 search error:", error);
220
+ return [];
221
+ }
222
+ }
223
+ mergeResults(vectorResults, keywordResults, limit) {
224
+ const byName = /* @__PURE__ */ new Map();
225
+ for (const r of vectorResults) {
226
+ byName.set(r.name, { ...r, vectorScore: r.score });
227
+ }
228
+ for (const r of keywordResults) {
229
+ const existing = byName.get(r.name);
230
+ if (existing) {
231
+ existing.keywordScore = r.keywordScore;
232
+ existing.score = TOOL_RAG_VECTOR_WEIGHT * (existing.vectorScore ?? 0) + TOOL_RAG_KEYWORD_WEIGHT * (r.keywordScore ?? 0);
233
+ } else {
234
+ byName.set(r.name, {
235
+ ...r,
236
+ score: TOOL_RAG_KEYWORD_WEIGHT * (r.keywordScore ?? 0)
237
+ });
238
+ }
239
+ }
240
+ return Array.from(byName.values()).filter((r) => r.score >= TOOL_RAG_MIN_SCORE).sort((a, b) => b.score - a.score).slice(0, limit);
241
+ }
242
+ };
243
+ export {
244
+ ToolIndex
245
+ };