teleton 0.4.0 → 0.5.2

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 (33) hide show
  1. package/README.md +88 -13
  2. package/dist/BigInteger-DQ33LTTE.js +5 -0
  3. package/dist/chunk-4DU3C27M.js +30 -0
  4. package/dist/chunk-5WWR4CU3.js +124 -0
  5. package/dist/{chunk-E2NXSWOS.js → chunk-NUGDTPE4.js} +24 -64
  6. package/dist/{chunk-OA5L7GM6.js → chunk-O4R7V5Y2.js} +37 -5
  7. package/dist/chunk-QUAPFI2N.js +42 -0
  8. package/dist/chunk-TSKJCWQQ.js +1263 -0
  9. package/dist/{chunk-B2PRMXOH.js → chunk-WL2Q3VRD.js} +0 -2
  10. package/dist/{chunk-QU4ZOR35.js → chunk-WOXBZOQX.js} +3179 -3368
  11. package/dist/{chunk-7UPH62J2.js → chunk-WUTMT6DW.js} +293 -261
  12. package/dist/{chunk-OQGNS2FV.js → chunk-YBA6IBGT.js} +20 -5
  13. package/dist/cli/index.js +41 -172
  14. package/dist/{endpoint-FT2B2RZ2.js → endpoint-FLYNEZ2F.js} +1 -1
  15. package/dist/{get-my-gifts-AFKBG4YQ.js → get-my-gifts-KVULMBJ3.js} +1 -1
  16. package/dist/index.js +12 -12
  17. package/dist/{memory-SYTQ5P7P.js → memory-Y5J7CXAR.js} +4 -5
  18. package/dist/{migrate-ITXMRRSZ.js → migrate-UEQCDWL2.js} +4 -5
  19. package/dist/server-BQY7CM2N.js +1120 -0
  20. package/dist/{task-dependency-resolver-GY6PEBIS.js → task-dependency-resolver-TRPILAHM.js} +2 -2
  21. package/dist/{task-executor-4QKTZZ3P.js → task-executor-N7XNVK5N.js} +1 -1
  22. package/dist/{tasks-M3QDPTGY.js → tasks-QSCWSMPS.js} +1 -1
  23. package/dist/{transcript-DF2Y6CFY.js → transcript-7V4UNID4.js} +1 -1
  24. package/dist/web/assets/index-CDMbujHf.css +1 -0
  25. package/dist/web/assets/index-DDX8oQ2z.js +67 -0
  26. package/dist/web/index.html +16 -0
  27. package/dist/web/logo_dark.png +0 -0
  28. package/package.json +23 -6
  29. package/dist/chunk-67QC5FBN.js +0 -60
  30. package/dist/chunk-A64NPEFL.js +0 -74
  31. package/dist/chunk-DUW5VBAZ.js +0 -133
  32. package/dist/chunk-QBGUCUOW.js +0 -16
  33. package/dist/scraper-SH7GS7TO.js +0 -282
package/README.md CHANGED
@@ -19,7 +19,7 @@
19
19
  - **Multi-Provider LLM**: Anthropic, OpenAI, Google Gemini, xAI Grok, Groq, OpenRouter
20
20
  - **TON Blockchain**: Built-in wallet, send/receive TON & jettons, swap on STON.fi and DeDust, NFTs
21
21
  - **Persistent memory**: Remembers context across restarts with automatic context management
22
- - **116 built-in tools**: Messaging, media, blockchain, DEX trading, deals, market, DNS, journaling, and more
22
+ - **112 built-in tools**: Messaging, media, blockchain, DEX trading, deals, DNS, journaling, and more
23
23
  - **Plugin SDK**: Extend the agent with custom tools — full access to TON and Telegram APIs via namespaced SDK
24
24
  - **Secure by design**: Sandboxed workspace, immutable config, prompt injection defense
25
25
 
@@ -37,7 +37,6 @@
37
37
  | DeDust DEX | 5 | Swap, quote, pools, prices, token info |
38
38
  | TON DNS | 7 | Domain auctions, bidding, linking, resolution, availability checks |
39
39
  | Deals | 5 | Secure gift/TON trading with strategy enforcement and inline bot confirmations |
40
- | Market | 4 | Gift floor prices, search, cheapest listings, price history |
41
40
  | Journal | 3 | Trade/operation logging with natural language queries |
42
41
  | Workspace | 6 | Sandboxed file operations with path traversal protection |
43
42
 
@@ -49,7 +48,7 @@
49
48
  | **RAG + Hybrid Search** | Local embeddings with FTS5 keyword + sqlite-vec semantic search |
50
49
  | **Auto-Compaction** | AI-summarized context management prevents overflow, preserves key information |
51
50
  | **Observation Masking** | Compresses old tool results to save ~90% context window |
