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
package/dist/cli/index.js
CHANGED
|
@@ -1,176 +1,519 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TelegramUserClient,
|
|
3
|
+
main
|
|
4
|
+
} from "../chunk-OGIG552S.js";
|
|
5
|
+
import "../chunk-UDD7FYOU.js";
|
|
6
|
+
import "../chunk-EHEV7FJ7.js";
|
|
7
|
+
import "../chunk-U7FQYCBQ.js";
|
|
1
8
|
import {
|
|
2
9
|
CONFIGURABLE_KEYS,
|
|
10
|
+
configExists,
|
|
3
11
|
deleteNestedValue,
|
|
12
|
+
getDefaultConfigPath,
|
|
4
13
|
getNestedValue,
|
|
5
14
|
readRawConfig,
|
|
6
15
|
setNestedValue,
|
|
7
16
|
writeRawConfig
|
|
8
|
-
} from "../chunk-
|
|
9
|
-
import {
|
|
10
|
-
TelegramUserClient,
|
|
11
|
-
ensureWorkspace,
|
|
12
|
-
isNewWorkspace,
|
|
13
|
-
main
|
|
14
|
-
} from "../chunk-6L6KGATM.js";
|
|
15
|
-
import "../chunk-WL2Q3VRD.js";
|
|
16
|
-
import "../chunk-EHEV7FJ7.js";
|
|
17
|
-
import "../chunk-U7FQYCBQ.js";
|
|
17
|
+
} from "../chunk-TCD4NZDA.js";
|
|
18
18
|
import {
|
|
19
19
|
ConfigSchema,
|
|
20
20
|
DealsConfigSchema,
|
|
21
|
-
|
|
21
|
+
ensureWorkspace,
|
|
22
22
|
generateWallet,
|
|
23
|
-
getDefaultConfigPath,
|
|
24
|
-
getProviderMetadata,
|
|
25
|
-
getSupportedProviders,
|
|
26
23
|
importWallet,
|
|
24
|
+
isNewWorkspace,
|
|
27
25
|
loadWallet,
|
|
28
26
|
saveWallet,
|
|
29
|
-
validateApiKeyFormat,
|
|
30
27
|
walletExists
|
|
31
|
-
} from "../chunk-
|
|
32
|
-
import "../chunk-
|
|
33
|
-
import "../chunk-
|
|
34
|
-
import "../chunk-D5I7GBV7.js";
|
|
35
|
-
import "../chunk-ECSCVEQQ.js";
|
|
28
|
+
} from "../chunk-NERLQY2H.js";
|
|
29
|
+
import "../chunk-QUAPFI2N.js";
|
|
30
|
+
import "../chunk-TSKJCWQQ.js";
|
|
36
31
|
import {
|
|
37
|
-
|
|
38
|
-
} from "../chunk-
|
|
39
|
-
import "../chunk-
|
|
32
|
+
getErrorMessage
|
|
33
|
+
} from "../chunk-XBE4JB7C.js";
|
|
34
|
+
import "../chunk-ND2X5FWB.js";
|
|
35
|
+
import {
|
|
36
|
+
getProviderMetadata,
|
|
37
|
+
getSupportedProviders,
|
|
38
|
+
validateApiKeyFormat
|
|
39
|
+
} from "../chunk-LRCPA7SC.js";
|
|
40
|
+
import "../chunk-OCLG5GKI.js";
|
|
41
|
+
import "../chunk-N3F7E7DR.js";
|
|
42
|
+
import "../chunk-FNV5FF35.js";
|
|
43
|
+
import "../chunk-UCN6TI25.js";
|
|
44
|
+
import "../chunk-XBKSS6DM.js";
|
|
40
45
|
import {
|
|
41
46
|
TELEGRAM_MAX_MESSAGE_LENGTH
|
|
42
47
|
} from "../chunk-RO62LO6Z.js";
|
|
48
|
+
import {
|
|
49
|
+
fetchWithTimeout
|
|
50
|
+
} from "../chunk-VAUJSSD3.js";
|
|
51
|
+
import "../chunk-4DU3C27M.js";
|
|
43
52
|
import {
|
|
44
53
|
TELETON_ROOT
|
|
45
54
|
} from "../chunk-EYWNOHMJ.js";
|
|
55
|
+
import "../chunk-RCMD3U65.js";
|
|
46
56
|
import "../chunk-NUGDTPE4.js";
|
|
47
|
-
import "../chunk-QUAPFI2N.js";
|
|
48
|
-
import "../chunk-TSKJCWQQ.js";
|
|
49
57
|
import "../chunk-QGM4M3NI.js";
|
|
50
58
|
|
|
51
59
|
// src/cli/index.ts
|
|
52
60
|
import { Command } from "commander";
|
|
53
61
|
|
|
54
62
|
// src/cli/prompts.ts
|
|
55
|
-
import
|
|
56
|
-
|
|
63
|
+
import { input, select, checkbox, confirm, password } from "@inquirer/prompts";
|
|
64
|
+
import chalk from "chalk";
|
|
65
|
+
import ora from "ora";
|
|
66
|
+
var TON = chalk.hex("#0098EA");
|
|
67
|
+
var GREEN = chalk.green;
|
|
68
|
+
var CYAN = chalk.cyan;
|
|
69
|
+
var DIM = chalk.dim;
|
|
70
|
+
var BOLD = chalk.bold;
|
|
71
|
+
var RED = chalk.red;
|
|
72
|
+
var YELLOW = chalk.yellow;
|
|
73
|
+
var WHITE = chalk.white;
|
|
74
|
+
var inquirerTheme = {
|
|
75
|
+
prefix: { idle: TON("\u203A"), done: GREEN("\u2714") },
|
|
76
|
+
style: {
|
|
77
|
+
answer: (t) => CYAN.bold(t),
|
|
78
|
+
message: (t, status) => status === "done" ? DIM(t) : BOLD(t),
|
|
79
|
+
error: (t) => RED.bold(` \u2718 ${t}`),
|
|
80
|
+
help: (t) => DIM(t),
|
|
81
|
+
highlight: (t) => TON.bold(t),
|
|
82
|
+
description: (t) => DIM.italic(t)
|
|
83
|
+
},
|
|
84
|
+
icon: { cursor: TON("\u276F") }
|
|
85
|
+
};
|
|
86
|
+
function stripAnsi(s) {
|
|
87
|
+
return s.replace(/\x1B\[[0-9;]*m/g, "");
|
|
88
|
+
}
|
|
89
|
+
function padRight(s, len) {
|
|
90
|
+
return s + " ".repeat(Math.max(0, len - s.length));
|
|
91
|
+
}
|
|
92
|
+
function padRightAnsi(s, len) {
|
|
93
|
+
const visible = stripAnsi(s).length;
|
|
94
|
+
return s + " ".repeat(Math.max(0, len - visible));
|
|
95
|
+
}
|
|
96
|
+
function centerIn(text, width) {
|
|
97
|
+
const vis = stripAnsi(text).length;
|
|
98
|
+
const pad = width - vis;
|
|
99
|
+
const left = Math.floor(pad / 2);
|
|
100
|
+
const right = pad - left;
|
|
101
|
+
return " ".repeat(Math.max(0, left)) + text + " ".repeat(Math.max(0, right));
|
|
102
|
+
}
|
|
103
|
+
var BOX_WIDTH = 56;
|
|
104
|
+
var ASCII_ART_RAW = [
|
|
105
|
+
" ______ __ __ ___ __",
|
|
106
|
+
" /_ __/__ / /__ / /_____ ____ / | ____ ____ ____ / /_",
|
|
107
|
+
" / / / _ \\/ / _ \\/ __/ __ \\/ __ \\ / /| |/ __ `/ _ \\/ __ \\/ __/",
|
|
108
|
+
" / / / __/ / __/ /_/ /_/ / / / / / ___ / /_/ / __/ / / / /_",
|
|
109
|
+
" /_/ \\___/_/\\___/\\__/\\____/_/ /_/ /_/ |_\\__, /\\___/_/ /_/\\__/",
|
|
110
|
+
" /____/"
|
|
111
|
+
];
|
|
112
|
+
var ART_WIDTH = Math.max(...ASCII_ART_RAW.map((l) => l.length));
|
|
113
|
+
var ASCII_ART = ASCII_ART_RAW.map((l) => l + " ".repeat(ART_WIDTH - l.length));
|
|
114
|
+
var FRAME_WIDTH = Math.max(BOX_WIDTH, ART_WIDTH + 4);
|
|
115
|
+
function frameRow(content, border = TON) {
|
|
116
|
+
const pad = FRAME_WIDTH - stripAnsi(content).length;
|
|
117
|
+
return ` ${border("\u2551")}${content}${" ".repeat(Math.max(0, pad))}${border("\u2551")}`;
|
|
118
|
+
}
|
|
119
|
+
function emptyRow(border = TON) {
|
|
120
|
+
return ` ${border("\u2551")}${" ".repeat(FRAME_WIDTH)}${border("\u2551")}`;
|
|
121
|
+
}
|
|
122
|
+
function wizardFrame(currentStep, steps) {
|
|
123
|
+
const W = FRAME_WIDTH;
|
|
124
|
+
const out = [];
|
|
125
|
+
out.push(` ${TON("\u2554" + "\u2550".repeat(W) + "\u2557")}`);
|
|
126
|
+
out.push(emptyRow());
|
|
127
|
+
for (const line of ASCII_ART) {
|
|
128
|
+
out.push(frameRow(TON.bold(centerIn(line, W))));
|
|
129
|
+
}
|
|
130
|
+
out.push(emptyRow());
|
|
131
|
+
const subtitle = "Autonomous AI agent on Telegram with native TON blockchain integration";
|
|
132
|
+
out.push(frameRow(DIM(centerIn(subtitle, W))));
|
|
133
|
+
out.push(frameRow(DIM(centerIn("t.me/TeletonAgents | v0.7.0", W))));
|
|
134
|
+
out.push(` ${TON("\u2560" + "\u2550".repeat(W) + "\u2563")}`);
|
|
135
|
+
out.push(emptyRow());
|
|
136
|
+
const labelWidth = 14;
|
|
137
|
+
for (let i = 0; i < steps.length; i++) {
|
|
138
|
+
const s = steps[i];
|
|
139
|
+
let line;
|
|
140
|
+
if (i < currentStep) {
|
|
141
|
+
const val = s.value ?? "";
|
|
142
|
+
line = ` ${GREEN("\u2714")} ${WHITE(padRight(s.label, labelWidth))}${CYAN(val)}`;
|
|
143
|
+
} else if (i === currentStep) {
|
|
144
|
+
line = ` ${TON.bold("\u25B8")} ${TON.bold(padRight(s.label, labelWidth))}${DIM(s.desc)}`;
|
|
145
|
+
} else {
|
|
146
|
+
line = ` ${DIM("\u25CB")} ${DIM(padRight(s.label, labelWidth))}${DIM(s.desc)}`;
|
|
147
|
+
}
|
|
148
|
+
out.push(frameRow(padRightAnsi(line, W)));
|
|
149
|
+
}
|
|
150
|
+
out.push(emptyRow());
|
|
151
|
+
const pct = Math.round(currentStep / steps.length * 100);
|
|
152
|
+
const barLen = Math.max(10, W - 36);
|
|
153
|
+
const filled = Math.round(currentStep / steps.length * barLen);
|
|
154
|
+
const bar = TON("\u2588".repeat(filled)) + DIM("\u2591".repeat(barLen - filled));
|
|
155
|
+
const footer = ` ${bar} ${DIM(`${pct}% \xB7 Step ${currentStep + 1} of ${steps.length}`)}`;
|
|
156
|
+
out.push(frameRow(padRightAnsi(footer, W)));
|
|
157
|
+
out.push(emptyRow());
|
|
158
|
+
out.push(` ${TON("\u255A" + "\u2550".repeat(W) + "\u255D")}`);
|
|
159
|
+
return out.join("\n");
|
|
160
|
+
}
|
|
161
|
+
function noteBox(text, title, color = YELLOW) {
|
|
162
|
+
const W = FRAME_WIDTH;
|
|
163
|
+
const titleStr = ` ${title} `;
|
|
164
|
+
const titlePad = W - stripAnsi(titleStr).length - 1;
|
|
165
|
+
console.log(
|
|
166
|
+
` ${color("\u250C\u2500")}${color.bold(titleStr)}${color("\u2500".repeat(Math.max(0, titlePad)) + "\u2510")}`
|
|
167
|
+
);
|
|
168
|
+
const lines = text.split("\n");
|
|
169
|
+
for (const line of lines) {
|
|
170
|
+
const pad = W - stripAnsi(line).length - 2;
|
|
171
|
+
console.log(` ${color("\u2502")} ${line}${" ".repeat(Math.max(0, pad))}${color("\u2502")}`);
|
|
172
|
+
}
|
|
173
|
+
console.log(` ${color("\u2514" + "\u2500".repeat(W) + "\u2518")}`);
|
|
174
|
+
console.log();
|
|
175
|
+
}
|
|
176
|
+
function finalSummaryBox(steps, connected) {
|
|
177
|
+
const W = FRAME_WIDTH;
|
|
178
|
+
const B = GREEN;
|
|
179
|
+
const gRow = (content) => {
|
|
180
|
+
const pad = W - stripAnsi(content).length;
|
|
181
|
+
return ` ${B("\u2551")}${content}${" ".repeat(Math.max(0, pad))}${B("\u2551")}`;
|
|
182
|
+
};
|
|
183
|
+
const gEmpty = () => ` ${B("\u2551")}${" ".repeat(W)}${B("\u2551")}`;
|
|
184
|
+
const out = [];
|
|
185
|
+
const t1 = " Configuration Summary ";
|
|
186
|
+
const t1Pad = W - stripAnsi(t1).length - 1;
|
|
187
|
+
out.push(` ${B("\u2554\u2550" + B.bold(t1) + "\u2550".repeat(Math.max(0, t1Pad)) + "\u2557")}`);
|
|
188
|
+
out.push(gEmpty());
|
|
189
|
+
for (const s of steps) {
|
|
190
|
+
const val = s.value ?? DIM("not set");
|
|
191
|
+
const entry = ` ${GREEN("\u2714")} ${WHITE(padRight(s.label, 14))}${CYAN(val)}`;
|
|
192
|
+
out.push(gRow(entry));
|
|
193
|
+
}
|
|
194
|
+
const t2 = " Next Steps ";
|
|
195
|
+
const t2Pad = W - stripAnsi(t2).length - 1;
|
|
196
|
+
out.push(gEmpty());
|
|
197
|
+
out.push(` ${B("\u2560\u2550" + B.bold(t2) + "\u2550".repeat(Math.max(0, t2Pad)) + "\u2563")}`);
|
|
198
|
+
out.push(gEmpty());
|
|
199
|
+
const items = connected ? [
|
|
200
|
+
`${TON("1.")} Start the agent`,
|
|
201
|
+
` ${CYAN("$ teleton start")}`,
|
|
202
|
+
"",
|
|
203
|
+
`${TON("2.")} Send ${CYAN("/boot")} as your first message`,
|
|
204
|
+
` to bootstrap the agent's personality`,
|
|
205
|
+
"",
|
|
206
|
+
`${TON("3.")} Customize ${DIM("~/.teleton/workspace/SOUL.md")}`,
|
|
207
|
+
` to shape your agent's behavior`,
|
|
208
|
+
"",
|
|
209
|
+
`${TON("4.")} Read the docs`,
|
|
210
|
+
` ${TON.underline("https://github.com/TONresistor/teleton-agent")}`
|
|
211
|
+
] : [
|
|
212
|
+
`${TON("1.")} Start the agent`,
|
|
213
|
+
` ${CYAN("$ teleton start")}`,
|
|
214
|
+
"",
|
|
215
|
+
`${TON("2.")} On first launch, you will be asked for:`,
|
|
216
|
+
` - Telegram verification code`,
|
|
217
|
+
` - 2FA password (if enabled)`,
|
|
218
|
+
"",
|
|
219
|
+
`${TON("3.")} Send a message to your Telegram account to test`
|
|
220
|
+
];
|
|
221
|
+
for (const item of items) {
|
|
222
|
+
const pad = W - stripAnsi(item).length - 2;
|
|
223
|
+
out.push(` ${B("\u2551")} ${item}${" ".repeat(Math.max(0, pad))}${B("\u2551")}`);
|
|
224
|
+
}
|
|
225
|
+
out.push(gEmpty());
|
|
226
|
+
out.push(` ${B("\u255A" + "\u2550".repeat(W) + "\u255D")}`);
|
|
227
|
+
return out.join("\n");
|
|
228
|
+
}
|
|
229
|
+
var CancelledError = class extends Error {
|
|
230
|
+
constructor() {
|
|
231
|
+
super("Operation cancelled by user");
|
|
232
|
+
this.name = "CancelledError";
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
function wrapExitPromptError(promise) {
|
|
236
|
+
return promise.catch((err) => {
|
|
237
|
+
if (err?.name === "ExitPromptError") throw new CancelledError();
|
|
238
|
+
throw err;
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
function adaptValidate(fn) {
|
|
242
|
+
if (!fn) return void 0;
|
|
243
|
+
return (value) => {
|
|
244
|
+
const result = fn(value);
|
|
245
|
+
if (result === void 0) return true;
|
|
246
|
+
if (result instanceof Error) return result.message;
|
|
247
|
+
return result;
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
var InquirerPrompter = class {
|
|
57
251
|
async intro(title) {
|
|
58
|
-
|
|
252
|
+
console.log(`
|
|
253
|
+
${TON.bold(title)}
|
|
254
|
+
`);
|
|
59
255
|
}
|
|
60
256
|
async outro(message) {
|
|
61
|
-
|
|
257
|
+
console.log(`
|
|
258
|
+
${DIM(message)}
|
|
259
|
+
`);
|
|
62
260
|
}
|
|
63
261
|
async note(message, title) {
|
|
64
|
-
|
|
262
|
+
noteBox(message, title ?? "Note", YELLOW);
|
|
65
263
|
}
|
|
66
264
|
async text(options) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
return result;
|
|
265
|
+
return wrapExitPromptError(
|
|
266
|
+
input({
|
|
267
|
+
message: options.message,
|
|
268
|
+
default: options.initialValue,
|
|
269
|
+
theme: inquirerTheme,
|
|
270
|
+
validate: adaptValidate(options.validate)
|
|
271
|
+
})
|
|
272
|
+
);
|
|
77
273
|
}
|
|
78
274
|
async password(options) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return result;
|
|
275
|
+
return wrapExitPromptError(
|
|
276
|
+
password({
|
|
277
|
+
message: options.message,
|
|
278
|
+
theme: inquirerTheme,
|
|
279
|
+
validate: adaptValidate(options.validate)
|
|
280
|
+
})
|
|
281
|
+
);
|
|
87
282
|
}
|
|
88
283
|
async select(options) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
284
|
+
return wrapExitPromptError(
|
|
285
|
+
select({
|
|
286
|
+
message: options.message,
|
|
287
|
+
default: options.initialValue,
|
|
288
|
+
theme: inquirerTheme,
|
|
289
|
+
choices: options.options.map((opt) => ({
|
|
93
290
|
value: opt.value,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return mapped;
|
|
100
|
-
}),
|
|
101
|
-
initialValue: options.initialValue
|
|
102
|
-
});
|
|
103
|
-
if (clack.isCancel(result)) {
|
|
104
|
-
throw new CancelledError();
|
|
105
|
-
}
|
|
106
|
-
return result;
|
|
291
|
+
name: opt.label,
|
|
292
|
+
description: opt.hint
|
|
293
|
+
}))
|
|
294
|
+
})
|
|
295
|
+
);
|
|
107
296
|
}
|
|
108
297
|
async confirm(options) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return result;
|
|
298
|
+
return wrapExitPromptError(
|
|
299
|
+
confirm({
|
|
300
|
+
message: options.message,
|
|
301
|
+
default: options.initialValue ?? false,
|
|
302
|
+
theme: inquirerTheme
|
|
303
|
+
})
|
|
304
|
+
);
|
|
117
305
|
}
|
|
118
306
|
async multiselect(options) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
307
|
+
return wrapExitPromptError(
|
|
308
|
+
checkbox({
|
|
309
|
+
message: options.message,
|
|
310
|
+
theme: {
|
|
311
|
+
...inquirerTheme,
|
|
312
|
+
icon: { cursor: TON("\u276F"), checked: GREEN("\u2714"), unchecked: DIM("\u25CB") }
|
|
313
|
+
},
|
|
314
|
+
choices: options.options.map((opt) => ({
|
|
123
315
|
value: opt.value,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}),
|
|
131
|
-
required: options.required
|
|
132
|
-
});
|
|
133
|
-
if (clack.isCancel(result)) {
|
|
134
|
-
throw new CancelledError();
|
|
135
|
-
}
|
|
136
|
-
return result;
|
|
316
|
+
name: opt.label,
|
|
317
|
+
description: opt.hint
|
|
318
|
+
})),
|
|
319
|
+
required: options.required
|
|
320
|
+
})
|
|
321
|
+
);
|
|
137
322
|
}
|
|
138
323
|
spinner() {
|
|
139
|
-
|
|
324
|
+
let s = null;
|
|
140
325
|
return {
|
|
141
|
-
start: (message) =>
|
|
142
|
-
|
|
143
|
-
|
|
326
|
+
start: (message) => {
|
|
327
|
+
s = ora({ text: DIM(message), color: "cyan" }).start();
|
|
328
|
+
},
|
|
329
|
+
stop: (message) => {
|
|
330
|
+
if (s) s.succeed(DIM(message));
|
|
331
|
+
s = null;
|
|
332
|
+
},
|
|
333
|
+
message: (message) => {
|
|
334
|
+
if (s) s.text = DIM(message);
|
|
335
|
+
}
|
|
144
336
|
};
|
|
145
337
|
}
|
|
146
338
|
log(message) {
|
|
147
|
-
|
|
339
|
+
console.log(` ${DIM("\u25CB")} ${message}`);
|
|
148
340
|
}
|
|
149
341
|
warn(message) {
|
|
150
|
-
|
|
342
|
+
console.log(` ${YELLOW("\u26A0")} ${YELLOW(message)}`);
|
|
151
343
|
}
|
|
152
344
|
error(message) {
|
|
153
|
-
|
|
345
|
+
console.log(` ${RED("\u2717")} ${RED(message)}`);
|
|
154
346
|
}
|
|
155
347
|
success(message) {
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
var CancelledError = class extends Error {
|
|
160
|
-
constructor() {
|
|
161
|
-
super("Operation cancelled by user");
|
|
162
|
-
this.name = "CancelledError";
|
|
348
|
+
console.log(` ${GREEN("\u2713")} ${GREEN(message)}`);
|
|
163
349
|
}
|
|
164
350
|
};
|
|
165
351
|
function createPrompter() {
|
|
166
|
-
return new
|
|
352
|
+
return new InquirerPrompter();
|
|
167
353
|
}
|
|
168
354
|
|
|
169
355
|
// src/cli/commands/onboard.ts
|
|
170
|
-
import { writeFileSync, readFileSync, existsSync
|
|
356
|
+
import { writeFileSync, readFileSync, existsSync } from "fs";
|
|
171
357
|
import { join } from "path";
|
|
172
358
|
import YAML from "yaml";
|
|
359
|
+
import ora2 from "ora";
|
|
360
|
+
var STEPS = [
|
|
361
|
+
{ label: "Agent", desc: "Name & mode" },
|
|
362
|
+
{ label: "Provider", desc: "LLM & API key" },
|
|
363
|
+
{ label: "Telegram", desc: "Credentials" },
|
|
364
|
+
{ label: "Config", desc: "Model & policies" },
|
|
365
|
+
{ label: "Modules", desc: "Optional features" },
|
|
366
|
+
{ label: "Wallet", desc: "TON blockchain" },
|
|
367
|
+
{ label: "Connect", desc: "Telegram auth" }
|
|
368
|
+
];
|
|
369
|
+
function redraw(currentStep) {
|
|
370
|
+
console.clear();
|
|
371
|
+
console.log();
|
|
372
|
+
console.log(wizardFrame(currentStep, STEPS));
|
|
373
|
+
console.log();
|
|
374
|
+
}
|
|
375
|
+
function sleep(ms) {
|
|
376
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
377
|
+
}
|
|
378
|
+
var MODEL_OPTIONS = {
|
|
379
|
+
anthropic: [
|
|
380
|
+
{
|
|
381
|
+
value: "claude-opus-4-5-20251101",
|
|
382
|
+
name: "Claude Opus 4.5",
|
|
383
|
+
description: "Most capable, $5/M"
|
|
384
|
+
},
|
|
385
|
+
{ value: "claude-sonnet-4-0", name: "Claude Sonnet 4", description: "Balanced, $3/M" },
|
|
386
|
+
{
|
|
387
|
+
value: "claude-haiku-4-5-20251001",
|
|
388
|
+
name: "Claude Haiku 4.5",
|
|
389
|
+
description: "Fast & cheap, $1/M"
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
value: "claude-3-5-haiku-20241022",
|
|
393
|
+
name: "Claude 3.5 Haiku",
|
|
394
|
+
description: "Cheapest, $0.80/M"
|
|
395
|
+
}
|
|
396
|
+
],
|
|
397
|
+
openai: [
|
|
398
|
+
{ value: "gpt-5", name: "GPT-5", description: "Most capable, 400K ctx, $1.25/M" },
|
|
399
|
+
{ value: "gpt-4o", name: "GPT-4o", description: "Balanced, 128K ctx, $2.50/M" },
|
|
400
|
+
{ value: "gpt-4.1", name: "GPT-4.1", description: "1M ctx, $2/M" },
|
|
401
|
+
{ value: "gpt-4.1-mini", name: "GPT-4.1 Mini", description: "1M ctx, cheap, $0.40/M" },
|
|
402
|
+
{ value: "o3", name: "o3", description: "Reasoning, 200K ctx, $2/M" }
|
|
403
|
+
],
|
|
404
|
+
google: [
|
|
405
|
+
{ value: "gemini-2.5-flash", name: "Gemini 2.5 Flash", description: "Fast, 1M ctx, $0.30/M" },
|
|
406
|
+
{
|
|
407
|
+
value: "gemini-2.5-pro",
|
|
408
|
+
name: "Gemini 2.5 Pro",
|
|
409
|
+
description: "Most capable, 1M ctx, $1.25/M"
|
|
410
|
+
},
|
|
411
|
+
{ value: "gemini-2.0-flash", name: "Gemini 2.0 Flash", description: "Cheap, 1M ctx, $0.10/M" }
|
|
412
|
+
],
|
|
413
|
+
xai: [
|
|
414
|
+
{ value: "grok-4-fast", name: "Grok 4 Fast", description: "Vision, 2M ctx, $0.20/M" },
|
|
415
|
+
{ value: "grok-4", name: "Grok 4", description: "Reasoning, 256K ctx, $3/M" },
|
|
416
|
+
{ value: "grok-3", name: "Grok 3", description: "Stable, 131K ctx, $3/M" }
|
|
417
|
+
],
|
|
418
|
+
groq: [
|
|
419
|
+
{
|
|
420
|
+
value: "meta-llama/llama-4-maverick-17b-128e-instruct",
|
|
421
|
+
name: "Llama 4 Maverick",
|
|
422
|
+
description: "Vision, 131K ctx, $0.20/M"
|
|
423
|
+
},
|
|
424
|
+
{ value: "qwen/qwen3-32b", name: "Qwen3 32B", description: "Reasoning, 131K ctx, $0.29/M" },
|
|
425
|
+
{
|
|
426
|
+
value: "deepseek-r1-distill-llama-70b",
|
|
427
|
+
name: "DeepSeek R1 70B",
|
|
428
|
+
description: "Reasoning, 131K ctx, $0.75/M"
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
value: "llama-3.3-70b-versatile",
|
|
432
|
+
name: "Llama 3.3 70B",
|
|
433
|
+
description: "General purpose, 131K ctx, $0.59/M"
|
|
434
|
+
}
|
|
435
|
+
],
|
|
436
|
+
openrouter: [
|
|
437
|
+
{ value: "anthropic/claude-opus-4.5", name: "Claude Opus 4.5", description: "200K ctx, $5/M" },
|
|
438
|
+
{ value: "openai/gpt-5", name: "GPT-5", description: "400K ctx, $1.25/M" },
|
|
439
|
+
{ value: "google/gemini-2.5-flash", name: "Gemini 2.5 Flash", description: "1M ctx, $0.30/M" },
|
|
440
|
+
{
|
|
441
|
+
value: "deepseek/deepseek-r1",
|
|
442
|
+
name: "DeepSeek R1",
|
|
443
|
+
description: "Reasoning, 64K ctx, $0.70/M"
|
|
444
|
+
},
|
|
445
|
+
{ value: "x-ai/grok-4", name: "Grok 4", description: "256K ctx, $3/M" }
|
|
446
|
+
],
|
|
447
|
+
moonshot: [
|
|
448
|
+
{ value: "kimi-k2.5", name: "Kimi K2.5", description: "Free, 256K ctx, multimodal" },
|
|
449
|
+
{
|
|
450
|
+
value: "kimi-k2-thinking",
|
|
451
|
+
name: "Kimi K2 Thinking",
|
|
452
|
+
description: "Free, 256K ctx, reasoning"
|
|
453
|
+
}
|
|
454
|
+
],
|
|
455
|
+
mistral: [
|
|
456
|
+
{
|
|
457
|
+
value: "devstral-small-2507",
|
|
458
|
+
name: "Devstral Small",
|
|
459
|
+
description: "Coding, 128K ctx, $0.10/M"
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
value: "devstral-medium-latest",
|
|
463
|
+
name: "Devstral Medium",
|
|
464
|
+
description: "Coding, 262K ctx, $0.40/M"
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
value: "mistral-large-latest",
|
|
468
|
+
name: "Mistral Large",
|
|
469
|
+
description: "General, 128K ctx, $2/M"
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
value: "magistral-small",
|
|
473
|
+
name: "Magistral Small",
|
|
474
|
+
description: "Reasoning, 128K ctx, $0.50/M"
|
|
475
|
+
}
|
|
476
|
+
]
|
|
477
|
+
};
|
|
173
478
|
async function onboardCommand(options = {}) {
|
|
479
|
+
if (options.ui) {
|
|
480
|
+
const { SetupServer } = await import("../setup-server-C7ZTPHD5.js");
|
|
481
|
+
const port = parseInt(options.uiPort || "7777") || 7777;
|
|
482
|
+
const url = `http://localhost:${port}/setup`;
|
|
483
|
+
const blue2 = "\x1B[34m";
|
|
484
|
+
const reset2 = "\x1B[0m";
|
|
485
|
+
const dim = "\x1B[2m";
|
|
486
|
+
console.log(`
|
|
487
|
+
${blue2} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
|
|
488
|
+
\u2502 \u2502
|
|
489
|
+
\u2502 ______________ ________________ _ __ ___ _____________ ________ \u2502
|
|
490
|
+
\u2502 /_ __/ ____/ / / ____/_ __/ __ \\/ | / / / | / ____/ ____/ | / /_ __/ \u2502
|
|
491
|
+
\u2502 / / / __/ / / / __/ / / / / / / |/ / / /| |/ / __/ __/ / |/ / / / \u2502
|
|
492
|
+
\u2502 / / / /___/ /___/ /___ / / / /_/ / /| / / ___ / /_/ / /___/ /| / / / \u2502
|
|
493
|
+
\u2502 /_/ /_____/_____/_____/ /_/ \\____/_/ |_/ /_/ |_\\____/_____/_/ |_/ /_/ \u2502
|
|
494
|
+
\u2502 \u2502
|
|
495
|
+
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 DEV: ZKPROOF.T.ME \u2500\u2500\u2518${reset2}
|
|
496
|
+
|
|
497
|
+
${dim}Setup wizard running at${reset2} ${url}
|
|
498
|
+
${dim}Opening in your default browser...${reset2}
|
|
499
|
+
${dim}Press Ctrl+C to cancel.${reset2}
|
|
500
|
+
`);
|
|
501
|
+
const server = new SetupServer(port);
|
|
502
|
+
await server.start();
|
|
503
|
+
process.on("SIGINT", async () => {
|
|
504
|
+
await server.stop();
|
|
505
|
+
process.exit(0);
|
|
506
|
+
});
|
|
507
|
+
await server.waitForLaunch();
|
|
508
|
+
console.log("\n Launch signal received \u2014 stopping setup server");
|
|
509
|
+
await server.stop();
|
|
510
|
+
console.log(" Starting TonnetApp...\n");
|
|
511
|
+
const { TeletonApp } = await import("../index.js");
|
|
512
|
+
const configPath = join(TELETON_ROOT, "config.yaml");
|
|
513
|
+
const app = new TeletonApp(configPath);
|
|
514
|
+
await app.start();
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
174
517
|
const prompter = createPrompter();
|
|
175
518
|
try {
|
|
176
519
|
if (options.nonInteractive) {
|
|
@@ -180,386 +523,515 @@ async function onboardCommand(options = {}) {
|
|
|
180
523
|
}
|
|
181
524
|
} catch (err) {
|
|
182
525
|
if (err instanceof CancelledError) {
|
|
183
|
-
|
|
526
|
+
console.log(`
|
|
527
|
+
${DIM("Setup cancelled. No changes were made.")}
|
|
528
|
+
`);
|
|
184
529
|
process.exit(0);
|
|
185
530
|
}
|
|
186
531
|
throw err;
|
|
187
532
|
}
|
|
188
533
|
}
|
|
189
534
|
async function runInteractiveOnboarding(options, prompter) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
535
|
+
let selectedFlow = "quick";
|
|
536
|
+
let selectedProvider = "anthropic";
|
|
537
|
+
const dealsEnabled = true;
|
|
538
|
+
let selectedModel = "";
|
|
539
|
+
let apiKey = "";
|
|
540
|
+
let apiId = 0;
|
|
541
|
+
let apiHash = "";
|
|
542
|
+
let phone = "";
|
|
543
|
+
let userId = 0;
|
|
544
|
+
let tonapiKey;
|
|
545
|
+
let tavilyApiKey;
|
|
546
|
+
let botToken;
|
|
547
|
+
let botUsername;
|
|
548
|
+
let dmPolicy = "open";
|
|
549
|
+
let groupPolicy = "open";
|
|
550
|
+
let requireMention = true;
|
|
551
|
+
let maxAgenticIterations = "5";
|
|
552
|
+
let cocoonInstance = 1e4;
|
|
553
|
+
let buyMaxFloorPercent = 100;
|
|
554
|
+
let sellMinFloorPercent = 105;
|
|
555
|
+
console.clear();
|
|
556
|
+
console.log();
|
|
557
|
+
console.log(wizardFrame(0, STEPS));
|
|
558
|
+
console.log();
|
|
559
|
+
await sleep(800);
|
|
560
|
+
redraw(0);
|
|
561
|
+
noteBox(
|
|
562
|
+
"Your Teleton agent will have FULL CONTROL over:\n\n \u2022 TELEGRAM: Read, send, and delete messages on your behalf\n \u2022 TON WALLET: A new wallet will be generated that the agent\n can use to send transactions autonomously\n\nWe strongly recommend using a dedicated Telegram account.\nOnly fund the generated wallet with amounts you're comfortable\nletting the agent manage.",
|
|
563
|
+
"Security Warning",
|
|
564
|
+
RED
|
|
208
565
|
);
|
|
209
|
-
const acceptRisk = await
|
|
566
|
+
const acceptRisk = await confirm({
|
|
210
567
|
message: "I understand the risks and want to continue",
|
|
211
|
-
|
|
568
|
+
default: false,
|
|
569
|
+
theme: inquirerTheme
|
|
212
570
|
});
|
|
213
571
|
if (!acceptRisk) {
|
|
214
|
-
|
|
572
|
+
console.log(`
|
|
573
|
+
${DIM("Setup cancelled \u2014 you must accept the risks to continue.")}
|
|
574
|
+
`);
|
|
215
575
|
process.exit(1);
|
|
216
576
|
}
|
|
217
|
-
const
|
|
218
|
-
|
|
577
|
+
const spinner = ora2({ color: "cyan" });
|
|
578
|
+
spinner.start(DIM("Creating workspace..."));
|
|
219
579
|
const workspace = await ensureWorkspace({
|
|
220
580
|
workspaceDir: options.workspace,
|
|
221
581
|
ensureTemplates: true
|
|
222
582
|
});
|
|
223
583
|
const isNew = isNewWorkspace(workspace);
|
|
224
|
-
|
|
584
|
+
spinner.succeed(DIM(`Workspace: ${workspace.root}`));
|
|
225
585
|
if (!isNew) {
|
|
226
586
|
prompter.warn("Existing configuration detected");
|
|
227
|
-
const shouldOverwrite = await
|
|
587
|
+
const shouldOverwrite = await confirm({
|
|
228
588
|
message: "Overwrite existing configuration?",
|
|
229
|
-
|
|
589
|
+
default: false,
|
|
590
|
+
theme: inquirerTheme
|
|
230
591
|
});
|
|
231
592
|
if (!shouldOverwrite) {
|
|
232
|
-
|
|
593
|
+
console.log(`
|
|
594
|
+
${DIM("Setup cancelled \u2014 existing configuration preserved.")}
|
|
595
|
+
`);
|
|
233
596
|
return;
|
|
234
597
|
}
|
|
235
598
|
}
|
|
236
|
-
const agentName = await
|
|
599
|
+
const agentName = await input({
|
|
237
600
|
message: "Give your agent a name (optional)",
|
|
238
|
-
|
|
601
|
+
default: "Nova",
|
|
602
|
+
theme: inquirerTheme
|
|
239
603
|
});
|
|
240
604
|
if (agentName && agentName.trim() && existsSync(workspace.identityPath)) {
|
|
241
605
|
const identity = readFileSync(workspace.identityPath, "utf-8");
|
|
242
606
|
const updated = identity.replace("[Your name - pick one or ask your human]", agentName.trim());
|
|
243
607
|
writeFileSync(workspace.identityPath, updated, "utf-8");
|
|
244
608
|
}
|
|
245
|
-
|
|
609
|
+
selectedFlow = await select({
|
|
246
610
|
message: "Installation mode",
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
],
|
|
251
|
-
initialValue: "quick"
|
|
252
|
-
});
|
|
253
|
-
const enabledModules = await prompter.multiselect({
|
|
254
|
-
message: "Enable optional modules (Space to toggle, Enter to confirm)",
|
|
255
|
-
options: [
|
|
611
|
+
default: "quick",
|
|
612
|
+
theme: inquirerTheme,
|
|
613
|
+
choices: [
|
|
256
614
|
{
|
|
257
|
-
value: "
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
615
|
+
value: "quick",
|
|
616
|
+
name: "\u26A1 QuickStart",
|
|
617
|
+
description: "Minimal configuration (recommended)"
|
|
618
|
+
},
|
|
619
|
+
{ value: "advanced", name: "\u2699 Advanced", description: "Detailed configuration" }
|
|
620
|
+
]
|
|
263
621
|
});
|
|
264
|
-
|
|
622
|
+
STEPS[0].value = `${agentName} (${selectedFlow})`;
|
|
623
|
+
redraw(1);
|
|
265
624
|
const providers = getSupportedProviders();
|
|
266
|
-
|
|
625
|
+
selectedProvider = await select({
|
|
267
626
|
message: "AI Provider",
|
|
268
|
-
|
|
627
|
+
default: "anthropic",
|
|
628
|
+
theme: inquirerTheme,
|
|
629
|
+
choices: providers.map((p) => ({
|
|
269
630
|
value: p.id,
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}))
|
|
273
|
-
initialValue: "anthropic"
|
|
631
|
+
name: p.displayName,
|
|
632
|
+
description: p.toolLimit !== null ? `${p.defaultModel} (max ${p.toolLimit} tools)` : `${p.defaultModel}`
|
|
633
|
+
}))
|
|
274
634
|
});
|
|
275
635
|
const providerMeta = getProviderMetadata(selectedProvider);
|
|
276
636
|
if (providerMeta.toolLimit !== null) {
|
|
277
|
-
|
|
637
|
+
noteBox(
|
|
278
638
|
`${providerMeta.displayName} supports max ${providerMeta.toolLimit} tools.
|
|
279
639
|
Teleton currently has ~116 tools. If more tools are added,
|
|
280
640
|
some may be truncated.`,
|
|
281
641
|
"Tool Limit"
|
|
282
642
|
);
|
|
283
643
|
}
|
|
284
|
-
|
|
644
|
+
let localBaseUrl = "";
|
|
645
|
+
if (selectedProvider === "cocoon") {
|
|
646
|
+
apiKey = "";
|
|
647
|
+
const cocoonPort = await input({
|
|
648
|
+
message: "Cocoon proxy HTTP port",
|
|
649
|
+
default: "10000",
|
|
650
|
+
theme: inquirerTheme,
|
|
651
|
+
validate: (value = "") => {
|
|
652
|
+
const n = parseInt(value.trim(), 10);
|
|
653
|
+
return n >= 1 && n <= 65535 ? true : "Must be a port number (1-65535)";
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
cocoonInstance = parseInt(cocoonPort.trim(), 10);
|
|
657
|
+
noteBox(
|
|
658
|
+
`Cocoon Network \u2014 Decentralized LLM on TON
|
|
659
|
+
No API key needed. Requires cocoon-cli running externally.
|
|
660
|
+
Teleton will connect to http://localhost:${cocoonInstance}/v1/`,
|
|
661
|
+
"Cocoon Network",
|
|
662
|
+
TON
|
|
663
|
+
);
|
|
664
|
+
STEPS[1].value = `${providerMeta.displayName} ${DIM(`port ${cocoonInstance}`)}`;
|
|
665
|
+
} else if (selectedProvider === "local") {
|
|
666
|
+
apiKey = "";
|
|
667
|
+
localBaseUrl = await input({
|
|
668
|
+
message: "Local LLM server URL",
|
|
669
|
+
default: "http://localhost:11434/v1",
|
|
670
|
+
theme: inquirerTheme,
|
|
671
|
+
validate: (value = "") => {
|
|
672
|
+
try {
|
|
673
|
+
new URL(value.trim());
|
|
674
|
+
return true;
|
|
675
|
+
} catch {
|
|
676
|
+
return "Must be a valid URL (e.g. http://localhost:11434/v1)";
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
localBaseUrl = localBaseUrl.trim();
|
|
681
|
+
noteBox(
|
|
682
|
+
`Local LLM \u2014 OpenAI-compatible server
|
|
683
|
+
No API key needed. Models auto-discovered at startup.
|
|
684
|
+
Teleton will connect to ${localBaseUrl}`,
|
|
685
|
+
"Local LLM",
|
|
686
|
+
TON
|
|
687
|
+
);
|
|
688
|
+
STEPS[1].value = `${providerMeta.displayName} ${DIM(localBaseUrl)}`;
|
|
689
|
+
} else {
|
|
690
|
+
const envApiKey = process.env.TELETON_API_KEY;
|
|
691
|
+
if (options.apiKey) {
|
|
692
|
+
apiKey = options.apiKey;
|
|
693
|
+
} else if (envApiKey) {
|
|
694
|
+
const validationError = validateApiKeyFormat(selectedProvider, envApiKey);
|
|
695
|
+
if (validationError) {
|
|
696
|
+
prompter.warn(`TELETON_API_KEY env var found but invalid: ${validationError}`);
|
|
697
|
+
apiKey = await password({
|
|
698
|
+
message: `${providerMeta.displayName} API Key (${providerMeta.keyHint})`,
|
|
699
|
+
theme: inquirerTheme,
|
|
700
|
+
validate: (value = "") => validateApiKeyFormat(selectedProvider, value) ?? true
|
|
701
|
+
});
|
|
702
|
+
} else {
|
|
703
|
+
prompter.log(`Using API key from TELETON_API_KEY env var`);
|
|
704
|
+
apiKey = envApiKey;
|
|
705
|
+
}
|
|
706
|
+
} else {
|
|
707
|
+
noteBox(
|
|
708
|
+
`${providerMeta.displayName} API key required.
|
|
709
|
+
Get it at: ${providerMeta.consoleUrl}`,
|
|
710
|
+
"API Key",
|
|
711
|
+
TON
|
|
712
|
+
);
|
|
713
|
+
apiKey = await password({
|
|
714
|
+
message: `${providerMeta.displayName} API Key (${providerMeta.keyHint})`,
|
|
715
|
+
theme: inquirerTheme,
|
|
716
|
+
validate: (value = "") => validateApiKeyFormat(selectedProvider, value) ?? true
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
const maskedKey = apiKey.length > 10 ? apiKey.slice(0, 6) + "..." + apiKey.slice(-4) : "***";
|
|
720
|
+
STEPS[1].value = `${providerMeta.displayName} ${DIM(maskedKey)}`;
|
|
721
|
+
}
|
|
722
|
+
redraw(2);
|
|
723
|
+
noteBox(
|
|
285
724
|
"You need Telegram credentials from https://my.telegram.org/apps\nCreate an application and note the API ID and API Hash",
|
|
286
|
-
"Telegram"
|
|
725
|
+
"Telegram",
|
|
726
|
+
TON
|
|
287
727
|
);
|
|
288
728
|
const envApiId = process.env.TELETON_TG_API_ID;
|
|
289
729
|
const envApiHash = process.env.TELETON_TG_API_HASH;
|
|
290
730
|
const envPhone = process.env.TELETON_TG_PHONE;
|
|
291
|
-
const
|
|
292
|
-
const apiIdStr = options.apiId ? options.apiId.toString() : await prompter.text({
|
|
731
|
+
const apiIdStr = options.apiId ? options.apiId.toString() : await input({
|
|
293
732
|
message: envApiId ? "API ID (from env)" : "API ID (from my.telegram.org)",
|
|
294
|
-
|
|
733
|
+
default: envApiId,
|
|
734
|
+
theme: inquirerTheme,
|
|
295
735
|
validate: (value) => {
|
|
296
736
|
if (!value || isNaN(parseInt(value))) return "Invalid API ID (must be a number)";
|
|
737
|
+
return true;
|
|
297
738
|
}
|
|
298
739
|
});
|
|
299
|
-
|
|
300
|
-
|
|
740
|
+
apiId = parseInt(apiIdStr);
|
|
741
|
+
apiHash = options.apiHash ? options.apiHash : await input({
|
|
301
742
|
message: envApiHash ? "API Hash (from env)" : "API Hash (from my.telegram.org)",
|
|
302
|
-
|
|
743
|
+
default: envApiHash,
|
|
744
|
+
theme: inquirerTheme,
|
|
303
745
|
validate: (value) => {
|
|
304
746
|
if (!value || value.length < 10) return "Invalid API Hash";
|
|
747
|
+
return true;
|
|
305
748
|
}
|
|
306
749
|
});
|
|
307
|
-
|
|
308
|
-
message: envPhone ? "Phone number (from env)" : "Phone number (international format
|
|
309
|
-
|
|
310
|
-
|
|
750
|
+
phone = options.phone ? options.phone : await input({
|
|
751
|
+
message: envPhone ? "Phone number (from env)" : "Phone number (international format)",
|
|
752
|
+
default: envPhone,
|
|
753
|
+
theme: inquirerTheme,
|
|
311
754
|
validate: (value) => {
|
|
312
|
-
if (!value || !value.startsWith("+")) return "
|
|
755
|
+
if (!value || !value.startsWith("+")) return "Must start with +";
|
|
756
|
+
return true;
|
|
313
757
|
}
|
|
314
758
|
});
|
|
315
|
-
|
|
759
|
+
noteBox(
|
|
316
760
|
"To get your Telegram User ID:\n1. Open @userinfobot on Telegram\n2. Send /start\n3. Note the ID displayed",
|
|
317
|
-
"User ID"
|
|
761
|
+
"User ID",
|
|
762
|
+
TON
|
|
318
763
|
);
|
|
319
|
-
const userIdStr = options.userId ? options.userId.toString() : await
|
|
764
|
+
const userIdStr = options.userId ? options.userId.toString() : await input({
|
|
320
765
|
message: "Your Telegram User ID (for admin rights)",
|
|
766
|
+
theme: inquirerTheme,
|
|
321
767
|
validate: (value) => {
|
|
322
768
|
if (!value || isNaN(parseInt(value))) return "Invalid User ID";
|
|
769
|
+
return true;
|
|
323
770
|
}
|
|
324
771
|
});
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
);
|
|
331
|
-
let apiKey;
|
|
332
|
-
if (options.apiKey) {
|
|
333
|
-
apiKey = options.apiKey;
|
|
334
|
-
} else if (envApiKey) {
|
|
335
|
-
const validationError = validateApiKeyFormat(selectedProvider, envApiKey);
|
|
336
|
-
if (validationError) {
|
|
337
|
-
prompter.warn(`TELETON_API_KEY env var found but invalid: ${validationError}`);
|
|
338
|
-
apiKey = await prompter.password({
|
|
339
|
-
message: `${providerMeta.displayName} API Key (${providerMeta.keyHint})`,
|
|
340
|
-
validate: (value = "") => validateApiKeyFormat(selectedProvider, value)
|
|
341
|
-
});
|
|
342
|
-
} else {
|
|
343
|
-
prompter.log(`Using API key from TELETON_API_KEY env var`);
|
|
344
|
-
apiKey = envApiKey;
|
|
345
|
-
}
|
|
346
|
-
} else {
|
|
347
|
-
apiKey = await prompter.password({
|
|
348
|
-
message: `${providerMeta.displayName} API Key (${providerMeta.keyHint})`,
|
|
349
|
-
validate: (value = "") => validateApiKeyFormat(selectedProvider, value)
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
const MODEL_OPTIONS = {
|
|
353
|
-
anthropic: [
|
|
354
|
-
{ value: "claude-opus-4-5-20251101", label: "Claude Opus 4.5", hint: "Most capable, $5/M" },
|
|
355
|
-
{ value: "claude-sonnet-4-0", label: "Claude Sonnet 4", hint: "Balanced, $3/M" },
|
|
356
|
-
{ value: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5", hint: "Fast & cheap, $1/M" },
|
|
357
|
-
{ value: "claude-3-5-haiku-20241022", label: "Claude 3.5 Haiku", hint: "Cheapest, $0.80/M" }
|
|
358
|
-
],
|
|
359
|
-
openai: [
|
|
360
|
-
{ value: "gpt-5", label: "GPT-5", hint: "Most capable, 400K ctx, $1.25/M" },
|
|
361
|
-
{ value: "gpt-4o", label: "GPT-4o", hint: "Balanced, 128K ctx, $2.50/M" },
|
|
362
|
-
{ value: "gpt-4.1", label: "GPT-4.1", hint: "1M ctx, $2/M" },
|
|
363
|
-
{ value: "gpt-4.1-mini", label: "GPT-4.1 Mini", hint: "1M ctx, cheap, $0.40/M" },
|
|
364
|
-
{ value: "o3", label: "o3", hint: "Reasoning, 200K ctx, $2/M" }
|
|
365
|
-
],
|
|
366
|
-
google: [
|
|
367
|
-
{ value: "gemini-2.5-flash", label: "Gemini 2.5 Flash", hint: "Fast, 1M ctx, $0.30/M" },
|
|
368
|
-
{ value: "gemini-2.5-pro", label: "Gemini 2.5 Pro", hint: "Most capable, 1M ctx, $1.25/M" },
|
|
369
|
-
{ value: "gemini-2.0-flash", label: "Gemini 2.0 Flash", hint: "Cheap, 1M ctx, $0.10/M" }
|
|
370
|
-
],
|
|
371
|
-
xai: [
|
|
372
|
-
{ value: "grok-4-fast", label: "Grok 4 Fast", hint: "Vision, 2M ctx, $0.20/M" },
|
|
373
|
-
{ value: "grok-4", label: "Grok 4", hint: "Reasoning, 256K ctx, $3/M" },
|
|
374
|
-
{ value: "grok-3", label: "Grok 3", hint: "Stable, 131K ctx, $3/M" }
|
|
375
|
-
],
|
|
376
|
-
groq: [
|
|
377
|
-
{
|
|
378
|
-
value: "meta-llama/llama-4-maverick-17b-128e-instruct",
|
|
379
|
-
label: "Llama 4 Maverick",
|
|
380
|
-
hint: "Vision, 131K ctx, $0.20/M"
|
|
381
|
-
},
|
|
382
|
-
{ value: "qwen/qwen3-32b", label: "Qwen3 32B", hint: "Reasoning, 131K ctx, $0.29/M" },
|
|
383
|
-
{
|
|
384
|
-
value: "deepseek-r1-distill-llama-70b",
|
|
385
|
-
label: "DeepSeek R1 70B",
|
|
386
|
-
hint: "Reasoning, 131K ctx, $0.75/M"
|
|
387
|
-
},
|
|
388
|
-
{
|
|
389
|
-
value: "llama-3.3-70b-versatile",
|
|
390
|
-
label: "Llama 3.3 70B",
|
|
391
|
-
hint: "General purpose, 131K ctx, $0.59/M"
|
|
392
|
-
}
|
|
393
|
-
],
|
|
394
|
-
openrouter: [
|
|
395
|
-
{ value: "anthropic/claude-opus-4.5", label: "Claude Opus 4.5", hint: "200K ctx, $5/M" },
|
|
396
|
-
{ value: "openai/gpt-5", label: "GPT-5", hint: "400K ctx, $1.25/M" },
|
|
397
|
-
{ value: "google/gemini-2.5-flash", label: "Gemini 2.5 Flash", hint: "1M ctx, $0.30/M" },
|
|
398
|
-
{ value: "deepseek/deepseek-r1", label: "DeepSeek R1", hint: "Reasoning, 64K ctx, $0.70/M" },
|
|
399
|
-
{ value: "x-ai/grok-4", label: "Grok 4", hint: "256K ctx, $3/M" }
|
|
400
|
-
]
|
|
401
|
-
};
|
|
402
|
-
let selectedModel = providerMeta.defaultModel;
|
|
403
|
-
if (flow === "advanced") {
|
|
772
|
+
userId = parseInt(userIdStr);
|
|
773
|
+
STEPS[2].value = `${phone} (ID: ${userId})`;
|
|
774
|
+
redraw(3);
|
|
775
|
+
selectedModel = providerMeta.defaultModel;
|
|
776
|
+
if (selectedFlow === "advanced" && selectedProvider !== "cocoon" && selectedProvider !== "local") {
|
|
404
777
|
const providerModels = MODEL_OPTIONS[selectedProvider] || [];
|
|
405
|
-
const
|
|
778
|
+
const modelChoices = [
|
|
406
779
|
...providerModels,
|
|
407
|
-
{ value: "__custom__",
|
|
780
|
+
{ value: "__custom__", name: "Custom", description: "Enter a model ID manually" }
|
|
408
781
|
];
|
|
409
|
-
const modelChoice = await
|
|
782
|
+
const modelChoice = await select({
|
|
410
783
|
message: "Model",
|
|
411
|
-
|
|
412
|
-
|
|
784
|
+
default: providerMeta.defaultModel,
|
|
785
|
+
theme: inquirerTheme,
|
|
786
|
+
choices: modelChoices
|
|
413
787
|
});
|
|
414
788
|
if (modelChoice === "__custom__") {
|
|
415
|
-
const customModel = await
|
|
789
|
+
const customModel = await input({
|
|
416
790
|
message: "Model ID",
|
|
417
|
-
|
|
418
|
-
|
|
791
|
+
default: providerMeta.defaultModel,
|
|
792
|
+
theme: inquirerTheme
|
|
419
793
|
});
|
|
420
|
-
if (customModel
|
|
421
|
-
selectedModel = customModel.trim();
|
|
422
|
-
}
|
|
794
|
+
if (customModel?.trim()) selectedModel = customModel.trim();
|
|
423
795
|
} else {
|
|
424
796
|
selectedModel = modelChoice;
|
|
425
797
|
}
|
|
426
|
-
|
|
427
|
-
let dmPolicy = "open";
|
|
428
|
-
let groupPolicy = "open";
|
|
429
|
-
let requireMention = true;
|
|
430
|
-
let maxAgenticIterations = "5";
|
|
431
|
-
if (flow === "advanced") {
|
|
432
|
-
dmPolicy = await prompter.select({
|
|
798
|
+
dmPolicy = await select({
|
|
433
799
|
message: "DM policy (private messages)",
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
{ value: "
|
|
438
|
-
|
|
439
|
-
|
|
800
|
+
default: "open",
|
|
801
|
+
theme: inquirerTheme,
|
|
802
|
+
choices: [
|
|
803
|
+
{ value: "open", name: "Open", description: "Reply to everyone" },
|
|
804
|
+
{ value: "allowlist", name: "Allowlist", description: "Only specific users" },
|
|
805
|
+
{ value: "disabled", name: "Disabled", description: "No DM replies" }
|
|
806
|
+
]
|
|
440
807
|
});
|
|
441
|
-
groupPolicy = await
|
|
808
|
+
groupPolicy = await select({
|
|
442
809
|
message: "Group policy",
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
{ value: "
|
|
447
|
-
|
|
448
|
-
|
|
810
|
+
default: "open",
|
|
811
|
+
theme: inquirerTheme,
|
|
812
|
+
choices: [
|
|
813
|
+
{ value: "open", name: "Open", description: "Reply in all groups" },
|
|
814
|
+
{ value: "allowlist", name: "Allowlist", description: "Only specific groups" },
|
|
815
|
+
{ value: "disabled", name: "Disabled", description: "No group replies" }
|
|
816
|
+
]
|
|
449
817
|
});
|
|
450
|
-
requireMention = await
|
|
818
|
+
requireMention = await confirm({
|
|
451
819
|
message: "Require @mention in groups?",
|
|
452
|
-
|
|
820
|
+
default: true,
|
|
821
|
+
theme: inquirerTheme
|
|
453
822
|
});
|
|
454
|
-
maxAgenticIterations = await
|
|
823
|
+
maxAgenticIterations = await input({
|
|
455
824
|
message: "Max agentic iterations (tool call loops per message)",
|
|
456
|
-
|
|
457
|
-
|
|
825
|
+
default: "5",
|
|
826
|
+
theme: inquirerTheme,
|
|
827
|
+
validate: (v) => {
|
|
458
828
|
const n = parseInt(v, 10);
|
|
459
|
-
|
|
829
|
+
return !isNaN(n) && n >= 1 && n <= 50 ? true : "Must be 1\u201350";
|
|
460
830
|
}
|
|
461
831
|
});
|
|
832
|
+
const modelLabel = providerModels.find((m) => m.value === selectedModel)?.name ?? selectedModel;
|
|
833
|
+
STEPS[3].value = `${modelLabel}, ${dmPolicy}/${groupPolicy}`;
|
|
834
|
+
} else {
|
|
835
|
+
STEPS[3].value = `${selectedModel} (defaults)`;
|
|
462
836
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
let buyMaxFloorPercent = 100;
|
|
466
|
-
let sellMinFloorPercent = 105;
|
|
837
|
+
redraw(4);
|
|
838
|
+
const extras = [];
|
|
467
839
|
if (dealsEnabled) {
|
|
468
|
-
const customizeStrategy = await
|
|
469
|
-
message:
|
|
470
|
-
|
|
840
|
+
const customizeStrategy = await confirm({
|
|
841
|
+
message: `Customize trading thresholds? ${DIM("(default: buy \u2264 floor, sell \u2265 floor +5%)")}`,
|
|
842
|
+
default: false,
|
|
843
|
+
theme: inquirerTheme
|
|
471
844
|
});
|
|
472
845
|
if (customizeStrategy) {
|
|
473
|
-
const buyInput = await
|
|
846
|
+
const buyInput = await input({
|
|
474
847
|
message: "Max buy price (% of floor price)",
|
|
475
|
-
|
|
476
|
-
|
|
848
|
+
default: "100",
|
|
849
|
+
theme: inquirerTheme,
|
|
850
|
+
validate: (v) => {
|
|
477
851
|
const n = parseInt(v, 10);
|
|
478
|
-
|
|
852
|
+
return !isNaN(n) && n >= 50 && n <= 150 ? true : "Must be 50\u2013150";
|
|
479
853
|
}
|
|
480
854
|
});
|
|
481
855
|
buyMaxFloorPercent = parseInt(buyInput, 10);
|
|
482
|
-
const sellInput = await
|
|
856
|
+
const sellInput = await input({
|
|
483
857
|
message: "Min sell price (% of floor price)",
|
|
484
|
-
|
|
485
|
-
|
|
858
|
+
default: "105",
|
|
859
|
+
theme: inquirerTheme,
|
|
860
|
+
validate: (v) => {
|
|
486
861
|
const n = parseInt(v, 10);
|
|
487
|
-
|
|
862
|
+
return !isNaN(n) && n >= 100 && n <= 200 ? true : "Must be 100\u2013200";
|
|
488
863
|
}
|
|
489
864
|
});
|
|
490
865
|
sellMinFloorPercent = parseInt(sellInput, 10);
|
|
491
866
|
}
|
|
492
|
-
|
|
493
|
-
if (dealsEnabled) {
|
|
494
|
-
prompter.note(
|
|
867
|
+
noteBox(
|
|
495
868
|
"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"
|
|
869
|
+
"Deals Bot",
|
|
870
|
+
TON
|
|
497
871
|
);
|
|
498
|
-
const tokenInput = await
|
|
872
|
+
const tokenInput = await password({
|
|
499
873
|
message: "Bot token (from @BotFather)",
|
|
874
|
+
theme: inquirerTheme,
|
|
500
875
|
validate: (value) => {
|
|
501
|
-
if (!value || !value.includes(":")) return "Invalid
|
|
876
|
+
if (!value || !value.includes(":")) return "Invalid format (expected id:hash)";
|
|
877
|
+
return true;
|
|
502
878
|
}
|
|
503
879
|
});
|
|
504
|
-
|
|
880
|
+
spinner.start(DIM("Validating bot token..."));
|
|
505
881
|
try {
|
|
506
882
|
const res = await fetchWithTimeout(`https://api.telegram.org/bot${tokenInput}/getMe`);
|
|
507
883
|
const data = await res.json();
|
|
508
884
|
if (!data.ok) {
|
|
509
|
-
|
|
885
|
+
spinner.warn(DIM("Bot token is invalid \u2014 skipping bot setup"));
|
|
510
886
|
} else {
|
|
511
887
|
botToken = tokenInput;
|
|
512
888
|
botUsername = data.result.username;
|
|
513
|
-
|
|
889
|
+
spinner.succeed(DIM(`Bot verified: @${botUsername}`));
|
|
514
890
|
}
|
|
515
891
|
} catch {
|
|
516
|
-
|
|
892
|
+
spinner.warn(DIM("Could not validate bot token (network error) \u2014 saving anyway"));
|
|
517
893
|
botToken = tokenInput;
|
|
518
|
-
const usernameInput = await
|
|
894
|
+
const usernameInput = await input({
|
|
519
895
|
message: "Bot username (without @)",
|
|
896
|
+
theme: inquirerTheme,
|
|
520
897
|
validate: (value) => {
|
|
521
898
|
if (!value || value.length < 3) return "Username too short";
|
|
899
|
+
return true;
|
|
522
900
|
}
|
|
523
901
|
});
|
|
524
902
|
botUsername = usernameInput;
|
|
525
903
|
}
|
|
904
|
+
extras.push("Deals");
|
|
526
905
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
906
|
+
const setupTonapi = await confirm({
|
|
907
|
+
message: `Add a TonAPI key? ${DIM("(optional, recommended for 10x rate limits)")}`,
|
|
908
|
+
default: false,
|
|
909
|
+
theme: inquirerTheme
|
|
531
910
|
});
|
|
532
911
|
if (setupTonapi) {
|
|
533
|
-
|
|
912
|
+
noteBox(
|
|
534
913
|
"Without key: 1 req/s (you will hit rate limits)\nWith free key: 10 req/s (recommended)\n\nOpen @tonapibot on Telegram \u2192 tap the mini app \u2192 generate a server key",
|
|
535
|
-
"TonAPI"
|
|
914
|
+
"TonAPI",
|
|
915
|
+
TON
|
|
536
916
|
);
|
|
537
|
-
const keyInput = await
|
|
917
|
+
const keyInput = await input({
|
|
538
918
|
message: "TonAPI key",
|
|
919
|
+
theme: inquirerTheme,
|
|
539
920
|
validate: (v) => {
|
|
540
921
|
if (!v || v.length < 10) return "Key too short";
|
|
922
|
+
return true;
|
|
541
923
|
}
|
|
542
924
|
});
|
|
543
925
|
tonapiKey = keyInput;
|
|
926
|
+
extras.push("TonAPI");
|
|
544
927
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
928
|
+
const setupTavily = await confirm({
|
|
929
|
+
message: `Enable web search? ${DIM("(free Tavily key \u2014 1,000 req/month)")}`,
|
|
930
|
+
default: false,
|
|
931
|
+
theme: inquirerTheme
|
|
549
932
|
});
|
|
550
933
|
if (setupTavily) {
|
|
551
|
-
|
|
934
|
+
noteBox(
|
|
552
935
|
"Web search lets your agent search the internet and read web pages.\n\nTo get your free API key (takes 30 seconds):\n\n 1. Go to https://app.tavily.com/sign-in\n 2. Create an account (email or Google/GitHub)\n 3. Your API key is displayed on the dashboard\n (starts with tvly-)\n\nFree plan: 1,000 requests/month \u2014 no credit card required.",
|
|
553
|
-
"Tavily \u2014 Web Search API"
|
|
936
|
+
"Tavily \u2014 Web Search API",
|
|
937
|
+
TON
|
|
554
938
|
);
|
|
555
|
-
const keyInput = await
|
|
939
|
+
const keyInput = await input({
|
|
556
940
|
message: "Tavily API key (starts with tvly-)",
|
|
941
|
+
theme: inquirerTheme,
|
|
557
942
|
validate: (v) => {
|
|
558
|
-
if (!v || !v.startsWith("tvly-")) return "
|
|
943
|
+
if (!v || !v.startsWith("tvly-")) return "Should start with tvly-";
|
|
944
|
+
return true;
|
|
559
945
|
}
|
|
560
946
|
});
|
|
561
947
|
tavilyApiKey = keyInput;
|
|
948
|
+
extras.push("Tavily");
|
|
949
|
+
}
|
|
950
|
+
STEPS[4].value = extras.length ? extras.join(", ") : "defaults";
|
|
951
|
+
redraw(5);
|
|
952
|
+
let wallet;
|
|
953
|
+
const existingWallet = walletExists() ? loadWallet() : null;
|
|
954
|
+
if (existingWallet) {
|
|
955
|
+
noteBox(`Existing wallet found: ${existingWallet.address}`, "TON Wallet", TON);
|
|
956
|
+
const walletAction = await select({
|
|
957
|
+
message: "A TON wallet already exists. What do you want to do?",
|
|
958
|
+
default: "keep",
|
|
959
|
+
theme: inquirerTheme,
|
|
960
|
+
choices: [
|
|
961
|
+
{ value: "keep", name: "Keep existing", description: existingWallet.address },
|
|
962
|
+
{
|
|
963
|
+
value: "regenerate",
|
|
964
|
+
name: "Generate new",
|
|
965
|
+
description: "WARNING: old wallet will be lost"
|
|
966
|
+
},
|
|
967
|
+
{ value: "import", name: "Import mnemonic", description: "Restore from 24-word seed" }
|
|
968
|
+
]
|
|
969
|
+
});
|
|
970
|
+
if (walletAction === "keep") {
|
|
971
|
+
wallet = existingWallet;
|
|
972
|
+
} else if (walletAction === "import") {
|
|
973
|
+
const mnemonicInput = await input({
|
|
974
|
+
message: "Enter your 24-word mnemonic (space-separated)",
|
|
975
|
+
theme: inquirerTheme,
|
|
976
|
+
validate: (value = "") => {
|
|
977
|
+
const words = value.trim().split(/\s+/);
|
|
978
|
+
return words.length === 24 ? true : `Expected 24 words, got ${words.length}`;
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
spinner.start(DIM("Importing wallet..."));
|
|
982
|
+
wallet = await importWallet(mnemonicInput.trim().split(/\s+/));
|
|
983
|
+
saveWallet(wallet);
|
|
984
|
+
spinner.succeed(DIM(`Wallet imported: ${wallet.address}`));
|
|
985
|
+
} else {
|
|
986
|
+
spinner.start(DIM("Generating new TON wallet..."));
|
|
987
|
+
wallet = await generateWallet();
|
|
988
|
+
saveWallet(wallet);
|
|
989
|
+
spinner.succeed(DIM("New TON wallet generated"));
|
|
990
|
+
}
|
|
991
|
+
} else {
|
|
992
|
+
spinner.start(DIM("Generating TON wallet..."));
|
|
993
|
+
wallet = await generateWallet();
|
|
994
|
+
saveWallet(wallet);
|
|
995
|
+
spinner.succeed(DIM("TON wallet generated"));
|
|
562
996
|
}
|
|
997
|
+
if (!existingWallet || wallet !== existingWallet) {
|
|
998
|
+
const W = FRAME_WIDTH;
|
|
999
|
+
const mnTitle = " \u26A0 BACKUP REQUIRED \u2014 WRITE DOWN THESE 24 WORDS";
|
|
1000
|
+
console.log();
|
|
1001
|
+
console.log(RED(` \u250C${"\u2500".repeat(W)}\u2510`));
|
|
1002
|
+
console.log(RED(" \u2502") + RED.bold(padRight(mnTitle, W)) + RED("\u2502"));
|
|
1003
|
+
console.log(RED(` \u251C${"\u2500".repeat(W)}\u2524`));
|
|
1004
|
+
console.log(RED(" \u2502") + " ".repeat(W) + RED("\u2502"));
|
|
1005
|
+
const cols = 4;
|
|
1006
|
+
const wordWidth = Math.max(10, Math.floor((W - 8) / cols) - 5);
|
|
1007
|
+
const words = wallet.mnemonic;
|
|
1008
|
+
for (let r = 0; r < 6; r++) {
|
|
1009
|
+
const parts = [];
|
|
1010
|
+
for (let c = 0; c < cols; c++) {
|
|
1011
|
+
const idx = r * cols + c;
|
|
1012
|
+
const num = String(idx + 1).padStart(2, " ");
|
|
1013
|
+
parts.push(`${DIM(num + ".")} ${WHITE(padRight(words[idx], wordWidth))}`);
|
|
1014
|
+
}
|
|
1015
|
+
const line = ` ${parts.join(" ")}`;
|
|
1016
|
+
const visPad = W - stripAnsi(line).length;
|
|
1017
|
+
console.log(RED(" \u2502") + line + " ".repeat(Math.max(0, visPad)) + RED("\u2502"));
|
|
1018
|
+
}
|
|
1019
|
+
console.log(RED(" \u2502") + " ".repeat(W) + RED("\u2502"));
|
|
1020
|
+
console.log(
|
|
1021
|
+
RED(" \u2502") + padRightAnsi(DIM(" These words allow you to recover your wallet."), W) + RED("\u2502")
|
|
1022
|
+
);
|
|
1023
|
+
console.log(
|
|
1024
|
+
RED(" \u2502") + padRightAnsi(DIM(" Without them, you will lose access to your TON."), W) + RED("\u2502")
|
|
1025
|
+
);
|
|
1026
|
+
console.log(
|
|
1027
|
+
RED(" \u2502") + padRightAnsi(DIM(" Write them on paper and keep them safe."), W) + RED("\u2502")
|
|
1028
|
+
);
|
|
1029
|
+
console.log(RED(" \u2502") + " ".repeat(W) + RED("\u2502"));
|
|
1030
|
+
console.log(RED(` \u2514${"\u2500".repeat(W)}\u2518`));
|
|
1031
|
+
console.log();
|
|
1032
|
+
}
|
|
1033
|
+
STEPS[5].value = `${wallet.address.slice(0, 8)}...${wallet.address.slice(-4)}`;
|
|
1034
|
+
redraw(6);
|
|
563
1035
|
const config = {
|
|
564
1036
|
meta: {
|
|
565
1037
|
version: "1.0.0",
|
|
@@ -569,6 +1041,7 @@ Get it at: ${providerMeta.consoleUrl}`,
|
|
|
569
1041
|
agent: {
|
|
570
1042
|
provider: selectedProvider,
|
|
571
1043
|
api_key: apiKey,
|
|
1044
|
+
...selectedProvider === "local" && localBaseUrl ? { base_url: localBaseUrl } : {},
|
|
572
1045
|
model: selectedModel,
|
|
573
1046
|
max_tokens: 4096,
|
|
574
1047
|
temperature: 0.7,
|
|
@@ -637,68 +1110,28 @@ Get it at: ${providerMeta.consoleUrl}`,
|
|
|
637
1110
|
],
|
|
638
1111
|
skip_unlimited_providers: false
|
|
639
1112
|
},
|
|
1113
|
+
logging: { level: "info", pretty: true },
|
|
640
1114
|
mcp: { servers: {} },
|
|
641
1115
|
plugins: {},
|
|
1116
|
+
...selectedProvider === "cocoon" ? { cocoon: { port: cocoonInstance } } : {},
|
|
642
1117
|
tonapi_key: tonapiKey,
|
|
643
1118
|
tavily_api_key: tavilyApiKey
|
|
644
1119
|
};
|
|
645
|
-
|
|
1120
|
+
spinner.start(DIM("Saving configuration..."));
|
|
646
1121
|
const configYaml = YAML.stringify(config);
|
|
647
|
-
writeFileSync(workspace.configPath, configYaml, "utf-8");
|
|
648
|
-
|
|
649
|
-
spinner2.stop("\u2713 Configuration saved");
|
|
650
|
-
let wallet;
|
|
651
|
-
const existingWallet = walletExists() ? loadWallet() : null;
|
|
652
|
-
if (existingWallet) {
|
|
653
|
-
prompter.note(`Existing wallet found: ${existingWallet.address}`, "TON Wallet");
|
|
654
|
-
const walletAction = await prompter.select({
|
|
655
|
-
message: "A TON wallet already exists. What do you want to do?",
|
|
656
|
-
options: [
|
|
657
|
-
{ value: "keep", label: "Keep existing", hint: `${existingWallet.address}` },
|
|
658
|
-
{ value: "regenerate", label: "Generate new", hint: "WARNING: old wallet will be lost" },
|
|
659
|
-
{ value: "import", label: "Import mnemonic", hint: "Restore from 24-word seed" }
|
|
660
|
-
],
|
|
661
|
-
initialValue: "keep"
|
|
662
|
-
});
|
|
663
|
-
if (walletAction === "keep") {
|
|
664
|
-
wallet = existingWallet;
|
|
665
|
-
} else if (walletAction === "import") {
|
|
666
|
-
const mnemonicInput = await prompter.text({
|
|
667
|
-
message: "Enter your 24-word mnemonic (space-separated)",
|
|
668
|
-
validate: (value = "") => {
|
|
669
|
-
const words = value.trim().split(/\s+/);
|
|
670
|
-
if (words.length !== 24) return `Expected 24 words, got ${words.length}`;
|
|
671
|
-
}
|
|
672
|
-
});
|
|
673
|
-
spinner2.start("Importing wallet...");
|
|
674
|
-
wallet = await importWallet(mnemonicInput.trim().split(/\s+/));
|
|
675
|
-
saveWallet(wallet);
|
|
676
|
-
spinner2.stop(`\u2713 Wallet imported: ${wallet.address}`);
|
|
677
|
-
} else {
|
|
678
|
-
spinner2.start("Generating new TON wallet...");
|
|
679
|
-
wallet = await generateWallet();
|
|
680
|
-
saveWallet(wallet);
|
|
681
|
-
spinner2.stop("\u2713 New TON wallet generated");
|
|
682
|
-
}
|
|
683
|
-
} else {
|
|
684
|
-
spinner2.start("Generating TON wallet...");
|
|
685
|
-
wallet = await generateWallet();
|
|
686
|
-
saveWallet(wallet);
|
|
687
|
-
spinner2.stop("\u2713 TON wallet generated");
|
|
688
|
-
}
|
|
689
|
-
if (!existingWallet || wallet !== existingWallet) {
|
|
690
|
-
prompter.note(
|
|
691
|
-
"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.",
|
|
692
|
-
"Mnemonic Seed (24 words)"
|
|
693
|
-
);
|
|
694
|
-
}
|
|
1122
|
+
writeFileSync(workspace.configPath, configYaml, { encoding: "utf-8", mode: 384 });
|
|
1123
|
+
spinner.succeed(DIM(`Configuration saved: ${workspace.configPath}`));
|
|
695
1124
|
let telegramConnected = false;
|
|
696
|
-
const connectNow = await
|
|
697
|
-
message:
|
|
698
|
-
|
|
1125
|
+
const connectNow = await confirm({
|
|
1126
|
+
message: `Connect to Telegram now? ${DIM("(verification code will be sent to your phone)")}`,
|
|
1127
|
+
default: true,
|
|
1128
|
+
theme: inquirerTheme
|
|
699
1129
|
});
|
|
700
1130
|
if (connectNow) {
|
|
701
|
-
|
|
1131
|
+
console.log(
|
|
1132
|
+
`
|
|
1133
|
+
${DIM("Connecting to Telegram... Check your phone for the verification code.")}`
|
|
1134
|
+
);
|
|
702
1135
|
try {
|
|
703
1136
|
const sessionPath = join(TELETON_ROOT, "telegram_session.txt");
|
|
704
1137
|
const client = new TelegramUserClient({
|
|
@@ -711,53 +1144,54 @@ Get it at: ${providerMeta.consoleUrl}`,
|
|
|
711
1144
|
const me = client.getMe();
|
|
712
1145
|
await client.disconnect();
|
|
713
1146
|
telegramConnected = true;
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
1147
|
+
const displayName = `${me?.firstName || ""}${me?.username ? ` (@${me.username})` : ""}`;
|
|
1148
|
+
console.log(` ${GREEN("\u2713")} ${DIM("Telegram connected as")} ${CYAN(displayName)}
|
|
1149
|
+
`);
|
|
1150
|
+
STEPS[6].value = `Connected${me?.username ? ` (@${me.username})` : ""}`;
|
|
717
1151
|
} catch (err) {
|
|
718
1152
|
prompter.warn(
|
|
719
1153
|
`Telegram connection failed: ${err instanceof Error ? err.message : String(err)}
|
|
720
1154
|
You can authenticate later when running: teleton start`
|
|
721
1155
|
);
|
|
1156
|
+
STEPS[6].value = "Auth on first start";
|
|
722
1157
|
}
|
|
723
|
-
}
|
|
724
|
-
prompter.note(
|
|
725
|
-
`Workspace: ${workspace.root}
|
|
726
|
-
Config: ${workspace.configPath}
|
|
727
|
-
Templates: SOUL.md, MEMORY.md, IDENTITY.md, USER.md
|
|
728
|
-
Telegram: ${phone} (API ID: ${apiId})${telegramConnected ? " \u2713 connected" : ""}
|
|
729
|
-
Admin: User ID ${userId}
|
|
730
|
-
Provider: ${providerMeta.displayName}
|
|
731
|
-
Model: ${selectedModel}
|
|
732
|
-
TON Wallet: ${wallet.address}
|
|
733
|
-
Web Search: ${tavilyApiKey ? "Tavily \u2713" : "disabled (no Tavily key)"}`,
|
|
734
|
-
"Setup complete"
|
|
735
|
-
);
|
|
736
|
-
if (telegramConnected) {
|
|
737
|
-
prompter.note(
|
|
738
|
-
"Next steps:\n\n1. Start the agent:\n $ teleton start\n\n2. Send /boot as your first message to bootstrap\n the agent's personality and get to know each other",
|
|
739
|
-
"Ready"
|
|
740
|
-
);
|
|
741
1158
|
} else {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
1159
|
+
console.log(`
|
|
1160
|
+
${DIM("You can authenticate later when running: teleton start")}
|
|
1161
|
+
`);
|
|
1162
|
+
STEPS[6].value = "Auth on first start";
|
|
746
1163
|
}
|
|
747
|
-
|
|
1164
|
+
console.clear();
|
|
1165
|
+
console.log();
|
|
1166
|
+
console.log(wizardFrame(STEPS.length, STEPS));
|
|
1167
|
+
console.log();
|
|
1168
|
+
console.log(finalSummaryBox(STEPS, telegramConnected));
|
|
1169
|
+
console.log();
|
|
1170
|
+
console.log(
|
|
1171
|
+
` ${GREEN.bold("\u2714")} ${GREEN.bold("Setup complete!")} ${DIM(`Config saved to ${workspace.configPath}`)}`
|
|
1172
|
+
);
|
|
1173
|
+
console.log(` ${TON.bold("\u26A1")} Good luck!
|
|
1174
|
+
`);
|
|
748
1175
|
}
|
|
749
1176
|
async function runNonInteractiveOnboarding(options, prompter) {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
);
|
|
1177
|
+
const selectedProvider = options.provider || "anthropic";
|
|
1178
|
+
const needsApiKey = selectedProvider !== "cocoon" && selectedProvider !== "local";
|
|
1179
|
+
if (!options.apiId || !options.apiHash || !options.phone || !options.userId) {
|
|
1180
|
+
prompter.error("Non-interactive mode requires: --api-id, --api-hash, --phone, --user-id");
|
|
1181
|
+
process.exit(1);
|
|
1182
|
+
}
|
|
1183
|
+
if (needsApiKey && !options.apiKey) {
|
|
1184
|
+
prompter.error(`Non-interactive mode requires --api-key for provider "${selectedProvider}"`);
|
|
1185
|
+
process.exit(1);
|
|
1186
|
+
}
|
|
1187
|
+
if (selectedProvider === "local" && !options.baseUrl) {
|
|
1188
|
+
prompter.error("Non-interactive mode requires --base-url for local provider");
|
|
754
1189
|
process.exit(1);
|
|
755
1190
|
}
|
|
756
1191
|
const workspace = await ensureWorkspace({
|
|
757
1192
|
workspaceDir: options.workspace,
|
|
758
1193
|
ensureTemplates: true
|
|
759
1194
|
});
|
|
760
|
-
const selectedProvider = options.provider || "anthropic";
|
|
761
1195
|
const providerMeta = getProviderMetadata(selectedProvider);
|
|
762
1196
|
const config = {
|
|
763
1197
|
meta: {
|
|
@@ -767,7 +1201,8 @@ async function runNonInteractiveOnboarding(options, prompter) {
|
|
|
767
1201
|
},
|
|
768
1202
|
agent: {
|
|
769
1203
|
provider: selectedProvider,
|
|
770
|
-
api_key: options.apiKey,
|
|
1204
|
+
api_key: options.apiKey || "",
|
|
1205
|
+
...options.baseUrl ? { base_url: options.baseUrl } : {},
|
|
771
1206
|
model: providerMeta.defaultModel,
|
|
772
1207
|
max_tokens: 4096,
|
|
773
1208
|
temperature: 0.7,
|
|
@@ -832,14 +1267,14 @@ async function runNonInteractiveOnboarding(options, prompter) {
|
|
|
832
1267
|
],
|
|
833
1268
|
skip_unlimited_providers: false
|
|
834
1269
|
},
|
|
1270
|
+
logging: { level: "info", pretty: true },
|
|
835
1271
|
mcp: { servers: {} },
|
|
836
1272
|
plugins: {},
|
|
837
1273
|
tavily_api_key: options.tavilyApiKey
|
|
838
1274
|
};
|
|
839
1275
|
const configYaml = YAML.stringify(config);
|
|
840
|
-
writeFileSync(workspace.configPath, configYaml, "utf-8");
|
|
841
|
-
|
|
842
|
-
prompter.success(`\u2713 Configuration created: ${workspace.configPath}`);
|
|
1276
|
+
writeFileSync(workspace.configPath, configYaml, { encoding: "utf-8", mode: 384 });
|
|
1277
|
+
prompter.success(`Configuration created: ${workspace.configPath}`);
|
|
843
1278
|
}
|
|
844
1279
|
|
|
845
1280
|
// src/cli/commands/doctor.ts
|
|
@@ -951,6 +1386,13 @@ async function checkApiKey(workspaceDir) {
|
|
|
951
1386
|
message: `Unknown provider: ${provider}`
|
|
952
1387
|
};
|
|
953
1388
|
}
|
|
1389
|
+
if (provider === "cocoon" || provider === "local") {
|
|
1390
|
+
return {
|
|
1391
|
+
name: `${meta.displayName}`,
|
|
1392
|
+
status: "ok",
|
|
1393
|
+
message: "No API key needed"
|
|
1394
|
+
};
|
|
1395
|
+
}
|
|
954
1396
|
if (!apiKey) {
|
|
955
1397
|
return {
|
|
956
1398
|
name: `${meta.displayName} API key`,
|
|
@@ -966,8 +1408,8 @@ async function checkApiKey(workspaceDir) {
|
|
|
966
1408
|
message: validationError
|
|
967
1409
|
};
|
|
968
1410
|
}
|
|
969
|
-
const maskLen = Math.min(
|
|
970
|
-
const masked = apiKey.substring(0, maskLen) + "
|
|
1411
|
+
const maskLen = Math.min(4, Math.max(0, apiKey.length - 4));
|
|
1412
|
+
const masked = apiKey.substring(0, maskLen) + "****" + apiKey.substring(apiKey.length - 4);
|
|
971
1413
|
return {
|
|
972
1414
|
name: `${meta.displayName} API key`,
|
|
973
1415
|
status: "ok",
|
|
@@ -1250,8 +1692,8 @@ async function mcpAddCommand(pkg, extraArgs, options) {
|
|
|
1250
1692
|
if (options.url) {
|
|
1251
1693
|
entry.url = pkg;
|
|
1252
1694
|
} else {
|
|
1253
|
-
|
|
1254
|
-
entry.
|
|
1695
|
+
entry.command = "npx";
|
|
1696
|
+
entry.args = ["-y", pkg, ...extraArgs];
|
|
1255
1697
|
}
|
|
1256
1698
|
if (options.scope && options.scope !== "always") {
|
|
1257
1699
|
entry.scope = options.scope;
|
|
@@ -1458,20 +1900,23 @@ function findPackageJson() {
|
|
|
1458
1900
|
var packageJson = findPackageJson();
|
|
1459
1901
|
var program = new Command();
|
|
1460
1902
|
program.name("teleton").description("Teleton Agent - Personal AI Agent for Telegram").version(packageJson.version);
|
|
1461
|
-
program.command("setup").description("Interactive wizard to set up Teleton").option("--workspace <dir>", "Workspace directory").option("--non-interactive", "Non-interactive mode").option("--api-id <id>", "Telegram API ID").option("--api-hash <hash>", "Telegram API Hash").option("--phone <number>", "Phone number").option("--api-key <key>", "
|
|
1903
|
+
program.command("setup").description("Interactive wizard to set up Teleton").option("--workspace <dir>", "Workspace directory").option("--non-interactive", "Non-interactive mode").option("--ui", "Launch web-based setup wizard").option("--ui-port <port>", "Port for setup WebUI", "7777").option("--api-id <id>", "Telegram API ID").option("--api-hash <hash>", "Telegram API Hash").option("--phone <number>", "Phone number").option("--api-key <key>", "LLM provider API key").option("--base-url <url>", "Base URL for local LLM server").option("--user-id <id>", "Telegram User ID").option("--tavily-api-key <key>", "Tavily API key for web search").action(async (options) => {
|
|
1462
1904
|
try {
|
|
1463
1905
|
await onboardCommand({
|
|
1464
1906
|
workspace: options.workspace,
|
|
1465
1907
|
nonInteractive: options.nonInteractive,
|
|
1908
|
+
ui: options.ui,
|
|
1909
|
+
uiPort: options.uiPort,
|
|
1466
1910
|
apiId: options.apiId ? parseInt(options.apiId) : void 0,
|
|
1467
1911
|
apiHash: options.apiHash,
|
|
1468
1912
|
phone: options.phone,
|
|
1469
1913
|
apiKey: options.apiKey,
|
|
1914
|
+
baseUrl: options.baseUrl,
|
|
1470
1915
|
userId: options.userId ? parseInt(options.userId) : void 0,
|
|
1471
1916
|
tavilyApiKey: options.tavilyApiKey
|
|
1472
1917
|
});
|
|
1473
1918
|
} catch (error) {
|
|
1474
|
-
console.error("Error:",
|
|
1919
|
+
console.error("Error:", getErrorMessage(error));
|
|
1475
1920
|
process.exit(1);
|
|
1476
1921
|
}
|
|
1477
1922
|
});
|
|
@@ -1491,7 +1936,7 @@ program.command("start").description("Start the Teleton agent").option("-c, --co
|
|
|
1491
1936
|
}
|
|
1492
1937
|
await main(options.config);
|
|
1493
1938
|
} catch (error) {
|
|
1494
|
-
console.error("Error:",
|
|
1939
|
+
console.error("Error:", getErrorMessage(error));
|
|
1495
1940
|
process.exit(1);
|
|
1496
1941
|
}
|
|
1497
1942
|
});
|
|
@@ -1499,7 +1944,7 @@ program.command("doctor").description("Run system health checks").action(async (
|
|
|
1499
1944
|
try {
|
|
1500
1945
|
await doctorCommand();
|
|
1501
1946
|
} catch (error) {
|
|
1502
|
-
console.error("Error:",
|
|
1947
|
+
console.error("Error:", getErrorMessage(error));
|
|
1503
1948
|
process.exit(1);
|
|
1504
1949
|
}
|
|
1505
1950
|
});
|
|
@@ -1515,7 +1960,7 @@ mcp.command("add <package> [args...]").description(
|
|
|
1515
1960
|
try {
|
|
1516
1961
|
await mcpAddCommand(pkg, args, options);
|
|
1517
1962
|
} catch (error) {
|
|
1518
|
-
console.error("Error:",
|
|
1963
|
+
console.error("Error:", getErrorMessage(error));
|
|
1519
1964
|
process.exit(1);
|
|
1520
1965
|
}
|
|
1521
1966
|
});
|
|
@@ -1523,7 +1968,7 @@ mcp.command("remove <name>").description("Remove an MCP server by name").option(
|
|
|
1523
1968
|
try {
|
|
1524
1969
|
await mcpRemoveCommand(name, options);
|
|
1525
1970
|
} catch (error) {
|
|
1526
|
-
console.error("Error:",
|
|
1971
|
+
console.error("Error:", getErrorMessage(error));
|
|
1527
1972
|
process.exit(1);
|
|
1528
1973
|
}
|
|
1529
1974
|
});
|
|
@@ -1531,7 +1976,7 @@ mcp.command("list").description("List configured MCP servers").option("-c, --con
|
|
|
1531
1976
|
try {
|
|
1532
1977
|
await mcpListCommand(options);
|
|
1533
1978
|
} catch (error) {
|
|
1534
|
-
console.error("Error:",
|
|
1979
|
+
console.error("Error:", getErrorMessage(error));
|
|
1535
1980
|
process.exit(1);
|
|
1536
1981
|
}
|
|
1537
1982
|
});
|
|
@@ -1539,7 +1984,7 @@ program.command("config").description("Manage configuration keys (set, get, list
|
|
|
1539
1984
|
try {
|
|
1540
1985
|
await configCommand(action, key, value, options);
|
|
1541
1986
|
} catch (error) {
|
|
1542
|
-
console.error("Error:",
|
|
1987
|
+
console.error("Error:", getErrorMessage(error));
|
|
1543
1988
|
process.exit(1);
|
|
1544
1989
|
}
|
|
1545
1990
|
});
|