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
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getCachedHttpEndpoint
|
|
3
|
+
} from "./chunk-QUAPFI2N.js";
|
|
4
|
+
import {
|
|
5
|
+
COINGECKO_API_URL,
|
|
6
|
+
tonapiFetch
|
|
7
|
+
} from "./chunk-XBKSS6DM.js";
|
|
8
|
+
import {
|
|
9
|
+
TELEGRAM_MAX_MESSAGE_LENGTH
|
|
10
|
+
} from "./chunk-RO62LO6Z.js";
|
|
11
|
+
import {
|
|
12
|
+
fetchWithTimeout
|
|
13
|
+
} from "./chunk-VAUJSSD3.js";
|
|
14
|
+
import {
|
|
15
|
+
TELETON_ROOT,
|
|
16
|
+
WORKSPACE_PATHS,
|
|
17
|
+
WORKSPACE_ROOT
|
|
18
|
+
} from "./chunk-EYWNOHMJ.js";
|
|
19
|
+
import {
|
|
20
|
+
createLogger
|
|
21
|
+
} from "./chunk-RCMD3U65.js";
|
|
22
|
+
|
|
23
|
+
// src/ton/wallet-service.ts
|
|
24
|
+
import { mnemonicNew, mnemonicToPrivateKey, mnemonicValidate } from "@ton/crypto";
|
|
25
|
+
import { WalletContractV5R1, TonClient, fromNano } from "@ton/ton";
|
|
26
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
27
|
+
import { join, dirname } from "path";
|
|
28
|
+
var log = createLogger("TON");
|
|
29
|
+
var WALLET_FILE = join(TELETON_ROOT, "wallet.json");
|
|
30
|
+
var _walletCache;
|
|
31
|
+
var _keyPairCache = null;
|
|
32
|
+
async function generateWallet() {
|
|
33
|
+
const mnemonic = await mnemonicNew(24);
|
|
34
|
+
const keyPair = await mnemonicToPrivateKey(mnemonic);
|
|
35
|
+
const wallet = WalletContractV5R1.create({
|
|
36
|
+
workchain: 0,
|
|
37
|
+
publicKey: keyPair.publicKey
|
|
38
|
+
});
|
|
39
|
+
const address = wallet.address.toString({ bounceable: true, testOnly: false });
|
|
40
|
+
return {
|
|
41
|
+
version: "w5r1",
|
|
42
|
+
address,
|
|
43
|
+
publicKey: keyPair.publicKey.toString("hex"),
|
|
44
|
+
mnemonic,
|
|
45
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function saveWallet(wallet) {
|
|
49
|
+
const dir = dirname(WALLET_FILE);
|
|
50
|
+
if (!existsSync(dir)) {
|
|
51
|
+
mkdirSync(dir, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
writeFileSync(WALLET_FILE, JSON.stringify(wallet, null, 2), { encoding: "utf-8", mode: 384 });
|
|
54
|
+
_walletCache = void 0;
|
|
55
|
+
_keyPairCache = null;
|
|
56
|
+
}
|
|
57
|
+
function loadWallet() {
|
|
58
|
+
if (_walletCache !== void 0) return _walletCache;
|
|
59
|
+
if (!existsSync(WALLET_FILE)) {
|
|
60
|
+
_walletCache = null;
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const content = readFileSync(WALLET_FILE, "utf-8");
|
|
65
|
+
const parsed = JSON.parse(content);
|
|
66
|
+
if (!parsed.mnemonic || !Array.isArray(parsed.mnemonic) || parsed.mnemonic.length !== 24) {
|
|
67
|
+
throw new Error("Invalid wallet.json: mnemonic must be a 24-word array");
|
|
68
|
+
}
|
|
69
|
+
_walletCache = parsed;
|
|
70
|
+
return _walletCache;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
log.error({ err: error }, "Failed to load wallet");
|
|
73
|
+
_walletCache = null;
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function walletExists() {
|
|
78
|
+
return existsSync(WALLET_FILE);
|
|
79
|
+
}
|
|
80
|
+
async function importWallet(mnemonic) {
|
|
81
|
+
const valid = await mnemonicValidate(mnemonic);
|
|
82
|
+
if (!valid) {
|
|
83
|
+
throw new Error("Invalid mnemonic: words do not form a valid TON seed phrase");
|
|
84
|
+
}
|
|
85
|
+
const keyPair = await mnemonicToPrivateKey(mnemonic);
|
|
86
|
+
const wallet = WalletContractV5R1.create({
|
|
87
|
+
workchain: 0,
|
|
88
|
+
publicKey: keyPair.publicKey
|
|
89
|
+
});
|
|
90
|
+
const address = wallet.address.toString({ bounceable: true, testOnly: false });
|
|
91
|
+
return {
|
|
92
|
+
version: "w5r1",
|
|
93
|
+
address,
|
|
94
|
+
publicKey: keyPair.publicKey.toString("hex"),
|
|
95
|
+
mnemonic,
|
|
96
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function getWalletAddress() {
|
|
100
|
+
const wallet = loadWallet();
|
|
101
|
+
return wallet?.address || null;
|
|
102
|
+
}
|
|
103
|
+
async function getKeyPair() {
|
|
104
|
+
if (_keyPairCache) return _keyPairCache;
|
|
105
|
+
const wallet = loadWallet();
|
|
106
|
+
if (!wallet) return null;
|
|
107
|
+
_keyPairCache = await mnemonicToPrivateKey(wallet.mnemonic);
|
|
108
|
+
return _keyPairCache;
|
|
109
|
+
}
|
|
110
|
+
async function getWalletBalance(address) {
|
|
111
|
+
try {
|
|
112
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
113
|
+
const client = new TonClient({ endpoint });
|
|
114
|
+
const { Address } = await import("@ton/core");
|
|
115
|
+
const addressObj = Address.parse(address);
|
|
116
|
+
const balance = await client.getBalance(addressObj);
|
|
117
|
+
const balanceFormatted = fromNano(balance);
|
|
118
|
+
return {
|
|
119
|
+
balance: balanceFormatted,
|
|
120
|
+
balanceNano: balance.toString()
|
|
121
|
+
};
|
|
122
|
+
} catch (error) {
|
|
123
|
+
log.error({ err: error }, "Failed to get balance");
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
var TON_PRICE_CACHE_TTL_MS = 3e4;
|
|
128
|
+
var _tonPriceCache = null;
|
|
129
|
+
async function getTonPrice() {
|
|
130
|
+
if (_tonPriceCache && Date.now() - _tonPriceCache.timestamp < TON_PRICE_CACHE_TTL_MS) {
|
|
131
|
+
return { ..._tonPriceCache };
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
const response = await tonapiFetch(`/rates?tokens=ton¤cies=usd`);
|
|
135
|
+
if (response.ok) {
|
|
136
|
+
const data = await response.json();
|
|
137
|
+
const price = data?.rates?.TON?.prices?.USD;
|
|
138
|
+
if (typeof price === "number" && price > 0) {
|
|
139
|
+
_tonPriceCache = { usd: price, source: "TonAPI", timestamp: Date.now() };
|
|
140
|
+
return _tonPriceCache;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
} catch {
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const response = await fetchWithTimeout(
|
|
147
|
+
`${COINGECKO_API_URL}/simple/price?ids=the-open-network&vs_currencies=usd`
|
|
148
|
+
);
|
|
149
|
+
if (!response.ok) {
|
|
150
|
+
throw new Error(`CoinGecko API error: ${response.status}`);
|
|
151
|
+
}
|
|
152
|
+
const data = await response.json();
|
|
153
|
+
const price = data["the-open-network"]?.usd;
|
|
154
|
+
if (typeof price === "number" && price > 0) {
|
|
155
|
+
_tonPriceCache = { usd: price, source: "CoinGecko", timestamp: Date.now() };
|
|
156
|
+
return _tonPriceCache;
|
|
157
|
+
}
|
|
158
|
+
} catch (error) {
|
|
159
|
+
log.error({ err: error }, "Failed to get TON price");
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/config/schema.ts
|
|
165
|
+
import { z } from "zod";
|
|
166
|
+
var DMPolicy = z.enum(["pairing", "allowlist", "open", "disabled"]);
|
|
167
|
+
var GroupPolicy = z.enum(["open", "allowlist", "disabled"]);
|
|
168
|
+
var SessionResetPolicySchema = z.object({
|
|
169
|
+
daily_reset_enabled: z.boolean().default(true).describe("Enable daily session reset"),
|
|
170
|
+
daily_reset_hour: z.number().min(0).max(23).default(4).describe("Hour of day (0-23) to reset sessions"),
|
|
171
|
+
idle_expiry_enabled: z.boolean().default(true).describe("Enable session reset after idle period"),
|
|
172
|
+
idle_expiry_minutes: z.number().default(1440).describe("Minutes of inactivity before session reset (default: 24h)")
|
|
173
|
+
});
|
|
174
|
+
var AgentConfigSchema = z.object({
|
|
175
|
+
provider: z.enum([
|
|
176
|
+
"anthropic",
|
|
177
|
+
"openai",
|
|
178
|
+
"google",
|
|
179
|
+
"xai",
|
|
180
|
+
"groq",
|
|
181
|
+
"openrouter",
|
|
182
|
+
"moonshot",
|
|
183
|
+
"mistral",
|
|
184
|
+
"cocoon",
|
|
185
|
+
"local"
|
|
186
|
+
]).default("anthropic"),
|
|
187
|
+
api_key: z.string().default(""),
|
|
188
|
+
base_url: z.string().url().optional().describe("Base URL for local LLM server (e.g. http://localhost:11434/v1)"),
|
|
189
|
+
model: z.string().default("claude-opus-4-5-20251101"),
|
|
190
|
+
utility_model: z.string().optional().describe("Cheap model for summarization (auto-detected if omitted)"),
|
|
191
|
+
max_tokens: z.number().default(4096),
|
|
192
|
+
temperature: z.number().default(0.7),
|
|
193
|
+
system_prompt: z.string().nullable().default(null),
|
|
194
|
+
max_agentic_iterations: z.number().default(5).describe("Maximum number of agentic loop iterations (tool call \u2192 result \u2192 tool call cycles)"),
|
|
195
|
+
session_reset_policy: SessionResetPolicySchema.default(SessionResetPolicySchema.parse({}))
|
|
196
|
+
});
|
|
197
|
+
var TelegramConfigSchema = z.object({
|
|
198
|
+
api_id: z.number(),
|
|
199
|
+
api_hash: z.string(),
|
|
200
|
+
phone: z.string(),
|
|
201
|
+
session_name: z.string().default("teleton_session"),
|
|
202
|
+
session_path: z.string().default("~/.teleton"),
|
|
203
|
+
dm_policy: DMPolicy.default("pairing"),
|
|
204
|
+
allow_from: z.array(z.number()).default([]),
|
|
205
|
+
group_policy: GroupPolicy.default("open"),
|
|
206
|
+
group_allow_from: z.array(z.number()).default([]),
|
|
207
|
+
require_mention: z.boolean().default(true),
|
|
208
|
+
max_message_length: z.number().default(TELEGRAM_MAX_MESSAGE_LENGTH),
|
|
209
|
+
typing_simulation: z.boolean().default(true),
|
|
210
|
+
rate_limit_messages_per_second: z.number().default(1),
|
|
211
|
+
rate_limit_groups_per_minute: z.number().default(20),
|
|
212
|
+
admin_ids: z.array(z.number()).default([]),
|
|
213
|
+
agent_channel: z.string().nullable().default(null),
|
|
214
|
+
owner_name: z.string().optional().describe("Owner's first name (e.g., 'Alex')"),
|
|
215
|
+
owner_username: z.string().optional().describe("Owner's Telegram username (without @)"),
|
|
216
|
+
owner_id: z.number().optional().describe("Owner's Telegram user ID"),
|
|
217
|
+
debounce_ms: z.number().default(1500).describe("Debounce delay in milliseconds for group messages (0 = disabled)"),
|
|
218
|
+
bot_token: z.string().optional().describe("Telegram Bot token from @BotFather for inline deal buttons"),
|
|
219
|
+
bot_username: z.string().optional().describe("Bot username without @ (e.g., 'teleton_deals_bot')")
|
|
220
|
+
});
|
|
221
|
+
var StorageConfigSchema = z.object({
|
|
222
|
+
sessions_file: z.string().default("~/.teleton/sessions.json"),
|
|
223
|
+
pairing_file: z.string().default("~/.teleton/pairing.json"),
|
|
224
|
+
memory_file: z.string().default("~/.teleton/memory.json"),
|
|
225
|
+
history_limit: z.number().default(100)
|
|
226
|
+
});
|
|
227
|
+
var MetaConfigSchema = z.object({
|
|
228
|
+
version: z.string().default("1.0.0"),
|
|
229
|
+
created_at: z.string().optional(),
|
|
230
|
+
last_modified_at: z.string().optional(),
|
|
231
|
+
onboard_command: z.string().default("teleton setup")
|
|
232
|
+
});
|
|
233
|
+
var _DealsObject = z.object({
|
|
234
|
+
enabled: z.boolean().default(true),
|
|
235
|
+
expiry_seconds: z.number().default(120),
|
|
236
|
+
buy_max_floor_percent: z.number().default(100),
|
|
237
|
+
sell_min_floor_percent: z.number().default(105),
|
|
238
|
+
poll_interval_ms: z.number().default(5e3),
|
|
239
|
+
max_verification_retries: z.number().default(12),
|
|
240
|
+
expiry_check_interval_ms: z.number().default(6e4)
|
|
241
|
+
});
|
|
242
|
+
var DealsConfigSchema = _DealsObject.default(_DealsObject.parse({}));
|
|
243
|
+
var _WebUIObject = z.object({
|
|
244
|
+
enabled: z.boolean().default(false).describe("Enable WebUI server"),
|
|
245
|
+
port: z.number().default(7777).describe("HTTP server port"),
|
|
246
|
+
host: z.string().default("127.0.0.1").describe("Bind address (localhost only for security)"),
|
|
247
|
+
auth_token: z.string().optional().describe("Bearer token for API auth (auto-generated if omitted)"),
|
|
248
|
+
cors_origins: z.array(z.string()).default(["http://localhost:5173", "http://localhost:7777"]).describe("Allowed CORS origins for development"),
|
|
249
|
+
log_requests: z.boolean().default(false).describe("Log all HTTP requests")
|
|
250
|
+
});
|
|
251
|
+
var WebUIConfigSchema = _WebUIObject.default(_WebUIObject.parse({}));
|
|
252
|
+
var _EmbeddingObject = z.object({
|
|
253
|
+
provider: z.enum(["local", "anthropic", "none"]).default("local").describe("Embedding provider: local (ONNX), anthropic (API), or none (FTS5-only)"),
|
|
254
|
+
model: z.string().optional().describe("Model override (default: Xenova/all-MiniLM-L6-v2 for local)")
|
|
255
|
+
});
|
|
256
|
+
var EmbeddingConfigSchema = _EmbeddingObject.default(_EmbeddingObject.parse({}));
|
|
257
|
+
var _LoggingObject = z.object({
|
|
258
|
+
level: z.enum(["trace", "debug", "info", "warn", "error", "fatal"]).default("info").describe("Log level (trace/debug/info/warn/error/fatal)"),
|
|
259
|
+
pretty: z.boolean().default(true).describe("Enable pino-pretty formatting (human-readable, colored output)")
|
|
260
|
+
});
|
|
261
|
+
var LoggingConfigSchema = _LoggingObject.default(_LoggingObject.parse({}));
|
|
262
|
+
var _DevObject = z.object({
|
|
263
|
+
hot_reload: z.boolean().default(false).describe("Enable plugin hot-reload (watches ~/.teleton/plugins/ for changes)")
|
|
264
|
+
});
|
|
265
|
+
var DevConfigSchema = _DevObject.default(_DevObject.parse({}));
|
|
266
|
+
var McpServerSchema = z.object({
|
|
267
|
+
command: z.string().optional().describe("Stdio command (e.g. 'npx @modelcontextprotocol/server-filesystem /tmp')"),
|
|
268
|
+
args: z.array(z.string()).optional().describe("Explicit args array (overrides command splitting)"),
|
|
269
|
+
env: z.record(z.string(), z.string()).optional().describe("Environment variables for stdio server"),
|
|
270
|
+
url: z.string().url().optional().describe("SSE/HTTP endpoint URL (alternative to command)"),
|
|
271
|
+
scope: z.enum(["always", "dm-only", "group-only", "admin-only"]).default("always").describe("Tool scope"),
|
|
272
|
+
enabled: z.boolean().default(true).describe("Enable/disable this server")
|
|
273
|
+
}).refine((s) => s.command || s.url, {
|
|
274
|
+
message: "Each MCP server needs either 'command' (stdio) or 'url' (SSE/HTTP)"
|
|
275
|
+
});
|
|
276
|
+
var _McpObject = z.object({
|
|
277
|
+
servers: z.record(z.string(), McpServerSchema).default({})
|
|
278
|
+
});
|
|
279
|
+
var McpConfigSchema = _McpObject.default(_McpObject.parse({}));
|
|
280
|
+
var _ToolRagObject = z.object({
|
|
281
|
+
enabled: z.boolean().default(false).describe("Enable semantic tool retrieval (Tool RAG)"),
|
|
282
|
+
top_k: z.number().default(25).describe("Max tools to retrieve per LLM call"),
|
|
283
|
+
always_include: z.array(z.string()).default([
|
|
284
|
+
"telegram_send_message",
|
|
285
|
+
"telegram_reply_message",
|
|
286
|
+
"telegram_send_photo",
|
|
287
|
+
"telegram_send_document",
|
|
288
|
+
"journal_*",
|
|
289
|
+
"workspace_*",
|
|
290
|
+
"web_*"
|
|
291
|
+
]).describe("Tool name patterns always included (prefix glob with *)"),
|
|
292
|
+
skip_unlimited_providers: z.boolean().default(false).describe("Skip Tool RAG for providers with no tool limit (e.g. Anthropic)")
|
|
293
|
+
});
|
|
294
|
+
var ToolRagConfigSchema = _ToolRagObject.default(_ToolRagObject.parse({}));
|
|
295
|
+
var ConfigSchema = z.object({
|
|
296
|
+
meta: MetaConfigSchema.default(MetaConfigSchema.parse({})),
|
|
297
|
+
agent: AgentConfigSchema,
|
|
298
|
+
telegram: TelegramConfigSchema,
|
|
299
|
+
storage: StorageConfigSchema.default(StorageConfigSchema.parse({})),
|
|
300
|
+
embedding: EmbeddingConfigSchema,
|
|
301
|
+
deals: DealsConfigSchema,
|
|
302
|
+
webui: WebUIConfigSchema,
|
|
303
|
+
logging: LoggingConfigSchema,
|
|
304
|
+
dev: DevConfigSchema,
|
|
305
|
+
tool_rag: ToolRagConfigSchema,
|
|
306
|
+
mcp: McpConfigSchema,
|
|
307
|
+
plugins: z.record(z.string(), z.unknown()).default({}).describe("Per-plugin config (key = plugin name with underscores)"),
|
|
308
|
+
cocoon: z.object({
|
|
309
|
+
port: z.number().min(1).max(65535).default(1e4).describe("HTTP port of the cocoon-cli proxy")
|
|
310
|
+
}).optional().describe("Cocoon Network \u2014 expects external cocoon-cli running on this port"),
|
|
311
|
+
tonapi_key: z.string().optional().describe("TonAPI key for higher rate limits (from @tonapi_bot)"),
|
|
312
|
+
tavily_api_key: z.string().optional().describe("Tavily API key for web search & extract (free at https://tavily.com)")
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// src/workspace/manager.ts
|
|
316
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, copyFileSync } from "fs";
|
|
317
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
318
|
+
import { fileURLToPath } from "url";
|
|
319
|
+
var log2 = createLogger("Workspace");
|
|
320
|
+
function findPackageRoot() {
|
|
321
|
+
let dir = dirname2(fileURLToPath(import.meta.url));
|
|
322
|
+
for (let i = 0; i < 10; i++) {
|
|
323
|
+
if (existsSync2(join2(dir, "package.json"))) return dir;
|
|
324
|
+
dir = dirname2(dir);
|
|
325
|
+
}
|
|
326
|
+
return process.cwd();
|
|
327
|
+
}
|
|
328
|
+
var TEMPLATES_DIR = join2(findPackageRoot(), "src", "templates");
|
|
329
|
+
async function ensureWorkspace(config) {
|
|
330
|
+
if (!existsSync2(TELETON_ROOT)) {
|
|
331
|
+
mkdirSync2(TELETON_ROOT, { recursive: true });
|
|
332
|
+
log2.info(`Created Teleton root at ${TELETON_ROOT}`);
|
|
333
|
+
}
|
|
334
|
+
if (!existsSync2(WORKSPACE_ROOT)) {
|
|
335
|
+
mkdirSync2(WORKSPACE_ROOT, { recursive: true });
|
|
336
|
+
log2.info(`Created workspace at ${WORKSPACE_ROOT}`);
|
|
337
|
+
}
|
|
338
|
+
const directories = [
|
|
339
|
+
WORKSPACE_PATHS.MEMORY_DIR,
|
|
340
|
+
WORKSPACE_PATHS.DOWNLOADS_DIR,
|
|
341
|
+
WORKSPACE_PATHS.UPLOADS_DIR,
|
|
342
|
+
WORKSPACE_PATHS.TEMP_DIR,
|
|
343
|
+
WORKSPACE_PATHS.MEMES_DIR
|
|
344
|
+
];
|
|
345
|
+
for (const dir of directories) {
|
|
346
|
+
if (!existsSync2(dir)) {
|
|
347
|
+
mkdirSync2(dir, { recursive: true });
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
const workspace = {
|
|
351
|
+
root: TELETON_ROOT,
|
|
352
|
+
workspace: WORKSPACE_ROOT,
|
|
353
|
+
// Workspace files
|
|
354
|
+
soulPath: WORKSPACE_PATHS.SOUL,
|
|
355
|
+
memoryPath: WORKSPACE_PATHS.MEMORY,
|
|
356
|
+
identityPath: WORKSPACE_PATHS.IDENTITY,
|
|
357
|
+
userPath: WORKSPACE_PATHS.USER,
|
|
358
|
+
strategyPath: WORKSPACE_PATHS.STRATEGY,
|
|
359
|
+
securityPath: WORKSPACE_PATHS.SECURITY,
|
|
360
|
+
// Workspace directories
|
|
361
|
+
memoryDir: WORKSPACE_PATHS.MEMORY_DIR,
|
|
362
|
+
downloadsDir: WORKSPACE_PATHS.DOWNLOADS_DIR,
|
|
363
|
+
uploadsDir: WORKSPACE_PATHS.UPLOADS_DIR,
|
|
364
|
+
tempDir: WORKSPACE_PATHS.TEMP_DIR,
|
|
365
|
+
memesDir: WORKSPACE_PATHS.MEMES_DIR,
|
|
366
|
+
// Protected files (outside workspace)
|
|
367
|
+
sessionPath: join2(TELETON_ROOT, "telegram_session.txt"),
|
|
368
|
+
configPath: join2(TELETON_ROOT, "config.yaml"),
|
|
369
|
+
walletPath: join2(TELETON_ROOT, "wallet.json")
|
|
370
|
+
};
|
|
371
|
+
if (config?.ensureTemplates) {
|
|
372
|
+
await bootstrapTemplates(workspace);
|
|
373
|
+
}
|
|
374
|
+
return workspace;
|
|
375
|
+
}
|
|
376
|
+
async function bootstrapTemplates(workspace) {
|
|
377
|
+
const templates = [
|
|
378
|
+
{ name: "SOUL.md", path: workspace.soulPath },
|
|
379
|
+
{ name: "MEMORY.md", path: workspace.memoryPath },
|
|
380
|
+
{ name: "IDENTITY.md", path: workspace.identityPath },
|
|
381
|
+
{ name: "USER.md", path: workspace.userPath },
|
|
382
|
+
{ name: "SECURITY.md", path: workspace.securityPath },
|
|
383
|
+
{ name: "STRATEGY.md", path: workspace.strategyPath }
|
|
384
|
+
];
|
|
385
|
+
for (const template of templates) {
|
|
386
|
+
if (!existsSync2(template.path)) {
|
|
387
|
+
const templateSource = join2(TEMPLATES_DIR, template.name);
|
|
388
|
+
if (existsSync2(templateSource)) {
|
|
389
|
+
copyFileSync(templateSource, template.path);
|
|
390
|
+
log2.info(`Created ${template.name}`);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
function isNewWorkspace(workspace) {
|
|
396
|
+
return !existsSync2(workspace.configPath);
|
|
397
|
+
}
|
|
398
|
+
function loadTemplate(name) {
|
|
399
|
+
const templatePath = join2(TEMPLATES_DIR, name);
|
|
400
|
+
if (!existsSync2(templatePath)) {
|
|
401
|
+
throw new Error(`Template ${name} not found at ${templatePath}`);
|
|
402
|
+
}
|
|
403
|
+
return readFileSync2(templatePath, "utf-8");
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export {
|
|
407
|
+
DealsConfigSchema,
|
|
408
|
+
ConfigSchema,
|
|
409
|
+
ensureWorkspace,
|
|
410
|
+
isNewWorkspace,
|
|
411
|
+
loadTemplate,
|
|
412
|
+
generateWallet,
|
|
413
|
+
saveWallet,
|
|
414
|
+
loadWallet,
|
|
415
|
+
walletExists,
|
|
416
|
+
importWallet,
|
|
417
|
+
getWalletAddress,
|
|
418
|
+
getKeyPair,
|
|
419
|
+
getWalletBalance,
|
|
420
|
+
getTonPrice
|
|
421
|
+
};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TELETON_ROOT
|
|
3
3
|
} from "./chunk-EYWNOHMJ.js";
|
|
4
|
+
import {
|
|
5
|
+
createLogger
|
|
6
|
+
} from "./chunk-RCMD3U65.js";
|
|
4
7
|
|
|
5
8
|
// src/session/transcript.ts
|
|
6
9
|
import {
|
|
@@ -14,6 +17,7 @@ import {
|
|
|
14
17
|
statSync
|
|
15
18
|
} from "fs";
|
|
16
19
|
import { join } from "path";
|
|
20
|
+
var log = createLogger("Session");
|
|
17
21
|
var SESSIONS_DIR = join(TELETON_ROOT, "sessions");
|
|
18
22
|
function getTranscriptPath(sessionId) {
|
|
19
23
|
return join(SESSIONS_DIR, `${sessionId}.jsonl`);
|
|
@@ -30,17 +34,15 @@ function appendToTranscript(sessionId, message) {
|
|
|
30
34
|
try {
|
|
31
35
|
appendFileSync(transcriptPath, line, "utf-8");
|
|
32
36
|
} catch (error) {
|
|
33
|
-
|
|
37
|
+
log.error({ err: error }, `Failed to append to transcript ${sessionId}`);
|
|
34
38
|
}
|
|
35
39
|
}
|
|
36
40
|
function extractToolCallIds(msg) {
|
|
37
41
|
const ids = /* @__PURE__ */ new Set();
|
|
38
42
|
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
39
43
|
for (const block of msg.content) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const id = block.id || block.toolCallId || block.tool_use_id;
|
|
43
|
-
if (id) ids.add(id);
|
|
44
|
+
if (block.type === "toolCall") {
|
|
45
|
+
if (block.id) ids.add(block.id);
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
}
|
|
@@ -55,17 +57,15 @@ function sanitizeMessages(messages) {
|
|
|
55
57
|
if (msg.role === "assistant") {
|
|
56
58
|
const newToolIds = extractToolCallIds(msg);
|
|
57
59
|
if (pendingToolCallIds.size > 0 && newToolIds.size > 0) {
|
|
58
|
-
|
|
59
|
-
`\u26A0\uFE0F Found ${pendingToolCallIds.size} pending tool results that were never received`
|
|
60
|
-
);
|
|
60
|
+
log.warn(`Found ${pendingToolCallIds.size} pending tool results that were never received`);
|
|
61
61
|
}
|
|
62
62
|
pendingToolCallIds = newToolIds;
|
|
63
63
|
sanitized.push(msg);
|
|
64
|
-
} else if (msg.role === "toolResult"
|
|
65
|
-
const toolCallId = msg.toolCallId
|
|
64
|
+
} else if (msg.role === "toolResult") {
|
|
65
|
+
const toolCallId = msg.toolCallId;
|
|
66
66
|
if (!toolCallId || typeof toolCallId !== "string") {
|
|
67
67
|
removedCount++;
|
|
68
|
-
|
|
68
|
+
log.warn(`Removing toolResult with missing/invalid toolCallId`);
|
|
69
69
|
continue;
|
|
70
70
|
}
|
|
71
71
|
if (pendingToolCallIds.has(toolCallId)) {
|
|
@@ -73,13 +73,13 @@ function sanitizeMessages(messages) {
|
|
|
73
73
|
sanitized.push(msg);
|
|
74
74
|
} else {
|
|
75
75
|
removedCount++;
|
|
76
|
-
|
|
76
|
+
log.warn(`Removing orphaned toolResult: ${toolCallId.slice(0, 20)}...`);
|
|
77
77
|
continue;
|
|
78
78
|
}
|
|
79
79
|
} else if (msg.role === "user") {
|
|
80
80
|
if (pendingToolCallIds.size > 0) {
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
log.warn(
|
|
82
|
+
`User message arrived while ${pendingToolCallIds.size} tool results pending - marking them as orphaned`
|
|
83
83
|
);
|
|
84
84
|
pendingToolCallIds.clear();
|
|
85
85
|
}
|
|
@@ -89,7 +89,7 @@ function sanitizeMessages(messages) {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
if (removedCount > 0) {
|
|
92
|
-
|
|
92
|
+
log.info(`Sanitized ${removedCount} orphaned/out-of-order toolResult(s) from transcript`);
|
|
93
93
|
}
|
|
94
94
|
return sanitized;
|
|
95
95
|
}
|
|
@@ -107,16 +107,16 @@ function readTranscript(sessionId) {
|
|
|
107
107
|
return JSON.parse(line);
|
|
108
108
|
} catch {
|
|
109
109
|
corruptCount++;
|
|
110
|
-
|
|
110
|
+
log.warn(`Skipping corrupt line ${i + 1} in transcript ${sessionId}`);
|
|
111
111
|
return null;
|
|
112
112
|
}
|
|
113
113
|
}).filter(Boolean);
|
|
114
114
|
if (corruptCount > 0) {
|
|
115
|
-
|
|
115
|
+
log.warn(`${corruptCount} corrupt line(s) skipped in transcript ${sessionId}`);
|
|
116
116
|
}
|
|
117
117
|
return sanitizeMessages(messages);
|
|
118
118
|
} catch (error) {
|
|
119
|
-
|
|
119
|
+
log.error({ err: error }, `Failed to read transcript ${sessionId}`);
|
|
120
120
|
return [];
|
|
121
121
|
}
|
|
122
122
|
}
|
|
@@ -138,10 +138,10 @@ function deleteTranscript(sessionId) {
|
|
|
138
138
|
}
|
|
139
139
|
try {
|
|
140
140
|
unlinkSync(transcriptPath);
|
|
141
|
-
|
|
141
|
+
log.info(`Deleted transcript: ${sessionId}`);
|
|
142
142
|
return true;
|
|
143
143
|
} catch (error) {
|
|
144
|
-
|
|
144
|
+
log.error({ err: error }, `Failed to delete transcript ${sessionId}`);
|
|
145
145
|
return false;
|
|
146
146
|
}
|
|
147
147
|
}
|
|
@@ -154,10 +154,10 @@ function archiveTranscript(sessionId) {
|
|
|
154
154
|
}
|
|
155
155
|
try {
|
|
156
156
|
renameSync(transcriptPath, archivePath);
|
|
157
|
-
|
|
157
|
+
log.info(`Archived transcript: ${sessionId} \u2192 ${timestamp}.archived`);
|
|
158
158
|
return true;
|
|
159
159
|
} catch (error) {
|
|
160
|
-
|
|
160
|
+
log.error({ err: error }, `Failed to archive transcript ${sessionId}`);
|
|
161
161
|
return false;
|
|
162
162
|
}
|
|
163
163
|
}
|
|
@@ -179,10 +179,10 @@ function cleanupOldTranscripts(maxAgeDays = 30) {
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
} catch (error) {
|
|
182
|
-
|
|
182
|
+
log.error({ err: error }, "Failed to cleanup old transcripts");
|
|
183
183
|
}
|
|
184
184
|
if (deleted > 0) {
|
|
185
|
-
|
|
185
|
+
log.info(`Cleaned up ${deleted} transcript(s) older than ${maxAgeDays} days`);
|
|
186
186
|
}
|
|
187
187
|
return deleted;
|
|
188
188
|
}
|