52
- | **Plugin SDK** | Namespaced SDK (`sdk.ton`, `sdk.telegram`) with isolated databases and lifecycle hooks |
51
+ | **Plugin SDK** | Namespaced SDK (`sdk.ton`, `sdk.telegram`, `sdk.secrets`, `sdk.storage`) with 53 methods, isolated databases and lifecycle hooks |
53
52
  | **Vision Analysis** | Image understanding via multimodal LLM |
54
53
  | **Voice Synthesis** | Text-to-speech for voice messages |
55
54
  | **Scheduled Tasks** | Time-based task execution with dependency resolution |
@@ -170,6 +169,12 @@ telegram:
170
169
  session_reset_policy:
171
170
  daily_reset_enabled: true
172
171
  daily_reset_hour: 4
172
+
173
+ webui: # Optional: Web dashboard
174
+ enabled: false # Enable WebUI server
175
+ port: 7777 # HTTP server port
176
+ host: "127.0.0.1" # Localhost only (security)
177
+ # auth_token: "..." # Auto-generated if omitted
173
178
  ```
174
179
 
175
180
  ### Environment Variables
@@ -181,6 +186,69 @@ telegram:
181
186
  | `TELETON_TG_API_ID` | Telegram API ID (overrides config) | - |
182
187
  | `TELETON_TG_API_HASH` | Telegram API Hash (overrides config) | - |
183
188
  | `TELETON_TG_PHONE` | Phone number (overrides config) | - |
189
+ | `TELETON_WEBUI_ENABLED` | Enable WebUI (overrides config) | `false` |
190
+ | `TELETON_WEBUI_PORT` | WebUI port (overrides config) | `7777` |
191
+
192
+ ---
193
+
194
+ ## WebUI Dashboard
195
+
196
+ Teleton includes an **optional web dashboard** for monitoring and configuration. The WebUI is disabled by default and runs only on localhost for security.
197
+
198
+ ### Features
199
+
200
+ - **Dashboard**: System status, uptime, model info, session count
201
+ - **Tools Management**: View all 112+ tools grouped by module with scope badges
202
+ - **Plugins Browser**: List loaded plugins with manifests
203
+ - **Soul Editor**: Edit SOUL.md, SECURITY.md, STRATEGY.md, MEMORY.md files
204
+ - **Memory Search**: Search knowledge base with hybrid vector+keyword search
205
+ - **Live Logs**: Real-time log streaming via Server-Sent Events
206
+
207
+ ### Usage
208
+
209
+ **Enable via config.yaml:**
210
+ ```yaml
211
+ webui:
212
+ enabled: true
213
+ port: 7777
214
+ ```
215
+
216
+ **Enable via CLI flag:**
217
+ ```bash
218
+ teleton start --webui
219
+ # or specify custom port
220
+ teleton start --webui --webui-port 8080
221
+ ```
222
+
223
+ **Enable via environment variable:**
224
+ ```bash
225
+ TELETON_WEBUI_ENABLED=true teleton start
226
+ ```
227
+
228
+ ### Access
229
+
230
+ When WebUI is enabled, the agent will display:
231
+ ```
232
+ 🌐 WebUI: http://localhost:7777?token=your-token-here
233
+ 🔑 Token: your-token-here
234
+ ```
235
+
236
+ 1. Click the URL (token is auto-filled) or visit `http://localhost:7777`
237
+ 2. Paste the token from the console (displayed once at startup)
238
+ 3. Token is stored in browser localStorage for subsequent visits
239
+
240
+ ### Security
241
+
242
+ - **Localhost only**: Server binds to `127.0.0.1` by default (not accessible from network)
243
+ - **Bearer token auth**: All API routes require authentication
244
+ - **No persistence**: Runtime changes (like model switches via WebUI) are not saved to config.yaml
245
+ - **For remote access**: Use SSH tunneling or reverse proxy (nginx/caddy) with HTTPS
246
+
247
+ **SSH tunnel example:**
248
+ ```bash
249
+ ssh -L 7777:localhost:7777 user@remote-server
250
+ # Then access http://localhost:7777 on your local machine
251
+ ```
184
252
 
185
253
  ### Workspace Files
186
254
 
@@ -234,10 +302,10 @@ src/
234
302
  ├── agent/ # Core agent runtime
235
303
  │ ├── runtime.ts # Agentic loop orchestration
236
304
  │ ├── client.ts # Multi-provider LLM client
237
- │ └── tools/ # 116 built-in tools
305
+ │ └── tools/ # 112 built-in tools
238
306
  │ ├── register-all.ts # Central tool registration
239
307
  │ ├── registry.ts # Tool registry + scope filtering
