@openacp/cli 0.6.9 → 0.6.10
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 +100 -154
- package/dist/{adapter-LNEGLMOE.js → adapter-ZOANORGM.js} +3 -3
- package/dist/{chunk-H5P2C6H4.js → chunk-CS3KCJ5D.js} +86 -38
- package/dist/chunk-CS3KCJ5D.js.map +1 -0
- package/dist/{chunk-BDYVCIBH.js → chunk-LCRLAV4G.js} +536 -186
- package/dist/chunk-LCRLAV4G.js.map +1 -0
- package/dist/{chunk-BN3X7UXB.js → chunk-MKHUZLII.js} +2 -2
- package/dist/chunk-MKHUZLII.js.map +1 -0
- package/dist/{chunk-JUYDFUSN.js → chunk-OWP7RZ62.js} +38 -14
- package/dist/chunk-OWP7RZ62.js.map +1 -0
- package/dist/cli.js +11 -6
- package/dist/cli.js.map +1 -1
- package/dist/{config-editor-RVLWZLVB.js → config-editor-QQTZMWGD.js} +3 -3
- package/dist/{discord-7IVQKB2H.js → discord-OMC52Y54.js} +238 -82
- package/dist/discord-OMC52Y54.js.map +1 -0
- package/dist/index.js +4 -4
- package/dist/{main-ZK4MPMBG.js → main-XOZCLFUK.js} +9 -9
- package/dist/main-XOZCLFUK.js.map +1 -0
- package/dist/{setup-3GQSYBE4.js → setup-XHS4OMPM.js} +4 -2
- package/package.json +1 -1
- package/dist/chunk-BDYVCIBH.js.map +0 -1
- package/dist/chunk-BN3X7UXB.js.map +0 -1
- package/dist/chunk-H5P2C6H4.js.map +0 -1
- package/dist/chunk-JUYDFUSN.js.map +0 -1
- package/dist/discord-7IVQKB2H.js.map +0 -1
- package/dist/main-ZK4MPMBG.js.map +0 -1
- /package/dist/{adapter-LNEGLMOE.js.map → adapter-ZOANORGM.js.map} +0 -0
- /package/dist/{config-editor-RVLWZLVB.js.map → config-editor-QQTZMWGD.js.map} +0 -0
- /package/dist/{setup-3GQSYBE4.js.map → setup-XHS4OMPM.js.map} +0 -0
|
@@ -5,16 +5,24 @@ import {
|
|
|
5
5
|
expandHome
|
|
6
6
|
} from "./chunk-33RP6K2O.js";
|
|
7
7
|
|
|
8
|
-
// src/core/setup.ts
|
|
9
|
-
import
|
|
8
|
+
// src/core/setup/wizard.ts
|
|
9
|
+
import * as clack9 from "@clack/prompts";
|
|
10
|
+
|
|
11
|
+
// src/core/setup/types.ts
|
|
12
|
+
var ONBOARD_SECTION_OPTIONS = [
|
|
13
|
+
{ value: "channels", label: "Channels", hint: "Link/update messaging platforms" },
|
|
14
|
+
{ value: "agents", label: "Agents", hint: "Install agents, change default" },
|
|
15
|
+
{ value: "workspace", label: "Workspace", hint: "Set workspace directory" },
|
|
16
|
+
{ value: "runMode", label: "Run mode", hint: "Foreground/daemon, auto-start" },
|
|
17
|
+
{ value: "integrations", label: "Integrations", hint: "Claude CLI session transfer" }
|
|
18
|
+
];
|
|
19
|
+
var CHANNEL_META = {
|
|
20
|
+
telegram: { label: "Telegram", method: "Bot API" },
|
|
21
|
+
discord: { label: "Discord", method: "Bot API" }
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// src/core/setup/helpers.ts
|
|
10
25
|
import * as clack from "@clack/prompts";
|
|
11
|
-
function guardCancel(value) {
|
|
12
|
-
if (clack.isCancel(value)) {
|
|
13
|
-
clack.cancel("Setup cancelled.");
|
|
14
|
-
process.exit(0);
|
|
15
|
-
}
|
|
16
|
-
return value;
|
|
17
|
-
}
|
|
18
26
|
var c = {
|
|
19
27
|
reset: "\x1B[0m",
|
|
20
28
|
bold: "\x1B[1m",
|
|
@@ -32,6 +40,67 @@ var step = (n, total, title) => `
|
|
|
32
40
|
${c.cyan}${c.bold}[${n}/${total}]${c.reset} ${c.bold}${title}${c.reset}
|
|
33
41
|
`;
|
|
34
42
|
var dim = (msg) => `${c.dim}${msg}${c.reset}`;
|
|
43
|
+
function guardCancel(value) {
|
|
44
|
+
if (clack.isCancel(value)) {
|
|
45
|
+
clack.cancel("Setup cancelled.");
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
function applyGradient(text4) {
|
|
51
|
+
const colors = [135, 99, 63, 33, 39, 44, 44];
|
|
52
|
+
const lines = text4.split("\n");
|
|
53
|
+
return lines.map((line, i) => {
|
|
54
|
+
const colorIdx = Math.min(i, colors.length - 1);
|
|
55
|
+
return `\x1B[38;5;${colors[colorIdx]}m${line}\x1B[0m`;
|
|
56
|
+
}).join("\n");
|
|
57
|
+
}
|
|
58
|
+
var BANNER = `
|
|
59
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
60
|
+
\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
|
|
61
|
+
\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
|
|
62
|
+
\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u255D
|
|
63
|
+
\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551
|
|
64
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D
|
|
65
|
+
`;
|
|
66
|
+
async function printStartBanner() {
|
|
67
|
+
let version = "0.0.0";
|
|
68
|
+
try {
|
|
69
|
+
const { getCurrentVersion } = await import("./version-NQZBM5M7.js");
|
|
70
|
+
version = getCurrentVersion();
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
73
|
+
console.log(applyGradient(BANNER));
|
|
74
|
+
console.log(`${c.dim} AI coding agents, anywhere. v${version}${c.reset}
|
|
75
|
+
`);
|
|
76
|
+
}
|
|
77
|
+
function summarizeConfig(config) {
|
|
78
|
+
const lines = [];
|
|
79
|
+
const channelStatuses = [];
|
|
80
|
+
for (const [id, meta] of Object.entries({
|
|
81
|
+
telegram: "Telegram",
|
|
82
|
+
discord: "Discord"
|
|
83
|
+
})) {
|
|
84
|
+
const ch = config.channels[id];
|
|
85
|
+
if (ch?.enabled) {
|
|
86
|
+
channelStatuses.push(`${meta} (enabled)`);
|
|
87
|
+
} else if (ch && Object.keys(ch).length > 1) {
|
|
88
|
+
channelStatuses.push(`${meta} (disabled)`);
|
|
89
|
+
} else {
|
|
90
|
+
channelStatuses.push(`${meta} (not configured)`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
lines.push(`Channels: ${channelStatuses.join(", ")}`);
|
|
94
|
+
lines.push(`Default agent: ${config.defaultAgent}`);
|
|
95
|
+
lines.push(`Workspace: ${config.workspace.baseDir}`);
|
|
96
|
+
lines.push(`Run mode: ${config.runMode}${config.autoStart ? " (auto-start)" : ""}`);
|
|
97
|
+
return lines.join("\n");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/core/setup/setup-telegram.ts
|
|
101
|
+
import * as clack2 from "@clack/prompts";
|
|
102
|
+
|
|
103
|
+
// src/core/setup/validation.ts
|
|
35
104
|
async function validateBotToken(token) {
|
|
36
105
|
try {
|
|
37
106
|
const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);
|
|
@@ -108,9 +177,28 @@ async function validateBotAdmin(token, chatId) {
|
|
|
108
177
|
return { ok: false, error: err.message };
|
|
109
178
|
}
|
|
110
179
|
}
|
|
180
|
+
async function validateDiscordToken(token) {
|
|
181
|
+
try {
|
|
182
|
+
const res = await fetch("https://discord.com/api/v10/users/@me", {
|
|
183
|
+
headers: { Authorization: `Bot ${token}` }
|
|
184
|
+
});
|
|
185
|
+
if (res.status === 200) {
|
|
186
|
+
const data = await res.json();
|
|
187
|
+
return { ok: true, username: data.username, id: data.id };
|
|
188
|
+
}
|
|
189
|
+
if (res.status === 401) {
|
|
190
|
+
return { ok: false, error: "Token rejected by Discord (401 Unauthorized)" };
|
|
191
|
+
}
|
|
192
|
+
return { ok: false, error: `Discord API returned ${res.status}` };
|
|
193
|
+
} catch (err) {
|
|
194
|
+
return { ok: false, error: err.message };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// src/core/setup/setup-telegram.ts
|
|
111
199
|
async function promptManualChatId() {
|
|
112
200
|
const val = guardCancel(
|
|
113
|
-
await
|
|
201
|
+
await clack2.text({
|
|
114
202
|
message: "Supergroup chat ID (e.g. -1001234567890):",
|
|
115
203
|
validate: (val2) => {
|
|
116
204
|
const n = Number((val2 ?? "").toString().trim());
|
|
@@ -206,7 +294,7 @@ async function detectChatId(token) {
|
|
|
206
294
|
value: id
|
|
207
295
|
}));
|
|
208
296
|
return guardCancel(
|
|
209
|
-
await
|
|
297
|
+
await clack2.select({
|
|
210
298
|
message: "Multiple groups found. Pick one:",
|
|
211
299
|
options
|
|
212
300
|
})
|
|
@@ -224,47 +312,69 @@ async function detectChatId(token) {
|
|
|
224
312
|
throw err;
|
|
225
313
|
}
|
|
226
314
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
315
|
+
async function detectAndValidateChatId(botToken) {
|
|
316
|
+
while (true) {
|
|
317
|
+
const chatId = await detectChatId(botToken);
|
|
318
|
+
const chatResult = await validateChatId(botToken, chatId);
|
|
319
|
+
if (!chatResult.ok) {
|
|
320
|
+
console.log(fail(chatResult.error));
|
|
321
|
+
console.log("");
|
|
322
|
+
console.log(` ${c.bold}How to fix:${c.reset}`);
|
|
323
|
+
console.log(dim(" 1. Make sure the bot is added to the group"));
|
|
324
|
+
console.log(dim(" 2. The group must be a Supergroup (Group Settings \u2192 convert)"));
|
|
325
|
+
console.log(dim(" 3. Send a message in the group after adding the bot"));
|
|
326
|
+
console.log("");
|
|
327
|
+
guardCancel(await clack2.text({ message: "Press Enter to try again..." }));
|
|
328
|
+
continue;
|
|
241
329
|
}
|
|
242
|
-
|
|
243
|
-
|
|
330
|
+
console.log(
|
|
331
|
+
ok(
|
|
332
|
+
`Group: ${c.bold}${chatResult.title}${c.reset}${c.green}${chatResult.isForum ? " (Topics enabled)" : ""}`
|
|
333
|
+
)
|
|
334
|
+
);
|
|
335
|
+
const adminResult = await validateBotAdmin(botToken, chatId);
|
|
336
|
+
if (!adminResult.ok) {
|
|
337
|
+
console.log(fail(adminResult.error));
|
|
338
|
+
console.log("");
|
|
339
|
+
console.log(` ${c.bold}How to fix:${c.reset}`);
|
|
340
|
+
console.log(dim(" 1. Open the group in Telegram"));
|
|
341
|
+
console.log(dim(" 2. Go to Group Settings \u2192 Administrators"));
|
|
342
|
+
console.log(dim(" 3. Add the bot as an administrator"));
|
|
343
|
+
console.log("");
|
|
344
|
+
guardCancel(await clack2.text({ message: "Press Enter to check again..." }));
|
|
345
|
+
continue;
|
|
244
346
|
}
|
|
347
|
+
console.log(ok("Bot has admin privileges"));
|
|
348
|
+
return chatId;
|
|
245
349
|
}
|
|
246
|
-
return found;
|
|
247
350
|
}
|
|
248
|
-
async function
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
} catch {
|
|
253
|
-
return false;
|
|
351
|
+
async function setupTelegram(opts) {
|
|
352
|
+
const { existing, stepNum, totalSteps } = opts ?? {};
|
|
353
|
+
if (stepNum != null && totalSteps != null) {
|
|
354
|
+
console.log(step(stepNum, totalSteps, "Telegram Bot"));
|
|
254
355
|
}
|
|
255
|
-
}
|
|
256
|
-
async function setupTelegram(stepNum = 1, totalSteps = 3) {
|
|
257
|
-
console.log(step(stepNum, totalSteps, "Telegram Bot"));
|
|
258
356
|
let botToken = "";
|
|
357
|
+
const existingToken = existing?.botToken;
|
|
259
358
|
while (true) {
|
|
260
|
-
|
|
261
|
-
await
|
|
262
|
-
message: "Bot token (from @BotFather):",
|
|
263
|
-
|
|
359
|
+
const tokenInput = guardCancel(
|
|
360
|
+
await clack2.text({
|
|
361
|
+
message: existingToken ? "Bot token (from @BotFather) \u2014 leave blank to keep current:" : "Bot token (from @BotFather):",
|
|
362
|
+
...existingToken ? { placeholder: "Leave blank to keep current" } : {},
|
|
363
|
+
validate: (val) => {
|
|
364
|
+
if (existingToken && (val ?? "").toString().trim().length === 0) return void 0;
|
|
365
|
+
if ((val ?? "").toString().trim().length > 0) return void 0;
|
|
366
|
+
return "Token cannot be empty";
|
|
367
|
+
}
|
|
264
368
|
})
|
|
265
369
|
);
|
|
266
|
-
|
|
267
|
-
|
|
370
|
+
const keptExisting = existingToken && !tokenInput.trim();
|
|
371
|
+
botToken = tokenInput.trim() || existingToken || "";
|
|
372
|
+
if (!botToken) continue;
|
|
373
|
+
if (keptExisting) {
|
|
374
|
+
console.log(ok("Keeping current bot token"));
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
const s = clack2.spinner();
|
|
268
378
|
s.start("Validating token...");
|
|
269
379
|
const result = await validateBotToken(botToken);
|
|
270
380
|
s.stop("Token validated");
|
|
@@ -274,7 +384,7 @@ async function setupTelegram(stepNum = 1, totalSteps = 3) {
|
|
|
274
384
|
}
|
|
275
385
|
console.log(fail(result.error));
|
|
276
386
|
const action = guardCancel(
|
|
277
|
-
await
|
|
387
|
+
await clack2.select({
|
|
278
388
|
message: "What to do?",
|
|
279
389
|
options: [
|
|
280
390
|
{ label: "Re-enter token", value: "retry" },
|
|
@@ -285,67 +395,52 @@ async function setupTelegram(stepNum = 1, totalSteps = 3) {
|
|
|
285
395
|
if (action === "skip") break;
|
|
286
396
|
}
|
|
287
397
|
let chatId;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
continue;
|
|
301
|
-
}
|
|
302
|
-
console.log(
|
|
303
|
-
ok(
|
|
304
|
-
`Group: ${c.bold}${chatResult.title}${c.reset}${c.green}${chatResult.isForum ? " (Topics enabled)" : ""}`
|
|
305
|
-
)
|
|
398
|
+
const existingChatId = existing?.chatId;
|
|
399
|
+
if (existingChatId && existingChatId !== 0) {
|
|
400
|
+
const chatIdAction = guardCancel(
|
|
401
|
+
await clack2.select({
|
|
402
|
+
message: `Group chat ID: ${existingChatId}`,
|
|
403
|
+
options: [
|
|
404
|
+
{ value: "keep", label: "Keep current" },
|
|
405
|
+
{ value: "manual", label: "Enter new chat ID" },
|
|
406
|
+
{ value: "detect", label: "Auto-detect from group" }
|
|
407
|
+
],
|
|
408
|
+
initialValue: "keep"
|
|
409
|
+
})
|
|
306
410
|
);
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
console.log(
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
411
|
+
if (chatIdAction === "keep") {
|
|
412
|
+
chatId = existingChatId;
|
|
413
|
+
console.log(ok("Keeping current group chat ID"));
|
|
414
|
+
} else if (chatIdAction === "manual") {
|
|
415
|
+
chatId = await promptManualChatId();
|
|
416
|
+
const chatResult = await validateChatId(botToken, chatId);
|
|
417
|
+
if (chatResult.ok) {
|
|
418
|
+
console.log(ok(`Group: ${c.bold}${chatResult.title}${c.reset}${c.green}${chatResult.isForum ? " (Topics enabled)" : ""}`));
|
|
419
|
+
} else {
|
|
420
|
+
console.log(fail(chatResult.error));
|
|
421
|
+
}
|
|
422
|
+
} else {
|
|
423
|
+
chatId = await detectAndValidateChatId(botToken);
|
|
318
424
|
}
|
|
319
|
-
|
|
320
|
-
|
|
425
|
+
} else {
|
|
426
|
+
chatId = await detectAndValidateChatId(botToken);
|
|
321
427
|
}
|
|
322
428
|
return {
|
|
323
429
|
enabled: true,
|
|
324
430
|
botToken,
|
|
325
431
|
chatId,
|
|
326
|
-
|
|
327
|
-
|
|
432
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
433
|
+
notificationTopicId: existing?.notificationTopicId ?? null,
|
|
434
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
435
|
+
assistantTopicId: existing?.assistantTopicId ?? null
|
|
328
436
|
};
|
|
329
437
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const data = await res.json();
|
|
337
|
-
return { ok: true, username: data.username, id: data.id };
|
|
338
|
-
}
|
|
339
|
-
if (res.status === 401) {
|
|
340
|
-
return { ok: false, error: "Token rejected by Discord (401 Unauthorized)" };
|
|
341
|
-
}
|
|
342
|
-
return { ok: false, error: `Discord API returned ${res.status}` };
|
|
343
|
-
} catch (err) {
|
|
344
|
-
return { ok: false, error: err.message };
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
async function setupDiscord() {
|
|
348
|
-
console.log("\n\u{1F4F1} Discord Setup\n");
|
|
438
|
+
|
|
439
|
+
// src/core/setup/setup-discord.ts
|
|
440
|
+
import * as clack3 from "@clack/prompts";
|
|
441
|
+
async function setupDiscord(opts) {
|
|
442
|
+
const { existing } = opts ?? {};
|
|
443
|
+
console.log("\nDiscord Setup\n");
|
|
349
444
|
console.log(` ${c.bold}Quick setup:${c.reset}`);
|
|
350
445
|
console.log(dim(" 1. Create app at https://discord.com/developers/applications"));
|
|
351
446
|
console.log(dim(" 2. Go to Bot \u2192 Reset Token \u2192 copy it"));
|
|
@@ -354,18 +449,30 @@ async function setupDiscord() {
|
|
|
354
449
|
console.log(dim(" 5. Bot Permissions: Manage Channels, Send Messages, Manage Threads, Attach Files"));
|
|
355
450
|
console.log(dim(" 6. Open generated URL \u2192 invite bot to your server"));
|
|
356
451
|
console.log("");
|
|
357
|
-
console.log(dim(`
|
|
452
|
+
console.log(dim(` Detailed guide: https://github.com/Open-ACP/OpenACP/blob/main/docs/guide/discord-setup.md`));
|
|
358
453
|
console.log("");
|
|
359
454
|
let botToken = "";
|
|
455
|
+
const existingToken = existing?.botToken;
|
|
360
456
|
while (true) {
|
|
361
|
-
|
|
362
|
-
await
|
|
363
|
-
message: "Bot token (from Discord Developer Portal):",
|
|
364
|
-
|
|
457
|
+
const tokenInput = guardCancel(
|
|
458
|
+
await clack3.text({
|
|
459
|
+
message: existingToken ? "Bot token (from Discord Developer Portal) \u2014 leave blank to keep current:" : "Bot token (from Discord Developer Portal):",
|
|
460
|
+
...existingToken ? { placeholder: "Leave blank to keep current" } : {},
|
|
461
|
+
validate: (val) => {
|
|
462
|
+
if (existingToken && (val ?? "").toString().trim().length === 0) return void 0;
|
|
463
|
+
if ((val ?? "").toString().trim().length > 0) return void 0;
|
|
464
|
+
return "Token cannot be empty";
|
|
465
|
+
}
|
|
365
466
|
})
|
|
366
467
|
);
|
|
367
|
-
|
|
368
|
-
|
|
468
|
+
const keptExisting = existingToken && !tokenInput.trim();
|
|
469
|
+
botToken = tokenInput.trim() || existingToken || "";
|
|
470
|
+
if (!botToken) continue;
|
|
471
|
+
if (keptExisting) {
|
|
472
|
+
console.log(ok("Keeping current bot token"));
|
|
473
|
+
break;
|
|
474
|
+
}
|
|
475
|
+
const s = clack3.spinner();
|
|
369
476
|
s.start("Validating token...");
|
|
370
477
|
const result = await validateDiscordToken(botToken);
|
|
371
478
|
s.stop("Token validated");
|
|
@@ -375,7 +482,7 @@ async function setupDiscord() {
|
|
|
375
482
|
}
|
|
376
483
|
console.log(fail(result.error));
|
|
377
484
|
const action = guardCancel(
|
|
378
|
-
await
|
|
485
|
+
await clack3.select({
|
|
379
486
|
message: "What to do?",
|
|
380
487
|
options: [
|
|
381
488
|
{ label: "Re-enter token", value: "retry" },
|
|
@@ -385,33 +492,69 @@ async function setupDiscord() {
|
|
|
385
492
|
);
|
|
386
493
|
if (action === "skip") break;
|
|
387
494
|
}
|
|
388
|
-
const
|
|
389
|
-
await
|
|
390
|
-
message: "Guild (server) ID:",
|
|
495
|
+
const guildIdInput = guardCancel(
|
|
496
|
+
await clack3.text({
|
|
497
|
+
message: existing?.guildId ? "Guild (server) ID \u2014 leave blank to keep current:" : "Guild (server) ID:",
|
|
498
|
+
...existing?.guildId ? { placeholder: `Current: ${existing.guildId}` } : {},
|
|
391
499
|
validate: (val) => {
|
|
392
500
|
const trimmed = (val ?? "").toString().trim();
|
|
501
|
+
if (existing?.guildId && !trimmed) return void 0;
|
|
393
502
|
if (!trimmed) return "Guild ID cannot be empty";
|
|
394
503
|
if (!/^\d{17,20}$/.test(trimmed)) return "Guild ID must be a numeric Discord snowflake (17-20 digits)";
|
|
395
504
|
return void 0;
|
|
396
505
|
}
|
|
397
506
|
})
|
|
398
507
|
);
|
|
508
|
+
const guildId = guildIdInput.trim() || existing?.guildId || "";
|
|
399
509
|
return {
|
|
400
510
|
enabled: true,
|
|
401
511
|
botToken,
|
|
402
512
|
guildId: guildId.trim(),
|
|
403
|
-
forumChannelId: null,
|
|
404
|
-
notificationChannelId: null,
|
|
405
|
-
assistantThreadId: null
|
|
513
|
+
forumChannelId: existing?.forumChannelId ?? null,
|
|
514
|
+
notificationChannelId: existing?.notificationChannelId ?? null,
|
|
515
|
+
assistantThreadId: existing?.assistantThreadId ?? null
|
|
406
516
|
};
|
|
407
517
|
}
|
|
518
|
+
|
|
519
|
+
// src/core/setup/setup-agents.ts
|
|
520
|
+
import { execFileSync } from "child_process";
|
|
521
|
+
import * as clack4 from "@clack/prompts";
|
|
522
|
+
var KNOWN_AGENTS = [
|
|
523
|
+
// claude-agent-acp is bundled as a dependency — no detection needed, but
|
|
524
|
+
// kept here so detectAgents() still returns it for display purposes.
|
|
525
|
+
{ name: "claude", commands: ["claude-agent-acp"] },
|
|
526
|
+
{ name: "codex", commands: ["codex"] }
|
|
527
|
+
];
|
|
528
|
+
async function detectAgents() {
|
|
529
|
+
const found = [];
|
|
530
|
+
for (const agent of KNOWN_AGENTS) {
|
|
531
|
+
const available = [];
|
|
532
|
+
for (const cmd of agent.commands) {
|
|
533
|
+
if (commandExists(cmd)) {
|
|
534
|
+
available.push(cmd);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
if (available.length > 0) {
|
|
538
|
+
found.push({ name: agent.name, command: available[0] });
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return found;
|
|
542
|
+
}
|
|
543
|
+
async function validateAgentCommand(command) {
|
|
544
|
+
try {
|
|
545
|
+
execFileSync("which", [command], { stdio: "pipe" });
|
|
546
|
+
return true;
|
|
547
|
+
} catch {
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
408
551
|
async function setupAgents() {
|
|
409
552
|
const { AgentCatalog } = await import("./agent-catalog-FC3HGDEQ.js");
|
|
410
553
|
const { muteLogger, unmuteLogger } = await import("./log-NXABYJTT.js");
|
|
411
554
|
muteLogger();
|
|
412
555
|
const catalog = new AgentCatalog();
|
|
413
556
|
catalog.load();
|
|
414
|
-
const s =
|
|
557
|
+
const s = clack4.spinner();
|
|
415
558
|
s.start("Checking available agents...");
|
|
416
559
|
await catalog.refreshRegistryIfStale();
|
|
417
560
|
if (!catalog.getInstalledAgent("claude")) {
|
|
@@ -463,7 +606,7 @@ async function setupAgents() {
|
|
|
463
606
|
}
|
|
464
607
|
const installedKeys = installed.map((a) => a.key);
|
|
465
608
|
const selected = guardCancel(
|
|
466
|
-
await
|
|
609
|
+
await clack4.autocompleteMultiselect({
|
|
467
610
|
message: "Install additional agents? (type to search, Space to select)",
|
|
468
611
|
options,
|
|
469
612
|
initialValues: installedKeys,
|
|
@@ -473,7 +616,7 @@ async function setupAgents() {
|
|
|
473
616
|
for (const key of selected) {
|
|
474
617
|
const regAgent = catalog.findRegistryAgent(key);
|
|
475
618
|
if (regAgent) {
|
|
476
|
-
const installSpinner =
|
|
619
|
+
const installSpinner = clack4.spinner();
|
|
477
620
|
installSpinner.start(`Installing ${regAgent.name}...`);
|
|
478
621
|
muteLogger();
|
|
479
622
|
const result = await catalog.install(key);
|
|
@@ -490,7 +633,7 @@ async function setupAgents() {
|
|
|
490
633
|
let defaultAgent = "claude";
|
|
491
634
|
if (installedAgents.length > 1) {
|
|
492
635
|
defaultAgent = guardCancel(
|
|
493
|
-
await
|
|
636
|
+
await clack4.select({
|
|
494
637
|
message: "Which agent should be the default?",
|
|
495
638
|
options: installedAgents.map((key) => {
|
|
496
639
|
const agent = catalog.getInstalledAgent(key);
|
|
@@ -503,25 +646,38 @@ async function setupAgents() {
|
|
|
503
646
|
console.log(ok(`Default agent: ${c.bold}${defaultAgent}${c.reset}`));
|
|
504
647
|
return { defaultAgent };
|
|
505
648
|
}
|
|
506
|
-
|
|
507
|
-
|
|
649
|
+
|
|
650
|
+
// src/core/setup/setup-workspace.ts
|
|
651
|
+
import * as clack5 from "@clack/prompts";
|
|
652
|
+
async function setupWorkspace(opts) {
|
|
653
|
+
const { existing, stepNum, totalSteps } = opts ?? {};
|
|
654
|
+
if (stepNum != null && totalSteps != null) {
|
|
655
|
+
console.log(step(stepNum, totalSteps, "Workspace"));
|
|
656
|
+
}
|
|
508
657
|
const baseDir = guardCancel(
|
|
509
|
-
await
|
|
658
|
+
await clack5.text({
|
|
510
659
|
message: "Base directory for workspaces:",
|
|
511
|
-
initialValue: "~/openacp-workspace",
|
|
660
|
+
initialValue: existing ?? "~/openacp-workspace",
|
|
512
661
|
validate: (val) => (val ?? "").toString().trim().length > 0 ? void 0 : "Path cannot be empty"
|
|
513
662
|
})
|
|
514
663
|
);
|
|
515
664
|
return { baseDir: baseDir.trim().replace(/^['"]|['"]$/g, "") };
|
|
516
665
|
}
|
|
517
|
-
|
|
518
|
-
|
|
666
|
+
|
|
667
|
+
// src/core/setup/setup-run-mode.ts
|
|
668
|
+
import * as clack6 from "@clack/prompts";
|
|
669
|
+
async function setupRunMode(opts) {
|
|
670
|
+
const { existing, stepNum, totalSteps } = opts ?? {};
|
|
671
|
+
if (stepNum != null && totalSteps != null) {
|
|
672
|
+
console.log(step(stepNum, totalSteps, "Run Mode"));
|
|
673
|
+
}
|
|
519
674
|
if (process.platform === "win32") {
|
|
520
675
|
console.log(dim(" (Daemon mode not available on Windows)"));
|
|
521
676
|
return { runMode: "foreground", autoStart: false };
|
|
522
677
|
}
|
|
678
|
+
const initialValue = existing?.runMode === "daemon" ? "daemon" : "foreground";
|
|
523
679
|
const mode = guardCancel(
|
|
524
|
-
await
|
|
680
|
+
await clack6.select({
|
|
525
681
|
message: "How would you like to run OpenACP?",
|
|
526
682
|
options: [
|
|
527
683
|
{
|
|
@@ -534,14 +690,19 @@ async function setupRunMode(stepNum = 3, totalSteps = 3) {
|
|
|
534
690
|
value: "foreground",
|
|
535
691
|
hint: "Runs in current terminal session. Start with: openacp"
|
|
536
692
|
}
|
|
537
|
-
]
|
|
693
|
+
],
|
|
694
|
+
initialValue
|
|
538
695
|
})
|
|
539
696
|
);
|
|
697
|
+
const wasDaemon = existing?.runMode === "daemon";
|
|
540
698
|
if (mode === "daemon") {
|
|
541
699
|
const { installAutoStart, isAutoStartSupported } = await import("./autostart-X33OGMX6.js");
|
|
700
|
+
const { muteLogger, unmuteLogger } = await import("./log-NXABYJTT.js");
|
|
542
701
|
const autoStart = isAutoStartSupported();
|
|
543
702
|
if (autoStart) {
|
|
703
|
+
muteLogger();
|
|
544
704
|
const result = installAutoStart(expandHome("~/.openacp/logs"));
|
|
705
|
+
unmuteLogger();
|
|
545
706
|
if (result.success) {
|
|
546
707
|
console.log(ok("Auto-start on boot enabled"));
|
|
547
708
|
} else {
|
|
@@ -550,44 +711,181 @@ async function setupRunMode(stepNum = 3, totalSteps = 3) {
|
|
|
550
711
|
}
|
|
551
712
|
return { runMode: "daemon", autoStart };
|
|
552
713
|
}
|
|
714
|
+
if (wasDaemon) {
|
|
715
|
+
const { muteLogger, unmuteLogger } = await import("./log-NXABYJTT.js");
|
|
716
|
+
muteLogger();
|
|
717
|
+
try {
|
|
718
|
+
const { stopDaemon } = await import("./daemon-4CS6HMB5.js");
|
|
719
|
+
const result = await stopDaemon();
|
|
720
|
+
unmuteLogger();
|
|
721
|
+
if (result.stopped) {
|
|
722
|
+
console.log(ok(`Daemon stopped (was PID ${result.pid})`));
|
|
723
|
+
}
|
|
724
|
+
} catch {
|
|
725
|
+
unmuteLogger();
|
|
726
|
+
}
|
|
727
|
+
muteLogger();
|
|
728
|
+
try {
|
|
729
|
+
const { uninstallAutoStart } = await import("./autostart-X33OGMX6.js");
|
|
730
|
+
uninstallAutoStart();
|
|
731
|
+
unmuteLogger();
|
|
732
|
+
} catch {
|
|
733
|
+
unmuteLogger();
|
|
734
|
+
}
|
|
735
|
+
}
|
|
553
736
|
return { runMode: "foreground", autoStart: false };
|
|
554
737
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
738
|
+
|
|
739
|
+
// src/core/setup/setup-integrations.ts
|
|
740
|
+
import * as clack7 from "@clack/prompts";
|
|
741
|
+
async function setupIntegrations(config) {
|
|
742
|
+
const claudeIntegration = config?.integrations?.claude;
|
|
743
|
+
const isInstalled = claudeIntegration?.installed === true;
|
|
744
|
+
const installClaude = guardCancel(
|
|
745
|
+
await clack7.confirm({
|
|
746
|
+
message: isInstalled ? "Claude CLI integration is installed. Reinstall?" : "Install session transfer for Claude? (enables /openacp:handoff in your terminal)",
|
|
747
|
+
initialValue: !isInstalled
|
|
748
|
+
})
|
|
749
|
+
);
|
|
750
|
+
if (installClaude) {
|
|
751
|
+
try {
|
|
752
|
+
const { getIntegration } = await import("./integrate-PNEHRY2I.js");
|
|
753
|
+
const integration = getIntegration("claude");
|
|
754
|
+
if (integration) {
|
|
755
|
+
for (const item of integration.items) {
|
|
756
|
+
const result = await item.install();
|
|
757
|
+
for (const log of result.logs) console.log(` ${log}`);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
console.log("Claude CLI integration installed.\n");
|
|
761
|
+
} catch (err) {
|
|
762
|
+
console.log(`Could not install Claude CLI integration: ${err instanceof Error ? err.message : err}`);
|
|
763
|
+
console.log(" You can install it later with: openacp integrate claude\n");
|
|
764
|
+
}
|
|
765
|
+
}
|
|
562
766
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
767
|
+
|
|
768
|
+
// src/core/setup/setup-channels.ts
|
|
769
|
+
import * as clack8 from "@clack/prompts";
|
|
770
|
+
function getChannelStatuses(config) {
|
|
771
|
+
const statuses = [];
|
|
772
|
+
for (const [id, meta] of Object.entries(CHANNEL_META)) {
|
|
773
|
+
const ch = config.channels[id];
|
|
774
|
+
const enabled = ch?.enabled === true;
|
|
775
|
+
const configured = !!ch && Object.keys(ch).length > 1;
|
|
776
|
+
let hint;
|
|
777
|
+
if (id === "telegram" && ch?.botToken && typeof ch.botToken === "string" && ch.botToken !== "YOUR_BOT_TOKEN_HERE") {
|
|
778
|
+
hint = `Chat ID: ${ch.chatId}`;
|
|
779
|
+
}
|
|
780
|
+
if (id === "discord" && ch?.guildId) {
|
|
781
|
+
hint = `Guild: ${ch.guildId}`;
|
|
782
|
+
}
|
|
783
|
+
statuses.push({ id, label: meta.label, configured, enabled, hint });
|
|
577
784
|
}
|
|
578
|
-
|
|
579
|
-
console.log(`${c.dim} AI coding agents, anywhere. v${version}${c.reset}
|
|
580
|
-
`);
|
|
785
|
+
return statuses;
|
|
581
786
|
}
|
|
582
|
-
|
|
583
|
-
|
|
787
|
+
function noteChannelStatus(config) {
|
|
788
|
+
const statuses = getChannelStatuses(config);
|
|
789
|
+
const lines = statuses.map((s) => {
|
|
790
|
+
const status = s.enabled ? "enabled" : s.configured ? "disabled" : "not configured";
|
|
791
|
+
const hintStr = s.hint ? ` \u2014 ${s.hint}` : "";
|
|
792
|
+
return ` ${s.label}: ${status}${hintStr}`;
|
|
793
|
+
});
|
|
794
|
+
console.log("");
|
|
795
|
+
console.log(`${c.bold} Channel status${c.reset}`);
|
|
796
|
+
for (const line of lines) console.log(line);
|
|
797
|
+
console.log("");
|
|
584
798
|
}
|
|
799
|
+
async function promptConfiguredAction(label) {
|
|
800
|
+
return guardCancel(
|
|
801
|
+
await clack8.select({
|
|
802
|
+
message: `${label} already configured. What do you want to do?`,
|
|
803
|
+
options: [
|
|
804
|
+
{ value: "modify", label: "Modify settings" },
|
|
805
|
+
{ value: "disable", label: "Disable bot" },
|
|
806
|
+
{ value: "delete", label: "Delete config" },
|
|
807
|
+
{ value: "skip", label: "Skip (leave as-is)" }
|
|
808
|
+
],
|
|
809
|
+
initialValue: "modify"
|
|
810
|
+
})
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
async function configureChannels(config) {
|
|
814
|
+
const next = structuredClone(config);
|
|
815
|
+
let changed = false;
|
|
816
|
+
noteChannelStatus(next);
|
|
817
|
+
while (true) {
|
|
818
|
+
const statuses = getChannelStatuses(next);
|
|
819
|
+
const options = statuses.map((s) => {
|
|
820
|
+
const status = s.enabled ? "enabled" : s.configured ? "disabled" : "not configured";
|
|
821
|
+
return {
|
|
822
|
+
value: s.id,
|
|
823
|
+
label: `${s.label} (${CHANNEL_META[s.id].method})`,
|
|
824
|
+
hint: status + (s.hint ? ` \xB7 ${s.hint}` : "")
|
|
825
|
+
};
|
|
826
|
+
});
|
|
827
|
+
const choice = guardCancel(
|
|
828
|
+
await clack8.select({
|
|
829
|
+
message: "Select a channel",
|
|
830
|
+
options: [
|
|
831
|
+
...options,
|
|
832
|
+
{ value: "__done__", label: "Finished" }
|
|
833
|
+
]
|
|
834
|
+
})
|
|
835
|
+
);
|
|
836
|
+
if (choice === "__done__") break;
|
|
837
|
+
const channelId = choice;
|
|
838
|
+
const meta = CHANNEL_META[channelId];
|
|
839
|
+
const existing = next.channels[channelId];
|
|
840
|
+
const isConfigured = !!existing && Object.keys(existing).length > 1;
|
|
841
|
+
if (isConfigured) {
|
|
842
|
+
const action = await promptConfiguredAction(meta.label);
|
|
843
|
+
if (action === "skip") continue;
|
|
844
|
+
if (action === "disable") {
|
|
845
|
+
next.channels[channelId].enabled = false;
|
|
846
|
+
changed = true;
|
|
847
|
+
console.log(ok(`${meta.label} disabled`));
|
|
848
|
+
continue;
|
|
849
|
+
}
|
|
850
|
+
if (action === "delete") {
|
|
851
|
+
const confirmed = guardCancel(
|
|
852
|
+
await clack8.confirm({
|
|
853
|
+
message: `Delete ${meta.label} config? This cannot be undone.`,
|
|
854
|
+
initialValue: false
|
|
855
|
+
})
|
|
856
|
+
);
|
|
857
|
+
if (confirmed) {
|
|
858
|
+
delete next.channels[channelId];
|
|
859
|
+
changed = true;
|
|
860
|
+
console.log(ok(`${meta.label} config deleted`));
|
|
861
|
+
}
|
|
862
|
+
continue;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
if (channelId === "telegram") {
|
|
866
|
+
const result = await setupTelegram({
|
|
867
|
+
existing: isConfigured ? existing : void 0
|
|
868
|
+
});
|
|
869
|
+
next.channels.telegram = result;
|
|
870
|
+
changed = true;
|
|
871
|
+
} else if (channelId === "discord") {
|
|
872
|
+
const result = await setupDiscord({
|
|
873
|
+
existing: isConfigured ? existing : void 0
|
|
874
|
+
});
|
|
875
|
+
next.channels.discord = result;
|
|
876
|
+
changed = true;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
return { config: next, changed };
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
// src/core/setup/wizard.ts
|
|
585
883
|
async function runSetup(configManager, opts) {
|
|
586
|
-
await
|
|
587
|
-
|
|
884
|
+
await printStartBanner();
|
|
885
|
+
clack9.intro("Let's set up OpenACP");
|
|
588
886
|
try {
|
|
589
887
|
const channelChoice = guardCancel(
|
|
590
|
-
await
|
|
888
|
+
await clack9.select({
|
|
591
889
|
message: "Which messaging platform do you want to use?",
|
|
592
890
|
options: [
|
|
593
891
|
{ label: "Telegram", value: "telegram" },
|
|
@@ -604,44 +902,21 @@ async function runSetup(configManager, opts) {
|
|
|
604
902
|
let currentStep = 0;
|
|
605
903
|
if (channelChoice === "telegram" || channelChoice === "both") {
|
|
606
904
|
currentStep++;
|
|
607
|
-
telegram = await setupTelegram(currentStep, totalSteps);
|
|
905
|
+
telegram = await setupTelegram({ stepNum: currentStep, totalSteps });
|
|
608
906
|
}
|
|
609
907
|
if (channelChoice === "discord" || channelChoice === "both") {
|
|
610
908
|
currentStep++;
|
|
611
909
|
discord = await setupDiscord();
|
|
612
910
|
}
|
|
613
911
|
const { defaultAgent } = await setupAgents();
|
|
614
|
-
|
|
615
|
-
const installClaude = guardCancel(
|
|
616
|
-
await clack.confirm({
|
|
617
|
-
message: "Install session transfer for Claude? (enables /openacp:handoff in your terminal)",
|
|
618
|
-
initialValue: true
|
|
619
|
-
})
|
|
620
|
-
);
|
|
621
|
-
if (installClaude) {
|
|
622
|
-
try {
|
|
623
|
-
const { getIntegration } = await import("./integrate-PNEHRY2I.js");
|
|
624
|
-
const integration = getIntegration("claude");
|
|
625
|
-
if (integration) {
|
|
626
|
-
for (const item of integration.items) {
|
|
627
|
-
const result = await item.install();
|
|
628
|
-
for (const log of result.logs) console.log(` ${log}`);
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
console.log("Claude CLI integration installed.\n");
|
|
632
|
-
} catch (err) {
|
|
633
|
-
console.log(`Could not install Claude CLI integration: ${err instanceof Error ? err.message : err}`);
|
|
634
|
-
console.log(" You can install it later with: openacp integrate claude\n");
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
}
|
|
912
|
+
await setupIntegrations();
|
|
638
913
|
currentStep++;
|
|
639
|
-
const workspace = await setupWorkspace(currentStep, totalSteps);
|
|
914
|
+
const workspace = await setupWorkspace({ stepNum: currentStep, totalSteps });
|
|
640
915
|
let runMode = "foreground";
|
|
641
916
|
let autoStart = false;
|
|
642
917
|
if (!opts?.skipRunMode) {
|
|
643
918
|
currentStep++;
|
|
644
|
-
const result = await setupRunMode(currentStep, totalSteps);
|
|
919
|
+
const result = await setupRunMode({ stepNum: currentStep, totalSteps });
|
|
645
920
|
runMode = result.runMode;
|
|
646
921
|
autoStart = result.autoStart;
|
|
647
922
|
}
|
|
@@ -702,7 +977,7 @@ async function runSetup(configManager, opts) {
|
|
|
702
977
|
);
|
|
703
978
|
return false;
|
|
704
979
|
}
|
|
705
|
-
|
|
980
|
+
clack9.outro(`Config saved to ${configManager.getConfigPath()}`);
|
|
706
981
|
if (!opts?.skipRunMode) {
|
|
707
982
|
console.log(ok("Starting OpenACP..."));
|
|
708
983
|
console.log("");
|
|
@@ -710,26 +985,101 @@ async function runSetup(configManager, opts) {
|
|
|
710
985
|
return true;
|
|
711
986
|
} catch (err) {
|
|
712
987
|
if (err.name === "ExitPromptError") {
|
|
713
|
-
|
|
988
|
+
clack9.cancel("Setup cancelled.");
|
|
714
989
|
return false;
|
|
715
990
|
}
|
|
716
991
|
throw err;
|
|
717
992
|
}
|
|
718
993
|
}
|
|
994
|
+
async function selectSection(hasSelection) {
|
|
995
|
+
return guardCancel(
|
|
996
|
+
await clack9.select({
|
|
997
|
+
message: "Select sections to configure",
|
|
998
|
+
options: [
|
|
999
|
+
...ONBOARD_SECTION_OPTIONS,
|
|
1000
|
+
{
|
|
1001
|
+
value: "__continue",
|
|
1002
|
+
label: "Continue",
|
|
1003
|
+
hint: hasSelection ? "Done" : "Skip for now"
|
|
1004
|
+
}
|
|
1005
|
+
],
|
|
1006
|
+
initialValue: ONBOARD_SECTION_OPTIONS[0].value
|
|
1007
|
+
})
|
|
1008
|
+
);
|
|
1009
|
+
}
|
|
1010
|
+
async function runReconfigure(configManager) {
|
|
1011
|
+
await printStartBanner();
|
|
1012
|
+
clack9.intro("OpenACP \u2014 Reconfigure");
|
|
1013
|
+
try {
|
|
1014
|
+
await configManager.load();
|
|
1015
|
+
let config = configManager.get();
|
|
1016
|
+
clack9.note(summarizeConfig(config), "Current configuration");
|
|
1017
|
+
let ranSection = false;
|
|
1018
|
+
while (true) {
|
|
1019
|
+
const choice = await selectSection(ranSection);
|
|
1020
|
+
if (choice === "__continue") break;
|
|
1021
|
+
ranSection = true;
|
|
1022
|
+
if (choice === "channels") {
|
|
1023
|
+
const result = await configureChannels(config);
|
|
1024
|
+
if (result.changed) {
|
|
1025
|
+
config = { ...config, channels: result.config.channels };
|
|
1026
|
+
await configManager.writeNew(config);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
if (choice === "agents") {
|
|
1030
|
+
const { defaultAgent } = await setupAgents();
|
|
1031
|
+
await configManager.save({ defaultAgent });
|
|
1032
|
+
config = configManager.get();
|
|
1033
|
+
}
|
|
1034
|
+
if (choice === "workspace") {
|
|
1035
|
+
const { baseDir } = await setupWorkspace({
|
|
1036
|
+
existing: config.workspace.baseDir
|
|
1037
|
+
});
|
|
1038
|
+
await configManager.save({ workspace: { baseDir } });
|
|
1039
|
+
config = configManager.get();
|
|
1040
|
+
}
|
|
1041
|
+
if (choice === "runMode") {
|
|
1042
|
+
const result = await setupRunMode({
|
|
1043
|
+
existing: { runMode: config.runMode, autoStart: config.autoStart }
|
|
1044
|
+
});
|
|
1045
|
+
await configManager.save({
|
|
1046
|
+
runMode: result.runMode,
|
|
1047
|
+
autoStart: result.autoStart
|
|
1048
|
+
});
|
|
1049
|
+
config = configManager.get();
|
|
1050
|
+
}
|
|
1051
|
+
if (choice === "integrations") {
|
|
1052
|
+
await setupIntegrations(config);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
if (!ranSection) {
|
|
1056
|
+
clack9.outro("No changes made.");
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
clack9.outro(`Config saved to ${configManager.getConfigPath()}`);
|
|
1060
|
+
} catch (err) {
|
|
1061
|
+
if (err.name === "ExitPromptError") {
|
|
1062
|
+
clack9.cancel("Setup cancelled.");
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
throw err;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
719
1068
|
|
|
720
1069
|
export {
|
|
1070
|
+
printStartBanner,
|
|
721
1071
|
validateBotToken,
|
|
722
1072
|
validateChatId,
|
|
723
1073
|
validateBotAdmin,
|
|
724
|
-
detectAgents,
|
|
725
|
-
validateAgentCommand,
|
|
726
|
-
setupTelegram,
|
|
727
1074
|
validateDiscordToken,
|
|
1075
|
+
setupTelegram,
|
|
728
1076
|
setupDiscord,
|
|
1077
|
+
detectAgents,
|
|
1078
|
+
validateAgentCommand,
|
|
729
1079
|
setupAgents,
|
|
730
1080
|
setupWorkspace,
|
|
731
1081
|
setupRunMode,
|
|
732
|
-
|
|
733
|
-
|
|
1082
|
+
runSetup,
|
|
1083
|
+
runReconfigure
|
|
734
1084
|
};
|
|
735
|
-
//# sourceMappingURL=chunk-
|
|
1085
|
+
//# sourceMappingURL=chunk-LCRLAV4G.js.map
|