teleton 0.8.4 → 0.8.6
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 +40 -17
- package/dist/{bootstrap-NNEI3Z5H.js → bootstrap-PFBH6ALD.js} +11 -8
- package/dist/bridge-guards-HZTNH7IB.js +9 -0
- package/dist/{chunk-NH2CNRKJ.js → chunk-2UUGRY5B.js} +151 -159
- package/dist/{chunk-UMUONAD6.js → chunk-4MFN75ZK.js} +5941 -2716
- package/dist/{chunk-LC4TV3KL.js → chunk-4MG2AROG.js} +5 -7
- package/dist/{chunk-LZQOX6YY.js → chunk-6IFNQWIM.js} +7714 -8748
- package/dist/chunk-7KI25UJU.js +215 -0
- package/dist/chunk-AX5NBEHX.js +12 -0
- package/dist/{chunk-5LOHRZYY.js → chunk-BLUES3FJ.js} +80 -101
- package/dist/{chunk-CUE4UZXR.js → chunk-BT2I3ETV.js} +3 -3
- package/dist/chunk-CXTZPOTA.js +107 -0
- package/dist/{chunk-LVTKJQ7O.js → chunk-D3GT6YIY.js} +59 -7
- package/dist/chunk-EKCXKL5M.js +53 -0
- package/dist/{chunk-XDZDOKIF.js → chunk-F6S3L3OV.js} +3 -3
- package/dist/{chunk-C4NKJT2Z.js → chunk-J4WDJ7XS.js} +1 -1
- package/dist/{chunk-G7PCW63M.js → chunk-JYF2MM5I.js} +147 -113
- package/dist/{chunk-NVKBBTI6.js → chunk-K3QSIIMZ.js} +9 -6
- package/dist/{chunk-EYWNOHMJ.js → chunk-L653KKCR.js} +1 -0
- package/dist/chunk-OMQIAWEU.js +273 -0
- package/dist/chunk-PCT7GYBP.js +274 -0
- package/dist/chunk-QYZBWU2D.js +139 -0
- package/dist/{chunk-WTDAICGT.js → chunk-R6W4DJRK.js} +7 -7
- package/dist/{chunk-5SEMA47R.js → chunk-RILOEIK6.js} +1 -1
- package/dist/{chunk-6OOHHJ4N.js → chunk-TFTNZZDH.js} +20 -20
- package/dist/chunk-TTOZCZWE.js +96 -0
- package/dist/chunk-UJ54YT2T.js +12 -0
- package/dist/{chunk-GHMXWAXI.js → chunk-ULVL2W3D.js} +211 -445
- package/dist/{chunk-NQ6FZKCE.js → chunk-V3S3NXBQ.js} +3 -1
- package/dist/{chunk-H7MFXJZK.js → chunk-WSL4KIOI.js} +31 -26
- package/dist/{chunk-35MX4ZUI.js → chunk-Z5WY7BSB.js} +5 -5
- package/dist/{chunk-ALKAAG4O.js → chunk-ZGKE3OTA.js} +112 -49
- package/dist/{chunk-JROBTXWY.js → chunk-ZHRDETCX.js} +38 -4
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +272 -159
- package/dist/{client-5KD25NOP.js → client-S5UIK6OG.js} +10 -8
- package/dist/daily-logs-3WXGYAQF.js +25 -0
- package/dist/{get-my-gifts-Y7EN7RK4.js → get-my-gifts-3YSYM3LI.js} +3 -2
- package/dist/harden-permissions-PV5SGV5D.js +100 -0
- package/dist/index.d.ts +923 -0
- package/dist/index.js +29 -20
- package/dist/knowledge-RRWUIO3G.js +19 -0
- package/dist/{local-IHKJFQJS.js → local-MSZAXWUL.js} +3 -3
- package/dist/mcp-loader-OELDFR63.js +15 -0
- package/dist/{memory-QMJRM3XJ.js → memory-6U6HGRK2.js} +23 -12
- package/dist/memory-hook-T7Y235KY.js +19 -0
- package/dist/messages-KV5ADNJB.js +17 -0
- package/dist/{migrate-5VBAP52B.js → migrate-AX3HOKOO.js} +10 -7
- package/dist/{paths-XA2RJH4S.js → paths-WMVV7ZAJ.js} +1 -1
- package/dist/{server-WWGVDFPW.js → server-MFRYOGHR.js} +21 -23
- package/dist/{server-AJCOURH7.js → server-SFLCAZFR.js} +221 -27
- package/dist/{setup-server-VDY64CWW.js → setup-server-YWAPKZVE.js} +26 -26
- package/dist/{store-BY7S6IFN.js → store-PGHQASBC.js} +11 -8
- package/dist/{task-dependency-resolver-L6UUMTHK.js → task-dependency-resolver-YQKADDEU.js} +24 -10
- package/dist/{task-executor-XBNJLUCS.js → task-executor-LWAWD225.js} +4 -4
- package/dist/{tool-adapter-IVX2XQJE.js → tool-adapter-VKLUZSQS.js} +1 -1
- package/dist/{tool-index-FTERJSZK.js → tool-index-YEWDF5CK.js} +5 -5
- package/dist/{transcript-IM7G25OS.js → transcript-4Y3Z2BJ3.js} +3 -3
- package/dist/web/assets/Config-MNxA69ib.js +1 -0
- package/dist/web/assets/Conversations-Dk958paA.js +1 -0
- package/dist/web/assets/Dashboard-dM18fGOm.js +1 -0
- package/dist/web/assets/Hooks-D2griQnI.js +1 -0
- package/dist/web/assets/Mcp-CtWNzwsz.js +1 -0
- package/dist/web/assets/Memory-CfLwH45G.js +1 -0
- package/dist/web/assets/Plugins-3hoJprFo.js +1 -0
- package/dist/web/assets/SearchInput-CpcETdpE.js +1 -0
- package/dist/web/assets/Soul-BSxE73aK.js +1 -0
- package/dist/web/assets/Tasks-DkCkfu3A.js +1 -0
- package/dist/web/assets/TelegramSettingsPanel-BRzc5G6e.js +1 -0
- package/dist/web/assets/Tools-Du8B8Mb4.js +1 -0
- package/dist/web/assets/Wallet-BLILP2Gn.js +1 -0
- package/dist/web/assets/Workspace-qklcXpXV.js +1 -0
- package/dist/web/assets/index-BwEPTTKp.js +90 -0
- package/dist/web/assets/index-noejUsK7.css +1 -0
- package/dist/web/assets/{index.es-DitvF-9H.js → index.es-DdpKlnGb.js} +1 -1
- package/dist/web/assets/useToolManager-tdxkKn3H.js +1 -0
- package/dist/web/assets/utils-CnsbSMo4.js +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +7 -12
- package/src/templates/HEARTBEAT.md +5 -0
- package/dist/memory-hook-VUNWZ3NY.js +0 -19
- package/dist/web/assets/index-BfYCdwLI.js +0 -80
- package/dist/web/assets/index-DmlyQVhR.css +0 -1
- package/dist/{chunk-WFTC3JJW.js → chunk-3NO7QU7W.js} +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
<p align="center">Teleton is an autonomous AI agent platform that operates as a real Telegram user account (not a bot). It thinks through an agentic loop with tool calling, remembers conversations across sessions with hybrid RAG, and natively integrates the TON blockchain: send crypto, swap on DEXs, bid on domains, verify payments - all from a chat message. It can schedule tasks to run autonomously at any time. It ships with
|
|
18
|
+
<p align="center">Teleton is an autonomous AI agent platform that operates as a real Telegram user account (not a bot). It thinks through an agentic loop with tool calling, remembers conversations across sessions with hybrid RAG, and natively integrates the TON blockchain: send crypto, swap on DEXs, bid on domains, verify payments - all from a chat message. It can schedule tasks to run autonomously at any time. It ships with 135+ built-in tools, supports 15 LLM providers, and exposes a Plugin SDK so you can build your own tools on top of the platform.</p>
|
|
19
19
|
|
|
20
20
|
### Key Highlights
|
|
21
21
|
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<tr>
|
|
29
29
|
<td align="center"><br><b><ins>TON Blockchain</ins></b><br>Wallet, jettons, DEX swaps, DNS, NFTs<br><br></td>
|
|
30
30
|
<td align="center"><br><b><ins>Persistent Memory</ins></b><br>Hybrid RAG, vector + keyword, auto-compaction<br><br></td>
|
|
31
|
-
<td align="center"><br><b><ins>
|
|
31
|
+
<td align="center"><br><b><ins>135+ Built-in Tools</ins></b><br>Messaging, media, crypto, DEX, DNS, files<br><br></td>
|
|
32
32
|
</tr>
|
|
33
33
|
<tr>
|
|
34
34
|
<td align="center"><br><b><ins>Plugin SDK</ins></b><br>Custom tools, isolated DBs, secrets, hooks<br><br></td>
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
|
|
46
46
|
| Category | Tools | Description |
|
|
47
47
|
| ------------- | ----- | -------------------------------------------------------------- |
|
|
48
|
-
| Telegram |
|
|
48
|
+
| Telegram | 80 | Messages, media, chats, polls, stickers, gifts, stars, stories |
|
|
49
49
|
| TON & Jettons | 15 | Wallet, send/receive, balances, prices, NFTs, DEX router |
|
|
50
50
|
| STON.fi DEX | 5 | Swap, quote, search, trending, pools |
|
|
51
51
|
| DeDust DEX | 5 | Swap, quote, pools, prices, token analytics |
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
| Web | 2 | Search and page extraction via Tavily |
|
|
56
56
|
| Workspace | 6 | Sandboxed file operations, path traversal protection |
|
|
57
57
|
| Exec | 4 | Shell, files, processes (off by default, admin-only) |
|
|
58
|
+
| Bot | 1 | Inline bot message sending for plugin interactions |
|
|
58
59
|
|
|
59
60
|
### Advanced Capabilities
|
|
60
61
|
|
|
@@ -77,6 +78,7 @@
|
|
|
77
78
|
| **TON Proxy** | Browse .ton domains via HTTP proxy, auto-installed |
|
|
78
79
|
| **Management API** | HTTPS control plane for remote admin, bootstrap mode, lifecycle control |
|
|
79
80
|
| **Sandboxed Workspace** | Path traversal protection, symlink detection, immutable configs |
|
|
81
|
+
| **Heartbeat** | Autonomous periodic wake-up, HEARTBEAT.md task checklist, configurable intervals |
|
|
80
82
|
|
|
81
83
|
---
|
|
82
84
|
|
|
@@ -144,6 +146,26 @@ Agent: [Displays uptime, model, tool count, wallet balance]
|
|
|
144
146
|
|
|
145
147
|
---
|
|
146
148
|
|
|
149
|
+
## User Mode vs Bot Mode
|
|
150
|
+
|
|
151
|
+
Teleton can run as a **user account** (MTProto) or a **Telegram bot** (Bot API). Set `telegram.mode` in your config:
|
|
152
|
+
|
|
153
|
+
| | User Mode (default) | Bot Mode |
|
|
154
|
+
|---|---|---|
|
|
155
|
+
| **Auth** | Phone + api_id + api_hash | Bot token from @BotFather |
|
|
156
|
+
| **Protocol** | MTProto (GramJS) | Bot API (Grammy) |
|
|
157
|
+
| **Tools** | 135+ | 67 (11 Telegram + 56 non-Telegram) |
|
|
158
|
+
| **Risk** | Account ban possible | No ban risk |
|
|
159
|
+
| **Dialogs/History** | Full access | Not available |
|
|
160
|
+
| **Media sending** | All types | Photos only (v1) |
|
|
161
|
+
| **Inline keyboards** | Via bot_token | Native |
|
|
162
|
+
| **Stars/Gifts** | Full access | Not available |
|
|
163
|
+
| **Profile editing** | Yes | No |
|
|
164
|
+
| **Scheduled tasks** | Yes | Not available |
|
|
165
|
+
| **Setup** | `telegram.mode: "user"` | `telegram.mode: "bot"` |
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
147
169
|
## Configuration
|
|
148
170
|
|
|
149
171
|
The `teleton setup` wizard generates a fully configured `~/.teleton/config.yaml` file. Manual editing is only necessary if you want to adjust settings after the initial setup.
|
|
@@ -155,6 +177,10 @@ agent:
|
|
|
155
177
|
model: "claude-opus-4-6"
|
|
156
178
|
utility_model: "claude-haiku-4-5-20251001" # for summarization, compaction, vision
|
|
157
179
|
max_agentic_iterations: 5
|
|
180
|
+
session_reset_policy:
|
|
181
|
+
daily_reset_enabled: true
|
|
182
|
+
daily_reset_hour: 4
|
|
183
|
+
idle_expiry_minutes: 1440 # 24h idle → new session
|
|
158
184
|
|
|
159
185
|
telegram:
|
|
160
186
|
dm_policy: "admin-only" # open | allowlist | admin-only | disabled
|
|
@@ -169,11 +195,6 @@ telegram:
|
|
|
169
195
|
bot_token: "123456:ABC-DEF..."
|
|
170
196
|
bot_username: "your_bot"
|
|
171
197
|
|
|
172
|
-
session_reset_policy:
|
|
173
|
-
daily_reset_enabled: true
|
|
174
|
-
daily_reset_hour: 4
|
|
175
|
-
idle_expiry_minutes: 1440 # 24h idle → new session
|
|
176
|
-
|
|
177
198
|
webui: # Optional: Web dashboard
|
|
178
199
|
enabled: false # Enable WebUI server
|
|
179
200
|
port: 7777 # HTTP server port
|
|
@@ -289,16 +310,19 @@ Optional web dashboard, localhost only, token auth. Start with `teleton start --
|
|
|
289
310
|
</tr>
|
|
290
311
|
<tr>
|
|
291
312
|
<td align="center"><br><b>Memory Search</b><br>Vector + keyword hybrid<br><br></td>
|
|
292
|
-
<td align="center"><br><b>Live Logs</b><br>Real-time SSE streaming<br><br></td>
|
|
313
|
+
<td align="center"><br><b>Live Logs (in Dashboard)</b><br>Real-time SSE streaming<br><br></td>
|
|
293
314
|
<td align="center"><br><b>Workspace</b><br>File browser + editor<br><br></td>
|
|
294
315
|
<td align="center"><br><b>MCP Servers</b><br>Add, remove, configure<br><br></td>
|
|
295
316
|
</tr>
|
|
296
317
|
<tr>
|
|
297
|
-
<td align="center"><br><b>TON Proxy</b><br>Start/stop, auto-install<br><br></td>
|
|
318
|
+
<td align="center"><br><b>TON Proxy (in Config)</b><br>Start/stop, auto-install<br><br></td>
|
|
298
319
|
<td align="center"><br><b>Tasks</b><br>Schedule, dependencies, bulk<br><br></td>
|
|
299
320
|
<td align="center"><br><b>Setup Wizard</b><br>QR code + phone auth<br><br></td>
|
|
300
321
|
<td align="center"><br><b>Config</b><br>Provider switch, key validation<br><br></td>
|
|
301
322
|
</tr>
|
|
323
|
+
<tr>
|
|
324
|
+
<td align="center"><br><b>Hooks</b><br>Plugin hook registrations<br><br></td>
|
|
325
|
+
</tr>
|
|
302
326
|
</table>
|
|
303
327
|
|
|
304
328
|
Auth token is printed at startup. Stored as HttpOnly cookie for 7 days. For remote access:
|
|
@@ -437,7 +461,7 @@ The SDK provides namespaced access to core services:
|
|
|
437
461
|
| `sdk.config` | Sanitized app config (no API keys) |
|
|
438
462
|
| `sdk.pluginConfig` | Plugin-specific config from `config.yaml` |
|
|
439
463
|
| `sdk.log` | `info()`, `warn()`, `error()`, `debug()` |
|
|
440
|
-
| `sdk.on()` | Register hooks: `message:receive`, `response:before
|
|
464
|
+
| `sdk.on()` | Register hooks: `tool:before`, `tool:after`, `tool:error`, `prompt:before`, `prompt:after`, `session:start`, `session:end`, `message:receive`, `response:before`, `response:after`, `response:error`, `agent:start`, `agent:stop` |
|
|
441
465
|
|
|
442
466
|
**Lifecycle hooks**: `migrate(db)`, `start(ctx)`, `stop()`, `onMessage(event)`, `onCallbackQuery(event)`
|
|
443
467
|
|
|
@@ -452,7 +476,7 @@ The SDK provides namespaced access to core services:
|
|
|
452
476
|
| Layer | Technology |
|
|
453
477
|
|-------|------------|
|
|
454
478
|
| LLM | Multi-provider via [pi-ai](https://github.com/mariozechner/pi-ai) (15 providers: Anthropic, Claude Code, OpenAI, Google, xAI, Groq, OpenRouter, Moonshot, Mistral, Cerebras, ZAI, MiniMax, Hugging Face, Cocoon, Local) |
|
|
455
|
-
| Telegram Userbot | [GramJS](https://gram.js.org/) Layer
|
|
479
|
+
| Telegram Userbot | [GramJS](https://gram.js.org/) Layer 223 fork (MTProto) |
|
|
456
480
|
| Inline Bot | [Grammy](https://grammy.dev/) (Bot API, for deals) |
|
|
457
481
|
| Blockchain | [TON SDK](https://github.com/ton-org/ton) (W5R1 wallet) |
|
|
458
482
|
| DeFi | STON.fi SDK, DeDust SDK |
|
|
@@ -460,7 +484,6 @@ The SDK provides namespaced access to core services:
|
|
|
460
484
|
| Vector Search | [sqlite-vec](https://github.com/asg017/sqlite-vec) (cosine similarity) |
|
|
461
485
|
| Full-Text Search | SQLite FTS5 (BM25 ranking) |
|
|
462
486
|
| Embeddings | [@huggingface/transformers](https://www.npmjs.com/package/@huggingface/transformers) (local ONNX) or Voyage AI |
|
|
463
|
-
| Token Counting | [js-tiktoken](https://github.com/dqbd/tiktoken) |
|
|
464
487
|
| MCP Client | [@modelcontextprotocol/sdk](https://modelcontextprotocol.io/) (stdio + SSE + Streamable HTTP) |
|
|
465
488
|
| WebUI | [Hono](https://hono.dev/) (API) + React + Vite (frontend) |
|
|
466
489
|
| Language | TypeScript 5.7, Node.js 20+ |
|
|
@@ -473,13 +496,13 @@ src/
|
|
|
473
496
|
├── agent/ # Core agent runtime
|
|
474
497
|
│ ├── runtime.ts # Agentic loop (5 iterations, tool calling, masking, compaction)
|
|
475
498
|
│ ├── client.ts # Multi-provider LLM client
|
|
476
|
-
│ └── tools/ #
|
|
477
|
-
│ ├── register-all.ts # Central tool registration (
|
|
499
|
+
│ └── tools/ # 135+ built-in tools
|
|
500
|
+
│ ├── register-all.ts # Central tool registration (9 categories)
|
|
478
501
|
│ ├── registry.ts # Tool registry, scope filtering, provider limits
|
|
479
502
|
│ ├── module-loader.ts # Built-in module loading (deals + exec)
|
|
480
503
|
│ ├── plugin-loader.ts # External plugin discovery, validation, hot-reload
|
|
481
504
|
│ ├── mcp-loader.ts # MCP client (stdio/SSE), tool discovery, lifecycle
|
|
482
|
-
│ ├── telegram/ # Telegram operations (
|
|
505
|
+
│ ├── telegram/ # Telegram operations (80 tools)
|
|
483
506
|
│ ├── ton/ # TON blockchain + jettons + DEX router (15 tools)
|
|
484
507
|
│ ├── stonfi/ # STON.fi DEX (5 tools)
|
|
485
508
|
│ ├── dedust/ # DeDust DEX (5 tools)
|
|
@@ -549,7 +572,7 @@ src/
|
|
|
549
572
|
├── templates/ # Workspace template files (SOUL.md, etc.)
|
|
550
573
|
└── cli/ # CLI commands (setup, config, doctor, mcp)
|
|
551
574
|
|
|
552
|
-
web/ # React + Vite frontend (
|
|
575
|
+
web/ # React + Vite frontend (11 pages)
|
|
553
576
|
packages/sdk/ # Published @teleton-agent/sdk
|
|
554
577
|
```
|
|
555
578
|
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AgentLifecycle
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-K3QSIIMZ.js";
|
|
4
4
|
import {
|
|
5
5
|
configExists,
|
|
6
|
-
ensureWorkspace,
|
|
7
6
|
getDefaultConfigPath
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import
|
|
7
|
+
} from "./chunk-2UUGRY5B.js";
|
|
8
|
+
import "./chunk-3UFPFWYP.js";
|
|
9
|
+
import {
|
|
10
|
+
ensureWorkspace
|
|
11
|
+
} from "./chunk-CXTZPOTA.js";
|
|
12
|
+
import "./chunk-J4WDJ7XS.js";
|
|
13
|
+
import "./chunk-TFTNZZDH.js";
|
|
11
14
|
import {
|
|
12
15
|
SHUTDOWN_TIMEOUT_MS
|
|
13
16
|
} from "./chunk-R4YSJ4EY.js";
|
|
14
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-L653KKCR.js";
|
|
15
18
|
import {
|
|
16
19
|
createLogger
|
|
17
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-V3S3NXBQ.js";
|
|
18
21
|
import "./chunk-3RG5ZIWI.js";
|
|
19
22
|
|
|
20
23
|
// src/api/bootstrap.ts
|
|
@@ -42,7 +45,7 @@ async function startApiOnly(options) {
|
|
|
42
45
|
marketplace: null,
|
|
43
46
|
userHookEvaluator: null
|
|
44
47
|
};
|
|
45
|
-
const { ApiServer } = await import("./server-
|
|
48
|
+
const { ApiServer } = await import("./server-MFRYOGHR.js");
|
|
46
49
|
const apiConfig = {
|
|
47
50
|
enabled: true,
|
|
48
51
|
port: parseInt(options.apiPort || process.env.TELETON_API_PORT || "7778"),
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TELEGRAM_MAX_MESSAGE_LENGTH
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-J4WDJ7XS.js";
|
|
4
4
|
import {
|
|
5
5
|
getProviderMetadata
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TFTNZZDH.js";
|
|
7
7
|
import {
|
|
8
|
-
TELETON_ROOT
|
|
9
|
-
|
|
10
|
-
WORKSPACE_ROOT
|
|
11
|
-
} from "./chunk-EYWNOHMJ.js";
|
|
8
|
+
TELETON_ROOT
|
|
9
|
+
} from "./chunk-L653KKCR.js";
|
|
12
10
|
import {
|
|
13
11
|
createLogger
|
|
14
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-V3S3NXBQ.js";
|
|
15
13
|
|
|
16
14
|
// src/config/loader.ts
|
|
17
15
|
import { readFileSync, existsSync, writeFileSync, mkdirSync } from "fs";
|
|
@@ -55,12 +53,14 @@ var AgentConfigSchema = z.object({
|
|
|
55
53
|
temperature: z.number().default(0.7),
|
|
56
54
|
system_prompt: z.string().nullable().default(null),
|
|
57
55
|
max_agentic_iterations: z.number().default(5).describe("Maximum number of agentic loop iterations (tool call \u2192 result \u2192 tool call cycles)"),
|
|
56
|
+
toolset: z.string().default("full").describe("Active toolset profile: minimal, standard, trading, full"),
|
|
58
57
|
session_reset_policy: SessionResetPolicySchema.default(SessionResetPolicySchema.parse({}))
|
|
59
58
|
});
|
|
60
59
|
var TelegramConfigSchema = z.object({
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
mode: z.enum(["user", "bot"]).default("user"),
|
|
61
|
+
api_id: z.number().optional(),
|
|
62
|
+
api_hash: z.string().optional(),
|
|
63
|
+
phone: z.string().optional(),
|
|
64
64
|
session_name: z.string().default("teleton_session"),
|
|
65
65
|
session_path: z.string().default("~/.teleton"),
|
|
66
66
|
dm_policy: DMPolicy.default("allowlist"),
|
|
@@ -79,7 +79,45 @@ var TelegramConfigSchema = z.object({
|
|
|
79
79
|
owner_id: z.number().optional().describe("Owner's Telegram user ID"),
|
|
80
80
|
debounce_ms: z.number().default(1500).describe("Debounce delay in milliseconds for group messages (0 = disabled)"),
|
|
81
81
|
bot_token: z.string().optional().describe("Telegram Bot token from @BotFather for inline deal buttons"),
|
|
82
|
-
bot_username: z.string().optional().describe("Bot username without @ (e.g., 'teleton_deals_bot')")
|
|
82
|
+
bot_username: z.string().optional().describe("Bot username without @ (e.g., 'teleton_deals_bot')"),
|
|
83
|
+
stream_mode: z.enum(["all", "replace", "off"]).default("replace").describe(
|
|
84
|
+
"Bot streaming mode: replace=each iteration replaces draft (default), all=concatenate all iterations, off=no streaming"
|
|
85
|
+
)
|
|
86
|
+
}).superRefine((data, ctx) => {
|
|
87
|
+
if (data.mode === "user") {
|
|
88
|
+
if (!data.api_id)
|
|
89
|
+
ctx.addIssue({
|
|
90
|
+
code: z.ZodIssueCode.custom,
|
|
91
|
+
message: "api_id is required in user mode",
|
|
92
|
+
path: ["api_id"]
|
|
93
|
+
});
|
|
94
|
+
if (!data.api_hash)
|
|
95
|
+
ctx.addIssue({
|
|
96
|
+
code: z.ZodIssueCode.custom,
|
|
97
|
+
message: "api_hash is required in user mode",
|
|
98
|
+
path: ["api_hash"]
|
|
99
|
+
});
|
|
100
|
+
if (!data.phone)
|
|
101
|
+
ctx.addIssue({
|
|
102
|
+
code: z.ZodIssueCode.custom,
|
|
103
|
+
message: "phone is required in user mode",
|
|
104
|
+
path: ["phone"]
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (data.mode === "bot") {
|
|
108
|
+
if (!data.bot_token)
|
|
109
|
+
ctx.addIssue({
|
|
110
|
+
code: z.ZodIssueCode.custom,
|
|
111
|
+
message: "bot_token is required in bot mode",
|
|
112
|
+
path: ["bot_token"]
|
|
113
|
+
});
|
|
114
|
+
if (!data.owner_id)
|
|
115
|
+
ctx.addIssue({
|
|
116
|
+
code: z.ZodIssueCode.custom,
|
|
117
|
+
message: "owner_id is required in bot mode",
|
|
118
|
+
path: ["owner_id"]
|
|
119
|
+
});
|
|
120
|
+
}
|
|
83
121
|
});
|
|
84
122
|
var StorageConfigSchema = z.object({
|
|
85
123
|
sessions_file: z.string().default("~/.teleton/sessions.json"),
|
|
@@ -143,7 +181,7 @@ var McpServerSchema = z.object({
|
|
|
143
181
|
args: z.array(z.string()).optional().describe("Explicit args array (overrides command splitting)"),
|
|
144
182
|
env: z.record(z.string(), z.string()).optional().describe("Environment variables for stdio server"),
|
|
145
183
|
url: z.string().url().optional().describe("SSE/HTTP endpoint URL (alternative to command)"),
|
|
146
|
-
scope: z.enum(["always", "dm-only", "group-only", "admin-only"]).default("always").describe("Tool scope"),
|
|
184
|
+
scope: z.enum(["always", "dm-only", "group-only", "admin-only", "open", "allowlist", "disabled"]).default("always").describe("Tool scope"),
|
|
147
185
|
enabled: z.boolean().default(true).describe("Enable/disable this server")
|
|
148
186
|
}).refine((s) => s.command || s.url, {
|
|
149
187
|
message: "Each MCP server needs either 'command' (stdio) or 'url' (SSE/HTTP)"
|
|
@@ -154,15 +192,13 @@ var _McpObject = z.object({
|
|
|
154
192
|
var McpConfigSchema = _McpObject.default(_McpObject.parse({}));
|
|
155
193
|
var _ToolRagObject = z.object({
|
|
156
194
|
enabled: z.boolean().default(true).describe("Enable semantic tool retrieval (Tool RAG)"),
|
|
157
|
-
top_k: z.number().default(
|
|
195
|
+
top_k: z.number().default(35).describe("Max tools to retrieve per LLM call"),
|
|
158
196
|
always_include: z.array(z.string()).default([
|
|
159
197
|
"telegram_send_message",
|
|
160
|
-
"
|
|
198
|
+
"telegram_quote_reply",
|
|
161
199
|
"telegram_send_photo",
|
|
162
|
-
"telegram_send_document",
|
|
163
200
|
"journal_*",
|
|
164
|
-
"workspace_*"
|
|
165
|
-
"web_*"
|
|
201
|
+
"workspace_*"
|
|
166
202
|
]).describe("Tool name patterns always included (prefix glob with *)"),
|
|
167
203
|
skip_unlimited_providers: z.boolean().default(false).describe("Skip Tool RAG for providers with no tool limit (e.g. Anthropic)")
|
|
168
204
|
});
|
|
@@ -185,6 +221,13 @@ var _CapabilitiesObject = z.object({
|
|
|
185
221
|
exec: _ExecObject.default(_ExecObject.parse({}))
|
|
186
222
|
});
|
|
187
223
|
var CapabilitiesConfigSchema = _CapabilitiesObject.default(_CapabilitiesObject.parse({}));
|
|
224
|
+
var _HeartbeatObject = z.object({
|
|
225
|
+
enabled: z.boolean().default(true).describe("Enable periodic heartbeat timer"),
|
|
226
|
+
interval_ms: z.number().min(6e4).default(36e5).describe("Heartbeat interval in milliseconds (min 60s, default 60min)"),
|
|
227
|
+
prompt: z.string().default("Execute your HEARTBEAT.md checklist now. Work through each item using tool calls.").describe("Prompt sent to agent on each heartbeat tick"),
|
|
228
|
+
self_configurable: z.boolean().default(false).describe("Allow agent to modify heartbeat config via config_set")
|
|
229
|
+
});
|
|
230
|
+
var HeartbeatConfigSchema = _HeartbeatObject.default(_HeartbeatObject.parse({}));
|
|
188
231
|
var ConfigSchema = z.object({
|
|
189
232
|
meta: MetaConfigSchema.default(MetaConfigSchema.parse({})),
|
|
190
233
|
agent: AgentConfigSchema,
|
|
@@ -199,6 +242,7 @@ var ConfigSchema = z.object({
|
|
|
199
242
|
capabilities: CapabilitiesConfigSchema,
|
|
200
243
|
api: ApiConfigSchema.optional(),
|
|
201
244
|
ton_proxy: TonProxyConfigSchema,
|
|
245
|
+
heartbeat: HeartbeatConfigSchema,
|
|
202
246
|
mcp: McpConfigSchema,
|
|
203
247
|
plugins: z.record(z.string(), z.unknown()).default({}).describe("Per-plugin config (key = plugin name with underscores)"),
|
|
204
248
|
cocoon: z.object({
|
|
@@ -209,8 +253,64 @@ var ConfigSchema = z.object({
|
|
|
209
253
|
tavily_api_key: z.string().optional().describe("Tavily API key for web search & extract (free at https://tavily.com)")
|
|
210
254
|
});
|
|
211
255
|
|
|
256
|
+
// src/config/env.ts
|
|
257
|
+
import { z as z2 } from "zod";
|
|
258
|
+
var log = createLogger("Env");
|
|
259
|
+
var optionalString = z2.string().optional();
|
|
260
|
+
var optionalInt = z2.coerce.number().int().optional();
|
|
261
|
+
var optionalPort = z2.coerce.number().int().min(1).max(65535).optional();
|
|
262
|
+
var optionalBoolean = z2.string().optional().transform(
|
|
263
|
+
(v) => v === "true" || v === "1" || v === "yes" ? true : v === "false" || v === "0" || v === "no" ? false : void 0
|
|
264
|
+
);
|
|
265
|
+
var envSchema = z2.object({
|
|
266
|
+
// Core
|
|
267
|
+
TELETON_HOME: optionalString,
|
|
268
|
+
TELETON_API_KEY: optionalString,
|
|
269
|
+
TELETON_BASE_URL: optionalString,
|
|
270
|
+
// Telegram
|
|
271
|
+
TELETON_TG_API_ID: optionalInt,
|
|
272
|
+
TELETON_TG_API_HASH: optionalString,
|
|
273
|
+
TELETON_TG_PHONE: optionalString,
|
|
274
|
+
// WebUI
|
|
275
|
+
TELETON_WEBUI_ENABLED: optionalBoolean,
|
|
276
|
+
TELETON_WEBUI_PORT: optionalPort,
|
|
277
|
+
TELETON_WEBUI_HOST: optionalString,
|
|
278
|
+
// Management API
|
|
279
|
+
TELETON_API_ENABLED: optionalBoolean,
|
|
280
|
+
TELETON_API_PORT: optionalPort,
|
|
281
|
+
TELETON_JSON_CREDENTIALS: optionalBoolean,
|
|
282
|
+
// Logging
|
|
283
|
+
TELETON_LOG_LEVEL: optionalString,
|
|
284
|
+
TELETON_LOG: optionalString,
|
|
285
|
+
TELETON_LOG_PRETTY: optionalString,
|
|
286
|
+
// External API keys
|
|
287
|
+
TELETON_TAVILY_API_KEY: optionalString,
|
|
288
|
+
TELETON_TONAPI_KEY: optionalString,
|
|
289
|
+
TELETON_TONCENTER_API_KEY: optionalString
|
|
290
|
+
});
|
|
291
|
+
function validateEnv() {
|
|
292
|
+
const result = envSchema.safeParse(process.env);
|
|
293
|
+
if (!result.success) {
|
|
294
|
+
for (const issue of result.error.issues) {
|
|
295
|
+
const path = issue.path.join(".");
|
|
296
|
+
if (path === "TELETON_TG_API_ID" && process.env.TELETON_TG_API_ID) {
|
|
297
|
+
throw new Error(
|
|
298
|
+
`Invalid TELETON_TG_API_ID environment variable: "${process.env.TELETON_TG_API_ID}" is not a valid integer`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
log.warn({ path, message: issue.message }, "Invalid env var");
|
|
302
|
+
}
|
|
303
|
+
const invalidKeys = new Set(result.error.issues.map((i) => String(i.path[0])));
|
|
304
|
+
const cleaned = { ...process.env };
|
|
305
|
+
for (const key of invalidKeys) delete cleaned[key];
|
|
306
|
+
const retry = envSchema.safeParse(cleaned);
|
|
307
|
+
return retry.success ? retry.data : {};
|
|
308
|
+
}
|
|
309
|
+
return result.data;
|
|
310
|
+
}
|
|
311
|
+
|
|
212
312
|
// src/config/loader.ts
|
|
213
|
-
var
|
|
313
|
+
var log2 = createLogger("Config");
|
|
214
314
|
var DEFAULT_CONFIG_PATH = join(TELETON_ROOT, "config.yaml");
|
|
215
315
|
function expandPath(path) {
|
|
216
316
|
if (path.startsWith("~")) {
|
|
@@ -219,6 +319,7 @@ function expandPath(path) {
|
|
|
219
319
|
return path;
|
|
220
320
|
}
|
|
221
321
|
function loadConfig(configPath = DEFAULT_CONFIG_PATH) {
|
|
322
|
+
const env = validateEnv();
|
|
222
323
|
const fullPath = expandPath(configPath);
|
|
223
324
|
if (!existsSync(fullPath)) {
|
|
224
325
|
throw new Error(`Config file not found: ${fullPath}
|
|
@@ -237,7 +338,7 @@ Run 'teleton setup' to create one.`);
|
|
|
237
338
|
throw new Error(`Invalid YAML in ${fullPath}: ${error.message}`);
|
|
238
339
|
}
|
|
239
340
|
if (raw && typeof raw === "object" && "market" in raw) {
|
|
240
|
-
|
|
341
|
+
log2.warn("config.market is deprecated and ignored. Use market-api plugin instead.");
|
|
241
342
|
delete raw.market;
|
|
242
343
|
}
|
|
243
344
|
const result = ConfigSchema.safeParse(raw);
|
|
@@ -253,71 +354,57 @@ Run 'teleton setup' to create one.`);
|
|
|
253
354
|
config.telegram.session_path = expandPath(config.telegram.session_path);
|
|
254
355
|
config.storage.sessions_file = expandPath(config.storage.sessions_file);
|
|
255
356
|
config.storage.memory_file = expandPath(config.storage.memory_file);
|
|
256
|
-
if (
|
|
257
|
-
config.agent.api_key =
|
|
357
|
+
if (env.TELETON_API_KEY) {
|
|
358
|
+
config.agent.api_key = env.TELETON_API_KEY;
|
|
258
359
|
}
|
|
259
|
-
if (
|
|
260
|
-
|
|
261
|
-
if (isNaN(apiId)) {
|
|
262
|
-
throw new Error(
|
|
263
|
-
`Invalid TELETON_TG_API_ID environment variable: "${process.env.TELETON_TG_API_ID}" is not a valid integer`
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
config.telegram.api_id = apiId;
|
|
360
|
+
if (env.TELETON_TG_API_ID != null) {
|
|
361
|
+
config.telegram.api_id = env.TELETON_TG_API_ID;
|
|
267
362
|
}
|
|
268
|
-
if (
|
|
269
|
-
config.telegram.api_hash =
|
|
363
|
+
if (env.TELETON_TG_API_HASH) {
|
|
364
|
+
config.telegram.api_hash = env.TELETON_TG_API_HASH;
|
|
270
365
|
}
|
|
271
|
-
if (
|
|
272
|
-
config.telegram.phone =
|
|
366
|
+
if (env.TELETON_TG_PHONE) {
|
|
367
|
+
config.telegram.phone = env.TELETON_TG_PHONE;
|
|
273
368
|
}
|
|
274
|
-
if (
|
|
275
|
-
config.webui.enabled =
|
|
369
|
+
if (env.TELETON_WEBUI_ENABLED != null) {
|
|
370
|
+
config.webui.enabled = env.TELETON_WEBUI_ENABLED;
|
|
276
371
|
}
|
|
277
|
-
if (
|
|
278
|
-
|
|
279
|
-
if (!isNaN(port) && port >= 1024 && port <= 65535) {
|
|
280
|
-
config.webui.port = port;
|
|
281
|
-
}
|
|
372
|
+
if (env.TELETON_WEBUI_PORT != null && env.TELETON_WEBUI_PORT >= 1024) {
|
|
373
|
+
config.webui.port = env.TELETON_WEBUI_PORT;
|
|
282
374
|
}
|
|
283
|
-
if (
|
|
284
|
-
config.webui.host =
|
|
375
|
+
if (env.TELETON_WEBUI_HOST) {
|
|
376
|
+
config.webui.host = env.TELETON_WEBUI_HOST;
|
|
285
377
|
if (!["127.0.0.1", "localhost", "::1"].includes(config.webui.host)) {
|
|
286
|
-
|
|
378
|
+
log2.warn(
|
|
287
379
|
{ host: config.webui.host },
|
|
288
380
|
"WebUI bound to non-loopback address \u2014 ensure auth_token is set"
|
|
289
381
|
);
|
|
290
382
|
}
|
|
291
383
|
}
|
|
292
|
-
if (
|
|
384
|
+
if (env.TELETON_API_ENABLED != null) {
|
|
293
385
|
if (!config.api) config.api = { enabled: false, port: 7778, key_hash: "", allowed_ips: [] };
|
|
294
|
-
config.api.enabled =
|
|
386
|
+
config.api.enabled = env.TELETON_API_ENABLED;
|
|
295
387
|
}
|
|
296
|
-
if (
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
if (!config.api) config.api = { enabled: false, port: 7778, key_hash: "", allowed_ips: [] };
|
|
300
|
-
config.api.port = port;
|
|
301
|
-
}
|
|
388
|
+
if (env.TELETON_API_PORT != null && env.TELETON_API_PORT >= 1024) {
|
|
389
|
+
if (!config.api) config.api = { enabled: false, port: 7778, key_hash: "", allowed_ips: [] };
|
|
390
|
+
config.api.port = env.TELETON_API_PORT;
|
|
302
391
|
}
|
|
303
|
-
if (
|
|
392
|
+
if (env.TELETON_BASE_URL) {
|
|
304
393
|
try {
|
|
305
|
-
new URL(
|
|
306
|
-
config.agent.base_url =
|
|
394
|
+
new URL(env.TELETON_BASE_URL);
|
|
395
|
+
config.agent.base_url = env.TELETON_BASE_URL;
|
|
307
396
|
} catch {
|
|
308
|
-
throw new Error(
|
|
309
|
-
`Invalid TELETON_BASE_URL: "${process.env.TELETON_BASE_URL}" is not a valid URL`
|
|
310
|
-
);
|
|
397
|
+
throw new Error(`Invalid TELETON_BASE_URL: "${env.TELETON_BASE_URL}" is not a valid URL`);
|
|
311
398
|
}
|
|
312
399
|
}
|
|
313
|
-
if (
|
|
314
|
-
config.tavily_api_key =
|
|
400
|
+
if (env.TELETON_TAVILY_API_KEY) {
|
|
401
|
+
config.tavily_api_key = env.TELETON_TAVILY_API_KEY;
|
|
315
402
|
}
|
|
316
|
-
if (
|
|
317
|
-
config.tonapi_key =
|
|
403
|
+
if (env.TELETON_TONAPI_KEY) {
|
|
404
|
+
config.tonapi_key = env.TELETON_TONAPI_KEY;
|
|
318
405
|
}
|
|
319
|
-
if (
|
|
320
|
-
config.toncenter_api_key =
|
|
406
|
+
if (env.TELETON_TONCENTER_API_KEY) {
|
|
407
|
+
config.toncenter_api_key = env.TELETON_TONCENTER_API_KEY;
|
|
321
408
|
}
|
|
322
409
|
return config;
|
|
323
410
|
}
|
|
@@ -328,106 +415,11 @@ function getDefaultConfigPath() {
|
|
|
328
415
|
return DEFAULT_CONFIG_PATH;
|
|
329
416
|
}
|
|
330
417
|
|
|
331
|
-
// src/workspace/manager.ts
|
|
332
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, copyFileSync } from "fs";
|
|
333
|
-
import { join as join2, dirname as dirname2 } from "path";
|
|
334
|
-
import { fileURLToPath } from "url";
|
|
335
|
-
var log2 = createLogger("Workspace");
|
|
336
|
-
function findPackageRoot() {
|
|
337
|
-
let dir = dirname2(fileURLToPath(import.meta.url));
|
|
338
|
-
for (let i = 0; i < 10; i++) {
|
|
339
|
-
if (existsSync2(join2(dir, "package.json"))) return dir;
|
|
340
|
-
dir = dirname2(dir);
|
|
341
|
-
}
|
|
342
|
-
return process.cwd();
|
|
343
|
-
}
|
|
344
|
-
var TEMPLATES_DIR = join2(findPackageRoot(), "src", "templates");
|
|
345
|
-
async function ensureWorkspace(config) {
|
|
346
|
-
const silent = config?.silent ?? false;
|
|
347
|
-
if (!existsSync2(TELETON_ROOT)) {
|
|
348
|
-
mkdirSync2(TELETON_ROOT, { recursive: true });
|
|
349
|
-
if (!silent) log2.info(`Created Teleton root at ${TELETON_ROOT}`);
|
|
350
|
-
}
|
|
351
|
-
if (!existsSync2(WORKSPACE_ROOT)) {
|
|
352
|
-
mkdirSync2(WORKSPACE_ROOT, { recursive: true });
|
|
353
|
-
if (!silent) log2.info(`Created workspace at ${WORKSPACE_ROOT}`);
|
|
354
|
-
}
|
|
355
|
-
const directories = [
|
|
356
|
-
WORKSPACE_PATHS.MEMORY_DIR,
|
|
357
|
-
WORKSPACE_PATHS.DOWNLOADS_DIR,
|
|
358
|
-
WORKSPACE_PATHS.UPLOADS_DIR,
|
|
359
|
-
WORKSPACE_PATHS.TEMP_DIR,
|
|
360
|
-
WORKSPACE_PATHS.MEMES_DIR
|
|
361
|
-
];
|
|
362
|
-
for (const dir of directories) {
|
|
363
|
-
if (!existsSync2(dir)) {
|
|
364
|
-
mkdirSync2(dir, { recursive: true });
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
const workspace = {
|
|
368
|
-
root: TELETON_ROOT,
|
|
369
|
-
workspace: WORKSPACE_ROOT,
|
|
370
|
-
// Workspace files
|
|
371
|
-
soulPath: WORKSPACE_PATHS.SOUL,
|
|
372
|
-
memoryPath: WORKSPACE_PATHS.MEMORY,
|
|
373
|
-
identityPath: WORKSPACE_PATHS.IDENTITY,
|
|
374
|
-
userPath: WORKSPACE_PATHS.USER,
|
|
375
|
-
strategyPath: WORKSPACE_PATHS.STRATEGY,
|
|
376
|
-
securityPath: WORKSPACE_PATHS.SECURITY,
|
|
377
|
-
// Workspace directories
|
|
378
|
-
memoryDir: WORKSPACE_PATHS.MEMORY_DIR,
|
|
379
|
-
downloadsDir: WORKSPACE_PATHS.DOWNLOADS_DIR,
|
|
380
|
-
uploadsDir: WORKSPACE_PATHS.UPLOADS_DIR,
|
|
381
|
-
tempDir: WORKSPACE_PATHS.TEMP_DIR,
|
|
382
|
-
memesDir: WORKSPACE_PATHS.MEMES_DIR,
|
|
383
|
-
// Protected files (outside workspace)
|
|
384
|
-
sessionPath: join2(TELETON_ROOT, "telegram_session.txt"),
|
|
385
|
-
configPath: join2(TELETON_ROOT, "config.yaml"),
|
|
386
|
-
walletPath: join2(TELETON_ROOT, "wallet.json")
|
|
387
|
-
};
|
|
388
|
-
if (config?.ensureTemplates) {
|
|
389
|
-
await bootstrapTemplates(workspace, silent);
|
|
390
|
-
}
|
|
391
|
-
return workspace;
|
|
392
|
-
}
|
|
393
|
-
async function bootstrapTemplates(workspace, silent = false) {
|
|
394
|
-
const templates = [
|
|
395
|
-
{ name: "SOUL.md", path: workspace.soulPath },
|
|
396
|
-
{ name: "MEMORY.md", path: workspace.memoryPath },
|
|
397
|
-
{ name: "IDENTITY.md", path: workspace.identityPath },
|
|
398
|
-
{ name: "USER.md", path: workspace.userPath },
|
|
399
|
-
{ name: "SECURITY.md", path: workspace.securityPath },
|
|
400
|
-
{ name: "STRATEGY.md", path: workspace.strategyPath }
|
|
401
|
-
];
|
|
402
|
-
for (const template of templates) {
|
|
403
|
-
if (!existsSync2(template.path)) {
|
|
404
|
-
const templateSource = join2(TEMPLATES_DIR, template.name);
|
|
405
|
-
if (existsSync2(templateSource)) {
|
|
406
|
-
copyFileSync(templateSource, template.path);
|
|
407
|
-
if (!silent) log2.info(`Created ${template.name}`);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
function isNewWorkspace(workspace) {
|
|
413
|
-
return !existsSync2(workspace.configPath);
|
|
414
|
-
}
|
|
415
|
-
function loadTemplate(name) {
|
|
416
|
-
const templatePath = join2(TEMPLATES_DIR, name);
|
|
417
|
-
if (!existsSync2(templatePath)) {
|
|
418
|
-
throw new Error(`Template ${name} not found at ${templatePath}`);
|
|
419
|
-
}
|
|
420
|
-
return readFileSync2(templatePath, "utf-8");
|
|
421
|
-
}
|
|
422
|
-
|
|
423
418
|
export {
|
|
424
419
|
DealsConfigSchema,
|
|
425
420
|
ConfigSchema,
|
|
426
421
|
expandPath,
|
|
427
422
|
loadConfig,
|
|
428
423
|
configExists,
|
|
429
|
-
getDefaultConfigPath
|
|
430
|
-
ensureWorkspace,
|
|
431
|
-
isNewWorkspace,
|
|
432
|
-
loadTemplate
|
|
424
|
+
getDefaultConfigPath
|
|
433
425
|
};
|