240
- │ ├── module-loader.ts # Built-in module loading (deals, market)
308
+ │ ├── module-loader.ts # Built-in module loading (deals)
241
309
  │ ├── plugin-loader.ts # External plugin discovery
242
310
  │ ├── telegram/ # Telegram operations (66 tools)
243
311
  │ ├── ton/ # TON blockchain + jettons + DEX quote (15 tools)
@@ -250,10 +318,6 @@ src/
250
318
  │ ├── module.ts # Module definition + lifecycle
251
319
  │ ├── executor.ts # Deal execution logic
252
320
  │ └── strategy-checker.ts # Trading strategy enforcement
253
- ├── market/ # Market module (4 tools, loaded via module-loader)
254
- │ ├── module.ts # Module definition + lifecycle
255
- │ ├── price-service.ts # Gift floor-price tracking
256
- │ └── scraper.ts # Market data scraping (Playwright)
257
321
  ├── bot/ # Deals inline bot (Grammy + GramJS)
258
322
  │ ├── index.ts # DealBot (Grammy Bot API)
259
323
  │ ├── gramjs-bot.ts # GramJS MTProto for styled buttons
@@ -409,12 +473,23 @@ When `tools` is a function, the SDK provides namespaced access to core services:
409
473
 
410
474
  | Namespace | Methods |
411
475
  |-----------|---------|
412
- | `sdk.ton` | `getAddress()`, `getBalance()`, `getPrice()`, `sendTON(to, amount, comment?)`, `getTransactions()` |
413
- | `sdk.telegram` | `sendMessage()`, `editMessage()`, `sendDice()`, `sendReaction()`, `getMessages()`, `getMe()` |
414
- | `sdk.db` | SQLite database (available if `migrate()` is exported) |
476
+ | `sdk.ton` | **Wallet**: `getAddress()`, `getBalance()`, `getPrice()`, `sendTON()`, `getTransactions()`, `verifyPayment()` |
477
+ | | **Jettons**: `getJettonBalances()`, `getJettonInfo()`, `sendJetton()`, `getJettonWalletAddress()` |
478
+ | | **NFT**: `getNftItems()`, `getNftInfo()` |
479
+ | | **Utils**: `toNano()`, `fromNano()`, `validateAddress()` |
480
+ | `sdk.telegram` | **Messages**: `sendMessage()`, `editMessage()`, `deleteMessage()`, `forwardMessage()`, `pinMessage()`, `searchMessages()`, `scheduleMessage()`, `getReplies()` |
481
+ | | **Media**: `sendPhoto()`, `sendVideo()`, `sendVoice()`, `sendFile()`, `sendGif()`, `sendSticker()`, `downloadMedia()` |
482
+ | | **Chat & Users**: `getChatInfo()`, `getUserInfo()`, `resolveUsername()`, `getParticipants()` |
483
+ | | **Interactive**: `sendDice()`, `sendReaction()`, `createPoll()`, `createQuiz()` |
484
+ | | **Moderation**: `banUser()`, `unbanUser()`, `muteUser()` |
485
+ | | **Stars & Gifts**: `getStarsBalance()`, `sendGift()`, `getAvailableGifts()`, `getMyGifts()`, `getResaleGifts()`, `buyResaleGift()` |
486
+ | | **Advanced**: `getMe()`, `isAvailable()`, `getRawClient()`, `setTyping()`, `sendStory()` |
487
+ | `sdk.secrets` | `get()`, `require()`, `has()` — Multi-source secret resolution (env -> store -> config) |
488
+ | `sdk.storage` | `get()`, `set()`, `delete()`, `has()`, `clear()` — KV store with TTL support |
489
+ | `sdk.db` | Raw `better-sqlite3` database for custom SQL |
415
490
  | `sdk.config` | Sanitized app config (no API keys exposed) |
416
491
  | `sdk.pluginConfig` | Plugin-specific config from `config.yaml` `plugins:` section |
417
- | `sdk.log` | Prefixed logger (`info`, `warn`, `error`, `debug`) |
492
+ | `sdk.log` | `info()`, `warn()`, `error()`, `debug()` — Prefixed logger |
418
493
 
419
494
  Plugin config in `config.yaml`:
