teleton 0.1.0 → 0.1.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 +7 -7
- package/dist/chunk-5BEHAIBQ.js +38 -0
- package/dist/chunk-EBFMA7CL.js +40 -0
- package/dist/chunk-I6ZVPVLK.js +20 -0
- package/dist/{chunk-WDUHRPGA.js → chunk-MPU2XS5H.js} +121 -6
- package/dist/{chunk-WXVHT6CI.js → chunk-UQUYPDZJ.js} +944 -652
- package/dist/cli/index.js +334 -86
- package/dist/index.js +5 -2
- package/dist/{memory-O5NYYWF3.js → memory-WSP5MEER.js} +4 -1
- package/dist/{migrate-25RH22HJ.js → migrate-JPXMIIPI.js} +4 -1
- package/dist/{scraper-DW5Z2AP5.js → scraper-PGYSNQRD.js} +36 -17
- package/dist/{task-dependency-resolver-5I62EU67.js → task-dependency-resolver-KRQRZKAD.js} +7 -2
- package/dist/{task-executor-ZMXWLMI7.js → task-executor-L6DTJANH.js} +14 -6
- package/package.json +17 -7
- package/src/templates/SECURITY.md +31 -0
package/dist/cli/index.js
CHANGED
|
@@ -3,23 +3,36 @@ import {
|
|
|
3
3
|
ConfigSchema,
|
|
4
4
|
DealsConfigSchema,
|
|
5
5
|
MarketConfigSchema,
|
|
6
|
+
TelegramUserClient,
|
|
6
7
|
configExists,
|
|
7
8
|
ensureWorkspace,
|
|
8
9
|
generateWallet,
|
|
9
10
|
getDefaultConfigPath,
|
|
10
11
|
getProviderMetadata,
|
|
11
12
|
getSupportedProviders,
|
|
13
|
+
importWallet,
|
|
12
14
|
isNewWorkspace,
|
|
15
|
+
loadWallet,
|
|
13
16
|
main,
|
|
14
17
|
saveWallet,
|
|
15
|
-
validateApiKeyFormat
|
|
16
|
-
|
|
18
|
+
validateApiKeyFormat,
|
|
19
|
+
walletExists
|
|
20
|
+
} from "../chunk-UQUYPDZJ.js";
|
|
17
21
|
import "../chunk-XBGUNXF2.js";
|
|
18
|
-
import
|
|
22
|
+
import {
|
|
23
|
+
fetchWithTimeout
|
|
24
|
+
} from "../chunk-MPU2XS5H.js";
|
|
19
25
|
import "../chunk-UR2LQEKR.js";
|
|
20
26
|
import {
|
|
21
27
|
TELETON_ROOT
|
|
22
28
|
} from "../chunk-7NJ46ZIX.js";
|
|
29
|
+
import "../chunk-I6ZVPVLK.js";
|
|
30
|
+
import {
|
|
31
|
+
TELEGRAM_MAX_MESSAGE_LENGTH
|
|
32
|
+
} from "../chunk-5BEHAIBQ.js";
|
|
33
|
+
import {
|
|
34
|
+
ONBOARDING_PROMPT_TIMEOUT_MS
|
|
35
|
+
} from "../chunk-EBFMA7CL.js";
|
|
23
36
|
|
|
24
37
|
// src/cli/index.ts
|
|
25
38
|
import { Command } from "commander";
|
|
@@ -179,8 +192,9 @@ function createPrompter() {
|
|
|
179
192
|
}
|
|
180
193
|
|
|
181
194
|
// src/cli/commands/onboard.ts
|
|
182
|
-
import { writeFileSync } from "fs";
|
|
195
|
+
import { writeFileSync, readFileSync, existsSync, chmodSync } from "fs";
|
|
183
196
|
import { execSync } from "child_process";
|
|
197
|
+
import { join } from "path";
|
|
184
198
|
import YAML from "yaml";
|
|
185
199
|
async function onboardCommand(options = {}) {
|
|
186
200
|
const prompter = createPrompter();
|
|
@@ -245,6 +259,18 @@ ${blue2} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25
|
|
|
245
259
|
return;
|
|
246
260
|
}
|
|
247
261
|
}
|
|
262
|
+
const agentName = await prompter.text({
|
|
263
|
+
message: "Give your agent a name (optional)",
|
|
264
|
+
placeholder: "e.g. Nova, Kai, Echo..."
|
|
265
|
+
});
|
|
266
|
+
if (agentName && agentName.trim() && existsSync(workspace.identityPath)) {
|
|
267
|
+
const identity = readFileSync(workspace.identityPath, "utf-8");
|
|
268
|
+
const updated = identity.replace(
|
|
269
|
+
"[Ton nom - choisis-en un ou demande \xE0 ton humain]",
|
|
270
|
+
agentName.trim()
|
|
271
|
+
);
|
|
272
|
+
writeFileSync(workspace.identityPath, updated, "utf-8");
|
|
273
|
+
}
|
|
248
274
|
const flow = await prompter.select({
|
|
249
275
|
message: "Installation mode",
|
|
250
276
|
options: [
|
|
@@ -253,6 +279,22 @@ ${blue2} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25
|
|
|
253
279
|
],
|
|
254
280
|
initialValue: "quick"
|
|
255
281
|
});
|
|
282
|
+
const enabledModules = await prompter.multiselect({
|
|
283
|
+
message: "Enable optional modules",
|
|
284
|
+
options: [
|
|
285
|
+
{ value: "casino", label: "Casino", hint: "Slot machine & dice games with TON bets" },
|
|
286
|
+
{ value: "deals", label: "Deals", hint: "Secure gift/TON trading with inline buttons" },
|
|
287
|
+
{
|
|
288
|
+
value: "market",
|
|
289
|
+
label: "Gifts Market Data",
|
|
290
|
+
hint: "Scrape gift floor prices (requires Chromium)"
|
|
291
|
+
}
|
|
292
|
+
],
|
|
293
|
+
required: false
|
|
294
|
+
});
|
|
295
|
+
const casinoEnabled = enabledModules.includes("casino");
|
|
296
|
+
const dealsEnabled = enabledModules.includes("deals");
|
|
297
|
+
const marketEnabled = enabledModules.includes("market");
|
|
256
298
|
const providers = getSupportedProviders();
|
|
257
299
|
const selectedProvider = await prompter.select({
|
|
258
300
|
message: "AI Provider",
|
|
@@ -276,22 +318,29 @@ some may be truncated.`,
|
|
|
276
318
|
"You need Telegram credentials from https://my.telegram.org/apps\nCreate an application and note the API ID and API Hash",
|
|
277
319
|
"Telegram"
|
|
278
320
|
);
|
|
321
|
+
const envApiId = process.env.TELETON_TG_API_ID;
|
|
322
|
+
const envApiHash = process.env.TELETON_TG_API_HASH;
|
|
323
|
+
const envPhone = process.env.TELETON_TG_PHONE;
|
|
324
|
+
const envApiKey = process.env.TELETON_API_KEY;
|
|
279
325
|
const apiIdStr = options.apiId ? options.apiId.toString() : await prompter.text({
|
|
280
|
-
message: "API ID (from my.telegram.org)",
|
|
326
|
+
message: envApiId ? "API ID (from env)" : "API ID (from my.telegram.org)",
|
|
327
|
+
initialValue: envApiId,
|
|
281
328
|
validate: (value) => {
|
|
282
329
|
if (!value || isNaN(parseInt(value))) return "Invalid API ID (must be a number)";
|
|
283
330
|
}
|
|
284
331
|
});
|
|
285
332
|
const apiId = parseInt(apiIdStr);
|
|
286
333
|
const apiHash = options.apiHash ? options.apiHash : await prompter.text({
|
|
287
|
-
message: "API Hash (from my.telegram.org)",
|
|
334
|
+
message: envApiHash ? "API Hash (from env)" : "API Hash (from my.telegram.org)",
|
|
335
|
+
initialValue: envApiHash,
|
|
288
336
|
validate: (value) => {
|
|
289
337
|
if (!value || value.length < 10) return "Invalid API Hash";
|
|
290
338
|
}
|
|
291
339
|
});
|
|
292
340
|
const phone = options.phone ? options.phone : await prompter.text({
|
|
293
|
-
message: "Phone number (international format, e.g. +1234567890)",
|
|
341
|
+
message: envPhone ? "Phone number (from env)" : "Phone number (international format, e.g. +1234567890)",
|
|
294
342
|
placeholder: "+1234567890",
|
|
343
|
+
initialValue: envPhone,
|
|
295
344
|
validate: (value) => {
|
|
296
345
|
if (!value || !value.startsWith("+")) return "Invalid format (must start with +)";
|
|
297
346
|
}
|
|
@@ -312,19 +361,100 @@ some may be truncated.`,
|
|
|
312
361
|
Get it at: ${providerMeta.consoleUrl}`,
|
|
313
362
|
"API Key"
|
|
314
363
|
);
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
})
|
|
364
|
+
let apiKey;
|
|
365
|
+
if (options.apiKey) {
|
|
366
|
+
apiKey = options.apiKey;
|
|
367
|
+
} else if (envApiKey) {
|
|
368
|
+
const validationError = validateApiKeyFormat(selectedProvider, envApiKey);
|
|
369
|
+
if (validationError) {
|
|
370
|
+
prompter.warn(`TELETON_API_KEY env var found but invalid: ${validationError}`);
|
|
371
|
+
apiKey = await prompter.password({
|
|
372
|
+
message: `${providerMeta.displayName} API Key (${providerMeta.keyHint})`,
|
|
373
|
+
validate: (value) => validateApiKeyFormat(selectedProvider, value)
|
|
374
|
+
});
|
|
375
|
+
} else {
|
|
376
|
+
prompter.log(`Using API key from TELETON_API_KEY env var`);
|
|
377
|
+
apiKey = envApiKey;
|
|
378
|
+
}
|
|
379
|
+
} else {
|
|
380
|
+
apiKey = await prompter.password({
|
|
381
|
+
message: `${providerMeta.displayName} API Key (${providerMeta.keyHint})`,
|
|
382
|
+
validate: (value) => validateApiKeyFormat(selectedProvider, value)
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
const MODEL_OPTIONS = {
|
|
386
|
+
anthropic: [
|
|
387
|
+
{ value: "claude-opus-4-5-20251101", label: "Claude Opus 4.5", hint: "Most capable, $5/M" },
|
|
388
|
+
{ value: "claude-sonnet-4-0", label: "Claude Sonnet 4", hint: "Balanced, $3/M" },
|
|
389
|
+
{ value: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5", hint: "Fast & cheap, $1/M" },
|
|
390
|
+
{ value: "claude-3-5-haiku-20241022", label: "Claude 3.5 Haiku", hint: "Cheapest, $0.80/M" }
|
|
391
|
+
],
|
|
392
|
+
openai: [
|
|
393
|
+
{ value: "gpt-5", label: "GPT-5", hint: "Most capable, 400K ctx, $1.25/M" },
|
|
394
|
+
{ value: "gpt-4o", label: "GPT-4o", hint: "Balanced, 128K ctx, $2.50/M" },
|
|
395
|
+
{ value: "gpt-4.1", label: "GPT-4.1", hint: "1M ctx, $2/M" },
|
|
396
|
+
{ value: "gpt-4.1-mini", label: "GPT-4.1 Mini", hint: "1M ctx, cheap, $0.40/M" },
|
|
397
|
+
{ value: "o3", label: "o3", hint: "Reasoning, 200K ctx, $2/M" }
|
|
398
|
+
],
|
|
399
|
+
google: [
|
|
400
|
+
{ value: "gemini-2.5-flash", label: "Gemini 2.5 Flash", hint: "Fast, 1M ctx, $0.30/M" },
|
|
401
|
+
{ value: "gemini-2.5-pro", label: "Gemini 2.5 Pro", hint: "Most capable, 1M ctx, $1.25/M" },
|
|
402
|
+
{ value: "gemini-2.0-flash", label: "Gemini 2.0 Flash", hint: "Cheap, 1M ctx, $0.10/M" }
|
|
403
|
+
],
|
|
404
|
+
xai: [
|
|
405
|
+
{ value: "grok-4-fast", label: "Grok 4 Fast", hint: "Vision, 2M ctx, $0.20/M" },
|
|
406
|
+
{ value: "grok-4", label: "Grok 4", hint: "Reasoning, 256K ctx, $3/M" },
|
|
407
|
+
{ value: "grok-3", label: "Grok 3", hint: "Stable, 131K ctx, $3/M" }
|
|
408
|
+
],
|
|
409
|
+
groq: [
|
|
410
|
+
{
|
|
411
|
+
value: "meta-llama/llama-4-maverick-17b-128e-instruct",
|
|
412
|
+
label: "Llama 4 Maverick",
|
|
413
|
+
hint: "Vision, 131K ctx, $0.20/M"
|
|
414
|
+
},
|
|
415
|
+
{ value: "qwen/qwen3-32b", label: "Qwen3 32B", hint: "Reasoning, 131K ctx, $0.29/M" },
|
|
416
|
+
{
|
|
417
|
+
value: "deepseek-r1-distill-llama-70b",
|
|
418
|
+
label: "DeepSeek R1 70B",
|
|
419
|
+
hint: "Reasoning, 131K ctx, $0.75/M"
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
value: "llama-3.3-70b-versatile",
|
|
423
|
+
label: "Llama 3.3 70B",
|
|
424
|
+
hint: "General purpose, 131K ctx, $0.59/M"
|
|
425
|
+
}
|
|
426
|
+
],
|
|
427
|
+
openrouter: [
|
|
428
|
+
{ value: "anthropic/claude-opus-4.5", label: "Claude Opus 4.5", hint: "200K ctx, $5/M" },
|
|
429
|
+
{ value: "openai/gpt-5", label: "GPT-5", hint: "400K ctx, $1.25/M" },
|
|
430
|
+
{ value: "google/gemini-2.5-flash", label: "Gemini 2.5 Flash", hint: "1M ctx, $0.30/M" },
|
|
431
|
+
{ value: "deepseek/deepseek-r1", label: "DeepSeek R1", hint: "Reasoning, 64K ctx, $0.70/M" },
|
|
432
|
+
{ value: "x-ai/grok-4", label: "Grok 4", hint: "256K ctx, $3/M" }
|
|
433
|
+
]
|
|
434
|
+
};
|
|
319
435
|
let selectedModel = providerMeta.defaultModel;
|
|
320
436
|
if (flow === "advanced") {
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
437
|
+
const providerModels = MODEL_OPTIONS[selectedProvider] || [];
|
|
438
|
+
const modelOptions = [
|
|
439
|
+
...providerModels,
|
|
440
|
+
{ value: "__custom__", label: "Custom", hint: "Enter a model ID manually" }
|
|
441
|
+
];
|
|
442
|
+
const modelChoice = await prompter.select({
|
|
443
|
+
message: "Model",
|
|
444
|
+
options: modelOptions,
|
|
324
445
|
initialValue: providerMeta.defaultModel
|
|
325
446
|
});
|
|
326
|
-
if (
|
|
327
|
-
|
|
447
|
+
if (modelChoice === "__custom__") {
|
|
448
|
+
const customModel = await prompter.text({
|
|
449
|
+
message: "Model ID",
|
|
450
|
+
placeholder: providerMeta.defaultModel,
|
|
451
|
+
initialValue: providerMeta.defaultModel
|
|
452
|
+
});
|
|
453
|
+
if (customModel && customModel.trim()) {
|
|
454
|
+
selectedModel = customModel.trim();
|
|
455
|
+
}
|
|
456
|
+
} else {
|
|
457
|
+
selectedModel = modelChoice;
|
|
328
458
|
}
|
|
329
459
|
}
|
|
330
460
|
let dmPolicy = "open";
|
|
@@ -354,6 +484,46 @@ Get it at: ${providerMeta.consoleUrl}`,
|
|
|
354
484
|
initialValue: true
|
|
355
485
|
});
|
|
356
486
|
}
|
|
487
|
+
let botToken;
|
|
488
|
+
let botUsername;
|
|
489
|
+
const setupBot = dealsEnabled ? await prompter.confirm({
|
|
490
|
+
message: "Set up a Telegram bot for deal confirmations? (inline buttons)",
|
|
491
|
+
initialValue: true
|
|
492
|
+
}) : false;
|
|
493
|
+
if (setupBot) {
|
|
494
|
+
prompter.note(
|
|
495
|
+
"Create a bot with @BotFather on Telegram:\n1. Send /newbot and follow the instructions\n2. Copy the bot token\n3. Enable inline mode: /setinline on the bot",
|
|
496
|
+
"Deals Bot"
|
|
497
|
+
);
|
|
498
|
+
const tokenInput = await prompter.password({
|
|
499
|
+
message: "Bot token (from @BotFather)",
|
|
500
|
+
validate: (value) => {
|
|
501
|
+
if (!value || !value.includes(":")) return "Invalid bot token format (expected id:hash)";
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
spinner2.start("Validating bot token...");
|
|
505
|
+
try {
|
|
506
|
+
const res = await fetchWithTimeout(`https://api.telegram.org/bot${tokenInput}/getMe`);
|
|
507
|
+
const data = await res.json();
|
|
508
|
+
if (!data.ok) {
|
|
509
|
+
spinner2.stop("\u26A0 Bot token is invalid - skipping bot setup");
|
|
510
|
+
} else {
|
|
511
|
+
botToken = tokenInput;
|
|
512
|
+
botUsername = data.result.username;
|
|
513
|
+
spinner2.stop(`\u2713 Bot verified: @${botUsername}`);
|
|
514
|
+
}
|
|
515
|
+
} catch {
|
|
516
|
+
spinner2.stop("\u26A0 Could not validate bot token (network error) - saving anyway");
|
|
517
|
+
botToken = tokenInput;
|
|
518
|
+
const usernameInput = await prompter.text({
|
|
519
|
+
message: "Bot username (without @)",
|
|
520
|
+
validate: (value) => {
|
|
521
|
+
if (!value || value.length < 3) return "Username too short";
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
botUsername = usernameInput;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
357
527
|
const config = {
|
|
358
528
|
meta: {
|
|
359
529
|
version: "1.0.0",
|
|
@@ -386,15 +556,16 @@ Get it at: ${providerMeta.consoleUrl}`,
|
|
|
386
556
|
group_policy: groupPolicy,
|
|
387
557
|
group_allow_from: [],
|
|
388
558
|
require_mention: requireMention,
|
|
389
|
-
max_message_length:
|
|
559
|
+
max_message_length: TELEGRAM_MAX_MESSAGE_LENGTH,
|
|
390
560
|
typing_simulation: true,
|
|
391
561
|
rate_limit_messages_per_second: 1,
|
|
392
562
|
rate_limit_groups_per_minute: 20,
|
|
393
563
|
admin_ids: [userId],
|
|
564
|
+
owner_id: userId,
|
|
394
565
|
agent_channel: null,
|
|
395
566
|
debounce_ms: 1500,
|
|
396
|
-
bot_token:
|
|
397
|
-
bot_username:
|
|
567
|
+
bot_token: botToken,
|
|
568
|
+
bot_username: botUsername
|
|
398
569
|
},
|
|
399
570
|
storage: {
|
|
400
571
|
sessions_file: `${workspace.root}/sessions.json`,
|
|
@@ -402,50 +573,125 @@ Get it at: ${providerMeta.consoleUrl}`,
|
|
|
402
573
|
memory_file: `${workspace.root}/memory.json`,
|
|
403
574
|
history_limit: 100
|
|
404
575
|
},
|
|
405
|
-
casino: CasinoConfigSchema.parse({}),
|
|
406
|
-
deals: DealsConfigSchema.parse({}),
|
|
407
|
-
market: MarketConfigSchema.parse({})
|
|
576
|
+
casino: CasinoConfigSchema.parse({ enabled: casinoEnabled }),
|
|
577
|
+
deals: DealsConfigSchema.parse({ enabled: dealsEnabled }),
|
|
578
|
+
market: MarketConfigSchema.parse({ enabled: marketEnabled })
|
|
408
579
|
};
|
|
409
580
|
spinner2.start("Saving configuration...");
|
|
410
581
|
const configYaml = YAML.stringify(config);
|
|
411
582
|
writeFileSync(workspace.configPath, configYaml, "utf-8");
|
|
583
|
+
chmodSync(workspace.configPath, 384);
|
|
412
584
|
spinner2.stop("\u2713 Configuration saved");
|
|
413
|
-
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
585
|
+
let wallet;
|
|
586
|
+
const existingWallet = walletExists() ? loadWallet() : null;
|
|
587
|
+
if (existingWallet) {
|
|
588
|
+
prompter.note(`Existing wallet found: ${existingWallet.address}`, "TON Wallet");
|
|
589
|
+
const walletAction = await prompter.select({
|
|
590
|
+
message: "A TON wallet already exists. What do you want to do?",
|
|
591
|
+
options: [
|
|
592
|
+
{ value: "keep", label: "Keep existing", hint: `${existingWallet.address}` },
|
|
593
|
+
{ value: "regenerate", label: "Generate new", hint: "WARNING: old wallet will be lost" },
|
|
594
|
+
{ value: "import", label: "Import mnemonic", hint: "Restore from 24-word seed" }
|
|
595
|
+
],
|
|
596
|
+
initialValue: "keep"
|
|
423
597
|
});
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
598
|
+
if (walletAction === "keep") {
|
|
599
|
+
wallet = existingWallet;
|
|
600
|
+
} else if (walletAction === "import") {
|
|
601
|
+
const mnemonicInput = await prompter.text({
|
|
602
|
+
message: "Enter your 24-word mnemonic (space-separated)",
|
|
603
|
+
validate: (value) => {
|
|
604
|
+
const words = value.trim().split(/\s+/);
|
|
605
|
+
if (words.length !== 24) return `Expected 24 words, got ${words.length}`;
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
spinner2.start("Importing wallet...");
|
|
609
|
+
wallet = await importWallet(mnemonicInput.trim().split(/\s+/));
|
|
610
|
+
saveWallet(wallet);
|
|
611
|
+
spinner2.stop(`\u2713 Wallet imported: ${wallet.address}`);
|
|
612
|
+
} else {
|
|
613
|
+
spinner2.start("Generating new TON wallet...");
|
|
614
|
+
wallet = await generateWallet();
|
|
615
|
+
saveWallet(wallet);
|
|
616
|
+
spinner2.stop("\u2713 New TON wallet generated");
|
|
617
|
+
}
|
|
618
|
+
} else {
|
|
619
|
+
spinner2.start("Generating TON wallet...");
|
|
620
|
+
wallet = await generateWallet();
|
|
621
|
+
saveWallet(wallet);
|
|
622
|
+
spinner2.stop("\u2713 TON wallet generated");
|
|
623
|
+
}
|
|
624
|
+
if (marketEnabled) {
|
|
625
|
+
spinner2.start("Installing browser for market data...");
|
|
626
|
+
try {
|
|
627
|
+
execSync("npx playwright install chromium", {
|
|
628
|
+
stdio: "pipe",
|
|
629
|
+
timeout: ONBOARDING_PROMPT_TIMEOUT_MS
|
|
630
|
+
});
|
|
631
|
+
spinner2.stop("\u2713 Browser installed");
|
|
632
|
+
} catch {
|
|
633
|
+
spinner2.stop(
|
|
634
|
+
"\u26A0 Browser install failed (can be done later with: npx playwright install chromium)"
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (!existingWallet || wallet !== existingWallet) {
|
|
639
|
+
prompter.note(
|
|
640
|
+
"BACKUP REQUIRED - WRITE DOWN THESE 24 WORDS:\n\n" + wallet.mnemonic.join(" ") + "\n\nThese words allow you to recover your wallet.\nWithout them, you will lose access to your TON.\nWrite them on paper and keep them safe.",
|
|
641
|
+
"Mnemonic Seed (24 words)"
|
|
428
642
|
);
|
|
429
643
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
"
|
|
433
|
-
|
|
644
|
+
let telegramConnected = false;
|
|
645
|
+
const connectNow = await prompter.confirm({
|
|
646
|
+
message: "Connect to Telegram now? (you'll need the verification code sent to your phone)",
|
|
647
|
+
initialValue: true
|
|
648
|
+
});
|
|
649
|
+
if (connectNow) {
|
|
650
|
+
prompter.log("Connecting to Telegram... Check your phone for the verification code.");
|
|
651
|
+
try {
|
|
652
|
+
const sessionPath = join(TELETON_ROOT, "telegram_session.txt");
|
|
653
|
+
const client = new TelegramUserClient({
|
|
654
|
+
apiId,
|
|
655
|
+
apiHash,
|
|
656
|
+
phone,
|
|
657
|
+
sessionPath
|
|
658
|
+
});
|
|
659
|
+
await client.connect();
|
|
660
|
+
const me = client.getMe();
|
|
661
|
+
await client.disconnect();
|
|
662
|
+
telegramConnected = true;
|
|
663
|
+
prompter.success(
|
|
664
|
+
`\u2713 Telegram connected as ${me?.firstName || ""}${me?.username ? ` (@${me.username})` : ""}`
|
|
665
|
+
);
|
|
666
|
+
} catch (err) {
|
|
667
|
+
prompter.warn(
|
|
668
|
+
`Telegram connection failed: ${err instanceof Error ? err.message : String(err)}
|
|
669
|
+
You can authenticate later when running: teleton start`
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
434
673
|
prompter.note(
|
|
435
674
|
`Workspace: ${workspace.root}
|
|
436
675
|
Config: ${workspace.configPath}
|
|
437
676
|
Templates: SOUL.md, MEMORY.md, IDENTITY.md, USER.md
|
|
438
|
-
Telegram: ${phone} (API ID: ${apiId})
|
|
677
|
+
Telegram: ${phone} (API ID: ${apiId})${telegramConnected ? " \u2713 connected" : ""}
|
|
439
678
|
Admin: User ID ${userId}
|
|
440
679
|
Provider: ${providerMeta.displayName}
|
|
441
680
|
Model: ${selectedModel}
|
|
442
681
|
TON Wallet: ${wallet.address}`,
|
|
443
682
|
"Setup complete"
|
|
444
683
|
);
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
684
|
+
if (telegramConnected) {
|
|
685
|
+
prompter.note(
|
|
686
|
+
"Next steps:\n\n1. Start the agent:\n $ teleton start\n\n2. Send a message to your Telegram account to test",
|
|
687
|
+
"Ready"
|
|
688
|
+
);
|
|
689
|
+
} else {
|
|
690
|
+
prompter.note(
|
|
691
|
+
"Next steps:\n\n1. Start the agent:\n $ teleton start\n\n2. On first launch, you will be asked for:\n - Telegram verification code\n - 2FA password (if enabled)\n\n3. Send a message to your Telegram account to test",
|
|
692
|
+
"Ready"
|
|
693
|
+
);
|
|
694
|
+
}
|
|
449
695
|
prompter.outro("Good luck!");
|
|
450
696
|
}
|
|
451
697
|
async function runNonInteractiveOnboarding(options, prompter) {
|
|
@@ -493,15 +739,16 @@ async function runNonInteractiveOnboarding(options, prompter) {
|
|
|
493
739
|
group_policy: "open",
|
|
494
740
|
group_allow_from: [],
|
|
495
741
|
require_mention: true,
|
|
496
|
-
max_message_length:
|
|
742
|
+
max_message_length: TELEGRAM_MAX_MESSAGE_LENGTH,
|
|
497
743
|
typing_simulation: true,
|
|
498
744
|
rate_limit_messages_per_second: 1,
|
|
499
745
|
rate_limit_groups_per_minute: 20,
|
|
500
746
|
admin_ids: [options.userId],
|
|
747
|
+
owner_id: options.userId,
|
|
501
748
|
agent_channel: null,
|
|
502
749
|
debounce_ms: 1500,
|
|
503
|
-
bot_token:
|
|
504
|
-
bot_username:
|
|
750
|
+
bot_token: void 0,
|
|
751
|
+
bot_username: void 0
|
|
505
752
|
},
|
|
506
753
|
storage: {
|
|
507
754
|
sessions_file: `${workspace.root}/sessions.json`,
|
|
@@ -515,12 +762,13 @@ async function runNonInteractiveOnboarding(options, prompter) {
|
|
|
515
762
|
};
|
|
516
763
|
const configYaml = YAML.stringify(config);
|
|
517
764
|
writeFileSync(workspace.configPath, configYaml, "utf-8");
|
|
765
|
+
chmodSync(workspace.configPath, 384);
|
|
518
766
|
prompter.success(`\u2713 Configuration created: ${workspace.configPath}`);
|
|
519
767
|
}
|
|
520
768
|
|
|
521
769
|
// src/cli/commands/doctor.ts
|
|
522
|
-
import { existsSync, readFileSync, statSync } from "fs";
|
|
523
|
-
import { join } from "path";
|
|
770
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, statSync } from "fs";
|
|
771
|
+
import { join as join2 } from "path";
|
|
524
772
|
import { homedir } from "os";
|
|
525
773
|
import { parse } from "yaml";
|
|
526
774
|
var green = "\x1B[32m";
|
|
@@ -533,8 +781,8 @@ function formatResult(result) {
|
|
|
533
781
|
return `${icon} ${result.name}: ${result.message}`;
|
|
534
782
|
}
|
|
535
783
|
async function checkConfig(workspaceDir) {
|
|
536
|
-
const configPath =
|
|
537
|
-
if (!
|
|
784
|
+
const configPath = join2(workspaceDir, "config.yaml");
|
|
785
|
+
if (!existsSync2(configPath)) {
|
|
538
786
|
return {
|
|
539
787
|
name: "Config file",
|
|
540
788
|
status: "error",
|
|
@@ -542,7 +790,7 @@ async function checkConfig(workspaceDir) {
|
|
|
542
790
|
};
|
|
543
791
|
}
|
|
544
792
|
try {
|
|
545
|
-
const content =
|
|
793
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
546
794
|
const raw = parse(content);
|
|
547
795
|
const result = ConfigSchema.safeParse(raw);
|
|
548
796
|
if (!result.success) {
|
|
@@ -566,8 +814,8 @@ async function checkConfig(workspaceDir) {
|
|
|
566
814
|
}
|
|
567
815
|
}
|
|
568
816
|
async function checkTelegramCredentials(workspaceDir) {
|
|
569
|
-
const configPath =
|
|
570
|
-
if (!
|
|
817
|
+
const configPath = join2(workspaceDir, "config.yaml");
|
|
818
|
+
if (!existsSync2(configPath)) {
|
|
571
819
|
return {
|
|
572
820
|
name: "Telegram credentials",
|
|
573
821
|
status: "error",
|
|
@@ -575,7 +823,7 @@ async function checkTelegramCredentials(workspaceDir) {
|
|
|
575
823
|
};
|
|
576
824
|
}
|
|
577
825
|
try {
|
|
578
|
-
const content =
|
|
826
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
579
827
|
const config = parse(content);
|
|
580
828
|
if (!config.telegram?.api_id || !config.telegram?.api_hash) {
|
|
581
829
|
return {
|
|
@@ -605,8 +853,8 @@ async function checkTelegramCredentials(workspaceDir) {
|
|
|
605
853
|
}
|
|
606
854
|
}
|
|
607
855
|
async function checkApiKey(workspaceDir) {
|
|
608
|
-
const configPath =
|
|
609
|
-
if (!
|
|
856
|
+
const configPath = join2(workspaceDir, "config.yaml");
|
|
857
|
+
if (!existsSync2(configPath)) {
|
|
610
858
|
return {
|
|
611
859
|
name: "API key",
|
|
612
860
|
status: "error",
|
|
@@ -614,7 +862,7 @@ async function checkApiKey(workspaceDir) {
|
|
|
614
862
|
};
|
|
615
863
|
}
|
|
616
864
|
try {
|
|
617
|
-
const content =
|
|
865
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
618
866
|
const config = parse(content);
|
|
619
867
|
const provider = config.agent?.provider || "anthropic";
|
|
620
868
|
const apiKey = config.agent?.api_key;
|
|
@@ -659,8 +907,8 @@ async function checkApiKey(workspaceDir) {
|
|
|
659
907
|
}
|
|
660
908
|
}
|
|
661
909
|
async function checkWallet(workspaceDir) {
|
|
662
|
-
const walletPath =
|
|
663
|
-
if (!
|
|
910
|
+
const walletPath = join2(workspaceDir, "wallet.json");
|
|
911
|
+
if (!existsSync2(walletPath)) {
|
|
664
912
|
return {
|
|
665
913
|
name: "TON wallet",
|
|
666
914
|
status: "warn",
|
|
@@ -668,7 +916,7 @@ async function checkWallet(workspaceDir) {
|
|
|
668
916
|
};
|
|
669
917
|
}
|
|
670
918
|
try {
|
|
671
|
-
const content =
|
|
919
|
+
const content = readFileSync2(walletPath, "utf-8");
|
|
672
920
|
const wallet = JSON.parse(content);
|
|
673
921
|
if (!wallet.address) {
|
|
674
922
|
return {
|
|
@@ -692,8 +940,8 @@ async function checkWallet(workspaceDir) {
|
|
|
692
940
|
}
|
|
693
941
|
}
|
|
694
942
|
async function checkSoul(workspaceDir) {
|
|
695
|
-
const soulPath =
|
|
696
|
-
if (!
|
|
943
|
+
const soulPath = join2(workspaceDir, "SOUL.md");
|
|
944
|
+
if (!existsSync2(soulPath)) {
|
|
697
945
|
return {
|
|
698
946
|
name: "SOUL.md",
|
|
699
947
|
status: "warn",
|
|
@@ -717,8 +965,8 @@ async function checkSoul(workspaceDir) {
|
|
|
717
965
|
}
|
|
718
966
|
}
|
|
719
967
|
async function checkDatabase(workspaceDir) {
|
|
720
|
-
const dbPath =
|
|
721
|
-
if (!
|
|
968
|
+
const dbPath = join2(workspaceDir, "memory.db");
|
|
969
|
+
if (!existsSync2(dbPath)) {
|
|
722
970
|
return {
|
|
723
971
|
name: "Memory database",
|
|
724
972
|
status: "warn",
|
|
@@ -742,8 +990,8 @@ async function checkDatabase(workspaceDir) {
|
|
|
742
990
|
}
|
|
743
991
|
}
|
|
744
992
|
async function checkTelegramSession(workspaceDir) {
|
|
745
|
-
const sessionPath =
|
|
746
|
-
if (!
|
|
993
|
+
const sessionPath = join2(workspaceDir, "telegram_session.txt");
|
|
994
|
+
if (!existsSync2(sessionPath)) {
|
|
747
995
|
return {
|
|
748
996
|
name: "Telegram session",
|
|
749
997
|
status: "warn",
|
|
@@ -775,8 +1023,8 @@ async function checkTelegramSession(workspaceDir) {
|
|
|
775
1023
|
}
|
|
776
1024
|
}
|
|
777
1025
|
async function checkMarketData(workspaceDir) {
|
|
778
|
-
const dbPath =
|
|
779
|
-
if (!
|
|
1026
|
+
const dbPath = join2(workspaceDir, "gifts.db");
|
|
1027
|
+
if (!existsSync2(dbPath)) {
|
|
780
1028
|
return {
|
|
781
1029
|
name: "Gift market data",
|
|
782
1030
|
status: "warn",
|
|
@@ -830,8 +1078,8 @@ async function checkMarketData(workspaceDir) {
|
|
|
830
1078
|
}
|
|
831
1079
|
}
|
|
832
1080
|
async function checkModel(workspaceDir) {
|
|
833
|
-
const configPath =
|
|
834
|
-
if (!
|
|
1081
|
+
const configPath = join2(workspaceDir, "config.yaml");
|
|
1082
|
+
if (!existsSync2(configPath)) {
|
|
835
1083
|
return {
|
|
836
1084
|
name: "AI Model",
|
|
837
1085
|
status: "error",
|
|
@@ -839,7 +1087,7 @@ async function checkModel(workspaceDir) {
|
|
|
839
1087
|
};
|
|
840
1088
|
}
|
|
841
1089
|
try {
|
|
842
|
-
const content =
|
|
1090
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
843
1091
|
const config = parse(content);
|
|
844
1092
|
const provider = config.agent?.provider || "anthropic";
|
|
845
1093
|
let model = config.agent?.model;
|
|
@@ -864,8 +1112,8 @@ async function checkModel(workspaceDir) {
|
|
|
864
1112
|
}
|
|
865
1113
|
}
|
|
866
1114
|
async function checkAdmins(workspaceDir) {
|
|
867
|
-
const configPath =
|
|
868
|
-
if (!
|
|
1115
|
+
const configPath = join2(workspaceDir, "config.yaml");
|
|
1116
|
+
if (!existsSync2(configPath)) {
|
|
869
1117
|
return {
|
|
870
1118
|
name: "Admin users",
|
|
871
1119
|
status: "error",
|
|
@@ -873,7 +1121,7 @@ async function checkAdmins(workspaceDir) {
|
|
|
873
1121
|
};
|
|
874
1122
|
}
|
|
875
1123
|
try {
|
|
876
|
-
const content =
|
|
1124
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
877
1125
|
const config = parse(content);
|
|
878
1126
|
const admins = config.telegram?.admin_ids || [];
|
|
879
1127
|
if (admins.length === 0) {
|
|
@@ -915,14 +1163,14 @@ async function checkNodeVersion() {
|
|
|
915
1163
|
async function checkPlaywrightBrowser() {
|
|
916
1164
|
const homeDir = homedir();
|
|
917
1165
|
const browserPaths = [
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
1166
|
+
join2(homeDir, ".cache", "ms-playwright", "chromium-*"),
|
|
1167
|
+
join2(homeDir, ".cache", "ms-playwright"),
|
|
1168
|
+
join2(homeDir, "Library", "Caches", "ms-playwright"),
|
|
1169
|
+
join2(homeDir, "AppData", "Local", "ms-playwright")
|
|
922
1170
|
];
|
|
923
1171
|
for (const basePath of browserPaths) {
|
|
924
1172
|
const checkPath = basePath.replace("/chromium-*", "");
|
|
925
|
-
if (
|
|
1173
|
+
if (existsSync2(checkPath)) {
|
|
926
1174
|
try {
|
|
927
1175
|
const { readdirSync } = await import("fs");
|
|
928
1176
|
const contents = readdirSync(checkPath);
|
|
@@ -994,15 +1242,15 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
994
1242
|
}
|
|
995
1243
|
|
|
996
1244
|
// src/cli/index.ts
|
|
997
|
-
import { readFileSync as
|
|
998
|
-
import { dirname, join as
|
|
1245
|
+
import { readFileSync as readFileSync3, existsSync as existsSync3 } from "fs";
|
|
1246
|
+
import { dirname, join as join3 } from "path";
|
|
999
1247
|
import { fileURLToPath } from "url";
|
|
1000
1248
|
function findPackageJson() {
|
|
1001
1249
|
let dir = dirname(fileURLToPath(import.meta.url));
|
|
1002
1250
|
for (let i = 0; i < 10; i++) {
|
|
1003
|
-
const candidate =
|
|
1004
|
-
if (
|
|
1005
|
-
return JSON.parse(
|
|
1251
|
+
const candidate = join3(dir, "package.json");
|
|
1252
|
+
if (existsSync3(candidate)) {
|
|
1253
|
+
return JSON.parse(readFileSync3(candidate, "utf-8"));
|
|
1006
1254
|
}
|
|
1007
1255
|
dir = dirname(dir);
|
|
1008
1256
|
}
|