teleton 0.4.0 → 0.5.1
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 +88 -13
- package/dist/BigInteger-DQ33LTTE.js +5 -0
- package/dist/chunk-4DU3C27M.js +30 -0
- package/dist/chunk-5WWR4CU3.js +124 -0
- package/dist/{chunk-7UPH62J2.js → chunk-BYTHCDZA.js} +261 -255
- package/dist/{chunk-E2NXSWOS.js → chunk-NUGDTPE4.js} +24 -64
- package/dist/{chunk-OA5L7GM6.js → chunk-O4R7V5Y2.js} +37 -5
- package/dist/chunk-QUAPFI2N.js +42 -0
- package/dist/{chunk-QU4ZOR35.js → chunk-RRB6BWU7.js} +3108 -3345
- package/dist/chunk-TSKJCWQQ.js +1263 -0
- package/dist/{chunk-B2PRMXOH.js → chunk-WL2Q3VRD.js} +0 -2
- package/dist/{chunk-OQGNS2FV.js → chunk-YBA6IBGT.js} +20 -5
- package/dist/cli/index.js +39 -172
- package/dist/{endpoint-FT2B2RZ2.js → endpoint-FLYNEZ2F.js} +1 -1
- package/dist/{get-my-gifts-AFKBG4YQ.js → get-my-gifts-KVULMBJ3.js} +1 -1
- package/dist/index.js +12 -12
- package/dist/{memory-SYTQ5P7P.js → memory-657W5AS6.js} +4 -5
- package/dist/{migrate-ITXMRRSZ.js → migrate-PMB2JVXH.js} +4 -5
- package/dist/server-BQY7CM2N.js +1120 -0
- package/dist/{task-dependency-resolver-GY6PEBIS.js → task-dependency-resolver-TRPILAHM.js} +2 -2
- package/dist/{task-executor-4QKTZZ3P.js → task-executor-N7XNVK5N.js} +1 -1
- package/dist/{tasks-M3QDPTGY.js → tasks-QSCWSMPS.js} +1 -1
- package/dist/{transcript-DF2Y6CFY.js → transcript-7V4UNID4.js} +1 -1
- package/dist/web/assets/index-CDMbujHf.css +1 -0
- package/dist/web/assets/index-DDX8oQ2z.js +67 -0
- package/dist/web/index.html +16 -0
- package/dist/web/logo_dark.png +0 -0
- package/package.json +23 -4
- package/dist/chunk-67QC5FBN.js +0 -60
- package/dist/chunk-A64NPEFL.js +0 -74
- package/dist/chunk-DUW5VBAZ.js +0 -133
- package/dist/chunk-QBGUCUOW.js +0 -16
- 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
|
-
- **
|
|
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/ #
|
|
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
|
|
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(
|
|
413
|
-
|
|
|
414
|
-
|
|
|
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` |
|
|
492
|
+
| `sdk.log` | `info()`, `warn()`, `error()`, `debug()` — Prefixed logger |
|
|
418
493
|
|
|
419
494
|
Plugin config in `config.yaml`:
|
|
420
495
|
```yaml
|
|
@@ -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
|
+
};
|