420
495
  ```yaml
@@ -0,0 +1,5 @@
1
+ import {
2
+ require_BigInteger
3
+ } from "./chunk-TSKJCWQQ.js";
4
+ import "./chunk-QGM4M3NI.js";
5
+ export default require_BigInteger();
@@ -0,0 +1,30 @@
1
+ // src/constants/timeouts.ts
2
+ var TTS_TIMEOUT_MS = 3e4;
3
+ var BATCH_TRIGGER_DELAY_MS = 500;
4
+ var DEFAULT_FETCH_TIMEOUT_MS = 15e3;
5
+ var RETRY_DEFAULT_MAX_ATTEMPTS = 3;
6
+ var RETRY_DEFAULT_BASE_DELAY_MS = 1e3;
7
+ var RETRY_DEFAULT_MAX_DELAY_MS = 1e4;
8
+ var RETRY_DEFAULT_TIMEOUT_MS = 15e3;
9
+ var RETRY_BLOCKCHAIN_BASE_DELAY_MS = 2e3;
10
+ var RETRY_BLOCKCHAIN_MAX_DELAY_MS = 15e3;
11
+ var RETRY_BLOCKCHAIN_TIMEOUT_MS = 3e4;
12
+ var GRAMJS_RETRY_DELAY_MS = 1e3;
13
+ var TOOL_EXECUTION_TIMEOUT_MS = 9e4;
14
+ var SHUTDOWN_TIMEOUT_MS = 1e4;
15
+
16
+ export {
17
+ TTS_TIMEOUT_MS,
18
+ BATCH_TRIGGER_DELAY_MS,
19
+ DEFAULT_FETCH_TIMEOUT_MS,
20
+ RETRY_DEFAULT_MAX_ATTEMPTS,
21
+ RETRY_DEFAULT_BASE_DELAY_MS,
22
+ RETRY_DEFAULT_MAX_DELAY_MS,
23
+ RETRY_DEFAULT_TIMEOUT_MS,
24
+ RETRY_BLOCKCHAIN_BASE_DELAY_MS,
25
+ RETRY_BLOCKCHAIN_MAX_DELAY_MS,
26
+ RETRY_BLOCKCHAIN_TIMEOUT_MS,
27
+ GRAMJS_RETRY_DELAY_MS,
28
+ TOOL_EXECUTION_TIMEOUT_MS,
29
+ SHUTDOWN_TIMEOUT_MS
30
+ };
@@ -0,0 +1,124 @@
1
+ import {
2
+ ALLOWED_EXTENSIONS,
3
+ WORKSPACE_ROOT
4
+ } from "./chunk-EYWNOHMJ.js";
5
+
6
+ // src/workspace/validator.ts
7
+ import { existsSync, lstatSync, readdirSync } from "fs";
8
+ import { resolve, normalize, relative, extname, basename } from "path";
9
+ import { homedir } from "os";
10
+ var WorkspaceSecurityError = class extends Error {
11
+ constructor(message, attemptedPath) {
12
+ super(message);
13
+ this.attemptedPath = attemptedPath;
14
+ this.name = "WorkspaceSecurityError";
15
+ }
16
+ };
17
+ function decodeRecursive(str) {
18
+ let decoded = str;
19
+ let prev = "";
20
+ let iterations = 0;
21
+ const maxIterations = 10;
22
+ while (decoded !== prev && iterations < maxIterations) {
23
+ prev = decoded;
24
+ try {
25
+ decoded = decodeURIComponent(decoded);
26
+ } catch {
27
+ break;
28
+ }
29
+ iterations++;
30
+ }
31
+ return decoded;
32
+ }
33
+ function validatePath(inputPath, allowCreate = false) {
34
+ if (!inputPath || inputPath.trim() === "") {
35
+ throw new WorkspaceSecurityError("Path cannot be empty.", inputPath);
36
+ }
37
+ const trimmedPath = inputPath.trim().replace(/\\/g, "/");
38
+ const decodedPath = decodeRecursive(trimmedPath);
39
+ let absolutePath;
40
+ if (decodedPath.startsWith("/")) {
41
+ absolutePath = resolve(normalize(decodedPath));
42
+ } else if (decodedPath.startsWith("~/")) {
43
+ const expanded = decodedPath.replace(/^~(?=$|[\\/])/, homedir());
44
+ absolutePath = resolve(expanded);
45
+ } else {
46
+ absolutePath = resolve(WORKSPACE_ROOT, normalize(decodedPath));
47
+ }
48
+ const relativePath = relative(WORKSPACE_ROOT, absolutePath);
49
+ if (relativePath.startsWith("..") || relativePath.startsWith("/")) {
50
+ throw new WorkspaceSecurityError(
51
+ `Access denied: Path '${inputPath}' is outside the workspace. Only files in ~/.teleton/workspace/ are accessible.`,
52
+ inputPath
53
+ );
54
+ }
55
+ const exists = existsSync(absolutePath);
56
+ if (!exists && !allowCreate) {
57
+ throw new WorkspaceSecurityError(
58
+ `File not found: '${inputPath}' does not exist in workspace.`,
59
+ inputPath
60
+ );
61
+ }
62
+ if (exists) {
63
+ const stats = lstatSync(absolutePath);
64
+ if (stats.isSymbolicLink()) {
65
+ throw new WorkspaceSecurityError(
66
+ `Access denied: Symbolic links are not allowed for security reasons.`,
67
+ inputPath
68
+ );
69
+ }
70
+ }
71
+ return {
72
+ absolutePath,
73
+ relativePath,
74
+ exists,
75
+ isDirectory: exists ? lstatSync(absolutePath).isDirectory() : false,
76
+ extension: extname(absolutePath).toLowerCase(),
77
+ filename: basename(absolutePath)
78
+ };
79
+ }
80
+ function validateReadPath(inputPath) {
81
+ const validated = validatePath(inputPath, false);
82
+ if (validated.isDirectory) {
83
+ throw new WorkspaceSecurityError(`Cannot read directory as file: '${inputPath}'`, inputPath);
84
+ }
85
+ return validated;
86
+ }
87
+ var IMMUTABLE_FILES = ["SOUL.md", "STRATEGY.md", "SECURITY.md"];
88
+ function validateWritePath(inputPath, fileType) {
89
+ const validated = validatePath(inputPath, true);
90
+ if (IMMUTABLE_FILES.includes(validated.filename)) {
91
+ throw new WorkspaceSecurityError(
92
+ `Cannot write to ${validated.filename}. This file is configured by the owner. Use memory_write instead.`,
93
+ inputPath
94
+ );
95
+ }
96
+ if (fileType && ALLOWED_EXTENSIONS[fileType]) {
97
+ const allowedExts = ALLOWED_EXTENSIONS[fileType];
98
+ if (!allowedExts.includes(validated.extension)) {
99
+ throw new WorkspaceSecurityError(
100
+ `Invalid file type: '${validated.extension}' is not allowed for ${fileType}. Allowed: ${allowedExts.join(", ")}`,
101
+ inputPath
102
+ );
103
+ }
104
+ }
105
+ return validated;
106
+ }
107
+ function validateDirectory(inputPath) {
108
+ const validated = validatePath(inputPath, true);
109
+ if (validated.exists && !validated.isDirectory) {
110
+ throw new WorkspaceSecurityError(
111
+ `Path exists but is not a directory: '${inputPath}'`,
112
+ inputPath
113
+ );
114
+ }
115
+ return validated;
116
+ }
117
+
118
+ export {
119
+ WorkspaceSecurityError,
120
+ validatePath,
121
+ validateReadPath,
122
+ validateWritePath,
123
+ validateDirectory
124
+ };
@@ -4,9 +4,6 @@ var TaskStore = class {
4
4
  constructor(db) {
5
5
  this.db = db;
6
6
  }
7
- /**
8
- * Create a new task
9
- */
10
7
  createTask(task) {
11
8
  const id = randomUUID();
12
9
  const now = Math.floor(Date.now() / 1e3);
@@ -44,9 +41,6 @@ var TaskStore = class {
44
41
  scheduledMessageId: task.scheduledMessageId
45
42
  };
46
43
  }
47
- /**
48
- * Update a task
49
- */
50
44
  updateTask(taskId, updates) {
51
45
  const task = this.getTask(taskId);
52
46
  if (!task) return void 0;
@@ -92,9 +86,6 @@ var TaskStore = class {
92
86
  ).run(...updateValues);
93
87
  return this.getTask(taskId);
94
88
  }
95
- /**
96
- * Get a task by ID
97
- */
98
89
  getTask(id) {
99
90
  const row = this.db.prepare(`SELECT * FROM tasks WHERE id = ?`).get(id);
100
91
  if (!row) return void 0;
@@ -103,21 +94,18 @@ var TaskStore = class {
103
94
  description: row.description,
104
95
  status: row.status,
105
96
  priority: row.priority,
106
- createdBy: row.created_by,
97
+ createdBy: row.created_by ?? void 0,
107
98
  createdAt: new Date(row.created_at * 1e3),
108
99
  startedAt: row.started_at ? new Date(row.started_at * 1e3) : void 0,
109
100
  completedAt: row.completed_at ? new Date(row.completed_at * 1e3) : void 0,
110
- result: row.result,
111
- error: row.error,
101
+ result: row.result ?? void 0,
102
+ error: row.error ?? void 0,
112
103
  scheduledFor: row.scheduled_for ? new Date(row.scheduled_for * 1e3) : void 0,
113
- payload: row.payload,
114
- reason: row.reason,
115
- scheduledMessageId: row.scheduled_message_id
104
+ payload: row.payload ?? void 0,
105
+ reason: row.reason ?? void 0,
106
+ scheduledMessageId: row.scheduled_message_id ?? void 0
116
107
  };
117
108
  }
118
- /**
119
- * List tasks with optional filters
120
- */
121
109
  listTasks(filter) {
122
110
  let sql = `SELECT * FROM tasks WHERE 1=1`;
123
111
  const params = [];
@@ -136,21 +124,18 @@ var TaskStore = class {
136
124
  description: row.description,
137
125
  status: row.status,
138
126
  priority: row.priority,
139
- createdBy: row.created_by,
127
+ createdBy: row.created_by ?? void 0,
140
128
  createdAt: new Date(row.created_at * 1e3),
141
129
  startedAt: row.started_at ? new Date(row.started_at * 1e3) : void 0,
142
130
  completedAt: row.completed_at ? new Date(row.completed_at * 1e3) : void 0,
143
- result: row.result,
144
- error: row.error,
131
+ result: row.result ?? void 0,
132
+ error: row.error ?? void 0,
145
133
  scheduledFor: row.scheduled_for ? new Date(row.scheduled_for * 1e3) : void 0,
146
- payload: row.payload,
147
- reason: row.reason,
148
- scheduledMessageId: row.scheduled_message_id
134
+ payload: row.payload ?? void 0,
135
+ reason: row.reason ?? void 0,
136
+ scheduledMessageId: row.scheduled_message_id ?? void 0
149
137
  }));
150
138
  }
151
- /**
152
- * Get active (pending or in_progress) tasks
153
- */
154
139
  getActiveTasks() {
155
140
  const rows = this.db.prepare(
156
141
  `
@@ -164,52 +149,37 @@ var TaskStore = class {
164
149
  description: row.description,
165
150
  status: row.status,
166
151
  priority: row.priority,
167
- createdBy: row.created_by,
152
+ createdBy: row.created_by ?? void 0,
168
153
  createdAt: new Date(row.created_at * 1e3),
169
154
  startedAt: row.started_at ? new Date(row.started_at * 1e3) : void 0,
170
155
  completedAt: row.completed_at ? new Date(row.completed_at * 1e3) : void 0,
171
- result: row.result,
172
- error: row.error,
156
+ result: row.result ?? void 0,
157
+ error: row.error ?? void 0,
173
158
  scheduledFor: row.scheduled_for ? new Date(row.scheduled_for * 1e3) : void 0,
174
- payload: row.payload,
175
- reason: row.reason,
176
- scheduledMessageId: row.scheduled_message_id
159
+ payload: row.payload ?? void 0,
160
+ reason: row.reason ?? void 0,
161
+ scheduledMessageId: row.scheduled_message_id ?? void 0
177
162
  }));
178
163
  }
179
- /**
180
- * Delete a task
181
- */
182
164
  deleteTask(taskId) {
183
165
  const result = this.db.prepare(`DELETE FROM tasks WHERE id = ?`).run(taskId);
184
166
  return result.changes > 0;
185
167
  }
186
- /**
187
- * Mark task as done
188
- */
189
168
  completeTask(taskId, result) {
190
169
  return this.updateTask(taskId, { status: "done", result });
191
170
  }
192
- /**
193
- * Mark task as failed
194
- */
195
171
  failTask(taskId, error) {
196
172
  return this.updateTask(taskId, { status: "failed", error });
197
173
  }
198
- /**
199
- * Start a task
200
- */
201
174
  startTask(taskId) {
202
175
  return this.updateTask(taskId, { status: "in_progress" });
203
176
  }
204
- /**
205
- * Cancel a task
206
- */
207
177
  cancelTask(taskId) {
208
178
  return this.updateTask(taskId, { status: "cancelled" });
209
179
  }
210
180
  /**
211
- * Check if adding a dependency would create a cycle
212
- * Uses BFS to traverse dependency graph
181
+ * Check if adding a dependency would create a cycle.
182
+ * Uses BFS to traverse the dependency graph.
213
183
  */
214
184
  wouldCreateCycle(taskId, newParentId) {
215
185
  if (taskId === newParentId) {
@@ -231,10 +201,6 @@ var TaskStore = class {
231
201
  }
232
202
  return false;
233
203
  }
234
- /**
235
- * Add a dependency (taskId depends on parentTaskId)
236
- * Throws error if would create circular dependency
237
- */
238
204
  addDependency(taskId, parentTaskId) {
239
205
  if (this.wouldCreateCycle(taskId, parentTaskId)) {
240
206
  throw new Error(
@@ -245,23 +211,17 @@ var TaskStore = class {
245
211
  `INSERT OR IGNORE INTO task_dependencies (task_id, depends_on_task_id) VALUES (?, ?)`
246
212
  ).run(taskId, parentTaskId);
247
213
  }
248
- /**
249
- * Get all tasks that this task depends on
250
- */
251
214
  getDependencies(taskId) {
252
215
  const rows = this.db.prepare(`SELECT depends_on_task_id FROM task_dependencies WHERE task_id = ?`).all(taskId);
253
216
  return rows.map((r) => r.depends_on_task_id);
254
217
  }
255
- /**
256
- * Get all tasks that depend on this task
257
- */
258
218
  getDependents(taskId) {
259
219
  const rows = this.db.prepare(`SELECT task_id FROM task_dependencies WHERE depends_on_task_id = ?`).all(taskId);
260
220
  return rows.map((r) => r.task_id);
261
221
  }
262
222
  /**
263
- * Check if a task can execute (all dependencies are done)
264
- * Optimized: Single query with JOIN instead of N+1 queries
223
+ * Check if a task can execute (all dependencies are done).
224
+ * Uses a single JOIN query instead of N+1 queries.
265
225
  */
266
226
  canExecute(taskId) {
267
227
  const result = this.db.prepare(
@@ -276,8 +236,8 @@ var TaskStore = class {
276
236
  return result.pending_count === 0;
277
237
  }
278
238
  /**
279
- * Get all parent task results for a dependent task
280
- * Optimized: Single query with JOIN instead of N+1 queries
239
+ * Get all parent task results for a dependent task.
240
+ * Uses a single JOIN query instead of N+1 queries.
281
241
  */
282
242
  getParentResults(taskId) {
283
243
  const rows = this.db.prepare(
@@ -15,17 +15,16 @@ var COMPACTION_MAX_MESSAGES = 200;
15
15
  var COMPACTION_KEEP_RECENT = 20;
16
16
  var COMPACTION_MAX_TOKENS_RATIO = 0.75;
17
17
  var COMPACTION_SOFT_THRESHOLD_RATIO = 0.5;
18
- var SCRAPER_PARALLEL_WORKERS = 4;
19
18
  var PENDING_HISTORY_MAX_PER_CHAT = 50;
20
19
  var PENDING_HISTORY_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
21
20
  var DEBOUNCE_MAX_MULTIPLIER = 3;
22
21
  var DEBOUNCE_MAX_BUFFER_SIZE = 20;
23
22
  var CONTEXT_MAX_RECENT_MESSAGES = 10;
24
23
  var CONTEXT_MAX_RELEVANT_CHUNKS = 5;
24
+ var HYBRID_SEARCH_MIN_SCORE = 0.15;
25
25
  var CONTEXT_OVERFLOW_SUMMARY_MESSAGES = 15;
26
26
  var RATE_LIMIT_MAX_RETRIES = 3;
27
27
  var KNOWLEDGE_CHUNK_SIZE = 500;
28
- var KNOWLEDGE_CHUNK_OVERLAP = 50;
29
28
  var PAYMENT_TOLERANCE_RATIO = 0.99;
30
29
  var TELEGRAM_CONNECTION_RETRIES = 5;
31
30
  var TELEGRAM_FLOOD_SLEEP_THRESHOLD = 60;
@@ -34,6 +33,23 @@ var EMBEDDING_CACHE_MAX_ENTRIES = 5e4;
34
33
  var EMBEDDING_CACHE_TTL_DAYS = 60;
35
34
  var EMBEDDING_CACHE_EVICTION_INTERVAL = 1e3;
36
35
  var MAX_WRITE_SIZE = 50 * 1024 * 1024;
36
+ var DEFAULT_MAX_TOKENS = 96e3;
37
+ var DEFAULT_SOFT_THRESHOLD_TOKENS = 64e3;
38
+ var FALLBACK_SOFT_THRESHOLD_TOKENS = 6e3;
39
+ var DEFAULT_CONTEXT_WINDOW = 15e4;
40
+ var DEFAULT_MAX_SUMMARY_TOKENS = 2e3;
41
+ var DEFAULT_SUMMARY_FALLBACK_TOKENS = 1e3;
42
+ var MEMORY_FLUSH_RECENT_MESSAGES = 5;
43
+ var CHARS_PER_TOKEN_ESTIMATE = 4;
44
+ var TOKEN_ESTIMATE_SAFETY_MARGIN = 1.2;
45
+ var OVERSIZED_MESSAGE_RATIO = 0.5;
46
+ var ADAPTIVE_CHUNK_RATIO_BASE = 0.4;
47
+ var ADAPTIVE_CHUNK_RATIO_MIN = 0.15;
48
+ var ADAPTIVE_CHUNK_RATIO_TRIGGER = 0.1;
49
+ var SESSION_SLUG_RECENT_MESSAGES = 10;
50
+ var SESSION_SLUG_MAX_TOKENS = 50;
51
+ var MASKING_KEEP_RECENT_COUNT = 10;
52
+ var EMBEDDING_CACHE_EVICTION_RATIO = 0.1;
37
53
 
38
54
  export {
39
55
  MAX_TOOL_RESULT_SIZE,
@@ -52,17 +68,16 @@ export {
52
68
  COMPACTION_KEEP_RECENT,
53
69
  COMPACTION_MAX_TOKENS_RATIO,
54
70
  COMPACTION_SOFT_THRESHOLD_RATIO,
55
- SCRAPER_PARALLEL_WORKERS,
56
71
  PENDING_HISTORY_MAX_PER_CHAT,
57
72
  PENDING_HISTORY_MAX_AGE_MS,
58
73
  DEBOUNCE_MAX_MULTIPLIER,
59
74
  DEBOUNCE_MAX_BUFFER_SIZE,
60
75
  CONTEXT_MAX_RECENT_MESSAGES,
61
76
  CONTEXT_MAX_RELEVANT_CHUNKS,
77
+ HYBRID_SEARCH_MIN_SCORE,
62
78
  CONTEXT_OVERFLOW_SUMMARY_MESSAGES,
63
79
  RATE_LIMIT_MAX_RETRIES,
64
80
  KNOWLEDGE_CHUNK_SIZE,
65
- KNOWLEDGE_CHUNK_OVERLAP,
66
81
  PAYMENT_TOLERANCE_RATIO,
67
82
  TELEGRAM_CONNECTION_RETRIES,
68
83
  TELEGRAM_FLOOD_SLEEP_THRESHOLD,
@@ -70,5 +85,22 @@ export {
70
85
  EMBEDDING_CACHE_MAX_ENTRIES,
71
86
  EMBEDDING_CACHE_TTL_DAYS,
72
87
  EMBEDDING_CACHE_EVICTION_INTERVAL,
73
- MAX_WRITE_SIZE
88
+ MAX_WRITE_SIZE,
89
+ DEFAULT_MAX_TOKENS,
90
+ DEFAULT_SOFT_THRESHOLD_TOKENS,
91
+ FALLBACK_SOFT_THRESHOLD_TOKENS,
92
+ DEFAULT_CONTEXT_WINDOW,
93
+ DEFAULT_MAX_SUMMARY_TOKENS,
94
+ DEFAULT_SUMMARY_FALLBACK_TOKENS,
95
+ MEMORY_FLUSH_RECENT_MESSAGES,
96
+ CHARS_PER_TOKEN_ESTIMATE,
97
+ TOKEN_ESTIMATE_SAFETY_MARGIN,
98
+ OVERSIZED_MESSAGE_RATIO,
99
+ ADAPTIVE_CHUNK_RATIO_BASE,
100
+ ADAPTIVE_CHUNK_RATIO_MIN,
101
+ ADAPTIVE_CHUNK_RATIO_TRIGGER,
102
+ SESSION_SLUG_RECENT_MESSAGES,
103
+ SESSION_SLUG_MAX_TOKENS,
104
+ MASKING_KEEP_RECENT_COUNT,
105
+ EMBEDDING_CACHE_EVICTION_RATIO
74
106
  };
@@ -0,0 +1,42 @@
1
+ // src/ton/endpoint.ts
2
+ var ENDPOINT_CACHE_TTL_MS = 6e4;
3
+ var ORBS_HOST = "ton.access.orbs.network";
4
+ var ORBS_TOPOLOGY_URL = `https://${ORBS_HOST}/mngr/nodes?npm_version=2.3.3`;
5
+ var TONCENTER_FALLBACK = `https://toncenter.com/api/v2/jsonRPC`;
6
+ var _cache = null;
7
+ async function discoverOrbsEndpoint() {
8
+ const res = await fetch(ORBS_TOPOLOGY_URL);
9
+ const nodes = await res.json();
10
+ const healthy = nodes.filter(
11
+ (n) => n.Healthy === "1" && n.Weight > 0 && n.Mngr?.health?.["v2-mainnet"]
12
+ );
13
+ if (healthy.length === 0) throw new Error("no healthy orbs nodes");
14
+ const totalWeight = healthy.reduce((sum, n) => sum + n.Weight, 0);
15
+ let r = Math.floor(Math.random() * totalWeight);
16
+ let chosen = healthy[0];
17
+ for (const node of healthy) {
18
+ r -= node.Weight;
19
+ if (r < 0) {
20
+ chosen = node;
21
+ break;
22
+ }
23
+ }
24
+ return `https://${ORBS_HOST}/${chosen.NodeId}/1/mainnet/toncenter-api-v2/jsonRPC`;
25
+ }
26
+ async function getCachedHttpEndpoint() {
27
+ if (_cache && Date.now() - _cache.ts < ENDPOINT_CACHE_TTL_MS) {
28
+ return _cache.url;
29
+ }
30
+ let url;
31
+ try {
32
+ url = await discoverOrbsEndpoint();
33
+ } catch {
34
+ url = TONCENTER_FALLBACK;
35
+ }
36
+ _cache = { url, ts: Date.now() };
37
+ return url;
38
+ }
39
+
40
+ export {
41
+ getCachedHttpEndpoint
42
+ };